Skip to content

Commit 024a358

Browse files
Merge pull request skoruba#1 from chadbengen/feature/multitenant
Feature/multitenant
2 parents 3729ca3 + 200f723 commit 024a358

File tree

144 files changed

+6797
-1042
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

144 files changed

+6797
-1042
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,4 +277,5 @@ __pycache__/
277277
# Don't ignore these log folders
278278
!/src/Skoruba.IdentityServer4.Admin/Resources/Views/Log/
279279
!/src/Skoruba.IdentityServer4.Admin.BusinessLogic/Dtos/Log/
280-
!/src/Skoruba.IdentityServer4.Admin/Views/Log/
280+
!/src/Skoruba.IdentityServer4.Admin/Views/Log/
281+
*.development.json

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,12 @@ The following Gulp commands are available:
125125
Add-Migration AspNetIdentityDbInit -context AdminIdentityDbContext -output Data/Migrations/Identity
126126
Update-Database -context AdminIdentityDbContext
127127
```
128+
#### Migrations for Asp.Net Core MultiTenant Identity DbContext:
129+
130+
```powershell
131+
Add-Migration AspNetMultiTenantIdentityDbInit -context MultiTenantUserIdentityDbContext -output Data/Migrations/Identity
132+
Update-Database -context MultiTenantUserIdentityDbContext
133+
```
128134

129135
#### Migrations for Logging DbContext:
130136

Skoruba.IdentityServer4.Admin.sln

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Skoruba.IdentityServer4.Adm
3333
EndProject
3434
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Skoruba.IdentityServer4.Admin.EntityFramework.Shared", "src\Skoruba.IdentityServer4.Admin.EntityFramework.Shared\Skoruba.IdentityServer4.Admin.EntityFramework.Shared.csproj", "{E18F8C70-7448-4039-9D78-1369D7F498EF}"
3535
EndProject
36-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Skoruba.IdentityServer4.Admin.EntityFramework.Extensions", "src\Skoruba.IdentityServer4.Admin.EntityFramework.Extensions\Skoruba.IdentityServer4.Admin.EntityFramework.Extensions.csproj", "{2DD3CB7D-462E-4039-B684-81B1E88C7C6A}"
36+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Skoruba.IdentityServer4.Admin.EntityFramework.Extensions", "src\Skoruba.IdentityServer4.Admin.EntityFramework.Extensions\Skoruba.IdentityServer4.Admin.EntityFramework.Extensions.csproj", "{2DD3CB7D-462E-4039-B684-81B1E88C7C6A}"
3737
EndProject
3838
Global
3939
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
This is a configuration file for the SwitchStartupProject Visual Studio Extension
3+
See https://bitbucket.org/thirteen/switchstartupproject/src/tip/Configuration.md
4+
*/
5+
{
6+
/* Configuration File Version */
7+
"Version": 3,
8+
9+
/* Create an item in the dropdown list for each project in the solution? */
10+
"ListAllProjects": true,
11+
12+
/*
13+
Dictionary of named configurations with one or multiple startup projects
14+
and optional parameters like command line arguments and working directory.
15+
Example:
16+
17+
"MultiProjectConfigurations": {
18+
"A + B (Ext)": {
19+
"Projects": {
20+
"MyProjectA": {},
21+
"MyProjectB": {
22+
"CommandLineArguments": "1234",
23+
"WorkingDirectory": "%USERPROFILE%\\test",
24+
"StartExternalProgram": "c:\\myprogram.exe"
25+
}
26+
}
27+
},
28+
"A + B": {
29+
"Projects": {
30+
"MyProjectA": {},
31+
"MyProjectB": {
32+
"CommandLineArguments": "",
33+
"WorkingDirectory": "",
34+
"StartProject": true
35+
}
36+
}
37+
},
38+
"D (Debug x86)": {
39+
"Projects": {
40+
"MyProjectD": {}
41+
},
42+
"SolutionConfiguration": "Debug",
43+
"SolutionPlatform": "x86",
44+
},
45+
"D (Release x64)": {
46+
"Projects": {
47+
"MyProjectD": {}
48+
},
49+
"SolutionConfiguration": "Release",
50+
"SolutionPlatform": "x64",
51+
}
52+
}
53+
*/
54+
"MultiProjectConfigurations": {
55+
"Auth": {
56+
"Projects": {
57+
"Skoruba.IdentityServer4.STS.Identity": {},
58+
"Skoruba.IdentityServer4.Admin.Api": {},
59+
"Skoruba.IdentityServer4.Admin": {}
60+
}
61+
}
62+
}
63+
}

src/Skoruba.IdentityServer4.Admin.Api/Configuration/Constants/AuthorizationConsts.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,11 @@ public class AuthorizationConsts
88

99
public const string AdministrationPolicy = "RequireAdministratorRole";
1010
public const string AdministrationRole = "SkorubaIdentityAdminAdministrator";
11+
public const string TenantManagerPolicy = "RequireTenantManagerRole";
12+
public const string TenantManagerRole = "SkorubaIdentityTenantManager";
13+
public const string TenantAdministratorPolicy = "RequireTenantAdministratorRole";
14+
public const string TenantAdministratorRole = "TenantAdministrator";
15+
public const string TenantAdvancedUserPolicy = "RequireTenantAdvancedUserRole";
16+
public const string TenantAdvancedUserRole = "TenantAdvancedUser";
1117
}
1218
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using Microsoft.Extensions.DependencyInjection;
2+
3+
namespace Skoruba.IdentityServer4.Admin.Api.DependencyInjection
4+
{
5+
public class Builder : IBuilder
6+
{
7+
public Builder(IServiceCollection services)
8+
{
9+
Services = services;
10+
}
11+
12+
public IServiceCollection Services { get; }
13+
}
14+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
using Microsoft.AspNetCore.Identity;
2+
using Microsoft.EntityFrameworkCore;
3+
using Microsoft.Extensions.DependencyInjection;
4+
using System;
5+
using Microsoft.AspNetCore.Hosting;
6+
using Skoruba.IdentityServer4.Admin.EntityFramework.Shared.DbContexts;
7+
using Skoruba.IdentityServer4.Admin.EntityFramework.Shared.Entities.Identity;
8+
using IdentityServer4.EntityFramework.Options;
9+
using Skoruba.IdentityServer4.Admin.BusinessLogic.Identity.Dtos.Identity;
10+
using System.Linq;
11+
using Skoruba.IdentityServer4.Admin.EntityFramework.Shared.Validators;
12+
using Skoruba.IdentityServer4.Admin.BusinessLogic.Identity.Mappers;
13+
using System.Collections.Generic;
14+
15+
namespace Skoruba.IdentityServer4.Admin.Api.DependencyInjection
16+
{
17+
public static partial class BuilderExtensions
18+
{
19+
public static IBuilder AddMultiTenantConfiguration
20+
(this IServiceCollection services,
21+
IHostingEnvironment hostingEnvironment,
22+
Action<DbContextOptionsBuilder> identityDbContextOptions,
23+
Action<ConfigurationStoreOptions> configurationStoreOptions,
24+
Action<OperationalStoreOptions> operationalStoreOptions,
25+
Action<DbContextOptionsBuilder> logDbContextOptions,
26+
Action<IdentityOptions> identityOptions)
27+
{
28+
var builder = services
29+
.AddCustomConfiguration
30+
<MultiTenantUserIdentityDbContext, IdentityServerConfigurationDbContext, IdentityServerPersistedGrantDbContext, AdminLogDbContext>
31+
(identityDbContextOptions, configurationStoreOptions, operationalStoreOptions, logDbContextOptions)
32+
.AddCustomIdentity
33+
<MultiTenantUserIdentityDbContext, MultiTenantUserIdentity, UserIdentityRole>
34+
(identityOptions);
35+
36+
HashSet<Type> profileTypes = ProfileTypes;
37+
profileTypes.Add(typeof(TenantMapperProfile));
38+
39+
builder.Services.AddAdminAspNetIdentityServices<MultiTenantUserIdentityDbContext, IdentityServerPersistedGrantDbContext,
40+
MultiTenantUserDto<string>, string, RoleDto<string>, string, string, string,
41+
MultiTenantUserIdentity, UserIdentityRole, string, UserIdentityUserClaim, UserIdentityUserRole,
42+
UserIdentityUserLogin, UserIdentityRoleClaim, UserIdentityUserToken,
43+
UsersDto<MultiTenantUserDto<string>, string>, RolesDto<RoleDto<string>, string>, UserRolesDto<RoleDto<string>, string, string>,
44+
UserClaimsDto<string>, UserProviderDto<string>, UserProvidersDto<string>, UserChangePasswordDto<string>,
45+
RoleClaimsDto<string>, UserClaimDto<string>, RoleClaimDto<string>>(profileTypes);
46+
47+
builder.Services.AddMultiTenantServiceDepencies();
48+
49+
builder.Services.Remove(builder.Services.FirstOrDefault(d => d.ServiceType == typeof(IUserValidator<MultiTenantUserIdentity>)));
50+
builder.AddUserValidator<MultiTenantUserIdentity, MultiTenantUserValidator>();
51+
builder.AddUserValidator<MultiTenantUserIdentity, RequireTenant>();
52+
builder.AddUserValidator<MultiTenantUserIdentity, MightRequireTwoFactorAuthentication<MultiTenantUserIdentity>>();
53+
54+
builder.Services.AddAdminServices<IdentityServerConfigurationDbContext, IdentityServerPersistedGrantDbContext, AdminLogDbContext>();
55+
56+
builder.AddMvcServices<MultiTenantUserDto<string>, string, RoleDto<string>, string, string, string,
57+
UserIdentity, UserIdentityRole, string, UserIdentityUserClaim, UserIdentityUserRole,
58+
UserIdentityUserLogin, UserIdentityRoleClaim, UserIdentityUserToken,
59+
UsersDto<MultiTenantUserDto<string>, string>, RolesDto<RoleDto<string>, string>, UserRolesDto<RoleDto<string>, string, string>,
60+
UserClaimsDto<string>, UserProviderDto<string>, UserProvidersDto<string>, UserChangePasswordDto<string>,
61+
RoleClaimsDto<string>>();
62+
63+
return builder;
64+
}
65+
}
66+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
using Microsoft.AspNetCore.Identity;
2+
using Microsoft.EntityFrameworkCore;
3+
using Microsoft.Extensions.DependencyInjection;
4+
using System;
5+
using Microsoft.AspNetCore.Hosting;
6+
using Skoruba.IdentityServer4.Admin.EntityFramework.Shared.DbContexts;
7+
using Skoruba.IdentityServer4.Admin.EntityFramework.Shared.Entities.Identity;
8+
using IdentityServer4.EntityFramework.Options;
9+
using Skoruba.IdentityServer4.Admin.BusinessLogic.Identity.Dtos.Identity;
10+
11+
namespace Skoruba.IdentityServer4.Admin.Api.DependencyInjection
12+
{
13+
public static partial class BuilderExtensions
14+
{
15+
public static Builder AddSingleTenantConfiguration
16+
(this IServiceCollection services,
17+
IHostingEnvironment hostingEnvironment,
18+
Action<DbContextOptionsBuilder> identityDbContextOptions,
19+
Action<ConfigurationStoreOptions> configurationStoreOptions,
20+
Action<OperationalStoreOptions> operationalStoreOptions,
21+
Action<DbContextOptionsBuilder> logDbContextOptions,
22+
Action<IdentityOptions> identityOptions)
23+
{
24+
var builder = new Builder(services);
25+
26+
builder.Services.AddCustomConfiguration
27+
<AdminIdentityDbContext, IdentityServerConfigurationDbContext, IdentityServerPersistedGrantDbContext, AdminLogDbContext>
28+
(identityDbContextOptions, configurationStoreOptions, operationalStoreOptions, logDbContextOptions)
29+
.AddCustomIdentity<AdminIdentityDbContext, UserIdentity, UserIdentityRole>(identityOptions);
30+
31+
builder.Services.AddAdminAspNetIdentityServices<AdminIdentityDbContext, IdentityServerPersistedGrantDbContext, UserDto<string>, string, RoleDto<string>, string, string, string,
32+
UserIdentity, UserIdentityRole, string, UserIdentityUserClaim, UserIdentityUserRole,
33+
UserIdentityUserLogin, UserIdentityRoleClaim, UserIdentityUserToken,
34+
UsersDto<UserDto<string>, string>, RolesDto<RoleDto<string>, string>, UserRolesDto<RoleDto<string>, string, string>,
35+
UserClaimsDto<string>, UserProviderDto<string>, UserProvidersDto<string>, UserChangePasswordDto<string>,
36+
RoleClaimsDto<string>, UserClaimDto<string>, RoleClaimDto<string>>(ProfileTypes);
37+
38+
builder.Services.AddAdminServices<IdentityServerConfigurationDbContext, IdentityServerPersistedGrantDbContext, AdminLogDbContext>();
39+
40+
builder.AddMvcServices<UserDto<string>, string, RoleDto<string>, string, string, string,
41+
UserIdentity, UserIdentityRole, string, UserIdentityUserClaim, UserIdentityUserRole,
42+
UserIdentityUserLogin, UserIdentityRoleClaim, UserIdentityUserToken,
43+
UsersDto<UserDto<string>, string>, RolesDto<RoleDto<string>, string>, UserRolesDto<RoleDto<string>, string, string>,
44+
UserClaimsDto<string>, UserProviderDto<string>, UserProvidersDto<string>, UserChangePasswordDto<string>,
45+
RoleClaimsDto<string>>();
46+
47+
//Uncomment below to require 2fa
48+
//builder.AddUserValidator<UserIdentity, MightRequireTwoFactorAuthentication<UserIdentity>>();
49+
50+
return builder;
51+
}
52+
}
53+
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
using Microsoft.AspNetCore.Identity;
2+
using Microsoft.EntityFrameworkCore;
3+
using Microsoft.Extensions.DependencyInjection;
4+
using System;
5+
using IdentityServer4.EntityFramework.Options;
6+
using Skoruba.IdentityServer4.Admin.EntityFramework.Interfaces;
7+
using IdentityServer4.EntityFramework.Storage;
8+
using Skoruba.IdentityServer4.Admin.BusinessLogic.Identity.Dtos.Identity;
9+
using System.Collections.Generic;
10+
using Skoruba.IdentityServer4.Admin.Api.Mappers;
11+
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
12+
using Microsoft.Extensions.DependencyInjection.Extensions;
13+
using Skoruba.IdentityServer4.Admin.Api.Helpers.Localization;
14+
using Skoruba.IdentityServer4.Admin.Api.Configuration.ApplicationParts;
15+
using Microsoft.AspNetCore.Mvc;
16+
17+
namespace Skoruba.IdentityServer4.Admin.Api.DependencyInjection
18+
{
19+
public static partial class BuilderExtensions
20+
{
21+
public static IBuilder AddCustomConfiguration
22+
<TAdminIdentityDbContext, TIdentityServerConfigurationDbContext, TIdentityServerPersistedGrantDbContext, TAdminLogDbContext>
23+
(this IServiceCollection services,
24+
Action<DbContextOptionsBuilder> identityDbContextOptions,
25+
Action<ConfigurationStoreOptions> configurationStoreOptions,
26+
Action<OperationalStoreOptions> operationalStoreOptions,
27+
Action<DbContextOptionsBuilder> logDbContextOptions)
28+
where TAdminIdentityDbContext : DbContext
29+
where TIdentityServerConfigurationDbContext : DbContext, IAdminConfigurationDbContext
30+
where TIdentityServerPersistedGrantDbContext : DbContext, IAdminPersistedGrantDbContext
31+
where TAdminLogDbContext : DbContext, IAdminLogDbContext
32+
{
33+
var builder = new Builder(services);
34+
35+
services.AddDbContext<TAdminIdentityDbContext>(identityDbContextOptions);
36+
services.AddConfigurationDbContext<TIdentityServerConfigurationDbContext>(configurationStoreOptions);
37+
services.AddOperationalDbContext<TIdentityServerPersistedGrantDbContext>(operationalStoreOptions);
38+
services.AddDbContext<TAdminLogDbContext>(logDbContextOptions);
39+
40+
return builder;
41+
}
42+
43+
public static IBuilder AddCustomIdentity
44+
<TIdentityDbContext, TUserIdentity, TUserIdentityRole>
45+
(this IBuilder builder, Action<IdentityOptions> identityOptions)
46+
where TIdentityDbContext : DbContext
47+
where TUserIdentity : class
48+
where TUserIdentityRole : class
49+
{
50+
builder.Services
51+
.AddIdentity<TUserIdentity, TUserIdentityRole>(identityOptions)
52+
.AddEntityFrameworkStores<TIdentityDbContext>()
53+
.AddDefaultTokenProviders();
54+
55+
return builder;
56+
}
57+
58+
private static HashSet<Type> ProfileTypes => new HashSet<Type>
59+
{
60+
typeof(IdentityMapperProfile<RoleDto<string>, string, UserRolesDto<RoleDto<string>, string, string>, string, UserClaimsDto<string>, UserClaimDto<string>, UserProviderDto<string>, UserProvidersDto<string>, UserChangePasswordDto<string>,RoleClaimDto<string>, RoleClaimsDto<string>>)
61+
};
62+
63+
/// <summary>
64+
/// Register services for MVC
65+
/// </summary>
66+
/// <param name="services"></param>
67+
public static IBuilder AddMvcServices<TUserDto, TUserDtoKey, TRoleDto, TRoleDtoKey, TUserKey, TRoleKey,
68+
TUser, TRole, TKey, TUserClaim, TUserRole, TUserLogin, TRoleClaim, TUserToken,
69+
TUsersDto, TRolesDto, TUserRolesDto, TUserClaimsDto,
70+
TUserProviderDto, TUserProvidersDto, TUserChangePasswordDto, TRoleClaimsDto>
71+
(this IBuilder builder)
72+
where TUserDto : UserDto<TUserDtoKey>, new()
73+
where TRoleDto : RoleDto<TRoleDtoKey>, new()
74+
where TUser : IdentityUser<TKey>
75+
where TRole : IdentityRole<TKey>
76+
where TKey : IEquatable<TKey>
77+
where TUserClaim : IdentityUserClaim<TKey>
78+
where TUserRole : IdentityUserRole<TKey>
79+
where TUserLogin : IdentityUserLogin<TKey>
80+
where TRoleClaim : IdentityRoleClaim<TKey>
81+
where TUserToken : IdentityUserToken<TKey>
82+
where TRoleDtoKey : IEquatable<TRoleDtoKey>
83+
where TUserDtoKey : IEquatable<TUserDtoKey>
84+
where TUsersDto : UsersDto<TUserDto, TUserDtoKey>
85+
where TRolesDto : RolesDto<TRoleDto, TRoleDtoKey>
86+
where TUserRolesDto : UserRolesDto<TRoleDto, TUserDtoKey, TRoleDtoKey>
87+
where TUserClaimsDto : UserClaimsDto<TUserDtoKey>
88+
where TUserProviderDto : UserProviderDto<TUserDtoKey>
89+
where TUserProvidersDto : UserProvidersDto<TUserDtoKey>
90+
where TUserChangePasswordDto : UserChangePasswordDto<TUserDtoKey>
91+
where TRoleClaimsDto : RoleClaimsDto<TRoleDtoKey>
92+
{
93+
builder.Services.TryAddTransient(typeof(IGenericControllerLocalizer<>), typeof(GenericControllerLocalizer<>));
94+
95+
builder.Services.AddMvc(o =>
96+
{
97+
o.Conventions.Add(new GenericControllerRouteConvention());
98+
})
99+
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
100+
.AddDataAnnotationsLocalization()
101+
.ConfigureApplicationPartManager(m =>
102+
{
103+
m.FeatureProviders.Add(new GenericTypeControllerFeatureProvider<TUserDto, TUserDtoKey, TRoleDto, TRoleDtoKey, TUserKey, TRoleKey, TUser, TRole, TKey, TUserClaim, TUserRole, TUserLogin, TRoleClaim, TUserToken,
104+
TUsersDto, TRolesDto, TUserRolesDto, TUserClaimsDto,
105+
TUserProviderDto, TUserProvidersDto, TUserChangePasswordDto, TRoleClaimsDto>());
106+
});
107+
108+
return builder;
109+
}
110+
111+
public static IBuilder AddUserValidator<TUser, TValidator>(this IBuilder builder)
112+
where TUser : class
113+
where TValidator : class
114+
{
115+
builder.Services.AddScoped(typeof(IUserValidator<TUser>), typeof(TValidator));
116+
return builder;
117+
}
118+
}
119+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using Microsoft.Extensions.DependencyInjection;
2+
3+
namespace Skoruba.IdentityServer4.Admin.Api.DependencyInjection
4+
{
5+
/// <summary>
6+
/// Skoruba IdentityServer builder Interface
7+
/// </summary>
8+
public interface IBuilder
9+
{
10+
/// <summary>
11+
/// Gets the services.
12+
/// </summary>
13+
/// <value>
14+
/// The services.
15+
/// </value>
16+
IServiceCollection Services { get; }
17+
}
18+
}

0 commit comments

Comments
 (0)