The TenantManager
integrates cloud authentication with dedicated datastore Organizations over a certainly controlled management;
This is a Blazor
module, to use it you need:
- An
Organization
and aUser
BO in your solution - A dependency between them. A possible implementation is:
public class ApplicationUser : PermissionPolicyUser, IObjectSpaceLink, ISecurityUserWithLoginInfo {
[Association("ApplicationOrganization-ApplicationUsers")]
public XPCollection<ApplicationOrganization> ApplicationOrganizations => GetCollection<ApplicationOrganization>(nameof(ApplicationOrganizations));
}
public class ApplicationOrganization:BaseObject{
[Association("ApplicationOrganization-ApplicationUsers")]
public XPCollection<ApplicationUser> ApplicationUsers => GetCollection<ApplicationUser>(nameof(ApplicationUsers));
ApplicationUser _owner;
public ApplicationUser Owner{
get => _owner;
set => SetPropertyValue(nameof(Owner), ref _owner, value);
}
}
- A
ConnectionString
property on yourOrganization
.
public class ApplicationOrganization:BaseObject{
string _connectionString;
[Size(SizeAttribute.Unlimited)]
public string ConnectionString{
get => _connectionString;
set => SetPropertyValue(nameof(ConnectionString), ref _connectionString, value);
}
}
- A non persistent object to display the Organization lookup.
[DomainComponent]
public class SelectOrganization:NonPersistentBaseObject{
public string Message{ get; } = "To get a <b>licence</b> contact Sales.";
ApplicationOrganization _organization;
[RuleRequiredField]
public ApplicationOrganization Organization{
get => _organization;
set => SetPropertyValue(nameof(Organization), ref _organization, value);
}
}
-
Register the
Organization
type using the Model Editor and if the design is similar, the rest auto fill (see screencast).
- The
Manager
database controls the User-Organization relationship. TheManager
admin can assign 1 ownership to a user thus making himAdministrator
in his ownOrganization
or he can simply allow participation as aDefaultRole
. if the user isOwner
he can createnew users
without help of a Manager Admin. For each new OrganizationUserEmail
a new user is created in the Manager DB and is link to the Organization, so the user is ready for login. - The user can use for e.g. a B2C flow for authentication, registration etc. Once a new user is authenticated you are responsible for creating him in the manager db as per Solution Wizard sample code.
- The module will create an Organization user, using the same email stored in the Manager DB on user first authentication in the Organization database. A new user in the
Manager
database is created when a newOrganization
user is committed. TheDefaultRoleCriteria
,AdminRoleCriteria
model attributes will be used to query and link with a role. On each authentication in anOrganization
if the userowns
then theAdminRole
will be linked else theDefaultRole
- It is your responsibility to create initial data for all datastore. The
ModuleUpdater
will be called for all datastores. There are cases e.g. you want to createOrganization
only in the Manager db that you may need to differentiate base on the database name.if (ObjectSpace.Connection().Database.StartsWith("OrganizationManager")){ AddOrganization(); }
- The module assumes that the
Organization
type is used only from the Manager DB so it hides it from all possible places while an Organization. - The
Organization
holds itsConnectionString
in a property configured from the model. To override it mark the propertyNonBrowsable
,NonPersistent
and use a snippet like the next one.public override void Setup(ApplicationModulesManager moduleManager){ base.Setup(moduleManager); moduleManager.WhenApplication(xafApplication => xafApplication.WhenCustomizeConnectionString<ApplicationOrganization>(organization => organization.ConnectionString)) .Subscribe(this); }
In the screencast:
- I modify the project's
ApplicationOrganization
,ApplicationUser
declaring a dependecy with each other. - I create
SelectOrganization
prompt
BO/view. - I make the
TenantManager
package aware of my classes with the ModelEditor. - I start the app.
- I attempt to login with my GitHub account and the system responds with
To get a license please contact sales
markup. - A Manager DB login and makes me Owner of Org.
- I attempt login again with my GitHub account, the system prompts me to choose Organization.
- I login and confirm that I am Admin and can create users without the need of a Manager Admin.
Possible future improvements:
- Any other need you may have.
Let me know if you want me to implement them for you.
-
First you need the nuget package so issue this command to the
VS Nuget package console
Install-Package Xpand.XAF.Modules.TenantManager
.The above only references the dependencies and nexts steps are mandatory.
-
Ways to Register a Module or simply add the next call to your module constructor
RequiredModuleTypes.Add(typeof(Xpand.XAF.Modules.TenantManagerModule));
The module is not bound to DevExpress versioning, which means you can use the latest version with your old DevExpress projects Read more.
The module follows the Nuget Version Basics.
.NetFramework: net6.0
DevExpress.ExpressApp.Security | Any |
DevExpress.Persistent.Base | Any |
DevExpress.ExpressApp.Xpo | Any |
DevExpress.ExpressApp.Blazor | Any |
Xpand.VersionConverter | 4.232.3 |
Xpand.Extensions.Reactive | 4.232.3 |
Xpand.Extensions | 4.232.3 |
Xpand.Extensions.XAF | 4.232.3 |
Xpand.Extensions.XAF.Xpo | 4.232.3 |
Xpand.XAF.Modules.Reactive | 4.232.3 |
Xpand.XAF.Modules.Blazor | 4.232.3 |
Xpand.Extensions.Blazor | 4.232.3 |
Xpand.Patcher | 3.0.24 |
System.Reactive | 6.0.0 |
Fasterflect.Xpand | 2.0.7 |
System.Text.Json | 7.0.2 |
Xpand.Collections | 1.0.4 |
System.Threading.Tasks.Dataflow | 7.0.0 |
Microsoft.AspNetCore.Components | 6.0.0 |
Xpand.VersionConverter | 4.232.3 |
To Step in the source code
you need to enable Source Server support
in your Visual Studio/Tools/Options/Debugging/Enable Source Server Support. See also How to boost your DevExpress Debugging Experience.
If the package is installed in a way that you do not have access to uninstall it, then you can unload
it with the next call at the constructor of your module.
Xpand.XAF.Modules.Reactive.ReactiveModuleBase.Unload(typeof(Xpand.XAF.Modules.TenantManager.TenantManagerModule))
The module is tested on Azure for each build with these tests. All Tests run as per our Compatibility Matrix