Initial ...

This commit is contained in:
2026-03-22 14:08:25 +03:30
commit d3464ef39c
71 changed files with 19087 additions and 0 deletions
+168
View File
@@ -0,0 +1,168 @@
using System;
using System.Reflection;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using MySql.EntityFrameworkCore.Infrastructure;
using xCommons.Extensions;
using xIdentityModels.Configurations;
using xIds.Configurations;
using xIds.Constants;
using xIds.Models;
namespace xIds.Extensions
{
public static class DbExtensions
{
/// <summary>
/// Retrieve Data Provider Type from Configurations
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static XDbProviders GetXDbProviderType(this IConfiguration source)
{
//
var dbProvider = (source[$"{ConfigurationNodeNames.PROVIDER_NODE_NAME}"])
.ToNormalString();
//
return dbProvider == ProviderType.SQLServer.ToNormalString() ?
XDbProviders.SQLServer :
dbProvider == ProviderType.SQLite.ToNormalString() ?
XDbProviders.SQLite :
dbProvider == ProviderType.MySQL.ToNormalString() ?
XDbProviders.MySQL :
XDbProviders.None;
}
/// <summary>
/// Retrieve AspNet Identity Configurations
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static XIdentityConfiguration GetXIdentityConfiguration(this IConfiguration source)
{
//
var xIdentityConfigSection = source
.GetSection(ConfigurationNodeNames.IDENTITY_NODE_NAME);
return xIdentityConfigSection.Get<XIdentityConfiguration>();
}
/// <summary>
/// Retrieve XIdentityResource Configuration from AppSettings
/// </summary>
/// <param name="configuration"></param>
/// <returns></returns>
public static XIdentityResourceConfiguration GetXIdentityResourceConfiguration(this IConfiguration configuration)
{
//
var xIdentityResourceSection = configuration.GetSection(ConfigurationNodeNames.IDENTITY_RESOURCE_NODE_NAME);
return xIdentityResourceSection.Get<XIdentityResourceConfiguration>();
}
/// <summary>
/// Register XIdentityResourceConfiguration
/// </summary>
/// <param name="services"></param>
/// <param name="configuration"></param>
public static void AddXIdentityResourceConfiguration(
this IServiceCollection services,
IConfiguration configuration
)
{
//
var xIdentityResourceConfiguration = configuration.GetXIdentityResourceConfiguration();
if (!xIdentityResourceConfiguration.IsNull())
{
services.AddSingleton<XIdentityResourceConfiguration>(xIdentityResourceConfiguration);
}
}
/// <summary>
/// Converts DbInfo Options Builder for MySql Usage
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static Action<MySQLDbContextOptionsBuilder> GetMySqlOptionsBuilder(this XDbInfo source)
{
return ((Action<MySQLDbContextOptionsBuilder>)source.OptionsBuilder);
}
/// <summary>
/// Converts DbInfo Options Builder for SQLite Usage
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static Action<SqliteDbContextOptionsBuilder> GetSQLiteOptionsBuilder(this XDbInfo source)
{
return ((Action<SqliteDbContextOptionsBuilder>)source.OptionsBuilder);
}
/// <summary>
/// Converts DbInfo Options Builder for SQLServer Usage
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static Action<SqlServerDbContextOptionsBuilder> GetSQLServerOptionsBuilder(this XDbInfo source)
{
return ((Action<SqlServerDbContextOptionsBuilder>)source.OptionsBuilder);
}
/// <summary>
/// Retrieve Required Informations to Register DbContexts into Di as XDbInfo instance
/// </summary>
/// <param name="configuration"></param>
/// <returns></returns>
public static XDbInfo GetXDbInfo(this IConfiguration configuration)
{
return new XDbInfo
{
ProviderType = configuration.GetXDbProviderType(),
MigrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name
};
}
/// <summary>
/// Prepare DbContextOptionsBuilder with Propper data to Support Configured DbProvider
/// </summary>
/// <param name="source"></param>
/// <param name="dbInfo"></param>
/// <param name="connectionString"></param>
public static void PrepareXDbContextOptionsBuilder(
this DbContextOptionsBuilder source,
XDbInfo dbInfo,
string connectionString
)
{
//
if (dbInfo.ProviderType == XDbProviders.MySQL)
{
//
// Add Support for MySql ...
source.UseMySQL(
connectionString,
dbInfo.GetMySqlOptionsBuilder()
);
}
else if (dbInfo.ProviderType == XDbProviders.SQLite)
{
//
// Add Support for SQLite ...
source.UseSqlite(
connectionString,
dbInfo.GetSQLiteOptionsBuilder()
);
}
else if (dbInfo.ProviderType == XDbProviders.SQLServer)
{
//
// Add Support for SQLServer ...
source.UseSqlServer(
connectionString,
dbInfo.GetSQLServerOptionsBuilder()
);
}
}
}
}
@@ -0,0 +1,117 @@
using System.Reflection;
using System.Security.Cryptography.X509Certificates;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using xCommons.Extensions;
using xCommons.Models;
using xIds.Constants;
namespace xIds.Extensions
{
public static class IIdentityServerBuilderExtensions
{
/// <summary>
/// Add Support for Configured XDbProvider to IdentityServer
/// </summary>
/// <param name="source"></param>
/// <param name="configuration"></param>
/// <returns></returns>
public static IIdentityServerBuilder AddXDbProvider(
this IIdentityServerBuilder source,
IConfiguration configuration
)
{
//
// Retrieve DB Info ...
var dbInfo = configuration.GetXDbInfo();
dbInfo.OptionsBuilder = (optionsBuilder) =>
{
optionsBuilder.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
optionsBuilder.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery);
};
//
// Retrieve Connection String Names ...
var identityDbConnectionString = configuration.GetConnectionString(ConnectionStringNames.IDENTITY_CONNECTION_NAME);
var configDbConnectionString = configuration.GetConnectionString(ConnectionStringNames.CONFIGURATION_CONNECTION_NAME);
var persistedGrantDbConnectionString = configuration.GetConnectionString(ConnectionStringNames.PRESISTED_GRANTS_CONNECTION_NAME);
//
// Add Operational Store ...
source.AddOperationalStore(opt =>
{
opt.ConfigureDbContext =
builder =>
{
//
builder.PrepareXDbContextOptionsBuilder(
dbInfo,
persistedGrantDbConnectionString
);
//
builder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
};
//
// this enables automatic token cleanup. this is optional.
opt.EnableTokenCleanup = true;
opt.TokenCleanupInterval = 3600;
});
//
// Add Configuration Store ...
source.AddConfigurationStore(opt =>
{
opt.ConfigureDbContext =
builder =>
{
//
builder.PrepareXDbContextOptionsBuilder(
dbInfo,
configDbConnectionString
);
};
});
//
return source;
}
/// <summary>
/// Set Configured Certificate File to IdentityServer
/// </summary>
/// <param name="builder"></param>
/// <param name="certificate"></param>
/// <returns></returns>
public static IIdentityServerBuilder LoadSigningCredentialFrom(
this IIdentityServerBuilder builder,
XCertificate certificate
)
{
//
if (!certificate.IsNull() &&
!certificate.Path.IsNullOrEmpty() &&
!certificate.Secret.IsNullOrEmpty()
)
{
try
{
builder.AddSigningCredential(new X509Certificate2(certificate.Path, certificate.Secret));
}
catch
{
builder.AddDeveloperSigningCredential();
}
}
else
{
builder.AddDeveloperSigningCredential();
}
//
return builder;
}
}
}
+18
View File
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using xCommons.Extensions;
using xExceptions.Constants;
using xModels.Base;
using xIds.Constants;
namespace xIds.Extensions
{
public static class IQueryableExtensions
{
}
}
+29
View File
@@ -0,0 +1,29 @@
using Microsoft.Extensions.DependencyInjection;
using xIds.Interfaces;
using xIds.Providers;
namespace xIds.Extensions
{
public static class IdentityExtensions
{
/// <summary>
/// Register IdentityManager
/// </summary>
/// <param name="source"></param>
public static void AddXIdentityManager(this IServiceCollection source)
{
source.AddScoped<IXIdentityManager, XIdentityManager>();
}
/// <summary>
/// Register IdentityMessage Provider
/// </summary>
/// <param name="source"></param>
public static void AddXIdentityMessageProvider(
this IServiceCollection source
)
{
source.AddScoped<IXIdentityMessageProvider, XIdentityMessageProvider>();
}
}
}
+428
View File
@@ -0,0 +1,428 @@
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
{
/// <summary>
/// Retrieve DbSeedDescriptor from appSetting Configuration
/// </summary>
/// <param name="configuration"></param>
/// <returns></returns>
public static XDbSeedDescriptor GetXDbSeedDescriptor(this IConfiguration configuration)
{
//
var dbSeedSection = configuration.GetSection(ConfigurationNodeNames.DB_SEED_NODE_NAME);
return dbSeedSection.Get<XDbSeedDescriptor>();
}
/// <summary>
/// Register XDbSeedDescriptor as Singleton Service
/// </summary>
/// <param name="services"></param>
/// <param name="configuration"></param>
public static void AddXDebSeederDescriptor(
this IServiceCollection services,
IConfiguration configuration
)
{
//
var dbSeedDescriptor = configuration.GetXDbSeedDescriptor();
if (!dbSeedDescriptor.IsNull())
{
services.AddSingleton<XDbSeedDescriptor>(dbSeedDescriptor);
}
else
{
Console.WriteLine("Error: DbSeeder Configuration not found in AppSetting ...");
}
}
/// <summary>
/// Add Base Required Data to XIdentitySer DbContexts
/// </summary>
/// <param name="app"></param>
/// <param name="logger"></param>
/// <returns></returns>
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<XDbSeedDescriptor>();
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<IXIdentityManager>();
//
// Retrieve DbContexts ...
var grantDbContext = scope.ServiceProvider.GetService<PersistedGrantDbContext>();
var configDbContext = scope.ServiceProvider.GetService<ConfigurationDbContext>();
//
#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<string, Func<XIdentityUserDescriptor, object>> (
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 ...");
}
}
}
+91
View File
@@ -0,0 +1,91 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using xCommons.Extensions;
using xDataService.Configuration;
using xIdentityModels.Models;
namespace xIds.Extensions
{
public static class XModelExtensions
{
/// <summary>
/// Determine a banned time is passed or not
/// </summary>
/// <param name="source"></param>
/// <param name="delaySeconds"></param>
/// <returns></returns>
public static bool IsDelayTimePassed(
this XBannedDevice source,
int delaySeconds
)
{
//
var passedTime = source.BannedOn.AddSeconds(delaySeconds);
//
var result = DateTime.UtcNow >= passedTime;
//
return result;
}
/// <summary>
/// Applying Filter to IQueryable
/// /// </summary>
/// <typeparam name="T"></typeparam>
public static async Task<IQueryable<T>> ApplyFilterAsync<T>(
this IQueryable<T> source,
string filter
) where T : class
{
//
// Apply Filter ...
if (!filter.IsNullOrEmpty())
{
//
var items = source.AsAsyncEnumerable();
var filteredItems = new List<T>();
await
foreach (var item in items)
{
//
if (item.GetPropValues()
.ToNormalString()
.Contains(filter
.ToNormalString()))
{
//
filteredItems.Add(item);
}
}
//
return filteredItems.AsQueryable();
}
//
return source;
}
public static XDataServiceConfiguration ToXDataServiceConfig(this Configurations.XDataServiceConfiguration config)
{
//
var result = new XDataServiceConfiguration();
//
if (!config.IsNullOrDefault())
{
//
result.PagingConfiguration.DefaultPageSize = config.PagingConfiguration.DefaultPageSize;
result.PagingConfiguration.MaxAvailablePageSize = config.PagingConfiguration.MaxAvailablePageSize;
result.PagingConfiguration.MinAvailablePageSize = config.PagingConfiguration.MinAvailablePageSize;
}
//
return result;
}
}
}