diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/DataSeeder/AuthServerDataSeedContributor.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/DataSeeder/AuthServerDataSeedContributor.cs deleted file mode 100644 index b1348bf39..000000000 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/DataSeeder/AuthServerDataSeedContributor.cs +++ /dev/null @@ -1,309 +0,0 @@ -using Microsoft.Extensions.Configuration; -using OpenIddict.Abstractions; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Threading.Tasks; -using Volo.Abp.Authorization.Permissions; -using Volo.Abp.Data; -using Volo.Abp.DependencyInjection; -using Volo.Abp.MultiTenancy; -using Volo.Abp.OpenIddict.Applications; -using Volo.Abp.OpenIddict.Scopes; -using Volo.Abp.PermissionManagement; - -namespace LINGYUN.Abp.MicroService.AuthServer.DataSeeder; - -public class AuthServerDataSeedContributor : IDataSeedContributor, ITransientDependency -{ - public static HashSet InitializeScopes = new HashSet - { - // obsolete! microservice should be allocated separately - "lingyun-abp-application", - // admin service - "ams", - // identity service - "ids", - // localization service - "lts", - // platform service - "pts", - // message service - "mgs", - // task service - "tks", - // webhook service - "wks", - // workflow service - "wfs", - // wechat service - "was" - }; - - private readonly IConfiguration _configuration; - private readonly ICurrentTenant _currentTenant; - private readonly IOpenIddictApplicationManager _applicationManager; - private readonly IOpenIddictApplicationRepository _applicationRepository; - - private readonly IPermissionDataSeeder _permissionDataSeeder; - - private readonly IOpenIddictScopeManager _scopeManager; - private readonly IOpenIddictScopeRepository _scopeRepository; - - public AuthServerDataSeedContributor( - IConfiguration configuration, - ICurrentTenant currentTenant, - IOpenIddictScopeManager scopeManager, - IOpenIddictScopeRepository scopeRepository, - IPermissionDataSeeder permissionDataSeeder, - IOpenIddictApplicationManager applicationManager, - IOpenIddictApplicationRepository applicationRepository) - { - _configuration = configuration; - _currentTenant = currentTenant; - _scopeManager = scopeManager; - _scopeRepository = scopeRepository; - _permissionDataSeeder = permissionDataSeeder; - _applicationManager = applicationManager; - _applicationRepository = applicationRepository; - } - - public async Task SeedAsync(DataSeedContext context) - { - using (_currentTenant.Change(context.TenantId)) - { - await CreateScopeAsync(InitializeScopes); - - await CreateApplicationAsync(InitializeScopes); - } - } - - private async Task CreateScopeAsync(IEnumerable scopes) - { - foreach (var scope in scopes) - { - if (await _scopeRepository.FindByNameAsync(scope) == null) - { - await _scopeManager.CreateAsync(new OpenIddictScopeDescriptor() - { - Name = scope, - DisplayName = scope + " access", - DisplayNames = - { - [CultureInfo.GetCultureInfo("zh-Hans")] = "Abp API 应用程序访问", - [CultureInfo.GetCultureInfo("en")] = "Abp API Application Access" - }, - Resources = - { - scope - } - }); - } - } - } - - private async Task CreateApplicationAsync(IEnumerable scopes) - { - var configurationSection = _configuration.GetSection("OpenIddict:Applications"); - - var vueClientId = configurationSection["VueAdmin:ClientId"]; - if (!vueClientId.IsNullOrWhiteSpace()) - { - var vueClientRootUrl = configurationSection["VueAdmin:RootUrl"].EnsureEndsWith('/'); - - if (await _applicationRepository.FindByClientIdAsync(vueClientId) == null) - { - var application = new OpenIddictApplicationDescriptor - { - ClientId = vueClientId, - ClientSecret = configurationSection["VueAdmin:ClientSecret"], - ApplicationType = OpenIddictConstants.ApplicationTypes.Web, - ConsentType = OpenIddictConstants.ConsentTypes.Explicit, - DisplayName = "Abp Vue Admin Client", - PostLogoutRedirectUris = - { - new Uri(vueClientRootUrl + "signout-callback"), - new Uri(vueClientRootUrl) - }, - RedirectUris = - { - new Uri(vueClientRootUrl + "signin-callback"), - new Uri(vueClientRootUrl) - }, - Permissions = - { - OpenIddictConstants.Permissions.Endpoints.Authorization, - OpenIddictConstants.Permissions.Endpoints.Token, - OpenIddictConstants.Permissions.Endpoints.DeviceAuthorization, - OpenIddictConstants.Permissions.Endpoints.Introspection, - OpenIddictConstants.Permissions.Endpoints.Revocation, - OpenIddictConstants.Permissions.Endpoints.EndSession, - - OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode, - OpenIddictConstants.Permissions.GrantTypes.Implicit, - OpenIddictConstants.Permissions.GrantTypes.Password, - OpenIddictConstants.Permissions.GrantTypes.RefreshToken, - OpenIddictConstants.Permissions.GrantTypes.DeviceCode, - OpenIddictConstants.Permissions.GrantTypes.ClientCredentials, - - OpenIddictConstants.Permissions.ResponseTypes.Code, - OpenIddictConstants.Permissions.ResponseTypes.CodeIdToken, - OpenIddictConstants.Permissions.ResponseTypes.CodeIdTokenToken, - OpenIddictConstants.Permissions.ResponseTypes.CodeToken, - OpenIddictConstants.Permissions.ResponseTypes.IdToken, - OpenIddictConstants.Permissions.ResponseTypes.IdTokenToken, - OpenIddictConstants.Permissions.ResponseTypes.None, - OpenIddictConstants.Permissions.ResponseTypes.Token, - - OpenIddictConstants.Permissions.Scopes.Roles, - OpenIddictConstants.Permissions.Scopes.Profile, - OpenIddictConstants.Permissions.Scopes.Email, - OpenIddictConstants.Permissions.Scopes.Address, - OpenIddictConstants.Permissions.Scopes.Phone, - } - }; - foreach (var scope in scopes) - { - application.Permissions.AddIfNotContains(OpenIddictConstants.Permissions.Prefixes.Scope + scope); - } - - await _applicationManager.CreateAsync(application); - - var vueClientPermissions = new string[1] - { - "AbpIdentity.UserLookup" - }; - await _permissionDataSeeder.SeedAsync(ClientPermissionValueProvider.ProviderName, vueClientId, vueClientPermissions); - } - } - - var internalServiceClientId = configurationSection["InternalService:ClientId"]; - if (!internalServiceClientId.IsNullOrWhiteSpace()) - { - if (await _applicationRepository.FindByClientIdAsync(internalServiceClientId) == null) - { - var application = new OpenIddictApplicationDescriptor - { - ClientId = internalServiceClientId, - ClientSecret = configurationSection["InternalService:ClientSecret"], - ClientType = OpenIddictConstants.ClientTypes.Confidential, - ConsentType = OpenIddictConstants.ConsentTypes.Explicit, - ApplicationType = OpenIddictConstants.ApplicationTypes.Native, - DisplayName = "Abp Vue Admin Client", - Permissions = - { - OpenIddictConstants.Permissions.Endpoints.Authorization, - OpenIddictConstants.Permissions.Endpoints.Token, - OpenIddictConstants.Permissions.Endpoints.DeviceAuthorization, - OpenIddictConstants.Permissions.Endpoints.Introspection, - OpenIddictConstants.Permissions.Endpoints.Revocation, - OpenIddictConstants.Permissions.Endpoints.EndSession, - - OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode, - OpenIddictConstants.Permissions.GrantTypes.Implicit, - OpenIddictConstants.Permissions.GrantTypes.Password, - OpenIddictConstants.Permissions.GrantTypes.RefreshToken, - OpenIddictConstants.Permissions.GrantTypes.DeviceCode, - OpenIddictConstants.Permissions.GrantTypes.ClientCredentials, - - OpenIddictConstants.Permissions.ResponseTypes.Code, - OpenIddictConstants.Permissions.ResponseTypes.CodeIdToken, - OpenIddictConstants.Permissions.ResponseTypes.CodeIdTokenToken, - OpenIddictConstants.Permissions.ResponseTypes.CodeToken, - OpenIddictConstants.Permissions.ResponseTypes.IdToken, - OpenIddictConstants.Permissions.ResponseTypes.IdTokenToken, - OpenIddictConstants.Permissions.ResponseTypes.None, - OpenIddictConstants.Permissions.ResponseTypes.Token, - - OpenIddictConstants.Permissions.Scopes.Roles, - OpenIddictConstants.Permissions.Scopes.Profile, - OpenIddictConstants.Permissions.Scopes.Email, - OpenIddictConstants.Permissions.Scopes.Address, - OpenIddictConstants.Permissions.Scopes.Phone, - } - }; - foreach (var scope in scopes) - { - application.Permissions.AddIfNotContains(OpenIddictConstants.Permissions.Prefixes.Scope + scope); - } - - await _applicationManager.CreateAsync(application); - - var internalServicePermissions = new string[2] - { - "AbpIdentity.UserLookup","AbpIdentity.Users" - }; - await _permissionDataSeeder.SeedAsync(ClientPermissionValueProvider.ProviderName, internalServiceClientId, internalServicePermissions); - } - } - - var oauthClientId = configurationSection["VueOAuthClient:ClientId"]; - if (!oauthClientId.IsNullOrWhiteSpace()) - { - var oauthClientRootUrls = configurationSection.GetSection("VueOAuthClient:RootUrls").Get>(); - - if (await _applicationRepository.FindByClientIdAsync(oauthClientId) == null) - { - var application = new OpenIddictApplicationDescriptor - { - ClientId = oauthClientId, - ClientSecret = null, - ApplicationType = OpenIddictConstants.ApplicationTypes.Web, - ConsentType = OpenIddictConstants.ConsentTypes.Implicit, - DisplayName = "OAuth Client", - PostLogoutRedirectUris = { }, - RedirectUris = { }, - Permissions = - { - OpenIddictConstants.Permissions.Endpoints.Authorization, - OpenIddictConstants.Permissions.Endpoints.Token, - OpenIddictConstants.Permissions.Endpoints.DeviceAuthorization, - OpenIddictConstants.Permissions.Endpoints.Introspection, - OpenIddictConstants.Permissions.Endpoints.Revocation, - OpenIddictConstants.Permissions.Endpoints.EndSession, - - OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode, - OpenIddictConstants.Permissions.GrantTypes.RefreshToken, - - OpenIddictConstants.Permissions.ResponseTypes.Code, - OpenIddictConstants.Permissions.ResponseTypes.CodeIdToken, - OpenIddictConstants.Permissions.ResponseTypes.CodeIdTokenToken, - OpenIddictConstants.Permissions.ResponseTypes.CodeToken, - OpenIddictConstants.Permissions.ResponseTypes.IdToken, - OpenIddictConstants.Permissions.ResponseTypes.IdTokenToken, - OpenIddictConstants.Permissions.ResponseTypes.None, - OpenIddictConstants.Permissions.ResponseTypes.Token, - - OpenIddictConstants.Permissions.Scopes.Roles, - OpenIddictConstants.Permissions.Scopes.Profile, - OpenIddictConstants.Permissions.Scopes.Email, - OpenIddictConstants.Permissions.Scopes.Address, - OpenIddictConstants.Permissions.Scopes.Phone, - } - }; - foreach (var scope in scopes) - { - application.Permissions.AddIfNotContains(OpenIddictConstants.Permissions.Prefixes.Scope + scope); - } - - oauthClientRootUrls.ForEach(url => - { - application.PostLogoutRedirectUris.AddIfNotContains(new Uri(url.EnsureEndsWith('/'))); - application.PostLogoutRedirectUris.AddIfNotContains(new Uri(url.EnsureEndsWith('/') + "signout-callback")); - - application.RedirectUris.AddIfNotContains(new Uri(url)); - application.RedirectUris.AddIfNotContains(new Uri(url.EnsureEndsWith('/') + "signin-callback")); - application.RedirectUris.AddIfNotContains(new Uri(url.EnsureEndsWith('/') + "swagger/oauth2-redirect.html")); - }); - - await _applicationManager.CreateAsync(application); - - var oauthClientPermissions = new string[1] - { - "AbpIdentity.UserLookup" - }; - await _permissionDataSeeder.SeedAsync(ClientPermissionValueProvider.ProviderName, oauthClientId, oauthClientPermissions); - } - } - } -} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/DataSeeder/OpenIddictDataSeederContributor.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/DataSeeder/OpenIddictDataSeederContributor.cs new file mode 100644 index 000000000..73efc634f --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/DataSeeder/OpenIddictDataSeederContributor.cs @@ -0,0 +1,330 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using OpenIddict.Abstractions; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Threading.Tasks; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.OpenIddict; +using Volo.Abp.OpenIddict.Applications; +using Volo.Abp.OpenIddict.Scopes; +using Volo.Abp.PermissionManagement; + +namespace LINGYUN.Abp.MicroService.AuthServer.DataSeeder; + +public class OpenIddictDataSeederContributor : OpenIddictDataSeedContributorBase, IDataSeedContributor, ITransientDependency +{ + public ILogger Logger { protected get; set; } + protected IPermissionDataSeeder PermissionDataSeeder { get; } + public OpenIddictDataSeederContributor( + IConfiguration configuration, + IOpenIddictApplicationRepository openIddictApplicationRepository, + IAbpApplicationManager applicationManager, + IOpenIddictScopeRepository openIddictScopeRepository, + IOpenIddictScopeManager scopeManager, + IPermissionDataSeeder permissionDataSeeder) + : base(configuration, openIddictApplicationRepository, applicationManager, openIddictScopeRepository, scopeManager) + { + PermissionDataSeeder = permissionDataSeeder; + + Logger = NullLogger.Instance; + } + + public async virtual Task SeedAsync(DataSeedContext context) + { + if (context.TenantId.HasValue) + { + return; + } + var scope = "lingyun-abp-application"; + + Logger.LogInformation("Seeding the default scope..."); + await CreateDefaultScopeAsync(); + await CreateApiScopeAsync(scope); + + Logger.LogInformation("Seeding the default applications..."); + await CreateApplicationAsync(scope); + + Logger.LogInformation("Seeding default applications completed."); + } + + private async Task CreateDefaultScopeAsync() + { + // OpenID Connect核心scope - 用于标识这是一个OIDC请求 + await CreateScopesAsync(new OpenIddictScopeDescriptor + { + Name = OpenIddictConstants.Scopes.OpenId, + DisplayName = "OpenID Connect", // 友好的显示名称 + DisplayNames = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "身份认证", + [CultureInfo.GetCultureInfo("en")] = "OpenID Connect" + }, + Description = "使用OpenID Connect协议进行身份验证", + Descriptions = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "允许应用程序使用您的身份信息进行登录", + [CultureInfo.GetCultureInfo("en")] = "Allow the application to authenticate you using OpenID Connect" + } + }); + + // Profile scope - 用户基本信息 + await CreateScopesAsync(new OpenIddictScopeDescriptor + { + Name = OpenIddictConstants.Scopes.Profile, + DisplayName = "个人资料", + DisplayNames = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "个人资料", + [CultureInfo.GetCultureInfo("en")] = "Profile" + }, + Description = "访问您的基本个人资料信息", + Descriptions = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "允许应用程序访问您的姓名、头像等基本信息", + [CultureInfo.GetCultureInfo("en")] = "Allow the application to access your basic profile information like name and picture" + } + }); + + // Email scope + await CreateScopesAsync(new OpenIddictScopeDescriptor + { + Name = OpenIddictConstants.Scopes.Email, + DisplayName = "电子邮件", + DisplayNames = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "电子邮件", + [CultureInfo.GetCultureInfo("en")] = "Email" + }, + Description = "访问您的电子邮件地址", + Descriptions = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "允许应用程序访问您的电子邮件地址", + [CultureInfo.GetCultureInfo("en")] = "Allow the application to access your email address" + } + }); + + // Phone scope + await CreateScopesAsync(new OpenIddictScopeDescriptor + { + Name = OpenIddictConstants.Scopes.Phone, + DisplayName = "电话号码", + DisplayNames = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "电话号码", + [CultureInfo.GetCultureInfo("en")] = "Phone" + }, + Description = "访问您的电话号码", + Descriptions = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "允许应用程序访问您的电话号码", + [CultureInfo.GetCultureInfo("en")] = "Allow the application to access your phone number" + } + }); + + // Address scope + await CreateScopesAsync(new OpenIddictScopeDescriptor + { + Name = OpenIddictConstants.Scopes.Address, + DisplayName = "地址信息", + DisplayNames = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "地址信息", + [CultureInfo.GetCultureInfo("en")] = "Address" + }, + Description = "访问您的地址信息", + Descriptions = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "允许应用程序访问您的地址信息", + [CultureInfo.GetCultureInfo("en")] = "Allow the application to access your address information" + } + }); + + // Roles scope + await CreateScopesAsync(new OpenIddictScopeDescriptor + { + Name = OpenIddictConstants.Scopes.Roles, + DisplayName = "角色信息", + DisplayNames = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "角色信息", + [CultureInfo.GetCultureInfo("en")] = "Roles" + }, + Description = "访问您的角色信息", + Descriptions = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "允许应用程序访问您的角色和权限信息", + [CultureInfo.GetCultureInfo("en")] = "Allow the application to access your roles and permissions" + } + }); + + // Offline Access scope - 用于获取刷新令牌 + await CreateScopesAsync(new OpenIddictScopeDescriptor + { + Name = OpenIddictConstants.Scopes.OfflineAccess, + DisplayName = "离线访问", + DisplayNames = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "离线访问", + [CultureInfo.GetCultureInfo("en")] = "Offline Access" + }, + Description = "在您未登录时访问您的信息", + Descriptions = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "允许应用程序在您未登录时访问您的信息", + [CultureInfo.GetCultureInfo("en")] = "Allow the application to access your information while you are offline" + } + }); + } + + private async Task CreateApiScopeAsync(string scope) + { + await CreateScopesAsync(new OpenIddictScopeDescriptor + { + Name = scope, + DisplayName = "微服务访问授权", + DisplayNames = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "微服务访问授权", + [CultureInfo.GetCultureInfo("en")] = "Single Applications" + }, + Description = "适用于微服务体系的接口授权", + Descriptions = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "允许应用程序使用各微服务模块的接口", + [CultureInfo.GetCultureInfo("en")] = "Allow the application to use the interfaces of each microservice module" + }, + Resources = + { + "api-gateway", + "auth-server", + "admin-service", + "identity-service", + "localization-service", + "message-service", + "platform-service", + "task-service", + "webhook-service", + "wechat-service", + "workflow-service", + } + }); + } + + private async Task CreateApplicationAsync(string scope) + { + var configurationSection = Configuration.GetSection("OpenIddict:Applications"); + var vueClientId = configurationSection["VueAdmin:ClientId"]; + if (!vueClientId.IsNullOrWhiteSpace()) + { + Logger.LogInformation("Seeding application {vueClientId}...", vueClientId); + + var vueClientRootUrls = configurationSection.GetSection("VueAdmin:RootUrls").Get>() ?? []; + + var vueClientRedirectUrls = new List(); + var vueClientPostLogoutRedirectUrls = new List(); + vueClientRootUrls.ForEach(url => + { + vueClientRedirectUrls.Add(url.EnsureEndsWith('/')); + vueClientRedirectUrls.Add(url.EnsureEndsWith('/') + "signin-callback"); + + vueClientPostLogoutRedirectUrls.Add(url.EnsureEndsWith('/')); + vueClientPostLogoutRedirectUrls.Add(url.EnsureEndsWith('/') + "signout-callback"); + }); + + await CreateOrUpdateApplicationAsync( + OpenIddictConstants.ApplicationTypes.Web, + vueClientId, + OpenIddictConstants.ClientTypes.Confidential, + OpenIddictConstants.ConsentTypes.Explicit, + "Abp Vue Admin Client", + configurationSection["VueAdmin:ClientSecret"] ?? "1q2w3e*", + [OpenIddictConstants.GrantTypes.AuthorizationCode, + OpenIddictConstants.GrantTypes.Implicit, + OpenIddictConstants.GrantTypes.Password, + OpenIddictConstants.GrantTypes.RefreshToken], + [OpenIddictConstants.Scopes.OpenId, + OpenIddictConstants.Scopes.Email, + OpenIddictConstants.Scopes.Roles, + OpenIddictConstants.Scopes.Address, + OpenIddictConstants.Scopes.Phone, + OpenIddictConstants.Scopes.Profile, + OpenIddictConstants.Scopes.OfflineAccess, + scope], + vueClientRedirectUrls, + vueClientPostLogoutRedirectUrls); + + var vueClientPermissions = new string[1] + { + "AbpIdentity.UserLookup" + }; + await PermissionDataSeeder.SeedAsync(ClientPermissionValueProvider.ProviderName, vueClientId, vueClientPermissions); + } + + var internalServiceClientId = configurationSection["InternalService:ClientId"]; + if (!internalServiceClientId.IsNullOrWhiteSpace()) + { + Logger.LogInformation("Seeding application {internalServiceClientId}...", internalServiceClientId); + + await CreateOrUpdateApplicationAsync( + OpenIddictConstants.ApplicationTypes.Native, + internalServiceClientId, + OpenIddictConstants.ClientTypes.Confidential, + OpenIddictConstants.ConsentTypes.Explicit, + "Abp Internal Service Client", + configurationSection["InternalService:ClientSecret"] ?? "1q2w3e*", + [OpenIddictConstants.GrantTypes.ClientCredentials], + [OpenIddictConstants.ResponseTypes.Token, scope]); + } + + var oauthClientId = configurationSection["VueOAuthClient:ClientId"]; + if (!oauthClientId.IsNullOrWhiteSpace()) + { + Logger.LogInformation("Seeding application {oauthClientId}...", oauthClientId); + + var oauthClientRootUrls = configurationSection.GetSection("VueOAuthClient:RootUrls").Get>() ?? []; + + var oauthClientRedirectUrls = new List(); + var oauthClientPostLogoutRedirectUrls = new List(); + oauthClientRootUrls.ForEach(url => + { + oauthClientRedirectUrls.Add(url.EnsureEndsWith('/')); + oauthClientRedirectUrls.Add(url.EnsureEndsWith('/') + "signin-callback"); + oauthClientRedirectUrls.Add(url.EnsureEndsWith('/') + "swagger/oauth2-redirect.html"); + + oauthClientPostLogoutRedirectUrls.Add(url.EnsureEndsWith('/')); + oauthClientPostLogoutRedirectUrls.Add(url.EnsureEndsWith('/') + "signout-callback"); + }); + + await CreateOrUpdateApplicationAsync( + OpenIddictConstants.ApplicationTypes.Web, + oauthClientId, + OpenIddictConstants.ClientTypes.Public, + OpenIddictConstants.ConsentTypes.Implicit, + "Abp OAuth Client", + null, + [OpenIddictConstants.GrantTypes.AuthorizationCode, + OpenIddictConstants.GrantTypes.RefreshToken], + [OpenIddictConstants.Scopes.OpenId, + OpenIddictConstants.Scopes.Email, + OpenIddictConstants.Scopes.Roles, + OpenIddictConstants.Scopes.Address, + OpenIddictConstants.Scopes.Phone, + OpenIddictConstants.Scopes.Profile, + OpenIddictConstants.Scopes.OfflineAccess, + scope], + oauthClientRedirectUrls, + oauthClientPostLogoutRedirectUrls); + + var oauthClientPermissions = new string[1] + { + "AbpIdentity.UserLookup" + }; + await PermissionDataSeeder.SeedAsync(ClientPermissionValueProvider.ProviderName, oauthClientId, oauthClientPermissions); + } + } +} diff --git a/aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore/DataSeeder/IdentityClaimTypeDataSeedContributor.cs b/aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore/DataSeeder/IdentityClaimTypeDataSeedContributor.cs new file mode 100644 index 000000000..e3b348dfd --- /dev/null +++ b/aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore/DataSeeder/IdentityClaimTypeDataSeedContributor.cs @@ -0,0 +1,89 @@ +using JetBrains.Annotations; +using Microsoft.Extensions.Logging; +using OpenIddict.Abstractions; +using System.Threading.Tasks; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Guids; +using Volo.Abp.Identity; + +namespace LY.MicroService.Applications.Single.EntityFrameworkCore.DataSeeder; +public class IdentityClaimTypeDataSeedContributor : IDataSeedContributor, ITransientDependency +{ + public ILogger Logger { protected get; set; } + + protected IGuidGenerator GuidGenerator { get; } + protected IdentityClaimTypeManager IdentityClaimTypeManager { get; } + protected IIdentityClaimTypeRepository IdentityClaimTypeRepository { get; } + public IdentityClaimTypeDataSeedContributor( + IGuidGenerator guidGenerator, + IdentityClaimTypeManager identityClaimTypeManager, + IIdentityClaimTypeRepository identityClaimTypeRepository) + { + GuidGenerator = guidGenerator; + IdentityClaimTypeManager = identityClaimTypeManager; + IdentityClaimTypeRepository = identityClaimTypeRepository; + } + + public async virtual Task SeedAsync(DataSeedContext context) + { + if (context.TenantId.HasValue) + { + return; + } + + Logger.LogInformation("Seeding the default identity claim types..."); + + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Address); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Birthdate, valueType: IdentityClaimValueType.DateTime); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Country); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Email); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.EmailVerified, valueType: IdentityClaimValueType.Boolean); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.FamilyName); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Gender); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.GivenName); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Locale); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Locality); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.MiddleName); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Name); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Nickname); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.PhoneNumber); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.PhoneNumberVerified, valueType: IdentityClaimValueType.Boolean); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Picture); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.PostalCode); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.PreferredUsername); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Profile); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Region); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Role); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.StreetAddress); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Username); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Website); + await CreateIdentityClaimTypeAsync(OpenIddictConstants.Claims.Zoneinfo); + + Logger.LogInformation("Seeding default identity claim types completed."); + } + + private async Task CreateIdentityClaimTypeAsync( + [NotNull] string name, + bool required = false, + bool isStatic = false, + [CanBeNull] string regex = null, + [CanBeNull] string regexDescription = null, + [CanBeNull] string description = null, + IdentityClaimValueType valueType = IdentityClaimValueType.String) + { + if (!await IdentityClaimTypeRepository.AnyAsync(name)) + { + await IdentityClaimTypeManager.CreateAsync( + new IdentityClaimType( + GuidGenerator.Create(), + name, + required, + isStatic, + regex, + regexDescription, + description, + valueType)); + } + } +} diff --git a/aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore/DataSeeder/IdentityDataSeedContributor.cs b/aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore/DataSeeder/IdentityDataSeedContributor.cs index 7ef4134a7..c25d00c44 100644 --- a/aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore/DataSeeder/IdentityDataSeedContributor.cs +++ b/aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore/DataSeeder/IdentityDataSeedContributor.cs @@ -48,6 +48,8 @@ public class IdentityDataSeedContributor : IDataSeedContributor, ITransientDepen IsStatic = true, }); } + + Logger.LogInformation("Seeding default role Users completed."); } } } diff --git a/aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore/DataSeeder/OpenIddictDataSeederContributor.cs b/aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore/DataSeeder/OpenIddictDataSeederContributor.cs index d8922d0a4..9b30eefd8 100644 --- a/aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore/DataSeeder/OpenIddictDataSeederContributor.cs +++ b/aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore/DataSeeder/OpenIddictDataSeederContributor.cs @@ -18,7 +18,6 @@ namespace LY.MicroService.Applications.Single.EntityFrameworkCore.DataSeeder; public class OpenIddictDataSeederContributor : OpenIddictDataSeedContributorBase, IDataSeedContributor, ITransientDependency { public ILogger Logger { protected get; set; } - protected IPermissionDataSeeder PermissionDataSeeder { get; } public OpenIddictDataSeederContributor( IConfiguration configuration, @@ -36,29 +35,172 @@ public class OpenIddictDataSeederContributor : OpenIddictDataSeedContributorBase public async virtual Task SeedAsync(DataSeedContext context) { + if (context.TenantId.HasValue) + { + return; + } var scope = "lingyun-abp-application"; Logger.LogInformation("Seeding the default scope..."); - await CreateScopeAsync(scope); + await CreateDefaultScopeAsync(); + await CreateApiScopeAsync(scope, "all_in_one"); Logger.LogInformation("Seeding the default applications..."); await CreateApplicationAsync(scope); + + Logger.LogInformation("Seeding default applications completed."); } - private async Task CreateScopeAsync(string scope) + private async Task CreateDefaultScopeAsync() + { + // OpenID Connect核心scope - 用于标识这是一个OIDC请求 + await CreateScopesAsync(new OpenIddictScopeDescriptor + { + Name = OpenIddictConstants.Scopes.OpenId, + DisplayName = "OpenID Connect", // 友好的显示名称 + DisplayNames = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "身份认证", + [CultureInfo.GetCultureInfo("en")] = "OpenID Connect" + }, + Description = "使用OpenID Connect协议进行身份验证", + Descriptions = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "允许应用程序使用您的身份信息进行登录", + [CultureInfo.GetCultureInfo("en")] = "Allow the application to authenticate you using OpenID Connect" + } + }); + + // Profile scope - 用户基本信息 + await CreateScopesAsync(new OpenIddictScopeDescriptor + { + Name = OpenIddictConstants.Scopes.Profile, + DisplayName = "个人资料", + DisplayNames = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "个人资料", + [CultureInfo.GetCultureInfo("en")] = "Profile" + }, + Description = "访问您的基本个人资料信息", + Descriptions = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "允许应用程序访问您的姓名、头像等基本信息", + [CultureInfo.GetCultureInfo("en")] = "Allow the application to access your basic profile information like name and picture" + } + }); + + // Email scope + await CreateScopesAsync(new OpenIddictScopeDescriptor + { + Name = OpenIddictConstants.Scopes.Email, + DisplayName = "电子邮件", + DisplayNames = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "电子邮件", + [CultureInfo.GetCultureInfo("en")] = "Email" + }, + Description = "访问您的电子邮件地址", + Descriptions = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "允许应用程序访问您的电子邮件地址", + [CultureInfo.GetCultureInfo("en")] = "Allow the application to access your email address" + } + }); + + // Phone scope + await CreateScopesAsync(new OpenIddictScopeDescriptor + { + Name = OpenIddictConstants.Scopes.Phone, + DisplayName = "电话号码", + DisplayNames = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "电话号码", + [CultureInfo.GetCultureInfo("en")] = "Phone" + }, + Description = "访问您的电话号码", + Descriptions = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "允许应用程序访问您的电话号码", + [CultureInfo.GetCultureInfo("en")] = "Allow the application to access your phone number" + } + }); + + // Address scope + await CreateScopesAsync(new OpenIddictScopeDescriptor + { + Name = OpenIddictConstants.Scopes.Address, + DisplayName = "地址信息", + DisplayNames = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "地址信息", + [CultureInfo.GetCultureInfo("en")] = "Address" + }, + Description = "访问您的地址信息", + Descriptions = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "允许应用程序访问您的地址信息", + [CultureInfo.GetCultureInfo("en")] = "Allow the application to access your address information" + } + }); + + // Roles scope + await CreateScopesAsync(new OpenIddictScopeDescriptor + { + Name = OpenIddictConstants.Scopes.Roles, + DisplayName = "角色信息", + DisplayNames = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "角色信息", + [CultureInfo.GetCultureInfo("en")] = "Roles" + }, + Description = "访问您的角色信息", + Descriptions = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "允许应用程序访问您的角色和权限信息", + [CultureInfo.GetCultureInfo("en")] = "Allow the application to access your roles and permissions" + } + }); + + // Offline Access scope - 用于获取刷新令牌 + await CreateScopesAsync(new OpenIddictScopeDescriptor + { + Name = OpenIddictConstants.Scopes.OfflineAccess, + DisplayName = "离线访问", + DisplayNames = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "离线访问", + [CultureInfo.GetCultureInfo("en")] = "Offline Access" + }, + Description = "在您未登录时访问您的信息", + Descriptions = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "允许应用程序在您未登录时访问您的信息", + [CultureInfo.GetCultureInfo("en")] = "Allow the application to access your information while you are offline" + } + }); + } + + private async Task CreateApiScopeAsync(string scope, string apiResource) { await CreateScopesAsync(new OpenIddictScopeDescriptor { Name = scope, - DisplayName = scope + " access", + DisplayName = "Single Applications", DisplayNames = { - [CultureInfo.GetCultureInfo("zh-Hans")] = "Abp API 应用程序访问", - [CultureInfo.GetCultureInfo("en")] = "Abp API Application Access" + [CultureInfo.GetCultureInfo("zh-Hans")] = "单体应用程序", + [CultureInfo.GetCultureInfo("en")] = "Single Applications" + }, + Description = "适用于单体应用程序的接口授权", + Descriptions = + { + [CultureInfo.GetCultureInfo("zh-Hans")] = "允许应用程序使用单体应用程序的接口", + [CultureInfo.GetCultureInfo("en")] = "Allow applications to use the interface of monolithic applications" }, Resources = { - scope + apiResource, + "http://localhost:30000", } }); } diff --git a/aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore/DataSeeder/RolePermissionDataSeedContributor.cs b/aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore/DataSeeder/RolePermissionDataSeedContributor.cs index ce365bda4..ef4bbc1c5 100644 --- a/aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore/DataSeeder/RolePermissionDataSeedContributor.cs +++ b/aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore/DataSeeder/RolePermissionDataSeedContributor.cs @@ -48,6 +48,8 @@ public class RolePermissionDataSeedContributor : IDataSeedContributor, ITransien "Users", new string[] { "Platform.Feedback.Create" }, context.TenantId); + + Logger.LogInformation("Seeding new tenant admin role permissions completed."); } } }