using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using IdentityServer4.EntityFramework.DbContexts; using IdentityServer4.EntityFramework.Mappers; using Microsoft.AspNetCore.Builder; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using xCommons.Extensions; using xIdentityModels.Descriptors; using xIdentityModels.Extensions; using xIds.Constants; using xIds.Interfaces; using xIds.Models; namespace xIds.Extensions { public static class XDbSeeder { /// /// Retrieve DbSeedDescriptor from appSetting Configuration /// /// /// public static XDbSeedDescriptor GetXDbSeedDescriptor(this IConfiguration configuration) { // var dbSeedSection = configuration.GetSection(ConfigurationNodeNames.DB_SEED_NODE_NAME); return dbSeedSection.Get(); } /// /// Register XDbSeedDescriptor as Singleton Service /// /// /// public static void AddXDebSeederDescriptor( this IServiceCollection services, IConfiguration configuration ) { // var dbSeedDescriptor = configuration.GetXDbSeedDescriptor(); if (!dbSeedDescriptor.IsNull()) { services.AddSingleton(dbSeedDescriptor); } else { Console.WriteLine("Error: DbSeeder Configuration not found in AppSetting ..."); } } /// /// Add Base Required Data to XIdentitySer DbContexts /// /// /// /// public static async Task SeedData( this IApplicationBuilder app, ILogger logger ) { // logger.LogInformation($"Start Add/Update XIdentityServer Descriptors ..."); // // Create Scope ... using (var scope = app.ApplicationServices.CreateScope()) { // // Retrieve Required Configurations ... var dbSeedDescriptor = scope.ServiceProvider.GetService(); if (dbSeedDescriptor.IsNull()) { // Console.WriteLine("DbSeeder is Null ..."); return; } logger.LogInformation($"Update Exists Descriptors: {dbSeedDescriptor.UpdateExists.ToString()}"); // // Retrieve Required Services ... var identityProvider = scope.ServiceProvider.GetService(); // // Retrieve DbContexts ... var grantDbContext = scope.ServiceProvider.GetService(); var configDbContext = scope.ServiceProvider.GetService(); // #region Clients ... // logger.LogInformation($"Start Seeding Clients ..."); // var dClients = dbSeedDescriptor.Clients; var hasClient = configDbContext.Clients.Any(); if ((!hasClient || (hasClient && dbSeedDescriptor.UpdateExists)) && dClients.HasChild()) { // var clientEntities = dClients.Select(dc => dc.ToEntity()); // foreach (var client in clientEntities) { // logger.LogInformation($"Add/Update: {client.ClientId}"); // // Retrieve Exists Client ... var existsClient = configDbContext.Clients .Include(c => c.AllowedCorsOrigins) .Include(c => c.AllowedGrantTypes) .Include(c => c.AllowedScopes) .Include(c => c.Claims) .Include(c => c.ClientSecrets) .FirstOrDefault(cl => cl.ClientId == client.ClientId); // var isExistsClient = !existsClient.IsNull(); var isSameContent = isExistsClient && existsClient.IsSameContent(client, propertyBlackList: new[] { nameof(existsClient.Id) }); // if (isExistsClient) { // if (!isSameContent) { // logger.LogInformation($"Update Client: {existsClient.ClientId}"); // existsClient = existsClient.UpdateData(client, propertyBlackList: new[] { nameof(existsClient.Id) }); configDbContext.Clients.Update(existsClient); } } else { // logger.LogInformation($"Add Client: {client.ClientId}"); // await configDbContext.Clients.AddAsync(client); } } // // Save Changes on Config Db Context ... await configDbContext.SaveChangesAsync(); } // logger.LogInformation($"Finish Seeding Clients ..."); #endregion // #region IdentityResources ... // logger.LogInformation($"Start Seeding Identity Resources ..."); // var dIdentityResources = dbSeedDescriptor.IdentityResources; var hasIdentityResources = configDbContext.IdentityResources.Any(); if ((!hasIdentityResources || (hasIdentityResources && dbSeedDescriptor.UpdateExists)) && dIdentityResources.HasChild()) { // var identityResourceEntities = dIdentityResources.Select(di => di.ToEntity()); // foreach (var identityResource in identityResourceEntities) { // logger.LogInformation($"Add/Update: {identityResource.DisplayName}"); // // Retrieve Exists IdentityResource ... var existsIdentityResource = configDbContext.IdentityResources .AsNoTracking() .FirstOrDefault(ir => ir.Name == identityResource.Name); // var isExistsResource = !existsIdentityResource.IsNull(); var isSameContent = isExistsResource && existsIdentityResource.IsSameContent(identityResource, propertyBlackList: new[] { nameof(existsIdentityResource.Id) }); // if (isExistsResource && dbSeedDescriptor.UpdateExists) { // if (!isSameContent) { // logger.LogInformation($"Update IdentityResource: {identityResource.DisplayName}"); // existsIdentityResource = existsIdentityResource.UpdateData(identityResource, propertyBlackList: new[] { nameof(existsIdentityResource.Id) }); configDbContext.IdentityResources.Update(existsIdentityResource); } } else { // logger.LogInformation($"Add IdentityResource: {identityResource.DisplayName}"); // await configDbContext.IdentityResources.AddAsync(identityResource); } } // // Save Changes on Config Db Context ... // await configDbContext.SaveChangesAsync(); } // logger.LogInformation($"Finish Seeding Identity Resources ..."); #endregion // #region Api Resources ... // logger.LogInformation($"Start Seeding Api Resources ..."); // var dApiResources = dbSeedDescriptor.ApiResources; var hasApiResources = configDbContext.ApiResources.Any(); if ((!hasApiResources || (hasApiResources && dbSeedDescriptor.UpdateExists)) && dApiResources.HasChild()) { // var apiResourceEntities = dApiResources.Select(da => da.ToEntity()); // foreach (var apiResource in apiResourceEntities) { // logger.LogInformation($"Add/Update: {apiResource.DisplayName}"); // // Retrieve Exists ApiResource ... var existsApiResource = configDbContext.ApiResources .Include(r => r.Secrets) .Include(r => r.Scopes) .FirstOrDefault(ar => ar.Name == apiResource.Name); // var isExistsResource = !existsApiResource.IsNull(); var isSameContent = isExistsResource && existsApiResource.IsSameContent(apiResource, propertyBlackList: new[] { nameof(existsApiResource.Id) }); // if (isExistsResource && dbSeedDescriptor.UpdateExists) { // if (!isSameContent) { // logger.LogInformation($"Update ApiResource: {existsApiResource.DisplayName}"); // existsApiResource = existsApiResource.UpdateData(apiResource, propertyBlackList: new[] { nameof(existsApiResource.Id) }); configDbContext.ApiResources.Update(existsApiResource); } } else { // logger.LogInformation($"Add ApiResource: {apiResource.DisplayName}"); // await configDbContext.ApiResources.AddAsync(apiResource); } } // // Save Changes on Config Db Context ... // await configDbContext.SaveChangesAsync(); } // logger.LogInformation($"Finish Seeding Api Resources ..."); #endregion // #region Api Scopes ... // logger.LogInformation($"Start Seeding Scopes ..."); // var dScopes = dbSeedDescriptor.ApiScopes; var hasScope = configDbContext.ApiScopes.Any(); if ((!hasScope || (hasScope && dbSeedDescriptor.UpdateExists)) && dScopes.HasChild()) { // var apiScopeEntities = dScopes.Select(dc => dc.ToEntity()); // foreach (var apiScope in apiScopeEntities) { // logger.LogInformation($"Add/Update: {apiScope.DisplayName}"); // // Retrieve Exists Client ... var existsScope = configDbContext.ApiScopes .FirstOrDefault(sc => sc.Name == apiScope.Name); // var isExistsScope = !existsScope.IsNull(); var isSameContent = isExistsScope && existsScope.IsSameContent(apiScope, propertyBlackList: new[] { nameof(existsScope.Id) }); // if (isExistsScope && dbSeedDescriptor.UpdateExists) { // if (!isSameContent) { // logger.LogInformation($"Update ApiScope: {existsScope.Name}"); // existsScope = existsScope.UpdateData(apiScope, propertyBlackList: new[] { nameof(existsScope.Id) }); configDbContext.ApiScopes.Update(existsScope); } } else { // logger.LogInformation($"Add ApiScope: {apiScope.Name}"); // await configDbContext.ApiScopes.AddAsync(apiScope); } } // // Save Changes on Config Db Context ... await configDbContext.SaveChangesAsync(); } // logger.LogInformation($"Finish Seeding Scopes ..."); #endregion // #region Users ... // logger.LogInformation($"Start Seeding Users ..."); // var configUsers = dbSeedDescriptor.Users; var hasUser = identityProvider.GetUsersDbSet().Any(); if ((!hasUser || (hasUser && dbSeedDescriptor.UpdateExists)) && configUsers.HasChild()) { foreach (var user in configUsers) { // logger.LogInformation($"Add/Update User: {user.UserName}"); // var isUserExists = await identityProvider.IsUserExistsAsync(user.UserName); if (isUserExists && dbSeedDescriptor.UpdateExists) { // var existsUser = await identityProvider.GetUserAsync(user.UserName); var isSame = existsUser.IsSameAs(user); if (!isSame) { // // Update Entity ... existsUser = existsUser.UpdateData(user, propertyWhiteList: new[] { nameof (XIdentityUserDescriptor.FirstName), nameof (XIdentityUserDescriptor.LastName), nameof (XIdentityUserDescriptor.UserName), nameof (XIdentityUserDescriptor.Email), nameof (XIdentityUserDescriptor.EmailConfirmed), nameof (XIdentityUserDescriptor.PhoneNumber), nameof (XIdentityUserDescriptor.PhoneNumberConfirmed), nameof (XIdentityUserDescriptor.IsEnable), nameof (XIdentityUserDescriptor.IsBanned), nameof (XIdentityUserDescriptor.DateOfBirth) }, propertyValueProviders: new[] { new KeyValuePair> ( nameof (XIdentityUserDescriptor.DateOfBirth), (user) => DateTime.Parse (user.DateOfBirth)) }); // await identityProvider.UpdateUserAsync(existsUser, false, false); } } else { await identityProvider.CreateUserAsync(user); } } } // logger.LogInformation($"Finish Seeding Users ..."); #endregion } // logger.LogInformation($"Finish Add/Update XIdentityServer Descriptors ..."); } } }