Coder Social home page Coder Social logo

cloudscribe / cloudscribe Goto Github PK

View Code? Open in Web Editor NEW
1.3K 1.3K 277.0 28.05 MB

ASP.NET Core multi-tenant web application foundation with management for sites, users, roles, claims and more

License: Other

C# 45.35% JavaScript 27.57% CSS 1.44% HTML 23.64% PowerShell 0.09% Shell 0.04% TSQL 0.09% SCSS 1.78%

cloudscribe's Introduction

cloudscribe

cloudscribe is a related set of projects and components for building cross platform web applications on ASP.NET Core. Get the big picture at cloudscribe.com

The foundational set of projects in this repository, known as cloudscibe Core, provides support for single tenant or multi tenant management of sites, users, and roles. The other main cloudscribe project is cloudscribe SimpleContent. There are a lot of smaller useful libraries as well, you can find the full list of projects here.

If you have questions please visit our community forums https://www.cloudscribe.com/forum.

Build Status

Windows Linux
Build status Build Status

Twitter URL Twitter Follow

Why Start From Scratch?

Every web application or website project tends to need a certain amount of basic functionality, why build this over and over?

If you start a new web application project in Visual Studio using the standard project templates, what you get is just a basic implementation for user accounts via ASP.NET Identity. Those templates don't provide you any method for creating administrative users or creating roles or managing users and user role membership. You would typically have to implement that stuff yourself, and if you are like me, you don't want to have to implement that stuff again and again on every project. cloudscribe.Core aims to provide that for you with careful, well thought out implementations that adhere to OWASP web security guidelines.

To get started building your own features and applications with cloudscribe, please see our Introduction to learn about our project template for Visual Studio or the .NET Core CLI

Documentation

See the full documentation at cloudscribe.com (work in progress)

Introduction - get the big picture and learn how to start new projects using our project template for Visual Studio or the .NET Core CLI

What Is Included?:
  • Login and registration, with support for social authentication configured from the UI. With options for recaptcha on the login and registration pages
  • Support for extra content on the login page
  • Support for extra content and a terms of use section on the registration page. If you populate the terms of use then users will be required to check a box indicating that they accept the terms in order to register and login. Also if you change the terms later you can optionally force all users to re-accept the changed terms.
  • User Management (optionally multi-tenant user management) you can create and manage user accounts, create and manage roles and user role membership, and add custom claims to users all from the UI. You can optionally disable self serve user registration so that only users that you add are allowed.
  • If you change a user's role membership, the role cookie will be updated automatically so the changes are effective right away.
  • If you lock a user account or delete a user, the user will be signed out automatically.
  • A theme system that supports both shared themes and per tenant themes. You can set the theme from a dropdown list in Administration > Site Settings, and the starter kits have a bunch of bootstrap themes included, and you can also make your own themes.
  • Support for "Site is Closed" - you can set a site as closed and users will not be able to navigate any pages in the site, they will only see the message you provide on the closed page. Users can still login but only members of the Administrators or Content Administrators roles will be allowed to navigate the site, all other users will be redirected to the closed message.
  • You can optionally require a confirmed email address for users if you add SMTP settings for email. A confirmation email will be sent to the user and the user will not be able to login until they click the link to confirm their email address.
  • You can optionally require approval of new accounts before a user can login, and you can get notification when new users register so you can decide whether to approve the account. There is a separate page to make it easy to find users who have not yet been approved or who have not yet confirmed their email address.
  • If you setup social authentication, you can optionally make social authentication the only allowed way to sign in.
  • You can configure SMS settings for Twilio, and then users can enable 2 factor authentication using their phone.
  • There is a company information section where you can define company name, address, email etc, and then you could show that information in the footer for example by customizing the layout. SiteContext is already injected into the layout and the company information are just properties on that so you can wrap your own markup around whichever of those properties you want to show.
  • Integration with IdentityServer4 providing management of users, clients and scopes. This brings us support for Jwt as an alternative to cookie authentication so we can more readily support SPA (Single Page Application) style web apps as well as authentication from mobile devices.
  • Optional LDAP Authentication support
  • Localization Support
  • For data access, supports Entity Framework Core with either SQLite, MSSQL, MySql, or PostgreSql. NoDb file system storage is also supported for small sites or proptypes.
  • Data and IO operations are async all the way down
  • This project aims to follow the OWASP Guidelines for best practices in security
Need Content?

Take a look at cloudscribe.SimpleContent, a simple yet flexible content and blogging engine that works with cloudscribe Core.

Planned Features:
  • Implement options for Security Questions and Answers per OWASP guidelines
  • Implement tracking of password hash history to support scenarios where re-using old passwords is not allowed
  • MongoDB Support - we are interested in trying to implement the data repositories with MongoDB and would welcome help with that.
  • Lots of miscellaneous smaller stuff
Screenshots

administration menu screen shot

Keep In Touch

We are collecting email addresses for a potential newsletter in the future, depending on whether this project becomes popular. If you would like to subscribe to this possible future newsletter, please send an email to subscribe [at] cloudscribe.com with the subject line "subscribe"

If you are interested in consulting or other support services related to cloudscribe, please send an email to info [at] cloudscribe.com.

We're also on twitter at @cloudscribeweb

cloudscribe's People

Contributors

crispinf avatar dependabot[bot] avatar gitter-badger avatar hefin1 avatar jawn avatar jimkerslake avatar joeaudette avatar markidox avatar mfoitzik avatar programmino avatar simonannetts avatar stewartbellamy avatar tuespetre avatar zill-e-kazim avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cloudscribe's Issues

Identity Server Integration

currently in this repository the management features to manage clients, scopes, and resources for IdentityServer4 is broken. I've started fixing things but have put the effort on hold temporarily to focus on a client project.

The cause of the breakage is breaking changes upstream in IdentityServer4. These changes require re-writing the storage layer for the operational data (which I have done) and re-writing the controllers and views for managing the data (which I have not done yet but will do as soon as I can).

The examples in the StarterKits repo should still work because I have pinned the dependencies to specific versions that do not have the breaking changes. But it is probably best not to use that for new projects and instead wait until I complete the needed changes and update the Starter Kit samples to use the new versions.

Auth0 support?

I just found this project and find it quite interesting. All I've yet done is read the docs.

I've done some dev experiments with Auth0 and I really like their paradigm - I like getting out of the identity business. But I have to add in my own multitenancy layer and that's where I fould cloudscribe. Am curious if you'd consider doing an Auth0 integration.

heads up - breaking change in the works

just a heads up about a breaking change in the works for anyone building stuff on cloudscribe Core.

Currently there are a lot of places where SiteSettings is injected including in the layout files where it is used to display the site name.

After I make the planned changes SiteSettings will no longer be available from dependency injection so code where it is injected will break. This breakage would occur after I publish updated nugets, if you upgrade to the newer version if your app has any custom code or layouts, views etc where SiteSettings is injected.

The fix will be very simple, you will simply change from injecting SiteSettings to injecting a new object SiteContext

SiteContext will essentially be the same as SiteSettings except the properties are all read only, ie they have only getters and no setters.

The reason for this change is simply that it is bad to pass around a mutable version of SiteSettings everywhere, we only need that when we need to update the settings. using the immutable version SiteContext will prevent developers form accidentally changing SiteSettings properties from there own code. Even though that would not update the settings in storage, since it is cached it could affect things and it is better to eliminate that possibility

I will be making all the needed changes in the related source code projects and in the starter kit samples to adapt to these changes but wanted to note it here as a heads up for others who may have custom code impacted by this change

Error during run.

Unhandled Exception: System.Reflection.TargetInvocationException: Exception has
been thrown by the target of an invocation. ---> System.AggregateException: One
or more errors occurred. (Column 'Code' in table 'cs_Currency' is of a type that
 is invalid for use as a key column in an index.) ---> System.Data.SqlClient.Sql
Exception: Column 'Code' in table 'cs_Currency' is of a type that is invalid for
 use as a key column in an index.

SPA does not seem to work

Hi Joe,

project loads up great, but SPA does not seem to work. when loading /app.html I get a bunch of errors. Also I cannot login using the SPA.

Is there something one must do to config this to work?

Cheers

errors after updating to newer npgsql provider

After updating the npgsql ef driver to 1.1 from 1.0.2, I get this error when using postgresql 9.2.1

MissingMethodException: Method not found: 'Microsoft.EntityFrameworkCore.Metadata.NpgsqlPostgresExtensionBuilder Npgsql.EntityFrameworkCore.PostgreSQL.NpgsqlModelBuilderExtensions.HasPostgresExtension(Microsoft.EntityFrameworkCore.ModelBuilder, System.String, System.String)'.

using postgresql 9.6.1 I get a different error:

NotSupportedException: The Npgsql:ValueGeneratedOnAdd annotation has been found in your migrations, but is no longer supported. Please replace it with '.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)' where you want PostgreSQL serial (autoincrement) columns, and remove it in all other cases.

regenerating the migrations solved the problem, but is a breaking change for existing dbs. This issue is just to document the problem.

standardizing on guid ids - breaking changes

at the moment, some model classes in cloudscribe.Core have both integer ids and guids
this was based on the design I used in mojoPortal as I have a minor goal to make a data migration path from mojoportal as low friction as possible.

I won't get long winded here about the pros/cons of integer ids vs guids, you can google that if you are interested in the topic. suffice to say that guids have advantages of not clashing when data is merged or replicated across systems (and other advantages), whereas integers in some cases can have some performance advantages.
In mojoportal my idea was to get the best of both by using integer ids for sql joins while also providing a surrogate id in the form of a guid so that if data needed to be imported or merged the guids could be used to correctly wire up the relations for new integer ids that might be needed to avoid clashes when merging data.

in cloudscribe I have arrived at a decision to remove the integer ids and strictly use guids so I will be making major changes to the model in a branch and will merge it when complete.

However this process will be breaking for existing data and I thought I should give a heads up about that. I'm not even going to try to implement EF migrations, I'm going to just start with a new database based on the changed model.

Since this project is still in early preview I think it is reasonable to make such breaking changes which would be much more problematic to make once it is used in production.
Sorry for the inconvenience that this may cause.

Logging

Hi,
Why are you using a DIY logging rather then the popular frameworks? (i.e. log4net, serilog etc.)

supporting other db platforms with EFCore

I'm creating this issue based on a question in out gitter chat room. @nanopp expressed interest in using MySql with EF.

Currently we have an implementation for EFCore storage using MS SQL Server.

Some of the code for our current solution "could" be re-used with other EFCore database providers, but some things have to be implemented per provider because different providers have different features and capabilities so they need specific model mapping to make optimal use of the available features.

I did think ahead about the possibility to use different providers so I implemented an interface for the model mapping, and an MSSQL implementation of the interface.

However, that is not sufficient. afaik EFCore currently only supports model first development not database first, though there may be some external tools that can reverse engineer the mapping from the db schema.

EFCore provides commands to generate code migrations for the model based on the mappings. These migrations are specific to the mappings and providers. When you change the model and/or the mappings you generate a new migration using the command, and this automatically will update the db schema. Since the migrations are provider specific they need to be separated from the common code.

Solution Ideas

I think I could re-factor the re-useable bits of EF code into a separate class library from the provider specific code. Then there would be a library per provider that depends on the common code and inherits from the DBContexts but provides its own mappings and the generated migration code would be in those provider specific libraries.

I will try to experiment in that direction soon and update this issue when I can.

[Question] Extending the data layer

Hi Joe, very interesting repository, thanks for sharing.

I am developing an extensible CMS, where "modules" can be installed, and this has me wondering about how to best handle module authors wanting to "extend" core tables.

For example, suppose there was a module that wanted to add a column to your SiteHost table. What would the recommended method be? Ofcourse, the module developer could bypass EF all together and manually add the column using ADO,NET and use ADO.NET for future data access - but what if they added a mandatory column? It could break the existing CoreDbContext which wouldn't be aware of the model changes.

The only real solution i can think for this is that you just stipulate that the core tables are not extensible, and the core model is not extensible, and that if you want extend them, you'd have to create your own EF model / DbContext, and "join" to the appropriate core tables rather than extend them. But again this raised problems because let's say a module author creates a table that "joins" to the SiteHost table. Now if the core DBContext ever tries to delete that record, it will hit a foreign key violation.

This basically leads to the idea that:

  1. You shouldn't allow module developers to extend core tables.
  2. You shouldn't allow module developers to place new constraints (like foreign keys) on core table's.

This is generally bad for database design, as being able to extend tables and introduce new constraints where needed helps keep the integrity of data. Forcing people to drop that doesn't sound right.

Just wondering if you have thought about this kind of stuff or if it's not really a concern for you at the moment.

Solution error when build

This is a fix that I had to do in order to get the example.WebApp to run. please advise if I have done something wrong.

I Just cloned the app to my machine and tried to rebuild the project. I got an error on the following file:
cloudscribe/src/cloudscribe.Core.Web/Navigation/ExtendedNavigationNode.cs
Line #23

The solution:

  1. I deleted the whole "Navigation" folder from cloudscribe.Core.Web
  2. I added the project cloudscribe.Web.Navigation to the solution
  3. modified the code in file: cloudscribe/src/example.WebApp/Startup.CloudscribeCore.DI.MS.cs
    Line#261: services.TryAddScoped<INodeUrlPrefixProvider, FolderTenantNodeUrlPrefixProvider>();
    To : services.TryAddScoped<INodeUrlPrefixProvider, DefaultNodeUrlPrefixProvider>();

only then, I was able to run the example Web App.

My changes were based on instinct and not experience. please disregard if I don't make any sense.

Potential Bug: error with roleadmin

Using latest repo https://github.com/joeaudette/cloudscribe

Using Visual Studio 2017. Windows 7.

Error when visiting page: http://localhost:5000/roleadmin

An unhandled exception occurred while processing the request.

InvalidOperationException: No value provided for required parameter '_outer_Id'.
   Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.CreateCommand(IRelationalConnection connection, IReadOnlyDictionary<string, object> parameterValues)

The following may assist.

cloudscribe.Core.Storage.EFCore.Common.UserQueries+d__31.MoveNext() in UserQueries.cs
+
return await listQuery
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
cloudscribe.Core.Identity.SiteRoleManager+d__12.MoveNext() in SiteRoleManager.cs
+
return await queries.GetRolesBySite(siteId, searchInput, pageNumber, pageSize, CancellationToken);
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
cloudscribe.Core.Web.Controllers.RoleAdminController+d__13.MoveNext() in RoleAdminController.cs
+
model.SiteRoles = await RoleManager.GetRolesBySite(

cheers

Can't get currentNode for sidebar

Hi,

I have an issue for get the current node of the children of a children.

Let me explain, I have a sidenav and a topnav on my website. The topnav is just for the NavNode where parentKey="RootNode". The topnav is my principal nav and the sidebar is used to display their children when the user is in the current node of one of the tabs in the topbar.

Like this :

capture-1

capture-2

Now my issue is : I cant get the current node when I want to edit my table in another page with the project Id passed on URL like this :

capture-3

but I can go to this controller without an Id :
capture-4

I found the solution to Create or Edit with an Id when I remove the line :
if (node.EqualsNode(Model.CurrentNode))

But the issue is my sidebar display all childrens of xml navigation file like this :
capture-5

Those are the Shared files :

Topbar.cshtml : (I post th topbar file on pastebin because indentation is bad when i paste in there.)
http://pastebin.com/NiL5sBZw

Sidebar.cshtml :

`@if (Model.HasVisibleChildren(Model.RootNode))
{

foreach (var node in Model.RootNode.Children)
{
    if (!Model.ShouldAllowView(node)) { continue; }
    if (node.EqualsNode(Model.CurrentNode))
    {
        if (!Model.HasVisibleChildren(node))
        {
            @:
            <li class="@Model.GetClass(node.Value)">
                <a href="@Url.Content(Model.AdjustUrl(node))">
                    <i class="@node.Value.IconCssClass"></i><span>@Model.AdjustText(node)</span>
                </a>
            </li>
        }
        else
        {
            @:
            <li class="@Model.GetClass(node.Value)">
                @Model.UpdateTempNode(node)
                @Html.Partial("Partials/NodeSideNavPartial", Model)
            </li>
        }
    }
}

}`

NodeSideNavPartial.cshtml :

`@if ((Model.TempNode != null) && (Model.HasVisibleChildren(Model.TempNode)))
{
@foreach (var childNode in Model.TempNode.Children)
{
if (!Model.ShouldAllowView(childNode)) { continue; }

    if (!Model.HasVisibleChildren(childNode))
    {
        @:
        <li class="@Model.GetClass(childNode.Value)">
            <a href="@Url.Content(Model.AdjustUrl(childNode))">
                <i class="@childNode.Value.IconCssClass"></i><span>@childNode.Value.Text</span>
            </a>
        </li>
    }
    else
    {
        <li class="@Model.GetClass(childNode.Value)">
            <a href="@Url.Content(Model.AdjustUrl(childNode))">
                <i class="@childNode.Value.IconCssClass"></i><span>@childNode.Value.Text</span>
            </a>
            @Model.UpdateTempNode(childNode)
            @Html.Partial("Partials/NodeSideNavPartial", Model) @* recursion *@
        </li>
    }
}

}`

And the navigation.xml :

`

<NavNode key="Saisie" parentKey="RootNode" controller="Saisie" action="TableauDeBord" text="Saisie">
  <Children>
    <NavNode key="TableauDeBord" parentKey="Saisie" controller="Saisie" action="TableauDeBord" text="Tableau de bord" iconCssClass="fa fa-tachometer">
      <Children />
    </NavNode>
    <NavNode key="Kanban" parentKey="Saisie" controller="KanbanBoard" action="Index" text="kanban" iconCssClass="fa fa-share-alt">
      <Children />
    </NavNode>
  </Children>
</NavNode>

<NavNode key="Administration" parentKey="RootNode" controller="Projet" action="Index" text="Administration">
  <Children>
    <NavNode key="Projets" parentKey="Administration" controller="Projet" action="Index" text="Projets" iconCssClass="fa fa-file-powerpoint-o">
      <Children>
        <NavNode key="Fiche" parentKey="Projets" controller="Projet" action="CreateEdit" text="CRUD" preservedRouteParameters="id" componentVisibility="false">
          <Children />
        </NavNode>
      </Children>
    </NavNode>
    <Children />
    <NavNode key="Utilisateurs" parentKey="Administration" controller="Utilisateur" action="Index" text="Utilisateurs" iconCssClass="fa fa-tachometer">
      <Children />
    </NavNode>
  </Children>
</NavNode>

<NavNode key="Dรฉploiement" parentKey="RootNode" controller="Deploiement" action="Alive" text="Dรฉploiement">
  <Children>
    <NavNode key="Alive" parentKey="Dรฉploiement" controller="Deploiement" action="Alive" text="Alive" iconCssClass="fa fa-tachometer">
      <Children />
    </NavNode>
  </Children>
</NavNode>
`

Now my question is : How can i display just the children of the current NavNode like "Adminisitration" in previous exemples ?

Thanx for helping and grieve if you do not understand me ^^

Unit Tests?

You may notice there is very little at this point in the way of unit tests in this project. I acknowledge that I am not very experienced with TDD (Test Driven Development) and have not been working with that as my process. Much of the code was existing code migrated and refactored from mojoportal.

With this project I am trying to develop testable code and would like to add more and more test coverage over time. I would specifically welcome collaborators who are more experienced with TDD to help get the ball rolling by implementing tests, pointing out any areas where code is not testable currently, making pull requests that refactor code to become more testable, etc. I learn quickly from other people's examples and believe that with help and collaboration I could become proficient in TDD.

I'm not sure yet what mocking framework to use for example or which ones are compatible with the new .NET frameworks.

In short, please don't beat me up about lack of tests, instead help me move forward in making sure things are testable and adding to test coverage.

Error adding 'Same' scopes on different tenants

Hi There Joe,

Using this source. https://github.com/joeaudette/cloudscribe

getting this error:
An unhandled exception occurred while processing the request.

SqlException: Cannot insert duplicate key row in object 'dbo.csids_IdentityResources' with unique     index 'IX_csids_IdentityResources_Name'. The duplicate key value is (openid).

The statement has been terminated.

How to replicate:

  1. Setup a client tenant1jsclient in base 'default' tenant.
  2. Create another tenant and try to create a new client with same id tenant1jsclient. *** You will get this error ***

How to replicate

  1. Setup ientity resource in base 'default' tenant for openid
  2. Create another tenant and try to create an identity resource of openid. *** You will get this error ***

Cheers

nige

per tenant layout?

currently all the tenants use View/Shared/_Layout.cshtml, it should be possible to use different layouts per tenant.

This is a planned feature not yet implemented.

Per tenant database.

Is is possible to have per tenant database?
With saaskitwe have a database for any tenant.

Decoupling clouldscribe.Identity from cloudscribe.Core.Web

clouldscribe.Identity used in cloudscribe.Core.Web. Is it possible to remove this dependency and assemble cloudscribe.Identity whitin example.WebApp?
I had a try by adding a new project (e.g cloudscribe.Accounts) and move related controllers(AccountController and ManageController and related views) but some components like RequestTimeZoneResolver use it.
Although shipping views and html assets may be a problem with Nuget packaging.

It is possible to create Local Package for projects?

I copy cloudscribe projects to my src folder of my project then add those to my solution.It causes my solutions with many projects and be slow. It is possible to create Local Nuget package for projects so that we can add cloudscribe Nuget packages locally?
Thanks

Session

Hi,
Is there a reason for using Session in your project?
thanks

Bug: Cannot add API resource

Hi Joe,

Seems to be a bug here. All is well until one goes to add an API resource.

Try adding an API resource. You will get this error

An unhandled exception occurred while processing the request.

SqlException: The multi-part identifier "api.Id" could not be bound.
System.Data.SqlClient.SqlCommand+<>c.b__107_0(Task result)

The following may also help
cloudscribe.Core.IdentityServer.EFCore.Stores.ResourceStore+d__5.MoveNext() in ResourceStore.cs
+
var results = await apis.ToArrayAsync();
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()

image

Even if you are not asking for the api in your clients.

Please try and confirm.

Error at load solution

Hi,

I encounter this at solution load:
2016-05-25
By consequence at build I get this:
2016-05-25 1

I assume that I installed all net.core related. Any hints please?

People can use IdentityServer without cloudscribe.Identity

IdentityServer has a IUserService interface that can be implement to communicate with an accounts management database. I did some work to implement that with clouldscribe.Identity. But the work was hard to me because they don't support ASP.NET 5 and have their DI system.
BTW, I think the best point to start is:

  1. Setup a cloudscribe-based web application client to accounts management and user registration.
  2. Implement IUserService with clouldscribe.Identity to connect to the accounts management client database.
    3)Hosting IdentitySever in a cloudscribe-based web app is good idea to get some hosting features but it need to have 2 first.
    Accounts management as a client for IdentityServer is a nice a simple approach and Dominick Baier recommened it. I think google have the same architecture(account.google.com as Identity server and myaccount.google.com for user that can manage his/her account.
    But for now I need to interact from my cloudscribe-based web app with my hosted IdentityServer.This is my reason that I don't need to having clouldscribe.Identity in my cloudscribe-based web app at all.
    Thanks for attention.

Get Tenant from user claims.

I have an API that call from an angular App. In the API I need tenantId to filter data from database.
What is the best solution for this? I think one of the following options.
1- Send tenantId from angular app to the API.
2-Get it from user claims.

folder tenant cookies not working as intended

yesterday while testing I noticed that folder tenants are not using different cookie settings as they should. I swear it was working before so I'm not sure what happened, but logging it here to note that I am aware of the problem and working on a fix. It seems like once the second tenant gets loaded then the first tenant is using the same settings as the second tenant instead of its own settings

I think I will need to use the saaskit technique for configuring dependencies per tenant to get the correct cookie options to each tenant

project architecture

Hi,
I want to contribute to your project but there are some questions I have regarding your architecture choices:

  1. Why should you support different relational DBs? You're basically just duplicating code. It might be more reasonable to build a replaceable data-layer so anyone can just implement his favorite DB data-layer. I would like to see different DB solutions (i.e. NoSQL) rather then different flavors of the same type.
  2. You use a lot of repository classes, Wouldn't it be better to create a IRepository and implement a general repository pattern for all the entities?
  3. Why Are you using MSDI and not autofac or any other stable library? Although this project relies on beta product I believe that autofac might be a better choice (of course you can always move to MSDI with some effort in the future)
  4. It seems that you rely on many files in your software. The settings are from appsettings.json (except for siteSettings class), the localization resources are from the resx files. and also the menu comes from a json/xml file. It will make you troubles when you would like to create a CMS for the platform.
  5. On your core.models project you've created mvc DataAnnotations attributes. From my prespective the core project should consist on none web related object. Think about the future where you would like to create backend processes.
  6. why did you create your own logging pipeline. It seems that log4net/serilog should be a better approach. BTW - you can consider building a similar mechanics like the serilog sinks to use for your data layer

It seems like I'm criticizing but I really appreciate your effort.

Thanks

Page to manage tenants

Hi, it would be nice to have a page

  • Manage Add/Delete tenants
  • Impersonate a user role to test
  • SMS/Text based authentication and lockout/unlock out
  • User login activity audit

This page has some samples/demo to show - source

thanks

Question: How to allow Base (first) tenant to be accessible by all other tenants

Hi Joe,

This question comes after considering your last response back, about creating a filter to allow users from some tenants to access tenants from others.

This question comes from 2 use cases that have popped up for myself over the last couple of weeks. Which leads me to be believe the use case could be quite common.

In allot of multi-tenant sites, there is often a base tenant. And this is the case with your cloudscribe system.
Now often the case is that you wish all users of individual tenants completely isolated, but.... you wish for them to ALL be able to access a base tenant.

Think the case of some protected wiki which all of your customers whom have a tenant, should be able to access. Now you require ALL users to have an account, and ALL to access the base tenant where the wiki lives, however that does not allow users from one tenant to get into another.

Is there a way this use case could be built into your framework? Because I believe it to be a valid case that is common enough to warrant its inclusion.

To add further to this please consider the following scenario which would use this use case.

Scenario 1: Real Estate site:
Say you had a real estate site which provides house listings to buyers, sellers and agents.

You have 2 types of users.
private sellers
real estate agents.

Private sellers create an account on the base tenant. They are an individual so no need for a tenant.
Agency (real estate agents) create a tenant, add their staff members.

Both types of users can access the base tenant, but... only agent users can access the agency tenant.

I am looking through cloudscribe source and trying to figure out where best to mod to fit this need.
I'm looking at the controllers located under cloudscribe.Core.Web, things like the AccountController.

The other place I'm looking at is further up the chain. But it is hard to determine where exactly I should make changes.

If you could shed some light in any particular areas I should focus on to make the changes, or things to watch out for that would be greatly appreciated. Or If I'm trying to do something which is just not possible then please just say so.

Kind Regards

Nige

Build errors

I Clone the master branch, these are the build errors :

  Unable to resolve 'cloudscribe.Logging.EF (>= 1.0.0)' for '.NETCoreApp,Version=v1.0'.
  Unable to resolve 'cloudscribe.Logging.Web (>= 1.0.0)' for '.NETCoreApp,Version=v1.0'.
  Unable to resolve 'cloudscribe.Web.Navigation (>= 1.0.1)' for '.NETCoreApp,Version=v1.0'.
  Unable to resolve 'cloudscribe.Web.Pagination (>= 1.0.1)' for '.NETCoreApp,Version=v1.0'.
  Unable to resolve 'NoDb (>= 1.0.0)' for '.NETCoreApp,Version=v1.0'.

It seams some of projects build with netstandard1.5 and some build with netstandard1.0.

Using behind reverse proxy

My setup forces me to use a reverse proxy, so what I did is to run under http only and to disable the filter options.Filters.Add(new RequireHttpsAttribute()); The reverse proxy (nginx) is configured on public https and redirect to http for internal.
The thing is that the website works with direct http traffic (no reverse proxy) and logins works.
But using the public address and with reverse proxy, login ends with a timeout (504) and no login then. Here is the server trace. What am I doing wrong?

Now listening on: http://0.0.0.0:5000
Application started. Press Ctrl+C to shut down.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://**************:5000/Infra
dbug: SaasKit.Multitenancy.Internal.TenantResolutionMiddleware[0]
Resolving TenantContext using CachingSiteResolver.
dbug: Npgsql.NpgsqlConnection[3]
Opening connection to database 'HACorpus' on server 'tcp://127.0.0.1:5432'.
info: Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory[1]
Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT "x"."SiteFolderName"
FROM "cs_Site" AS "x"
WHERE "x"."SiteFolderName" IS NOT NULL AND (("x"."SiteFolderName" <> '') OR "x"."SiteFolderName" IS NULL)
ORDER BY "x"."SiteFolderName"
dbug: Npgsql.NpgsqlConnection[4]
Closing connection to database 'HACorpus' on server 'tcp://127.0.0.1:5432'.
dbug: SaasKit.Multitenancy.MemoryCacheTenantResolverBase[0]
Caching folder list with keys "folderList".
dbug: SaasKit.Multitenancy.MemoryCacheTenantResolverBase[0]
TenantContext not present in cache with key "root". Attempting to resolve.
dbug: SaasKit.Multitenancy.MemoryCacheTenantResolverBase[0]
Folder List retrieved from cache with key "folderList".
dbug: Npgsql.NpgsqlConnection[3]
Opening connection to database 'HACorpus' on server 'tcp://127.0.0.1:5432'.
info: Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory[1]
Executed DbCommand (33ms) [Parameters=[@__p_0='?'], CommandType='Text', CommandTimeout='30']
SELECT "t".*
FROM (
SELECT "s"."Id", "s"."AccountApprovalEmailCsv", "s"."AddThisDotComUsername", "s"."AliasId", "s"."AllowDbFallbackWithLdap", "s"."AllowNewRegistration", "s"."AllowPersistentLogin", "s"."AutoCreateLdapUserOnFirstLogin", "s"."CaptchaOnLogin", "s"."CaptchaOnRegistration", "s"."CompanyCountry", "s"."CompanyFax", "s"."CompanyLocality", "s"."CompanyName", "s"."CompanyPhone", "s"."CompanyPostalCode", "s"."CompanyPublicEmail", "s"."CompanyRegion", "s"."CompanyStreetAddress", "s"."CompanyStreetAddress2", "s"."ConcurrencyStamp", "s"."CreatedUtc", "s"."DefaultEmailFromAddress", "s"."DefaultEmailFromAlias", "s"."DisableDbAuth", "s"."DkimDomain", "s"."DkimPrivateKey", "s"."DkimPublicKey", "s"."DkimSelector", "s"."EmailLdapDbFallback", "s"."FacebookAppId", "s"."FacebookAppSecret", "s"."GoogleAnalyticsProfileId", "s"."GoogleClientId", "s"."GoogleClientSecret", "s"."IsDataProtected", "s"."IsServerAdminSite", "s"."LdapDomain", "s"."LdapPort", "s"."LdapRootDN", "s"."LdapServer", "s"."LdapUserDNKey", "s"."LoginInfoBottom", "s"."LoginInfoTop", "s"."MaxInvalidPasswordAttempts", "s"."MicrosoftClientId", "s"."MicrosoftClientSecret", "s"."MinRequiredPasswordLength", "s"."OidConnectAppId", "s"."OidConnectAppSecret", "s"."PreferredHostName", "s"."PrivacyPolicy", "s"."ReallyDeleteUsers", "s"."RecaptchaPrivateKey", "s"."RecaptchaPublicKey", "s"."RegistrationAgreement", "s"."RegistrationPreamble", "s"."RequireApprovalBeforeLogin", "s"."RequireConfirmedEmail", "s"."RequireConfirmedPhone", "s"."RequiresQuestionAndAnswer", "s"."SignEmailWithDkim", "s"."SiteFolderName", "s"."SiteIsClosed", "s"."SiteIsClosedMessage", "s"."SiteName", "s"."SmsClientId", "s"."SmsFrom", "s"."SmsSecureToken", "s"."SmtpPassword", "s"."SmtpPort", "s"."SmtpPreferredEncoding", "s"."SmtpRequiresAuth", "s"."SmtpServer", "s"."SmtpUseSsl", "s"."SmtpUser", "s"."Theme", "s"."TimeZoneId", "s"."TwitterConsumerKey", "s"."TwitterConsumerSecret", "s"."UseEmailForLogin", "s"."UseLdapAuth"
FROM "cs_Site" AS "s"
WHERE "s"."SiteFolderName" IS NULL OR ("s"."SiteFolderName" = '')
ORDER BY "s"."CreatedUtc"
LIMIT @__p_0
) AS "t"
LIMIT 2
dbug: Npgsql.NpgsqlConnection[4]
Closing connection to database 'HACorpus' on server 'tcp://127.0.0.1:5432'.
fail: cloudscribe.Core.Web.Components.SiteDataProtector[0]
data protection error
dbug: Npgsql.NpgsqlConnection[3]
Opening connection to database 'HACorpus' on server 'tcp://127.0.0.1:5432'.
dbug: Npgsql.NpgsqlConnection[5]
Beginning transaction with isolation level 'Unspecified'.
info: Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory[1]
Executed DbCommand (12ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p3='?', @P4='?', @p5='?', @p6='?', @P7='?', @p8='?', @p9='?', @p10='?', @p11='?'], CommandType='Text', CommandTimeout='30']
INSERT INTO "cs_SystemLog" ("Id", "Culture", "EventId", "IpAddress", "LogDate", "LogLevel", "Logger", "Message", "ShortUrl", "StateJson", "Thread", "Url")
VALUES (@p0, @p1, @p2, @p3, @P4, @p5, @p6, @P7, @p8, @p9, @p10, @p11);
dbug: Npgsql.NpgsqlConnection[6]
Committing transaction.
dbug: Npgsql.NpgsqlConnection[4]
Closing connection to database 'HACorpus' on server 'tcp://127.0.0.1:5432'.
dbug: SaasKit.Multitenancy.MemoryCacheTenantResolverBase[0]
TenantContext:b0a554e1-eb2a-47d1-9367-f91c97c3a529 resolved. Caching with keys "root, 94a6fb38-f650-4e04-96fc-95a79a17342d".
dbug: SaasKit.Multitenancy.Internal.TenantResolutionMiddleware[0]
TenantContext Resolved. Adding to HttpContext.
dbug: IdentityServer4.Hosting.CookieMiddlewareExtensions[0]
Using hosting application's CookieAuthentication middleware with scheme: Application
info: IdentityServer4.AccessTokenValidation.Infrastructure.NopAuthenticationMiddleware[7]
Bearer was not authenticated. Failure message: No token found.
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
Authorization failed for user: (null).
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
info: Microsoft.AspNetCore.Mvc.ChallengeResult[1]
Executing ChallengeResult with authentication schemes ().
info: IdentityServer4.AccessTokenValidation.Infrastructure.NopAuthenticationMiddleware[12]
AuthenticationScheme: Bearer was challenged.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
Executed action HACorpus.Controllers.InfraController.Index (HACorpus) in 45.0517ms
info: IdentityServer4.AccessTokenValidation.Infrastructure.NopAuthenticationMiddleware[7]
Bearer was not authenticated. Failure message: No token found.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]

And just login phase:

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://*******/Account/Login?returnurl=%2F
dbug: SaasKit.Multitenancy.Internal.TenantResolutionMiddleware[0]
      Resolving TenantContext using CachingSiteResolver.
dbug: SaasKit.Multitenancy.MemoryCacheTenantResolverBase[0]
      Folder List retrieved from cache with key "folderList".
dbug: SaasKit.Multitenancy.MemoryCacheTenantResolverBase[0]
      TenantContext:c936f349-9b98-49f6-afcf-f9e7a5fb1f1f retrieved from cache with key "root".
dbug: SaasKit.Multitenancy.Internal.TenantResolutionMiddleware[0]
      TenantContext Resolved. Adding to HttpContext.
info: IdentityServer4.AccessTokenValidation.Infrastructure.NopAuthenticationMiddleware[7]
      Bearer was not authenticated. Failure message: No token found.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
      Executing action method cloudscribe.Core.Web.Controllers.AccountController.Login (cloudscribe.Core.Web) with arguments (/) - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.ViewResultExecutor[1]
      Executing ViewResult, running view at path /Views/Sys/Account/Login.cshtml.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
      Executed action cloudscribe.Core.Web.Controllers.AccountController.Login (cloudscribe.Core.Web) in 7.1728ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 10.3521ms 200 text/html; charset=utf-8
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://*********/cscsr/requiredwhenvalidator
dbug: SaasKit.Multitenancy.Internal.TenantResolutionMiddleware[0]
      Resolving TenantContext using CachingSiteResolver.
dbug: SaasKit.Multitenancy.MemoryCacheTenantResolverBase[0]
      Folder List retrieved from cache with key "folderList".
dbug: SaasKit.Multitenancy.MemoryCacheTenantResolverBase[0]
      TenantContext:c936f349-9b98-49f6-afcf-f9e7a5fb1f1f retrieved from cache with key "root".
dbug: SaasKit.Multitenancy.Internal.TenantResolutionMiddleware[0]
      TenantContext Resolved. Adding to HttpContext.
info: IdentityServer4.AccessTokenValidation.Infrastructure.NopAuthenticationMiddleware[7]
      Bearer was not authenticated. Failure message: No token found.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
      Executing action method cloudscribe.Core.Web.Controllers.cscsrController.requiredwhenvalidator (cloudscribe.Core.Web) with arguments ((null)) - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.Internal.ContentResultExecutor[1]
      Executing ContentResult with HTTP Response ContentType of text/javascript
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
      Executed action cloudscribe.Core.Web.Controllers.cscsrController.requiredwhenvalidator (cloudscribe.Core.Web) in 0.2375ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 2.9142ms 200 text/javascript
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://*********/cscsr/jqueryvalidate
dbug: SaasKit.Multitenancy.Internal.TenantResolutionMiddleware[0]
      Resolving TenantContext using CachingSiteResolver.
dbug: SaasKit.Multitenancy.MemoryCacheTenantResolverBase[0]
      Folder List retrieved from cache with key "folderList".
dbug: SaasKit.Multitenancy.MemoryCacheTenantResolverBase[0]
      TenantContext:c936f349-9b98-49f6-afcf-f9e7a5fb1f1f retrieved from cache with key "root".
dbug: SaasKit.Multitenancy.Internal.TenantResolutionMiddleware[0]
      TenantContext Resolved. Adding to HttpContext.
info: IdentityServer4.AccessTokenValidation.Infrastructure.NopAuthenticationMiddleware[7]
      Bearer was not authenticated. Failure message: No token found.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
      Executing action method cloudscribe.Core.Web.Controllers.cscsrController.jqueryvalidate (cloudscribe.Core.Web) with arguments ((null)) - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.Internal.ContentResultExecutor[1]
      Executing ContentResult with HTTP Response ContentType of text/javascript
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
      Executed action cloudscribe.Core.Web.Controllers.cscsrController.jqueryvalidate (cloudscribe.Core.Web) in 0.5281ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 3.0175ms 200 text/javascript
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://*********/cscsr/jqueryvalidationunobtrusive
dbug: SaasKit.Multitenancy.Internal.TenantResolutionMiddleware[0]
      Resolving TenantContext using CachingSiteResolver.
dbug: SaasKit.Multitenancy.MemoryCacheTenantResolverBase[0]
      Folder List retrieved from cache with key "folderList".
dbug: SaasKit.Multitenancy.MemoryCacheTenantResolverBase[0]
      TenantContext:c936f349-9b98-49f6-afcf-f9e7a5fb1f1f retrieved from cache with key "root".
dbug: SaasKit.Multitenancy.Internal.TenantResolutionMiddleware[0]
      TenantContext Resolved. Adding to HttpContext.
info: IdentityServer4.AccessTokenValidation.Infrastructure.NopAuthenticationMiddleware[7]
      Bearer was not authenticated. Failure message: No token found.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
      Executing action method cloudscribe.Core.Web.Controllers.cscsrController.jqueryvalidationunobtrusive (cloudscribe.Core.Web) with arguments ((null)) - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.Internal.ContentResultExecutor[1]
      Executing ContentResult with HTTP Response ContentType of text/javascript
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
      Executed action cloudscribe.Core.Web.Controllers.cscsrController.jqueryvalidationunobtrusive (cloudscribe.Core.Web) in 0.2601ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 2.6182ms 200 text/javascript
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 POST http://*********/Account/Login?returnurl=%2F application/x-www-form-urlencoded 283
dbug: SaasKit.Multitenancy.Internal.TenantResolutionMiddleware[0]
      Resolving TenantContext using CachingSiteResolver.
dbug: SaasKit.Multitenancy.MemoryCacheTenantResolverBase[0]
      Folder List retrieved from cache with key "folderList".
dbug: SaasKit.Multitenancy.MemoryCacheTenantResolverBase[0]
      TenantContext:c936f349-9b98-49f6-afcf-f9e7a5fb1f1f retrieved from cache with key "root".
dbug: SaasKit.Multitenancy.Internal.TenantResolutionMiddleware[0]
      TenantContext Resolved. Adding to HttpContext.
info: IdentityServer4.AccessTokenValidation.Infrastructure.NopAuthenticationMiddleware[7]
      Bearer was not authenticated. Failure message: No token found.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
      Executing action method cloudscribe.Core.Web.Controllers.AccountController.Login (cloudscribe.Core.Web) with arguments (cloudscribe.Core.Web.ViewModels.SiteUser.LoginViewModel, /) - ModelState is Valid
dbug: cloudscribe.Core.Identity.UserStore[0]
      FindByNameAsync
dbug: Npgsql.NpgsqlConnection[3]
      Opening connection to database 'MyDb' on server 'tcp://127.0.0.1:5432'.
info: Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory[1]
      Executed DbCommand (1ms) [Parameters=[@__siteId_0='?', @__userName_1='?', @__userName_2='?'], CommandType='Text', CommandTimeout='30']
      SELECT "x"."Id", "x"."AccessFailedCount", "x"."AccountApproved", "x"."AuthorBio", "x"."AvatarUrl", "x"."CanAutoLockout", "x"."Comment", "x"."CreatedUtc", "x"."DateOfBirth", "x"."DisplayInMemberList", "x"."DisplayName", "x"."Email", "x"."EmailConfirmed", "x"."FirstName", "x"."Gender", "x"."IsDeleted", "x"."IsLockedOut", "x"."LastLoginUtc", "x"."LastModifiedUtc", "x"."LastName", "x"."LastPasswordChangeUtc", "x"."LockoutEndDateUtc", "x"."MustChangePwd", "x"."NewEmail", "x"."NewEmailApproved", "x"."NormalizedEmail", "x"."NormalizedUserName", "x"."PasswordHash", "x"."PhoneNumber", "x"."PhoneNumberConfirmed", "x"."RolesChanged", "x"."SecurityStamp", "x"."Signature", "x"."SiteId", "x"."TimeZoneId", "x"."Trusted", "x"."TwoFactorEnabled", "x"."UserName", "x"."WebSiteUrl"
      FROM "cs_User" AS "x"
      WHERE ("x"."SiteId" = @__siteId_0) AND (("x"."NormalizedUserName" = @__userName_1) OR ("x"."NormalizedEmail" = @__userName_2))
      LIMIT 2
dbug: Npgsql.NpgsqlConnection[4]
      Closing connection to database 'MyDb' on server 'tcp://127.0.0.1:5432'.
dbug: cloudscribe.Core.Identity.UserStore[0]
      FindByNameAsync
dbug: Npgsql.NpgsqlConnection[3]
      Opening connection to database 'MyDb' on server 'tcp://127.0.0.1:5432'.
info: Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory[1]
      Executed DbCommand (1ms) [Parameters=[@__siteId_0='?', @__userName_1='?', @__userName_2='?'], CommandType='Text', CommandTimeout='30']
      SELECT "x"."Id", "x"."AccessFailedCount", "x"."AccountApproved", "x"."AuthorBio", "x"."AvatarUrl", "x"."CanAutoLockout", "x"."Comment", "x"."CreatedUtc", "x"."DateOfBirth", "x"."DisplayInMemberList", "x"."DisplayName", "x"."Email", "x"."EmailConfirmed", "x"."FirstName", "x"."Gender", "x"."IsDeleted", "x"."IsLockedOut", "x"."LastLoginUtc", "x"."LastModifiedUtc", "x"."LastName", "x"."LastPasswordChangeUtc", "x"."LockoutEndDateUtc", "x"."MustChangePwd", "x"."NewEmail", "x"."NewEmailApproved", "x"."NormalizedEmail", "x"."NormalizedUserName", "x"."PasswordHash", "x"."PhoneNumber", "x"."PhoneNumberConfirmed", "x"."RolesChanged", "x"."SecurityStamp", "x"."Signature", "x"."SiteId", "x"."TimeZoneId", "x"."Trusted", "x"."TwoFactorEnabled", "x"."UserName", "x"."WebSiteUrl"
      FROM "cs_User" AS "x"
      WHERE ("x"."SiteId" = @__siteId_0) AND (("x"."NormalizedUserName" = @__userName_1) OR ("x"."NormalizedEmail" = @__userName_2))
      LIMIT 2
dbug: Npgsql.NpgsqlConnection[4]
      Closing connection to database 'MyDb' on server 'tcp://127.0.0.1:5432'.
dbug: cloudscribe.Core.Identity.UserStore[0]
      GetLockoutEnabledAsync
dbug: cloudscribe.Core.Identity.UserStore[0]
      GetLockoutEndDateAsync
dbug: cloudscribe.Core.Identity.UserStore[0]
      GetLockoutEnabledAsync
dbug: cloudscribe.Core.Identity.UserStore[0]
      GetLockoutEndDateAsync
dbug: cloudscribe.Core.Identity.UserStore[0]
      GetPasswordHashAsync
dbug: cloudscribe.Core.Identity.UserStore[0]
      GetAccessFailedCountAsync
dbug: cloudscribe.Core.Identity.UserStore[0]
      GetTwoFactorEnabledAsync
info: Microsoft.AspNetCore.Identity.SignInManager[0]
      SignInAsync called
dbug: cloudscribe.Core.Identity.UserStore[0]
      GetUserIdAsync
dbug: cloudscribe.Core.Identity.UserStore[0]
      GetUserNameAsync
dbug: cloudscribe.Core.Identity.UserStore[0]
      GetRolesAsync
dbug: Npgsql.NpgsqlConnection[3]
      Opening connection to database 'MyDb' on server 'tcp://127.0.0.1:5432'.
info: Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory[1]
      Executed DbCommand (1ms) [Parameters=[@__userId_0='?'], CommandType='Text', CommandTimeout='30']
      SELECT "x"."RoleName"
      FROM "cs_Role" AS "x"
      INNER JOIN "cs_UserRole" AS "y" ON "x"."Id" = "y"."RoleId"
      WHERE "y"."UserId" = @__userId_0
      ORDER BY "x"."RoleName"
dbug: Npgsql.NpgsqlConnection[4]
      Closing connection to database 'MyDb' on server 'tcp://127.0.0.1:5432'.
dbug: cloudscribe.Core.Identity.UserStore[0]
      GetClaimsAsync
dbug: Npgsql.NpgsqlConnection[3]
      Opening connection to database 'MyDb' on server 'tcp://127.0.0.1:5432'.
info: Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory[1]
      Executed DbCommand (0ms) [Parameters=[@__siteId_0='?', @__userId_1='?'], CommandType='Text', CommandTimeout='30']
      SELECT "l"."Id", "l"."ClaimType", "l"."ClaimValue", "l"."SiteId", "l"."UserId"
      FROM "cs_UserClaim" AS "l"
      WHERE ("l"."SiteId" = @__siteId_0) AND ("l"."UserId" = @__userId_1)
dbug: Npgsql.NpgsqlConnection[4]
      Closing connection to database 'MyDb' on server 'tcp://127.0.0.1:5432'.
dbug: Npgsql.NpgsqlConnection[3]
      Opening connection to database 'MyDb' on server 'tcp://127.0.0.1:5432'.
info: Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory[1]
      Executed DbCommand (2ms) [Parameters=[@__siteId_0='?'], CommandType='Text', CommandTimeout='30']
      SELECT "x"."Id", "x"."AccountApprovalEmailCsv", "x"."AddThisDotComUsername", "x"."AliasId", "x"."AllowDbFallbackWithLdap", "x"."AllowNewRegistration", "x"."AllowPersistentLogin", "x"."AutoCreateLdapUserOnFirstLogin", "x"."CaptchaOnLogin", "x"."CaptchaOnRegistration", "x"."CompanyCountry", "x"."CompanyFax", "x"."CompanyLocality", "x"."CompanyName", "x"."CompanyPhone", "x"."CompanyPostalCode", "x"."CompanyPublicEmail", "x"."CompanyRegion", "x"."CompanyStreetAddress", "x"."CompanyStreetAddress2", "x"."ConcurrencyStamp", "x"."CreatedUtc", "x"."DefaultEmailFromAddress", "x"."DefaultEmailFromAlias", "x"."DisableDbAuth", "x"."DkimDomain", "x"."DkimPrivateKey", "x"."DkimPublicKey", "x"."DkimSelector", "x"."EmailLdapDbFallback", "x"."FacebookAppId", "x"."FacebookAppSecret", "x"."GoogleAnalyticsProfileId", "x"."GoogleClientId", "x"."GoogleClientSecret", "x"."IsDataProtected", "x"."IsServerAdminSite", "x"."LdapDomain", "x"."LdapPort", "x"."LdapRootDN", "x"."LdapServer", "x"."LdapUserDNKey", "x"."LoginInfoBottom", "x"."LoginInfoTop", "x"."MaxInvalidPasswordAttempts", "x"."MicrosoftClientId", "x"."MicrosoftClientSecret", "x"."MinRequiredPasswordLength", "x"."OidConnectAppId", "x"."OidConnectAppSecret", "x"."PreferredHostName", "x"."PrivacyPolicy", "x"."ReallyDeleteUsers", "x"."RecaptchaPrivateKey", "x"."RecaptchaPublicKey", "x"."RegistrationAgreement", "x"."RegistrationPreamble", "x"."RequireApprovalBeforeLogin", "x"."RequireConfirmedEmail", "x"."RequireConfirmedPhone", "x"."RequiresQuestionAndAnswer", "x"."SignEmailWithDkim", "x"."SiteFolderName", "x"."SiteIsClosed", "x"."SiteIsClosedMessage", "x"."SiteName", "x"."SmsClientId", "x"."SmsFrom", "x"."SmsSecureToken", "x"."SmtpPassword", "x"."SmtpPort", "x"."SmtpPreferredEncoding", "x"."SmtpRequiresAuth", "x"."SmtpServer", "x"."SmtpUseSsl", "x"."SmtpUser", "x"."Theme", "x"."TimeZoneId", "x"."TwitterConsumerKey", "x"."TwitterConsumerSecret", "x"."UseEmailForLogin", "x"."UseLdapAuth"
      FROM "cs_Site" AS "x"
      WHERE "x"."Id" = @__siteId_0
      LIMIT 2
dbug: Npgsql.NpgsqlConnection[4]
      Closing connection to database 'MyDb' on server 'tcp://127.0.0.1:5432'.
dbug: IdentityServer4.Hosting.AuthenticationHandler[0]
      Augmenting SignInContext
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware[10]
      AuthenticationScheme: Application signed in.
dbug: cloudscribe.Core.Identity.UserStore[0]
      FindByNameAsync
dbug: Npgsql.NpgsqlConnection[3]
      Opening connection to database 'MyDb' on server 'tcp://127.0.0.1:5432'.
info: Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory[1]
      Executed DbCommand (1ms) [Parameters=[@__siteId_0='?', @__userName_1='?', @__userName_2='?'], CommandType='Text', CommandTimeout='30']
      SELECT "x"."Id", "x"."AccessFailedCount", "x"."AccountApproved", "x"."AuthorBio", "x"."AvatarUrl", "x"."CanAutoLockout", "x"."Comment", "x"."CreatedUtc", "x"."DateOfBirth", "x"."DisplayInMemberList", "x"."DisplayName", "x"."Email", "x"."EmailConfirmed", "x"."FirstName", "x"."Gender", "x"."IsDeleted", "x"."IsLockedOut", "x"."LastLoginUtc", "x"."LastModifiedUtc", "x"."LastName", "x"."LastPasswordChangeUtc", "x"."LockoutEndDateUtc", "x"."MustChangePwd", "x"."NewEmail", "x"."NewEmailApproved", "x"."NormalizedEmail", "x"."NormalizedUserName", "x"."PasswordHash", "x"."PhoneNumber", "x"."PhoneNumberConfirmed", "x"."RolesChanged", "x"."SecurityStamp", "x"."Signature", "x"."SiteId", "x"."TimeZoneId", "x"."Trusted", "x"."TwoFactorEnabled", "x"."UserName", "x"."WebSiteUrl"
      FROM "cs_User" AS "x"
      WHERE ("x"."SiteId" = @__siteId_0) AND (("x"."NormalizedUserName" = @__userName_1) OR ("x"."NormalizedEmail" = @__userName_2))
      LIMIT 2
dbug: Npgsql.NpgsqlConnection[4]
      Closing connection to database 'MyDb' on server 'tcp://127.0.0.1:5432'.
dbug: Npgsql.NpgsqlConnection[3]
      Opening connection to database 'MyDb' on server 'tcp://127.0.0.1:5432'.
info: Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory[1]
      Executed DbCommand (1ms) [Parameters=[@__userId_0='?', @__ipv4AddressAsLong_1='?'], CommandType='Text', CommandTimeout='30']
      SELECT "x"."Id", "x"."CaptureCount", "x"."City", "x"."Continent", "x"."Country", "x"."FirstCaptureUtc", "x"."HostName", "x"."IpAddress", "x"."IpAddressLong", "x"."Isp", "x"."LastCaptureUtc", "x"."Latitude", "x"."Longitude", "x"."Region", "x"."SiteId", "x"."TimeZone", "x"."UserId"
      FROM "cs_UserLocation" AS "x"
      WHERE ("x"."UserId" = @__userId_0) AND ("x"."IpAddressLong" = @__ipv4AddressAsLong_1)
      LIMIT 1
dbug: Npgsql.NpgsqlConnection[4]
      Closing connection to database 'MyDb' on server 'tcp://127.0.0.1:5432'.
dbug: Npgsql.NpgsqlConnection[3]
      Opening connection to database 'MyDb' on server 'tcp://127.0.0.1:5432'.
dbug: Npgsql.NpgsqlConnection[5]
      Beginning transaction with isolation level 'Unspecified'.
info: Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory[1]
      Executed DbCommand (1ms) [Parameters=[@p16='?', @p0='?', @p1='?', @p2='?', @p3='?', @p4='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?', @p12='?', @p13='?', @p14='?', @p15='?'], CommandType='Text', CommandTimeout='30']
      UPDATE "cs_UserLocation" SET "CaptureCount" = @p0, "City" = @p1, "Continent" = @p2, "Country" = @p3, "FirstCaptureUtc" = @p4, "HostName" = @p5, "IpAddress" = @p6, "IpAddressLong" = @p7, "Isp" = @p8, "LastCaptureUtc" = @p9, "Latitude" = @p10, "Longitude" = @p11, "Region" = @p12, "SiteId" = @p13, "TimeZone" = @p14, "UserId" = @p15
      WHERE "Id" = @p16;
dbug: Npgsql.NpgsqlConnection[6]
      Committing transaction.
dbug: Npgsql.NpgsqlConnection[4]
      Closing connection to database 'MyDb' on server 'tcp://127.0.0.1:5432'.
info: Microsoft.AspNetCore.Mvc.Internal.LocalRedirectResultExecutor[1]
      Executing LocalRedirectResult, redirecting to /.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
      Executed action cloudscribe.Core.Web.Controllers.AccountController.Login (cloudscribe.Core.Web) in 60100.9064ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 60103.8532ms 302

Can not view in view browser

Hi joe ,
i follow your instruction to add the source to my VS .
After rebuild , i try to Right click the example.WebApp project and choose View > View In Browser,
it open a page http://localhost:54671/ in browser , but with error "HTTP Error 502.3 - Bad Gateway
There was a connection error while trying to route the request."
What step i have miss from the setup ? i try to put http://localhost:54671/Setup in the url , but same error appear.
I like your mojoportal design and use it for long time , and i do hope can continue use your new project in the future .
Thanks

TackUserIpAddress Exception

When I view the example.WebApp in the browser everything seems ok. However when I try to login, using the admin credentials, the browser just shows a blank page.
Debugging the project, I found the problem resides in the code:

IPAddress ipv4 = context.Connection.RemoteIpAddress.MapToIPv4();

in file IpAddressTracker.cs. This line of code fails because context.Connection.RemoteIpAddress is null.

Edit: Apparently, it's a bug in dnx RC1: aspnet/IISIntegration#17

A route to render virtual pages.

I start a project to render virtual pages(e.g site/page1, site2/pag2 , /page1) I have a route to render pages in my project and add a maproute to startup.cs

routes.MapRoute(
                      name: "renderpage",
                      template: "{sitefolder}/{id?}",
                      defaults: new { controller = "RenderController", action = "RenderPage" },
                      constraints: new { name = new PageRouteConstraint() }
                      );

But the core routes (e.g SiteAdmin) refer to my route.

Password history

In a security review of a solution based on mojoPortal, a client wanted settings to prevent users' password changes using a password that had been used before (within N changes). This was the only issue we failed on. Perhaps you could put a password history option onto the roadmap for cloudscribe?
I think it could be a site setting as simple as "Allow re-use of a previous password when changing password?" yes/no, plus a table containing the previous pwds for each user? If set to "no" this would allow a site to pass all box-tick exercises.
Apologies if an "issue" is not the right place to log this request - suggestions?

Change DateTime to DateTimeOffset

Hi,
I would like to offer to change the DateTime properties to DateTimeOffset. That way we will be able to use the cloud more freely with out always worrying about transferring to/from Utc.
This type has native support by SQL and By the Many NoSQL c# drivers

Entityframework7 repository is nice feature to have.

I saw you told about having Entity framework repository in future. But I think if it be available , it help to rapid development. I think what you care about having O/R is performance, a developer can develop an app with Entity Framework rapidly and then implement the repository with what ever ADO repository that achieve the best performance.
Nowadays developer start a thing and end up with another thing according to competitions, so code first reduce maintenance of code at least in staring phase of a project. may I am in correct :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.