### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Program.cs using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Hosting; namespace xIds { public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); }); } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Startup.cs using System; using System.IO; using System.Reflection; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using xCommons.Configurations; using xCommons.Extensions; using xStorageService.DI; using xIds.Constants; using xIds.DI; using xIds.Interfaces; using xIds.Providers; namespace xIds { public class Startup { public IConfiguration Configuration { get; } public Startup(IConfiguration configuration) { Configuration = configuration; } public void ConfigureServices(IServiceCollection services) { // // Register Validation Provider and all XCommons Module Services ... services.AddXCommons(); // // Register App Configuration ... services.AddXAppConfiguration(Configuration); var appConfiguration = services.GetRegisteredService(); // // Register XDataService Configuration ... services.AddXDataServiceConfiguration(Configuration, ConnectionStringNames.IDENTITY_CONNECTION_NAME); // // Register Allowed Origins ... services.AddXCors(appConfiguration.AllowedOrigins); // // Register Swagger ... var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); services.AddXSwagger(Configuration, xmlFilePath: xmlPath); // // Register IdentityServer to DI ... // services.AddInMemoryXIdentityServer (Configuration); services.AddEfSupportXIdentityServer(Configuration); // services.AddControllers() .AddNewtonsoftJson(x => x.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore); // // Register Authentication ... services.AddXIdentityServerAuthentication(Configuration); // // Register Authorization ... services.AddXAuthorization(); // // Register Security Provider ... services.AddSingleton(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger logger) { // if (env.IsDevelopment()) { // app.UseDeveloperExceptionPage(); // // app.UseXRequestLogger(); } // // Use Swagger Middleware ... app.UseXSwagger(); // app.UseHttpsRedirection(); app.UseXForwardOptions(); // // Using Cors ... app.UseXCors(); // // Force App to Use IdentityServer ... app.UseXIdentityServer(logger); // // Force app to Use Storage Service ... app.UseXStorageService(); // app.UseRouting(); // app.UseAuthentication(); app.UseAuthorization(); // app.UseEndpoints(endpoints => { endpoints.MapDefaultControllerRoute(); }); } } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Configurations\CertificatesConfigurations.cs namespace xIds.Configurations { public class CertificatesConfigurations { public struct CertificateNames { public const string IdentityServerSigning = "IdentityServerSigning"; } } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Configurations\XDataServiceConfiguration.cs using xIds.Constants; namespace xIds.Configurations { /// /// Represent Configurations of DataService Module ... /// public partial class XDataServiceConfiguration { /// /// Provider Type ... /// /// public XDbProviders Provider { get; set; } /// /// Connection String which provide Requires Data to Connect to Db Provider ... /// /// public string ConnectionString { get; set; } /// /// Enable Tracking of Entities ... /// Only Used on EFCore ... /// /// public bool EnableTracking { get; set; } = false; /// /// Enable Logging Details of Errors ... /// Only Used on EFCore ... /// /// public bool EnableDetailedErrors { get; set; } = false; /// /// Enable Logging Sensitive Data ... /// Only Used on EFCore ... /// /// public bool EnableSensitiveDataLogging { get; set; } = false; /// /// this is a way to provide Default Pagination Data on XQuery based requests ... /// /// public PagingConfiguration PagingConfiguration { get; set; } = new PagingConfiguration(); } /// /// this is a way to provide Default Pagination Data on XQuery based requests ... /// public partial class PagingConfiguration { /// /// Default Page Size ... /// /// public int DefaultPageSize { get; set; } = XDataServiceConstants.DEFAULT_PAGE_SIZE; /// /// restrict Maximum Page Size ... /// /// public int MaxAvailablePageSize { get; set; } = XDataServiceConstants.MAX_AVAILABLE_PAGE_SIZE; /// /// restrice Minimum Page Size ... /// /// public int MinAvailablePageSize { get; set; } = XDataServiceConstants.MIN_AVAILABLE_PAGE_SIZE; } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Configurations\XIdentityResourceConfiguration.cs namespace xIds.Configurations { /// /// determines a resource and it's connection info /// public partial class XIdentityResourceConfiguration { public string Authority { get; set; } public string ApiName { get; set; } public string ApiSecret { get; set; } public string ClientId { get; set; } public string ClientSecret { get; set; } public string XPoweredValue { get; set; } public string XRevisionSecretKey { get; set; } } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Constants\ConfigurationNodeNames.cs namespace xIds.Constants { public struct ConfigurationNodeNames { public const string DB_SEED_NODE_NAME = "DbSeeder"; public const string PROVIDER_NODE_NAME = "DbProvider"; public const string IDENTITY_NODE_NAME = "IdentityConfiguration"; public const string DATA_SERVICE_NODE_NAME = "DataServiceConfiguration"; public const string IDENTITY_RESOURCE_NODE_NAME = "IdentityResourceConfiguration"; } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Constants\ConnectionStringNames.cs namespace xIds.Constants { public struct ConnectionStringNames { public const string IDENTITY_CONNECTION_NAME = "IdentityDb"; public const string CONFIGURATION_CONNECTION_NAME = "ConfigurationDb"; public const string PRESISTED_GRANTS_CONNECTION_NAME = "PersistedGrantDb"; } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Constants\IdentityMessagesKeys.cs namespace xIds.Constants { public struct IdentityMessagesKeys { public const string Terms = "terms"; public const string InviteMsg = "user_invite_msg"; public const string RegistrationApproveMsg = "registration_approve_msg"; public const string RegisteredMsg = "registered_msg"; public const string VerificationCodeMsg = "verification_code_msg"; public const string ChangePasswordMsg = "change_password_msg"; public const string PasswordChangedMsg = "password_changed_msg"; public const string NewDeviceLoggedInMsg = "new_device_logged_in_msg"; } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Constants\XDataServiceConstants.cs namespace xIds.Constants { /// /// /// Default Pagination Values ... /// public partial struct XDataServiceConstants { public static int DEFAULT_PAGE_SIZE = 50; public static int MAX_AVAILABLE_PAGE_SIZE = 500; public static int MIN_AVAILABLE_PAGE_SIZE = 20; } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Constants\XDbProviderConfigurations.cs namespace xIds.Constants { public partial class XDbProviderConfigurations { /// /// Default ConnectionString Name ... /// public const string DEFAULT_CONNECTION_NAME = "DataConnection"; } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Constants\XDbProviders.cs namespace xIds.Constants { /// /// /// Represent Supported DBMS for Managing Data ... /// public enum XDbProviders { None, MySQL, SQLite, SQLServer, } /// /// Represent Supported DBMS for Managing Data ... /// public partial struct ProviderType { public const string MySQL = "MYSQL"; public const string SQLite = "SQLITE"; public const string SQLServer = "SQLSERVER"; } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Controllers\AccountController.cs using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using xCommons.Configurations; using xCommons.Providers; using xIds.Controllers.Base; using xIds.Interfaces; namespace xIds.Controllers { /// /// Provide all available tools for manipulating users and accounts /// [ApiController] public partial class AccountController : XIBaseController { public AccountController( IXIdentityManager identityManager, ILogger logger, XAppConfiguration appConfiguration, XValidationProvider validationProvider ) : base( logger, appConfiguration, identityManager, validationProvider ) { } } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Controllers\StartupController.cs using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using xCommons.Configurations; using xCommons.Controllers; using xCommons.Providers; namespace xIds.Controllers { /// /// Startup and Running Controller /// [Route("")] [AllowAnonymous] public class StartupController : XBaseController { public StartupController( ILogger logger, XAppConfiguration appConfiguration, XValidationProvider validationProvider ) : base( logger, appConfiguration, validationProvider ) { } /// /// Show Configured Welcome Message /// /// an string message [HttpGet("")] [AllowAnonymous] public virtual ActionResult Index() { // var controllerName = GetControllerName(); var message = $"{AppConfiguration.WelcomeMessage}"; // return Ok(message); } } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Controllers\Account\AccountController+Admin.cs using System; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using xIdentityHelper; using xCommons.Attributes; using xCommons.Extensions; using xIdentityModels.Dtos; using static IdentityServer4.IdentityServerConstants; namespace xIds.Controllers { public partial class AccountController { // #region Admin Actions ... /// /// Ban Specific Users /// /// an instance of XUserNameIdRequest which represents user identifier list to Ban /// a list of banned users identifiers [RequireXPowered] [HttpPost("Ban")] [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledAdmin)] public async Task>> Ban( [FromBody] XUserNameIdRequest model ) { // // Do Action ... try { // // Validate Args ... await ValidationProvider .GroupValidationBuilder() .AddNotNull(model) .AddNotZeroChilds(model.Ids) .ValidateGroupAsync(); // var result = await IdentityManager .Ban( User.Identity.Name, model ); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } /// /// UnBann Specific Users /// /// an instance of XUserNameIdRequest which represents user identifier list to Ban /// a list of unbanned users identifiers [RequireXPowered] [HttpPost("UnBan")] [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledAdmin)] public async Task>> UnBan( [FromBody] XUserNameIdRequest model ) { // // Do Action ... try { // // Validate Args ... await ValidationProvider .GroupValidationBuilder() .AddNotNull(model) .AddNotZeroChilds(model.Ids) .ValidateGroupAsync(); // var result = await IdentityManager .UnBan( User.Identity.Name, model ); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } /// /// Check Specific User is Banned or not /// /// specified user's identifier /// a boolean value which represent user banned or not [RequireXPowered] [Authorize(Policy = LocalApi.PolicyName)] [HttpGet("IsBanned/{userSelectByParam?}")] [Authorize(Policy = XPolicies.EnabledAdmin)] [Authorize(Policy = XPolicies.EnabledAgent)] public async Task> IsBanned( [FromRoute] string userSelectByParam = null ) { // // Do Action ... try { // // Validate Args ... if (userSelectByParam.IsNullOrEmpty()) { userSelectByParam = User.Identity.Name; } ValidationProvider.NotEmpty(userSelectByParam); // var result = await IdentityManager .IsBanned( User.Identity.Name, userSelectByParam ); // return Ok(result); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } #endregion } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Controllers\Account\AccountController+Authentication.cs using System; using System.Threading.Tasks; using IdentityModel.Client; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using xIdentityHelper; using xCommons.Attributes; using xCommons.Extensions; using xExceptions.Constants; using xIdentityModels.Extensions; using xIdentityModels.Models; using static IdentityServer4.IdentityServerConstants; using static xIdentityHelper.XApiScopeHelper; using Microsoft.Extensions.Logging; namespace xIds.Controllers { public partial class AccountController { // #region Authentication Actions ... /// /// Retrieve OAuth Discovery Document /// /// an instance of DiscoveryDocumentResponse [AllowAnonymous] [RequireXPowered] [HttpGet("DiscoveryDocument")] public async Task> GetDiscoveryDocument() { // // Do Action ... try { // var result = await IdentityManager .RequestDiscoveryDocument(); // // Ceck Response Result ... if (result.IsError) { XException.InvalidConfiguration.Throw(); } // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var result = GetExceptionActionResult(ex); return result; } } /// /// Request AccessToken for Specific XApiScope /// /// a member of XApiScope /// an instance of XTokenResponse [AllowAnonymous] [RequireXPowered] [HttpPost("RequestScopeAccessToken")] public async Task> RequestScopeAccessToken( [FromHeader] XApiScope scope ) { // // Do Action ... try { // // Validate Args ... var scopeName = string.Empty; try { scopeName = scope.GetStringValue(); } catch { } ValidationProvider.NotEmpty(scopeName); // var result = await IdentityManager .RequestScopeAccessToken(scopeName); // // Ceck Response Result ... if (result.IsError) { XException.InvalidConfiguration.Throw(); } // return Ok(result .CreateXTokenResponse() .ToDynamicObject()); } catch (Exception ex) { // var result = GetExceptionActionResult(ex); return result; } } /// /// Authenticate User /// /// /// Sample request: /// /// { /// "password": "", /// "userSelectBy": "", /// } /// /// /// an instance of XLoginRequest class which represent Authentication requirements /// an instance of XTokenResponse [AllowAnonymous] [RequireXPowered] [HttpPost("Authenticate")] public async Task> Authenticate( [FromBody] XLoginRequest model ) { // // Do Action ... try { // // Validate Args ... if (!ModelState.IsValid) { XException.InvalidArgs.Throw(); } await ValidationProvider .GroupValidationBuilder() .AddNotNull(model) .AddNotEmpty( model.UserSelectBy, model.Password ) .ValidateGroupAsync(); // var result = await IdentityManager .Authenticate(model); // // Check Result ... if (result.IsError) { throw result.GetException(); } // // Return Result ... return Ok(result .CreateXTokenResponse() .ToDynamicObject()); } catch (Exception ex) { // var result = GetExceptionActionResult(ex); return result; } } /// /// Authenticate User /// /// /// Sample request: /// /// { /// "language": "fa-IR" /// "password": "", /// "userSelectBy": "", /// "device": { /// "os":"Mac", /// "browser":"Chrome", /// "osVersion":"mac-os-x-15", /// "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36", /// "deviceType":3, /// "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]", /// "token":"96f400dd9aa5c57a8cec9d6f4775bad3" /// } /// } /// /// /// an instance of XLoginRequest class which represent Authentication requirements /// an instance of XLoginResponse [AllowAnonymous] [RequireXPowered] [HttpPost("Login")] public async Task> Login( [FromBody] XLoginRequest model ) { // // Do Action ... try { // // Validate Args ... if (!ModelState.IsValid) { XException.InvalidArgs.Throw(); } await ValidationProvider .GroupValidationBuilder() .AddNotNull( model, model.Device) .AddNotEmpty( model.Language, model.UserSelectBy, model.Password ) .ValidateGroupAsync(); // var result = await IdentityManager .Login(model); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var result = GetExceptionActionResult(ex); return result; } } /// /// Refresh Expired Tokens /// /// /// in addition to AccessToken, you had to pass RefreshToken due to Headers /// /// an instance of XTokenResponse [AllowAnonymous] [RequireXPowered] [HttpPost("RefreshTokens")] public async Task> RefreshTokens() { // // Do Action ... try { // // Retrieve Toke Response ... var model = await RetrieveTokensAsXTokenResponse(); // // Validate Args ... ValidationProvider .GroupValidationBuilder() .AddNotNull(model) .AddNotEmpty( model.AccessToken, model.RefreshToken) .ValidateGroup(); // var result = await IdentityManager .RefreshTokens(model); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var result = GetExceptionActionResult(ex); return result; } } #endregion // #region Password Actions ... /// /// Change a User's Password ... /// /// /// for this action you have to provide: /// - Lang: client device currently used locale, such as: en-US. /// - Password: user's current active password. /// - NewPassword: user's new password to change. /// - Device: user's client device which is an instance of XDevice. /// - ReturnUrl: client application Login URL. /// /// Sample request: /// /// { /// "lang": "fa-IR", /// "password": "" /// "newPassword": "", /// "returnUrl": "http://localhost/login", /// "device": { /// "os":"Mac", /// "browser":"Chrome", /// "osVersion":"mac-os-x-15", /// "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36", /// "deviceType":3, /// "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]", /// "token":"96f400dd9aa5c57a8cec9d6f4775bad3" /// } /// } /// /// /// an instance of XActionRequest class which provider requirement for action /// [RequireXPowered] [HttpPost("ChangePassword")] [Authorize(Policy = XPolicies.User)] [Authorize(Policy = XPolicies.EnabledUser)] [Authorize(Policy = LocalApi.PolicyName)] public async Task ChangePassword( [FromBody] XActionRequest model ) { // // Do Action ... try { // // Validate Args ... if (!ModelState.IsValid) { XException.InvalidArgs.Throw(); } await ValidationProvider .GroupValidationBuilder() .AddNotNull( model, model.Device ) .AddNotEmpty( model.Lang, model.Password, model.NewPassword, model.ReturnUrl ) .ValidateGroupAsync(); // // Get User Select By ... var userSelectByParam = GetUserSelectByParam( model, forceNotNull: false ); if (userSelectByParam.IsNullOrEmpty()) { userSelectByParam = User.Identity.Name; } ValidationProvider.NotEmpty(userSelectByParam); // // Get Request ... await IdentityManager .ChangePassword( model.Lang, model.Device, userSelectByParam, model.Password, model.NewPassword, model.ReturnUrl ); // return Ok(); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } #endregion } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Controllers\Account\AccountController+Friendship.cs using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using xCommons.Attributes; using xCommons.Extensions; using xExceptions.Constants; using xIdentityHelper; using xIdentityModels.Constants; using xIdentityModels.Dtos; using xIdentityModels.Navigations; using xModels.Dtos; using static IdentityServer4.IdentityServerConstants; namespace xIds.Controllers { public partial class AccountController { // #region Friendship Actions ... // #region Actions ... /// /// Follow a User /// /// a user identifier which represent destination user /// an instance of XFriendshipFollowing [RequireXPowered] [HttpPost("Friendship/{destUser}/Follow")] [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] public async Task> Follow( [FromRoute] string destUser ) { // // Do Action ... try { // // Validate Args ... ValidationProvider.NotEmpty(destUser); // var result = await IdentityManager .Follow( User.Identity.Name, destUser ); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } /// /// Cancel Following /// /// a user identifier which represent destination user /// a boolean value [HttpPost("Friendship/{destUser}/Cancel")] [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] public async Task> Cancel( [FromRoute] string destUser ) { // // Do Action ... try { // // Validate Args ... ValidationProvider.NotEmpty(destUser); // var result = await IdentityManager .Cancel( User.Identity.Name, destUser ); // return Ok(result); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } /// /// Unfollow a Follower /// /// a user identifier which represent destination user /// [HttpPost("Friendship/{destUser}/UnFollowFollower")] [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] public async Task UnFollowFollower( [FromRoute] string destUser ) { // // Do Action ... try { // // Validate Args ... ValidationProvider.NotEmpty(destUser); // await IdentityManager .UnFollowFollower( User.Identity.Name, destUser ); // return Ok(); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } /// /// Unfollow Following /// /// a user identifier which represent destination user /// [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] [HttpPost("Friendship/{destUser}/UnFollowFollowing")] public async Task UnFollowFollowing( [FromRoute] string destUser ) { // // Do Action ... try { // // Validate Args ... ValidationProvider.NotEmpty(destUser); // await IdentityManager .UnFollowFollowing( User.Identity.Name, destUser ); // return Ok(); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } /// /// Block a Follower /// /// a user identifier which represent destination user /// an instance of XFriendshipFollowing [HttpPost("Friendship/{destUser}/Block")] [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] public async Task> Block( [FromRoute] string destUser ) { // // Do Action ... try { // // Validate Args ... ValidationProvider.NotEmpty(destUser); // var result = await IdentityManager .Block( User.Identity.Name, destUser ); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); // return exResult; } } /// /// Unblock a Blocked User /// /// an instance of XFriendshipFollowing /// an instance of XFriendshipFollowing [HttpPost("Friendship/{destUser}/UnBlock")] [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] public async Task> UnBlock( [FromRoute] string destUser ) { // // Do Action ... try { // // Validate Args ... ValidationProvider.NotEmpty(destUser); // var result = await IdentityManager .UnBlock( User.Identity.Name, destUser ); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } #endregion // #region Request Handlers ... /// /// Accept a Following Request /// /// a user identifier which represent destination user /// an instance of XFriendshipFollower [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] [HttpPost("Friendship/{destUser}/AcceptRequest")] public async Task> AcceptRequest( [FromRoute] string destUser ) { // // Do Action ... try { // // Validate Args ... ValidationProvider.NotEmpty(destUser); // var result = await IdentityManager .AcceptRequest( User.Identity.Name, destUser ); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } /// /// Reject a Following Request /// /// a user identifier which represent destination user /// an instance of XFriendshipFollower [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] [HttpPost("Friendship/{destUser}/RejectRequest")] public async Task> RejectRequest( [FromRoute] string destUser ) { // // Do Action ... try { // // Validate Args ... ValidationProvider.NotEmpty(destUser); // var result = await IdentityManager .RejectRequest( User.Identity.Name, destUser ); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } #endregion // #region Getters ... /// /// Check a User IsFollower of Requested User /// /// a user identifier which represent destination user /// a boolean value [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] [HttpGet("Friendship/{destUser}/IsFollower")] public async Task> IsFollower( [FromRoute] string destUser ) { // // Do Action ... try { // // Validate Args ... ValidationProvider.NotEmpty(destUser); // var result = await IdentityManager .IsFollower( User.Identity.Name, destUser ); // return Ok(result); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } /// /// Get Follower State of a User /// /// a user identifier which represent destination user /// an instance of XFriendshipState [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] [HttpGet("Friendship/{destUser}/FollowerState")] public async Task> FollowerState( [FromRoute] string destUser ) { // // Do Action ... try { // // Validate Args ... ValidationProvider.NotEmpty(destUser); // var result = await IdentityManager .GetFollowerState( User.Identity.Name, destUser ); // return Ok(result); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } /// /// Get Specific Follower /// /// a user identifier which represent destination user /// an instance of XFriendshipFollower [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] [HttpGet("Friendship/{destUser}/Follower")] public async Task> Follower( [FromRoute] string destUser ) { // // Do Action ... try { // // Validate Args ... ValidationProvider.NotEmpty(destUser); // var result = await IdentityManager .GetFollower( User.Identity.Name, destUser ); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } /// /// Get Followers List Of Current User /// /// a collection of XFriendshipFollower [HttpGet("Friendship/Followers")] [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] public async Task>> Followers() { // // Do Action ... try { // var result = await IdentityManager .GetFollowers(User.Identity.Name); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); // return exResult; } } /// /// Get All Followers List Includes Blocked, Requested and etc /// of Current User /// /// a collection of XFriendshipFollower [HttpGet("Friendship/AllFollowers")] [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] public async Task>> AllFollowers() { // // Do Action ... try { // var result = await IdentityManager .GetAllFollowers(User.Identity.Name); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } /// /// Get All Followers List Includes Blocked, Requested and etc /// of Current User based On Query Model ... /// /// a Query Result of XFriendDto [HttpGet("Friendship/QueryFollowers")] [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] public async Task>> QueryFollowers( [FromQuery] XQuery query, [FromQuery] string destUser ) { // // Do Action ... try { // // Normalizing Dest User ... var userInfo = await GetUserInfo(); bool isAdmin = userInfo.Roles.Contains(XUserRoles.ADMIN); if (destUser.IsNullOrEmpty()) { destUser = userInfo.UserName; } bool isDestUserValid = isAdmin || destUser == userInfo.UserId || destUser == userInfo.Email || destUser == userInfo.PhoneNumber || destUser == userInfo.UserName; if (!isDestUserValid) { XException.NotAllowed.Throw(); } // var result = await IdentityManager .QueryFollowers( query: query, userSelectByParam: destUser ); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } /// /// Check a User is in Followings of Current User /// /// a user identifier which represent destination user /// a boolean value [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] [HttpGet("Friendship/{destUser}/IsFollowing")] public async Task> IsFollowing( [FromRoute] string destUser ) { // // Do Action ... try { // // Validate Args ... ValidationProvider.NotEmpty(destUser); // var result = await IdentityManager .IsFollowing( User.Identity.Name, destUser ); // return Ok(result); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } /// /// Get Following State Relation between Specific User /// and Current User /// /// a user identifier which represent destination user /// an instance of XFriendshipState [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] [HttpGet("Friendship/{destUser}/FollowingState")] public async Task> FollowingState( [FromRoute] string destUser ) { // // Do Action ... try { // // Validate Args ... ValidationProvider.NotEmpty(destUser); // var result = await IdentityManager .GetFollowingState( User.Identity.Name, destUser ); // return Ok(result); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } /// /// Get Specific Following Model /// /// a user identifier which represent destination user /// an instance of XFriendshipFollowing [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] [HttpGet("Friendship/{destUser}/Following")] public async Task> Following( [FromRoute] string destUser ) { // // Do Action ... try { // // Validate Args ... ValidationProvider.NotEmpty(destUser); // var result = await IdentityManager .GetFollowing( User.Identity.Name, destUser ); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } /// /// Get Followings of Current User /// /// a collection of XFriendshipFollowing [HttpGet("Friendship/Followings")] [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] public async Task>> Followings() { // // Do Action ... try { // var result = await IdentityManager .GetFollowings(User.Identity.Name); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } /// /// Get All Following List Includes Blocked, Requested and etc /// of Current User /// /// a collection of XFriendshipFollowing [HttpGet("Friendship/AllFollowings")] [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] public async Task>> AllFollowings() { // // Do Action ... try { // var result = await IdentityManager .GetAllFollowings(User.Identity.Name); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } /// /// Get All Following List Includes Blocked, Requested and etc /// of Current User based On Query Model ... /// /// a Query Result of XFriendDto [HttpGet("Friendship/QueryFollowings")] [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] public async Task>> QueryFollowings( [FromQuery] XQuery query, [FromQuery] string destUser ) { // // Do Action ... try { // // Normalizing Dest User ... var userInfo = await GetUserInfo(); bool isAdmin = userInfo.Roles.Contains(XUserRoles.ADMIN); if (destUser.IsNullOrEmpty()) { destUser = userInfo.UserName; } bool isDestUserValid = isAdmin || destUser == userInfo.UserId || destUser == userInfo.Email || destUser == userInfo.PhoneNumber || destUser == userInfo.UserName; if (!isDestUserValid) { XException.NotAllowed.Throw(); } // var result = await IdentityManager .QueryFollowings( query: query, userSelectByParam: destUser ); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } #endregion // #region Others ... /// /// Return Following UserName's List of Current User /// /// a collection of UserNames [HttpGet("Friendship/FollowingsList")] [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] public async Task>> FollowingsList() { // // Do Action ... try { // var result = await IdentityManager .GetFollowingList(User.Identity.Name); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } /// /// Return Followers UserName's List of Current User /// /// a collection of UserNames [HttpGet("Friendship/FollowersList")] [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] public async Task>> FollowersList() { // // Do Action ... try { // var result = await IdentityManager .GetFollowersList(User.Identity.Name); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } /// /// Get Friendship Info Model between Specific User and Current User /// /// a user identifier which represent destination user /// an instance of XFriendshipInfoDto [HttpGet("Friendship/{destUser}/FriendshipInfo")] [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] public async Task> FriendshipInfo( [FromRoute] string destUser ) { // // Do Action ... try { // var result = await IdentityManager .GetFriendshipInfo(User.Identity.Name, destUser); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } #endregion #endregion } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Controllers\Account\AccountController+Open.cs using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using xCommons.Attributes; using xCommons.Constants; using xIdentityModels.Dtos; namespace xIds.Controllers { public partial class AccountController { // // Implememnt all Open Actions here ... // #region Open Actions ... [AllowAnonymous] [RequireXPowered] [HttpGet("Open")] public async Task> Get( [FromHeader] string token, [FromQuery] string request ) { // // Do Action ... try { // // Validate Args ... await ValidationProvider .GroupValidationBuilder() .AddNotEmpty(token) .AddNotEmpty(request) .ValidateGroupAsync(); // // Prepare Inner Dto Model ... var dto = new XOpenActionInnerDto { Token = token, Payload = request }; // // Do Action ... var resultDto = await IdentityManager.OpenGet(dto); Response.Headers.Add(XAuthentication.TOKEN, resultDto.Token); // // Return Result return Ok(resultDto.Payload); } catch (Exception ex) { // var result = GetExceptionActionResult(ex); return result; } } #endregion // #region Private ... #endregion } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Controllers\Account\AccountController+Profile.cs using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using xIdentityHelper; using xCommons.Attributes; using xCommons.Extensions; using xIdentityModels.Dtos; using xIdentityModels.Models; using xModels.Dtos; using static IdentityServer4.IdentityServerConstants; namespace xIds.Controllers { public partial class AccountController { // #region Retrieve Actions ... /// /// Retrieve User Names based on UserIds /// /// a comma seperated list of UserIds /// a collection of UserNames [HttpGet("Profile/{ids}/GetNames")] [Authorize(Policy = XPolicies.User)] [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] public async Task>> GetNames( [FromRoute] string ids ) { // // Do Action ... try { // ValidationProvider.NotEmpty(ids); // var xIdList = ids.ParseListString(); var result = await IdentityManager.GetUserNamesAsync( xIdList ); // // Return Result return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var result = GetExceptionActionResult(ex); return result; } } /// /// get user ids and retrieve corresponding user names /// /// an instance of XUserNameIdRequest which represent required UserIds collection /// a collection of XUserNameIdResponse instance [HttpPost("Profile/GetNameIds")] [Authorize(Policy = XPolicies.User)] [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] public async Task>> GetNameIds( [FromBody] XUserNameIdRequest model ) { // // Do Action ... try { // ValidationProvider.NotNull(model); // var result = await IdentityManager.GetUserNameIdsAsync( model ); // // Return Result return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var result = GetExceptionActionResult(ex); return result; } } /// /// Get Profile Object of Specific User /// /// specifies which user profile must be retrieved /// an instance of XUserProfileDto [RequireXPowered] [Authorize(Policy = XPolicies.User)] [Authorize(Policy = LocalApi.PolicyName)] [HttpGet("Profile/{userSelectByParam?}")] [Authorize(Policy = XPolicies.EnabledUser)] public async Task> GetProfile( [FromRoute] string userSelectByParam = "" ) { // // Do Action ... try { // if (userSelectByParam.IsNullOrEmpty()) { userSelectByParam = User.Identity.Name; } // var result = await IdentityManager .GetUserProfileAsync( userSelectByParam, User.Identity.Name ); // // Return Result return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var result = GetExceptionActionResult(ex); return result; } } /// /// Query Users /// for specifiy users role for query user 'role: string' and 'forceRole: boolean' in header /// /// how to filter results based on XQuery structure /// an string which represent user role /// if it's true the user must has exact role, otherwise top level users also listed /// an instance of XQueryResult of XUserProfileDto [RequireXPowered] [HttpGet("Profile/Query")] [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledAdmin)] [Authorize(Policy = XPolicies.EnabledAgent)] public async Task>> QueryProfiles( [FromQuery] XQuery query, [FromHeader] string role, [FromHeader] bool forceRole = false ) { // // Do Action ... try { // var userId = User.Identity.Name; // var result = new XQueryResult(); if (role.IsNullOrEmpty()) { // result = await IdentityManager.QueryUsers( userId, query ); } else { // result = await IdentityManager.QueryInRoleUsers( userId, role, query, forceRole ); } // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exception = GetExceptionActionResult(ex); return exception; } } /// /// Query Specified User's Profile Images /// /// determine's which user profile must be retrieved /// how to filter results based on XQuery structure /// an instance of XQueryResult of XProfileImage [RequireXPowered] [Authorize(Policy = XPolicies.User)] [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] [Authorize(Policy = XPolicies.EnabledAdmin)] [HttpGet("Profile/Avatars/Query/{userSelectByParam?}")] public async Task>> QueryAvatars( [FromQuery] XQuery query, [FromRoute] string userSelectByParam = null ) { // // Do Action ... try { // if (userSelectByParam.IsNullOrEmpty()) { userSelectByParam = User.Identity.Name; } // var result = await IdentityManager.QueryAvatars( userSelectByParam, query ); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exception = GetExceptionActionResult(ex); return exception; } } #endregion // #region Update Actions ... /// /// Update User Profile based on XProfileUpdateRequest (FirstName/LastName/DateOfBirth) /// /// user update info, an instance of XProfileUpdateRequest /// determine's which user profile must be retrieved /// an instance of XUserProfileDto [RequireXPowered] [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] [HttpPost("Profile/Update/{userSelectByParam?}")] public async Task> UpdateProfile( [FromBody] XProfileUpdateRequest model, [FromRoute] string userSelectByParam = null ) { // // Do Action ... try { // if (userSelectByParam.IsNullOrEmpty()) { userSelectByParam = User.Identity.Name; } // var result = await IdentityManager.ProfileUpdateAsync( userSelectByParam, User.Identity.Name, model ); // // Return Result return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var result = GetExceptionActionResult(ex); return result; } } /// /// Update a User Profile based on XProfileUpdateRequest Full /// /// user update info, an instance of XProfileUpdateRequest /// determine's which user profile must be retrieved /// an instance of XUserProfileDto [RequireXPowered] [Authorize(Policy = LocalApi.PolicyName)] [HttpPost("Profile/{userSelectByParam?}")] [Authorize(Policy = XPolicies.EnabledAdminOrAgent)] public async Task> FullUpdateProfile( [FromBody] XProfileUpdateRequest model, [FromRoute] string userSelectByParam = null ) { // // Do Action ... try { // if (userSelectByParam.IsNullOrEmpty()) { userSelectByParam = User.Identity.Name; } // var result = await IdentityManager.FullProfileUpdateAsync( userSelectByParam, User.Identity.Name, model ); // // Return Result return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var result = GetExceptionActionResult(ex); return result; } } #endregion // #region Avatar Actions ... /// /// Add a New Profile Image /// /// an specific File to upload, IFormFile /// an instance of XUserProfileDto [RequireXPowered] [HttpPost("Profile/Avatar")] [RequestSizeLimit(966_367_641)] [Authorize(Policy = XPolicies.User)] [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] public async Task> AddAvatar( [FromForm] IFormFile file ) { // // Do Action ... try { // // Validate Args ... ValidationProvider.NotNull(file); // // Get Request ... var result = await IdentityManager .AddAvatar( User.Identity.Name, file ); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } /// /// Add a New Collection of Profile Images /// /// a collection of Files to upload, IFormFileCollection /// an instance of XUserProfileDto [RequireXPowered] [HttpPost("Profile/Avatars")] [RequestSizeLimit(966_367_641)] [Authorize(Policy = XPolicies.User)] [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] public async Task> AddAvatars( [FromForm] IFormFileCollection files ) { // // Do Action ... try { // // Validate Args ... ValidationProvider.NotZeroChilds(files); // // Get Request ... var result = await IdentityManager.AddAvatars( User.Identity.Name, files ); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } /// /// Remove Profile Images /// /// a comma seperated list of avatarIds to remove /// an instance of XUserProfileDto [RequireXPowered] [Authorize(Policy = XPolicies.User)] [HttpDelete("Profile/Avatars/{ids}")] [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] public async Task> RemoveAvatars( [FromRoute] string ids ) { // // Do Action ... try { // ValidationProvider.NotEmpty(ids); var idList = ids.Split(","); var idCollection = new Collection(); // foreach (var s in idList) { idCollection.Add(int.Parse(s)); } // // Get Request ... var result = await IdentityManager .RemoveAvatar( User.Identity.Name, idCollection.ToArray() ); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var result = GetExceptionActionResult(ex); return result; } } /// /// set Specified Profile Image as Avatar /// /// an integer which reperesent AvatarId to set as current Avatar /// an instance of XUserProfileDto [RequireXPowered] [HttpPost("Profile/Avatars/{id:int}/Set")] [Authorize(Policy = XPolicies.User)] [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] public async Task> SetAvatar( [FromRoute] int id ) { // // Do Action ... try { // var result = await IdentityManager .SetAvatar( User.Identity.Name, id ); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exception = GetExceptionActionResult(ex); return exception; } } #endregion } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Controllers\Account\AccountController+Query.cs using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using xCommons.Attributes; using xCommons.Extensions; using xIdentityHelper; using xModels.Dtos; using static IdentityServer4.IdentityServerConstants; namespace xIds.Controllers { public partial class AccountController { /// /// Query Users /// for specifiy users role for query user 'role: string' and 'forceRole: boolean' in header /// /// how to filter results based on XQuery structure /// an string which represent user role /// if it's true the user must has exact role, otherwise top level users also listed /// an instance of XQueryResult of XUserProfileDto [RequireXPowered] [HttpGet("Users/Query")] [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] public async Task>> QueryUsers( [FromQuery] XQuery query, [FromHeader] string role, [FromHeader] bool forceRole = false ) { // // Do Actions ... try { // // Retrieve User Info ... var userInfo = await GetUserInfo(); // // Retrieve Result Based on Provided Query ... var result = await IdentityManager.QueryUsers( role: role, query: query, forceRole: forceRole, requestedUserSelectByParam: userInfo.UserId ); // // Return result ... return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exception = GetExceptionActionResult(ex); return exception; } } } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Controllers\Account\AccountController+Registration.cs using System; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using xIdentityHelper; using xCommons.Attributes; using xCommons.Extensions; using xExceptions.Constants; using xIdentityModels.Constants; using xIdentityModels.Models; using static IdentityServer4.IdentityServerConstants; namespace xIds.Controllers { public partial class AccountController { // #region CanRegister ... /// /// Check a UserName is Available For Registration or not /// /// an string value which represent desired username /// a boolean value [AllowAnonymous] [RequireXPowered] [HttpGet("CanRegisterUserName/{userName?}")] public async Task> CanRegisterUserName( [FromRoute] string userName ) { // // Validate Args ... if (userName.IsNullOrEmpty()) { return BadRequest( XException.InvalidArgs .ToXError() ); } // // Do Action ... try { // var result = await IdentityManager .CanRegister(userName); // // Return Result return Ok(result); } catch (Exception ex) { // var result = GetExceptionActionResult(ex); // return result; } } /// /// Check a Mobile Number is Available For Registration or not /// /// an string value which represent desired mobile number /// a boolean value [AllowAnonymous] [RequireXPowered] [HttpGet("CanRegisterMobileNumber/{mobileNumber?}")] public async Task> CanRegisterMobileNumber( [FromRoute] string mobileNumber ) { // // Validate Args ... if (mobileNumber.IsNullOrEmpty()) { return BadRequest( XException.InvalidArgs .ToXError() ); } if (!mobileNumber.IsValidMobileNumber()) { return BadRequest( XException.InvalidMobileNumber .ToXError() ); } // // Do Action ... try { // var result = await IdentityManager .CanRegister(mobileNumber); // // Return Result return Ok(result); } catch (Exception ex) { // var result = GetExceptionActionResult(ex); // return result; } } /// /// Check a Email Address is Available For Registration or not /// /// an string value which represent desired email address /// a boolean value [AllowAnonymous] [RequireXPowered] [HttpGet("CanRegisterEmail/{email?}")] public async Task> CanRegisterEmail( [FromRoute] string email ) { // // Validate Args ... if (email.IsNullOrEmpty()) { return BadRequest( XException.InvalidArgs .ToXError() ); } if (!email.IsValidEmail()) { return BadRequest( XException.InvalidEmailAddress .ToXError() ); } // // Do Action ... try { // var result = await IdentityManager .CanRegister(email); // // Return Result return Ok(result); } catch (Exception ex) { // var result = GetExceptionActionResult(ex); // return result; } } #endregion // #region Confirmations ... /// /// Check User is Confirmed Email or not /// /// a boolean value [RequireXPowered] [HttpGet("IsConfirmedEmail")] [Authorize(Policy = XPolicies.User)] [Authorize(Policy = LocalApi.PolicyName)] public async Task> IsConfirmedEmail() { // // Do Action ... try { // var result = await IdentityManager .IsConfirmedEmail(User.Identity.Name); // // Return Result return Ok(result); } catch (Exception ex) { // var result = GetExceptionActionResult(ex); // return result; } } /// /// Check User is Confirmed Mobile or not /// /// a boolean value [RequireXPowered] [HttpGet("IsConfirmedMobile")] [Authorize(Policy = XPolicies.User)] [Authorize(Policy = LocalApi.PolicyName)] public async Task> IsConfirmedMobile() { // // Do Action ... try { // var result = await IdentityManager .IsConfirmedMobile(User.Identity.Name); // // Return Result return Ok(result); } catch (Exception ex) { // var result = GetExceptionActionResult(ex); // return result; } } /// /// Confirm Registration /// /// /// for this action you have to provide: /// - Lang: client device currently used locale, such as: en-US. /// - ActionToken: user's requested action token for this action. /// - Device: user's client device which is an instance of XDevice. /// - ReturnUrl: client application Login URL. /// /// Sample request: /// /// { /// "lang": "fa-IR", /// "actionToken": "" /// "returnUrl": "http://localhost/login", /// "device": { /// "os":"Mac", /// "browser":"Chrome", /// "osVersion":"mac-os-x-15", /// "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36", /// "deviceType":3, /// "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]", /// "token":"96f400dd9aa5c57a8cec9d6f4775bad3" /// } /// } /// /// /// an instance of XActionRequest class which provider requirement for action /// [AllowAnonymous] [RequireXPowered] [HttpPost("ConfirmRegistration")] public async Task ConfirmRegistration( [FromBody] XActionRequest model ) { // // Do Action ... try { // // Validate Args ... if (!ModelState.IsValid) { XException.InvalidArgs.Throw(); } await ValidationProvider .GroupValidationBuilder() .AddNotEmpty( model.Lang, model.ActionToken, model.ReturnUrl ) .AddNotNull(model.Device) .ValidateGroupAsync(); // // Get Request ... await IdentityManager .ConfirmRegistration( model.Lang, model.Device, model.ActionToken, model.ReturnUrl ); // return Ok(); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } /// /// Confirm Requested Mobile Number /// /// /// for this action you have to provide: /// - Lang: client device currently used locale, such as: en-US. /// - ActionToken: user's requested action token for this action. /// - Device: user's client device which is an instance of XDevice. /// - MobileVerificationCode: a verification code which produced due Request Action. /// /// Sample request: /// /// { /// "lang": "fa-IR", /// "actionToken": "" /// "mobileVerificationCode": "", /// "device": { /// "os":"Mac", /// "browser":"Chrome", /// "osVersion":"mac-os-x-15", /// "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36", /// "deviceType":3, /// "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]", /// "token":"96f400dd9aa5c57a8cec9d6f4775bad3" /// } /// } /// /// /// an instance of XActionRequest class which provider requirement for action /// an instance of XActionResponse [AllowAnonymous] [RequireXPowered] [HttpPost("ConfirmMobileNumber")] public async Task> ConfirmMobileNumber( [FromBody] XActionRequest model ) { // // Do Action ... try { // // Validate Args ... if (!ModelState.IsValid) { XException.InvalidArgs.Throw(); } await ValidationProvider .GroupValidationBuilder() .AddNotEmpty( model.Lang, model.ActionToken, model.MobileVerificationCode ) .AddNotNull(model.Device) .ValidateGroupAsync(); // // Get Request ... var result = await IdentityManager .ConfirmMobileNumber( model.Lang, model.Device, model.ActionToken, model.MobileVerificationCode ); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } /// /// Confirm Requested Email Address /// /// /// for this action you have to provide: /// - Lang: client device currently used locale, such as: en-US. /// - ActionToken: user's requested action token for this action. /// - Device: user's client device which is an instance of XDevice. /// - EmailVerificationCode: a verification code which produced due Request Action. /// /// Sample request: /// /// { /// "lang": "fa-IR", /// "actionToken": "" /// "emailVerificationCode": "", /// "device": { /// "os":"Mac", /// "browser":"Chrome", /// "osVersion":"mac-os-x-15", /// "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36", /// "deviceType":3, /// "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]", /// "token":"96f400dd9aa5c57a8cec9d6f4775bad3" /// } /// } /// /// /// an instance of XActionRequest class which provider requirement for action /// an instance of XActionResponse [AllowAnonymous] [RequireXPowered] [HttpPost("ConfirmEmailAddress")] public async Task> ConfirmEmailAddress( [FromBody] XActionRequest model ) { // // Do Action ... try { // // Validate Args ... if (!ModelState.IsValid) { XException.InvalidArgs.Throw(); } await ValidationProvider .GroupValidationBuilder() .AddNotEmpty( model.Lang, model.ActionToken, model.EmailVerificationCode ) .AddNotNull(model.Device) .ValidateGroupAsync(); // // Get Request ... var result = await IdentityManager .ConfirmEmailAddress( model.Lang, model.Device, model.ActionToken, model.EmailVerificationCode ); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } #endregion // #region Request for Actions ... /// /// Request For Mobile Number Change/Confirm /// /// /// for this action you have to provide: /// - Lang: client device currently used locale, such as: en-US. /// - Password: user's current active password. /// - MobileNumber: which phone number is going to confirm. /// - Device: user's client device which is an instance of XDevice. /// /// Sample request: /// /// { /// "lang": "fa-IR", /// "password": "", /// "mobileNumber": "", /// "device": { /// "os":"Mac", /// "browser":"Chrome", /// "osVersion":"mac-os-x-15", /// "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36", /// "deviceType":3, /// "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]", /// "token":"96f400dd9aa5c57a8cec9d6f4775bad3" /// } /// } /// /// /// an instance of XActionRequest class which provider requirement for action /// an instance of XActionResponse [AllowAnonymous] [RequireXPowered] [HttpPost("RequestConfirmMobile")] public async Task> RequestConfirmMobile( [FromBody] XActionRequest model ) { // // Do Action ... try { // // Validate Args ... if (!ModelState.IsValid) { XException.InvalidArgs.Throw(); } await ValidationProvider .GroupValidationBuilder() .AddNotEmpty( model.Lang, model.Password, model.MobileNumber ) .AddNotNull(model.Device) .AddMobileNumber(model.MobileNumber) .ValidateGroupAsync(); // // Get UserSelect By Param ... var userSelectByParam = GetUserSelectByParam( model, excludes: new List { XUserSelectBy.Email, XUserSelectBy.MobileNumber }); // // Get Request ... var result = await IdentityManager .RequestConfirmMobile( model.Lang, model.Device, userSelectByParam, model.Password, model.MobileNumber ); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } /// /// Request For Email Address Change/Confirm /// /// /// for this action you have to provide: /// - Lang: client device currently used locale, such as: en-US. /// - Password: user's current active password. /// - Email: which email address is going to confirm. /// - Device: user's client device which is an instance of XDevice. /// /// Sample request: /// /// { /// "lang": "fa-IR", /// "password": "", /// "email": "", /// "device": { /// "os":"Mac", /// "browser":"Chrome", /// "osVersion":"mac-os-x-15", /// "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36", /// "deviceType":3, /// "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]", /// "token":"96f400dd9aa5c57a8cec9d6f4775bad3" /// } /// } /// /// /// an instance of XActionRequest class which provider requirement for action /// an instance of XActionResponse [AllowAnonymous] [RequireXPowered] [HttpPost("RequestConfirmEmail")] public async Task> RequestConfirmEmail( [FromBody] XActionRequest model ) { // // Do Action ... try { // // Validate Args ... if (!ModelState.IsValid) { XException.InvalidArgs.Throw(); } await ValidationProvider .GroupValidationBuilder() .AddNotEmpty( model.Lang, model.Email, model.Password) .AddNotNull(model.Device) .AddEmailAddress(model.Email) .ValidateGroupAsync(); // // Get UserSelect By Param ... var userSelectByParam = GetUserSelectByParam( model, excludes: new List { XUserSelectBy.Email, XUserSelectBy.MobileNumber }); // // Get Request ... var result = await IdentityManager .RequestConfirmEmail( model.Lang, model.Device, userSelectByParam, model.Password, model.Email ); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } /// /// Request Reset Password Action /// /// /// for this action you have to provide: /// - Lang: client device currently used locale, such as: en-US. /// - Device: user's client device which is an instance of XDevice. /// - ReturnUrl: client application ResetPassword URL. /// /// Sample request: /// /// { /// "lang": "fa-IR", /// "returnUrl": "http://localhost/reset-password", /// "device": { /// "os":"Mac", /// "browser":"Chrome", /// "osVersion":"mac-os-x-15", /// "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36", /// "deviceType":3, /// "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]", /// "token":"96f400dd9aa5c57a8cec9d6f4775bad3" /// } /// } /// /// /// an instance of XActionRequest class which provider requirement for action /// an instance of XActionResponse [AllowAnonymous] [RequireXPowered] [HttpPost("RequestResetPassword")] public async Task> RequestResetPassword( [FromBody] XActionRequest model ) { // // Do Action ... try { // // Validate Args ... if (!ModelState.IsValid) { XException.InvalidArgs.Throw(); } await ValidationProvider .GroupValidationBuilder() .AddNotEmpty( model.Lang, model.ReturnUrl) .AddNotNull(model.Device) .AddUrl(model.ReturnUrl) .ValidateGroupAsync(); // // Get UserSelect By Param ... var userSelectByParam = GetUserSelectByParam(model); // // Get Request ... var result = await IdentityManager .RequestResetPassword( model.Lang, model.Device, userSelectByParam, model.ReturnUrl ); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } /// /// Reset a User's Password /// /// /// for this action you have to provide: /// - Lang: client device currently used locale, such as: en-US. /// - ActionToken: user's requested action token for this action. /// - NewPassword: user's new password to change. /// - Device: user's client device which is an instance of XDevice. /// - ReturnUrl: client application Login URL. /// /// Sample request: /// /// { /// "lang": "fa-IR", /// "actionToken": "", /// "newPassword": "", /// "returnUrl": "http://localhost/login", /// "device": { /// "os":"Mac", /// "browser":"Chrome", /// "osVersion":"mac-os-x-15", /// "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36", /// "deviceType":3, /// "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]", /// "token":"96f400dd9aa5c57a8cec9d6f4775bad3" /// } /// } /// /// /// an instance of XActionRequest class which provider requirement for action /// [AllowAnonymous] [RequireXPowered] [HttpPost("ResetPassword")] public async Task ResetPassword( [FromBody] XActionRequest model ) { // // Do Action ... try { // // Validate Args ... if (!ModelState.IsValid) { XException.InvalidArgs.Throw(); } await ValidationProvider .GroupValidationBuilder() .AddNotEmpty( model.Lang, model.ActionToken, model.NewPassword, model.ReturnUrl) .AddNotNull(model.Device) .ValidateGroupAsync(); // // Get Request ... await IdentityManager .ResetPassword( model.Lang, model.Device, model.ActionToken, model.NewPassword, model.ReturnUrl ); // return Ok(); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } /// /// Request Registration Confirm /// /// /// for this action you have to provide: /// - a UserSelectedBy identifier which represet User. /// - Lang: client device currently used locale, such as: en-US. /// - Password: user's current active password. /// - Device: user's client device which is an instance of XDevice. /// - ReturnUrl: client application Confirm Registration URL. /// /// Sample request: /// /// { /// "lang": "fa-IR", /// "userId": "" /// "password": "", /// "returnUrl": "http://localhost/confirm", /// "device": { /// "os":"Mac", /// "browser":"Chrome", /// "osVersion":"mac-os-x-15", /// "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36", /// "deviceType":3, /// "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]", /// "token":"96f400dd9aa5c57a8cec9d6f4775bad3" /// } /// } /// /// /// an instance of XActionRequest class which provider requirement for action /// [AllowAnonymous] [RequireXPowered] [HttpPost("RequestConfirmRegistration")] public async Task RequestConfirmRegistration( [FromBody] XActionRequest model ) { // // Do Action ... try { // // Validate Args ... if (!ModelState.IsValid) { XException.InvalidArgs.Throw(); } await ValidationProvider .GroupValidationBuilder() .AddNotEmpty( model.Lang, model.Password, model.ReturnUrl) .AddNotNull(model.Device) .AddUrl(model.ReturnUrl) .ValidateGroupAsync(); // // Get UserSelect By Param ... var userSelectByParam = GetUserSelectByParam(model); // // Get Request ... await IdentityManager .RequestConfirmRegistration( model.Lang, model.Device, userSelectByParam, model.Password, model.ReturnUrl ); // return Ok(); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } #endregion // #region Registration ... /// /// Invite a User to Register on Dashboard /// /// /// for this action you have to provide: /// - Lang: client device currently used locale, such as: en-US. /// - Email: which email address is going to invite. /// - Device: user's client device which is an instance of XDevice. /// - ReturnUrl: client application Registration URL. /// notice in this step you had to provide all this informations as FormData /// /// Sample request: /// /// { /// "lang": "fa-IR", /// "email": "", /// "returnUrl": "", /// "device": { /// "os":"Mac", /// "browser":"Chrome", /// "osVersion":"mac-os-x-15", /// "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36", /// "deviceType":3, /// "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]", /// "token":"96f400dd9aa5c57a8cec9d6f4775bad3" /// } /// } /// /// /// an instance of XActionRequest class which provider requirement for action /// an instance of XActionResponse [RequireXPowered] [HttpPost("InviteUser")] [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledAdmin)] [Authorize(Policy = XPolicies.EnabledAgent)] public async Task> InviteUser( [FromBody] XActionRequest model ) { // // Do Action ... try { // // Validate Args ... if (!ModelState.IsValid) { XException.InvalidArgs.Throw(); } // await ValidationProvider .GroupValidationBuilder() .AddNotEmpty( model.Lang, model.Email, model.ReturnUrl) .AddEmailAddress(model.Email) .AddNotNull(model.Device) .ValidateGroupAsync(); // var result = await IdentityManager .InviteUser( model.Lang, model.Device, model.Email, model.ReturnUrl); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var result = GetExceptionActionResult(ex); return result; } } /// /// Recieve some Basic Informations and Start Registration Proccess /// if they Valid /// /// Registration Proccess Starts with Invoking this Action /// /// /// for this action you have to provide: /// - Lang: client device currently used locale, such as: en-US. /// - FirstName: user's FirstName. /// - LastName: user's LastName. /// - DateOfBirth: user's dob date. /// - MobileNumber: user's MobileNumber optional. /// - Email: user's Email optional. /// - ActionToken: user's requested action token for this action (if user invited). /// - Device: user's client device which is an instance of XDevice. /// /// Sample request: /// /// { /// "lang": "fa-IR", /// "firstName": "", /// "lastName": "", /// "dateOfBirth": "", /// "email": "", /// "mobileNumber": "", /// "actionToken": "", /// "device": { /// "os":"Mac", /// "browser":"Chrome", /// "osVersion":"mac-os-x-15", /// "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36", /// "deviceType":3, /// "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]", /// "token":"96f400dd9aa5c57a8cec9d6f4775bad3" /// } /// } /// /// /// an instance of XActionRequest class which provider requirement for action /// an instance of XActionResponse [AllowAnonymous] [RequireXPowered] [HttpPost("RequestRegistration")] public async Task> RequestRegistration( [FromBody] XActionRequest model ) { // // Do Action ... try { // // Validate Args ... if (!ModelState.IsValid) { XException.InvalidArgs.Throw(); } await ValidationProvider .GroupValidationBuilder() .AddNotEmpty( model.Lang, model.FirstName, model.LastName) .AddNotNull( model.Device, model.DateOfBirth) .ValidateGroupAsync(); // // Check Date Of Birth ... if (!model.DateOfBirth.HasValue) { XException.InvalidArgs.Throw(); ; } // // Validate Mobile Number if Exists ... if (!model.MobileNumber.IsNullOrEmpty()) { ValidationProvider.MobileNumber(model.MobileNumber); } // // Validate Email Address if Exists ... if (!model.Email.IsNullOrEmpty()) { ValidationProvider.EmailAddress(model.Email); } // // Get Request ... var result = await IdentityManager .RequestRegistration( model.Lang, model.Device, model.ActionToken, model.FirstName, model.LastName, model.DateOfBirth.GetValueOrDefault(), model.MobileNumber, model.Email ); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); // return exResult; } } /// /// Add User Account Informations /// /// /// for this action you have to provide: /// - Lang: client device currently used locale, such as: en-US. /// - ActionToken: user's requested action token for this action. /// - UserName: user name. /// - Password: assigne password. /// - Device: user's client device which is an instance of XDevice. /// /// Sample request: /// /// { /// "lang": "fa-IR", /// "userName": "", /// "password": "", /// "actionToken": "", /// "device": { /// "os":"Mac", /// "browser":"Chrome", /// "osVersion":"mac-os-x-15", /// "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36", /// "deviceType":3, /// "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]", /// "token":"96f400dd9aa5c57a8cec9d6f4775bad3" /// } /// } /// /// /// an instance of XActionRequest class which provider requirement for action /// an instance of XActionResponse [AllowAnonymous] [RequireXPowered] [HttpPost("AddAccountInfo")] public async Task> AddAccountInfo( [FromBody] XActionRequest model ) { // // Do Action ... try { // // Validate Args ... if (!ModelState.IsValid) { XException.InvalidArgs.Throw(); } await ValidationProvider .GroupValidationBuilder() .AddNotEmpty( model.Lang, model.ActionToken, model.UserName, model.Password) .AddNotNull(model.Device) .ValidateGroupAsync(); // // Get Request ... var result = await IdentityManager .AddAcountInfo( model.Lang, model.Device, model.ActionToken, model.UserName, model.Password); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } /// /// Upload and Attach a Profile Image for User. this is an Optional Step /// /// user's requested action token /// an instance of IFormFile for user's Avatar /// an instance of XActionResponse [AllowAnonymous] [RequireXPowered] [HttpPost("AttachProfileImage")] public async Task> AttachProfileImage( [FromForm] string actionToken, [FromForm] IFormFile file ) { // // Do Action ... try { // // Validate Args ... await ValidationProvider .GroupValidationBuilder() .AddNotEmpty(actionToken) .AddNotNull(file) .ValidateGroupAsync(); // var result = await IdentityManager .AttachProfileImage(actionToken, file); // return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); return exResult; } } /// /// Finish Registrationn Proccess /// /// /// for this action you have to provide: /// - a proper User Identifier such as: (UserId, UserName, Email or MobileNumber). /// - Lang: client device currently used locale, such as: en-US. /// - ActionToken: user's requested action token for this action. /// - Password: assigne password. /// - Device: user's client device which is an instance of XDevice. /// - ReturnUrl: client application Login URL. /// /// Sample request: /// /// { /// "lang": "fa-IR", /// "userName": "", /// "password": "", /// "returnUrl": "", /// "device": { /// "os":"Mac", /// "browser":"Chrome", /// "osVersion":"mac-os-x-15", /// "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36", /// "deviceType":3, /// "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]", /// "token":"96f400dd9aa5c57a8cec9d6f4775bad3" /// } /// } /// /// /// an instance of XActionRequest class which provider requirement for action /// [AllowAnonymous] [RequireXPowered] [HttpPost("FinishRegistration")] public async Task FinishRegistration( [FromBody] XActionRequest model ) { // // Do Action ... try { // // Validate Args ... if (!ModelState.IsValid) { XException.InvalidArgs.Throw(); } await ValidationProvider .GroupValidationBuilder() .AddNotEmpty( model.Lang, model.Password, model.ReturnUrl) .AddNotNull(model.Device) .AddUrl(model.ReturnUrl) .ValidateGroupAsync(); // var userSelectByParam = IdentityManager .GetUserSelectByParam(model); ValidationProvider .NotEmpty(userSelectByParam); // // Get Request ... await IdentityManager .FinishRegistration( model.Lang, model.Device, userSelectByParam, model.Password, model.ReturnUrl ); // return Ok(); } catch (Exception ex) { // var exResult = GetExceptionActionResult(ex); // return exResult; } } #endregion } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Controllers\Account\AccountController+Search.cs using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using xCommons.Attributes; using xCommons.Extensions; using xIdentityHelper; using xIdentityModels.Dtos; using xModels.Dtos; using static IdentityServer4.IdentityServerConstants; namespace xIds.Controllers { /// /// Actions which related to Search and Suggest Users for /// Friendship or Detecting ... /// public partial class AccountController { // #region Actions of Search ... /// /// Query Open To Search Users Profiles ... /// Query all Users Which their Profiles is Open To Search ... /// /// how to filter results based on XQuery structure /// an instance of XQueryResult of XUserProfileDto [RequireXPowered] [HttpGet("OpenToSearch/Query")] [Authorize(Policy = LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] public async Task>> QueryOpenToSearchProfiles( [FromQuery] XQuery query) { // // Do Action ... try { // var userId = User.Identity.Name; // var result = await IdentityManager.QueryOpenToSearchUsers( userId, query ); return Ok(result .ToDynamicObject()); } catch (Exception ex) { // var exception = GetExceptionActionResult(ex); return exception; } } #endregion } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Controllers\Account\AccountController+Test.cs using System.Linq; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using xIdentityHelper; using xCommons.Attributes; using static IdentityServer4.IdentityServerConstants; namespace xIds.Controllers { public partial class AccountController { // #region Test Actions ... /// /// API Read Scope /// /// string message [RequireXPowered] [Authorize(LocalApi.PolicyName)] [HttpGet("Test/PassReadAccess")] [Authorize(Policy = XPolicies.ReadAccess)] public ActionResult PassReadAccess() { return Ok("Read Access Passed ..."); } /// /// API Write Scope /// /// string message [RequireXPowered] [Authorize(LocalApi.PolicyName)] [HttpGet("Test/PassWriteAccess")] [Authorize(Policy = XPolicies.WriteAccess)] public ActionResult PassWriteAccess() { return Ok("Write Access Passed ..."); } /// /// API Admin Scope /// /// string message [RequireXPowered] [Authorize(LocalApi.PolicyName)] [HttpGet("Test/PassAdminAccess")] [Authorize(Policy = XPolicies.AdminAccess)] public ActionResult PassAdminAccess() { return Ok("Admin Access Passed ..."); } /// /// API Manage Scop /// /// string message [RequireXPowered] [Authorize(LocalApi.PolicyName)] [HttpGet("Test/PassManageAccess")] [Authorize(Policy = XPolicies.ManageAccess)] public ActionResult PassManageAccess() { return Ok("Manage Access Passed ..."); } /// /// a simple Action which returns a List of Authenticated User Claims /// /// string message which represent current user's claims [RequireXPowered] [HttpGet("Test/HiClaims")] [Authorize(LocalApi.PolicyName)] [Authorize(Policy = XPolicies.User)] public ActionResult HiClaims() { // var result = new { name = User.Identity.Name, claims = User.Claims.Select(c => new { c.Type, c.Value }) }; // return Ok(result); } /// /// a simple Hello User for Checking Authentication and Policy /// /// string message which contains authenticated user name [RequireXPowered] [HttpGet("Test/HiUser")] [Authorize(LocalApi.PolicyName)] [Authorize(Policy = XPolicies.User)] public ActionResult HiUser() { // var result = $"Hi User: {User.Identity.Name} ..."; // return Ok(result); } /// /// a simple Hello User for Checking Authentication and Policy /// /// string message which contains authenticated user name [RequireXPowered] [HttpGet("Test/HiEnabledUser")] [Authorize(LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledUser)] public ActionResult HiEnabledUser() { // var result = $"Hi User: {User.Identity.Name} is Enabled ..."; // return Ok(result); } /// /// a simple Hello User for Checking Authentication and Policy /// /// string message which contains authenticated user name [RequireXPowered] [HttpGet("Test/HiAdmin")] [Authorize(LocalApi.PolicyName)] [Authorize(Policy = XPolicies.Admin)] public ActionResult HiAdmin() { // var result = $"Hi Admin: {User.Identity.Name} ..."; // return Ok(result); } /// /// a simple Hello User for Checking Authentication and Policy /// /// string message which contains authenticated user name [RequireXPowered] [HttpGet("Test/HiEnabledAdmin")] [Authorize(LocalApi.PolicyName)] [Authorize(Policy = XPolicies.EnabledAdmin)] public ActionResult HiEnabledAdmin() { // var result = $"Hi Admin: {User.Identity.Name} is Enabled ..."; // return Ok(result); } #endregion } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Controllers\Base\XIBaseController.cs using System; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using xCommons.Configurations; using xCommons.Constants; using xCommons.Controllers; using xCommons.Extensions; using xCommons.Providers; using xExceptions.Constants; using xIdentityModels.Constants; using xIdentityModels.Models; using xIds.Interfaces; namespace xIds.Controllers.Base { public abstract class XIBaseController : XBaseController { public IXIdentityManager IdentityManager { get; } protected XIBaseController( ILogger logger, XAppConfiguration appConfiguration, IXIdentityManager identityManager, XValidationProvider validationProvider ) : base( logger, appConfiguration, validationProvider ) { IdentityManager = identityManager; } // #region User Handlers NonActions ... /// /// Retrieve User Identifier Base on XActionRequest /// /// /// /// /// [NonAction] public string GetUserSelectByParam( XActionRequest model, bool forceNotNull = true, ICollection excludes = null) { // // Validate Args ... ValidationProvider.NotNull(model); // var result = IdentityManager.GetUserSelectByParam( model, forceNotNull, excludes); // return result; } /// /// Retrieve Access Token /// /// [NonAction] public async Task GetAccessToken() { // var accessToken = Request.Headers[XAuthorization.Header].ToString(); if (accessToken.IsNullOrEmpty()) { accessToken = await HttpContext.GetTokenAsync(XAuthorization.AccessToken); } // if (accessToken .ToNormalString() .Contains(XAuthorization.TokenIdentifier.ToNormalString())) { accessToken = accessToken.Remove(0, XAuthorization.TokenIdentifier.Length); } // Logger.LogInformation($"Token: {accessToken}"); return accessToken; } /// /// Retrieve Refresh Token /// /// [NonAction] public async Task GetRefreshToken() { // var refreshToken = Request.Headers[XAuthorization.RefreshToken].ToString(); if (refreshToken.IsNullOrEmpty()) { refreshToken = await HttpContext.GetTokenAsync(XAuthorization.RefreshToken); } // Logger.LogInformation($"Refresh Token: {refreshToken}"); return refreshToken; } /// /// Retrieve Access Token Expiration Date /// /// [NonAction] public async Task GetTokenExpiresAt() { // var expiresAtStr = Request.Headers[XAuthorization.ExpiresAt].ToString(); if (expiresAtStr.IsNullOrEmpty()) { expiresAtStr = await HttpContext.GetTokenAsync(XAuthorization.ExpiresAt); } // var expiresAt = expiresAtStr.ConvertTo(); // Logger.LogInformation($"Token ExpiresAt: {expiresAtStr}"); return expiresAt; } /// /// Retrieve All Required Tokens /// /// [NonAction] public async Task RetrieveTokensAsXLoginResponse() { // var accessToken = await GetAccessToken(); var refreshToken = await GetRefreshToken(); var expiresAt = await GetTokenExpiresAt(); // return new XLoginResponse { AccessToken = accessToken, RefreshToken = refreshToken, ExpiresAt = expiresAt }; } /// /// Retrieve All Required Tokens /// /// [NonAction] public async Task RetrieveTokensAsXTokenResponse() { // var accessToken = await GetAccessToken(); var refreshToken = await GetRefreshToken(); var expiresAt = await GetTokenExpiresAt(); // return new XTokenResponse { AccessToken = accessToken, RefreshToken = refreshToken, ExpiresAt = expiresAt }; } /// /// Retrive UserInfo /// /// [NonAction] public async Task GetUserInfo() { // var claims = User.Claims ?? null; if (!claims.HasChild()) { return null; } var xTokens = await RetrieveTokensAsXTokenResponse(); var result = new XUserClaimsInfoDto( xTokens.AccessToken, xTokens.RefreshToken, xTokens.ExpiresAt, User.Claims ); // return result; } /// /// Validate User Authenticated and Retrieve User Info /// /// [NonAction] public async Task ValidateAndGetUserInfo() { // if (!User.Identity.IsAuthenticated) { XException.NotAuthorized.Throw(); } // var result = await GetUserInfo(); if (result.IsNull()) { XException.NotAuthorized.Throw(); } // return result; } #endregion // #region NonActions ... /// /// Convert an Exception to Propper Error Result /// /// /// [NonAction] public new ActionResult GetExceptionActionResult(Exception ex) { // var exception = GetExceptionResult(ex); var error = ex.Message.ToXError(); // Logger.LogError($"exception: {exception}, error: {error}"); // try { var xError = exception.Message.ToXError(); var xException = (XException)xError.Id; // switch (xException) { // case XException.NotFound: return NotFound(error); // case XException.NotAuthorized: return Unauthorized(error); } } catch { } // return BadRequest(error); } #endregion } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\DbContext\XIdentityDbContext.cs using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; using xIdentityModels; using xIdentityModels.Models; using xIdentityModels.Navigations; namespace xIds.DbContext { public class XIdentityDbContext : IdentityDbContext { // #region Props/DbSets ... public DbSet Tokens { get; set; } public DbSet Devices { get; set; } public DbSet Avatars { get; set; } public DbSet BannedDevices { get; set; } public DbSet Followers { get; set; } public DbSet Followings { get; set; } public DbSet VerificationRequests { get; set; } #endregion public XIdentityDbContext(DbContextOptions options) : base(options) { // try { Database.EnsureCreated(); Database.Migrate(); } catch { } } protected override void OnModelCreating(ModelBuilder modelBuilder) { // base.OnModelCreating(modelBuilder); // // Fix XUser GUID Generator on Add ... modelBuilder .Entity() .Property(e => e.Id) .ValueGeneratedOnAdd(); // // Handle Role List ... modelBuilder.Entity(u => { u.HasMany(x => x.Roles) .WithOne() .HasForeignKey(ur => ur.UserId) .IsRequired(); }); } } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\DI\XDIHelperExtension.cs using System.Collections.Generic; using IdentityServer4; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.HttpOverrides; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using xCommons.Authorization; using xCommons.Constants; using xCommons.Extensions; using xExceptions.Constants; using xIdentityHelper; using xIdentityModels; using xIdentityModels.Configurations; using xIds.Configurations; using xIds.Constants; using xIds.DbContext; using xIds.Extensions; using xIds.Helpers; using xIds.Interfaces; using xIds.Providers; using xIds.Validators; using xMessageService.DI; using xMessageService.Interfaces; using xStorageService.DI; using xStorageService.Interfaces; namespace xIds.DI { public static class XDIHelperExtension { /// /// Register Application DataProvider /// /// /// public static void AddXDataProvider( this IServiceCollection services, IConfiguration configuration ) { // // Retrieve DbInfo ... var dbInfo = configuration.GetXDbInfo(); var identityDbConnectionString = configuration.GetConnectionString(ConnectionStringNames.IDENTITY_CONNECTION_NAME); // // Register Db Context for EF ... services.AddDbContext(builder => { // builder.PrepareXDbContextOptionsBuilder( dbInfo, identityDbConnectionString ); }); } /// /// Extract Connection String From IConfiguration /// /// /// /// public static string GetXConnectionString( this IConfiguration config, string connectionName = null ) { // if (connectionName.IsNullOrEmpty()) { connectionName = XDbProviderConfigurations.DEFAULT_CONNECTION_NAME; } // return config.GetConnectionString(connectionName); } /// /// Retrive XDataService Configurations /// /// /// /// public static XDataServiceConfiguration GetXDataServiceConfiguration( this IConfiguration source, string connectionName = null ) { // var xDataServiceConfigSection = source .GetSection(Constants.ConfigurationNodeNames.DATA_SERVICE_NODE_NAME); var result = xDataServiceConfigSection.Get(); if (result.IsNull()) { result = new XDataServiceConfiguration(); } // result.Provider = source.GetXDbProviderType(); result.ConnectionString = source.GetXConnectionString(connectionName); // return result; } /// /// Register XDataService Configuration /// /// /// /// public static void AddXDataServiceConfiguration( this IServiceCollection services, IConfiguration configuration, string connectionName = null ) { // var dataServiceConfiguration = configuration .GetXDataServiceConfiguration(connectionName); // services.AddSingleton(dataServiceConfiguration); } /// /// Register All Requirements For XIdentityServer Usage /// /// /// public static void AddXIdentityServerRequirements( this IServiceCollection services, IConfiguration configuration ) { // services.AddXDataProvider(configuration); // // Register XIdentityMessageProvider ... services.AddXIdentityMessageProvider(); // // Register IdentityManager Service ... var xIdentityManager = services.GetRegisteredService(); if (xIdentityManager.IsNull()) { services.AddXIdentityManager(); } // // Check XMessage Service Registered or not and Register it if not ... var xMessageProvider = services.GetRegisteredService(); if (xMessageProvider.IsNull()) { services.AddXMessageService(configuration); } // // Check Storage Service Registered or not and Register it if not ... var xStorageProvider = services.GetRegisteredService(); if (xStorageProvider.IsNull()) { services.AddXStorageService(configuration); } // // Register XIdentityConfiguration ... var xIdentityConfiguration = configuration.GetXIdentityConfiguration(); services.AddSingleton(xIdentityConfiguration); // // Register XIdentityHelper ... services.AddSingleton(); var xIdentityHelper = services.GetRegisteredService(); // // Register Asp.net Identity ... services.AddXIdentity(); } /// /// Add IdentityServer with Support of Ef /// /// /// public static void AddEfSupportXIdentityServer( this IServiceCollection services, IConfiguration configuration ) { // // Register All Requirements ... services.AddXIdentityServerRequirements(configuration); // // add DbSeeder Config ... services.AddXDebSeederDescriptor(configuration); // // Retrieve Certificate ... var identityServerSigningCertificate = configuration.GetCertificate(CertificatesConfigurations.CertificateNames.IdentityServerSigning); // // Retrieve DbInfo ... var dbInfo = configuration.GetXDbInfo(); // // Retrieve Connection String Names ... var configDbConnectionString = configuration.GetConnectionString(ConnectionStringNames.CONFIGURATION_CONNECTION_NAME); var persistedGrantDbConnectionString = configuration.GetConnectionString(ConnectionStringNames.PRESISTED_GRANTS_CONNECTION_NAME); // // Register IdentityServer ... services.AddIdentityServer(options => { // options.Discovery.CustomEntries.Add("account_api", "~/account"); // // options.Events.RaiseErrorEvents = true; // options.Events.RaiseFailureEvents = true; // options.Events.RaiseSuccessEvents = true; // options.Events.RaiseInformationEvents = true; }) .LoadSigningCredentialFrom(identityServerSigningCertificate) .AddXDbProvider(configuration) .AddAspNetIdentity() .AddProfileService() .AddResourceOwnerValidator(); } /// /// force app to use IdentityServer /// /// /// public static void UseXIdentityServer( this IApplicationBuilder app, ILogger logger ) { // // Update XIdentityServer Configurations before Use Identity Server ... app.SeedData(logger) .GetAwaiter() .GetResult(); // // Use Identity Server ... app.UseIdentityServer(); } /// /// Register Asp.net Identity as User Store /// /// public static void AddXIdentity(this IServiceCollection services) { // var xIdentityConfiguration = services.GetRegisteredService(); if (xIdentityConfiguration.IsNull()) { XException.InvalidConfiguration.Throw(); } // var xIdentityHelper = services.GetRegisteredService(); if (xIdentityHelper.IsNull()) { XException.InvalidConfiguration.Throw(); } // // Add Identity for User Persists ... services.AddIdentity(options => { // var mLockoutSpan = xIdentityHelper.GetLockoutTimeSpan(); // // Lockout Setting ... options.Lockout.DefaultLockoutTimeSpan = mLockoutSpan; options.Lockout.MaxFailedAccessAttempts = xIdentityConfiguration.Policy.Lockout.MaxFailedAccessAttempts; options.Lockout.AllowedForNewUsers = xIdentityConfiguration.Policy.Lockout.AllowedForNewUsers; // // Password settings ... options.Password.RequireDigit = xIdentityConfiguration.Policy.Password.RequireDigit; options.Password.RequireLowercase = xIdentityConfiguration.Policy.Password.RequireLowercase; options.Password.RequireNonAlphanumeric = xIdentityConfiguration.Policy.Password.RequireNonAlphanumeric; options.Password.RequireUppercase = xIdentityConfiguration.Policy.Password.RequireUppercase; options.Password.RequiredLength = xIdentityConfiguration.Policy.Password.RequiredLength; options.Password.RequiredUniqueChars = xIdentityConfiguration.Policy.Password.RequiredUniqueChars; // // SignIn settings ... options.SignIn.RequireConfirmedEmail = xIdentityConfiguration.Policy.SignIn.RequireConfirmedEmail; options.SignIn.RequireConfirmedPhoneNumber = xIdentityConfiguration.Policy.SignIn.RequireConfirmedPhoneNumber; // // User settings ... options.User.AllowedUserNameCharacters = xIdentityConfiguration.Policy.User.AllowedUserNameCharacters; options.User.RequireUniqueEmail = xIdentityConfiguration.Policy.User.RequireUniqueEmail; }) .AddEntityFrameworkStores() .AddDefaultTokenProviders(); } /// /// Register IdentityServer Based Authentication /// /// /// public static void AddXIdentityServerAuthentication( this IServiceCollection services, IConfiguration configuration ) { // services.AddXIdentityResourceConfiguration(configuration); services.AddAuthentication() .AddJwtBearer(options => { // options.SaveToken = true; options.RequireHttpsMetadata = false; // options.ForwardDefault = XAuthentication.IDENTITY_SERVER_LOCAL_API; }) .AddLocalApi(); } /// /// Register Authorization Policies /// /// /// public static void AddXAuthorization( this IServiceCollection services, IDictionary policies = null ) { // services.AddAuthorization(options => { // if (!policies.IsNull()) { // // Fill Policies ... using (var policiesEnumerator = policies.GetEnumerator()) { while (policiesEnumerator.MoveNext()) { var policyDescriptor = policiesEnumerator.Current; options.AddPolicy(policyDescriptor.Key, policyDescriptor.Value); } } } // var xPolicies = XAuthorizationHelper.GetXAuthorizationPolicies(); if (!xPolicies.IsNull()) { // // Fill Policies ... using (var policiesEnumerator = xPolicies.GetEnumerator()) { while (policiesEnumerator.MoveNext()) { var policyDescriptor = policiesEnumerator.Current; options.AddPolicy(policyDescriptor.Key, policyDescriptor.Value); } } } // // Add Local APi Policy ... options.AddPolicy(IdentityServerConstants.LocalApi.PolicyName, policy => { // policy.AddAuthenticationSchemes(IdentityServerConstants.LocalApi.AuthenticationScheme); policy.RequireAuthenticatedUser(); }); }); // services.AddSingleton(); } /// /// Use Forward Headers Options for resolving behind a proxy issues ... /// /// /// public static void UseXForwardOptions(this IApplicationBuilder source) { // var forwardOptions = new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto, RequireHeaderSymmetry = false }; // forwardOptions.KnownNetworks.Clear(); forwardOptions.KnownProxies.Clear(); // // ref: https://github.com/aspnet/Docs/issues/2384 source.UseForwardedHeaders(forwardOptions); } } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Extensions\DbExtensions.cs 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 { /// /// Retrieve Data Provider Type from Configurations /// /// /// 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; } /// /// Retrieve AspNet Identity Configurations /// /// /// public static XIdentityConfiguration GetXIdentityConfiguration(this IConfiguration source) { // var xIdentityConfigSection = source .GetSection(ConfigurationNodeNames.IDENTITY_NODE_NAME); return xIdentityConfigSection.Get(); } /// /// Retrieve XIdentityResource Configuration from AppSettings /// /// /// public static XIdentityResourceConfiguration GetXIdentityResourceConfiguration(this IConfiguration configuration) { // var xIdentityResourceSection = configuration.GetSection(ConfigurationNodeNames.IDENTITY_RESOURCE_NODE_NAME); return xIdentityResourceSection.Get(); } /// /// Register XIdentityResourceConfiguration /// /// /// public static void AddXIdentityResourceConfiguration( this IServiceCollection services, IConfiguration configuration ) { // var xIdentityResourceConfiguration = configuration.GetXIdentityResourceConfiguration(); if (!xIdentityResourceConfiguration.IsNull()) { services.AddSingleton(xIdentityResourceConfiguration); } } /// /// Converts DbInfo Options Builder for MySql Usage /// /// /// public static Action GetMySqlOptionsBuilder(this XDbInfo source) { return ((Action)source.OptionsBuilder); } /// /// Converts DbInfo Options Builder for SQLite Usage /// /// /// public static Action GetSQLiteOptionsBuilder(this XDbInfo source) { return ((Action)source.OptionsBuilder); } /// /// Converts DbInfo Options Builder for SQLServer Usage /// /// /// public static Action GetSQLServerOptionsBuilder(this XDbInfo source) { return ((Action)source.OptionsBuilder); } /// /// Retrieve Required Informations to Register DbContexts into Di as XDbInfo instance /// /// /// public static XDbInfo GetXDbInfo(this IConfiguration configuration) { return new XDbInfo { ProviderType = configuration.GetXDbProviderType(), MigrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name }; } /// /// Prepare DbContextOptionsBuilder with Propper data to Support Configured DbProvider /// /// /// /// 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() ); } } } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Extensions\IdentityExtensions.cs using Microsoft.Extensions.DependencyInjection; using xIds.Interfaces; using xIds.Providers; namespace xIds.Extensions { public static class IdentityExtensions { /// /// Register IdentityManager /// /// public static void AddXIdentityManager(this IServiceCollection source) { source.AddScoped(); } /// /// Register IdentityMessage Provider /// /// public static void AddXIdentityMessageProvider( this IServiceCollection source ) { source.AddScoped(); } } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Extensions\IIdentityServerBuilderExtensions.cs 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 { /// /// Add Support for Configured XDbProvider to IdentityServer /// /// /// /// 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; } /// /// Set Configured Certificate File to IdentityServer /// /// /// /// 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; } } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Extensions\IQueryableExtensions.cs 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 { } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Extensions\XDbSeederExtensions.cs 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 ..."); } } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Extensions\XModelExtensions.cs 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 { /// /// Determine a banned time is passed or not /// /// /// /// public static bool IsDelayTimePassed( this XBannedDevice source, int delaySeconds ) { // var passedTime = source.BannedOn.AddSeconds(delaySeconds); // var result = DateTime.UtcNow >= passedTime; // return result; } /// /// Applying Filter to IQueryable /// /// /// public static async Task> ApplyFilterAsync( this IQueryable source, string filter ) where T : class { // // Apply Filter ... if (!filter.IsNullOrEmpty()) { // var items = source.AsAsyncEnumerable(); var filteredItems = new List(); 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; } } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Helpers\XIdentityHelper.cs using System; using System.IdentityModel.Tokens.Jwt; using Microsoft.IdentityModel.Tokens; using xCommons.Extensions; using xCommons.Providers; using xExceptions.Constants; using xIdentityModels.Configurations; using xIdentityModels.Extensions; using xIdentityModels.Models; using xIds.Interfaces; namespace xIds.Helpers { public class XIdentityHelper : IXIdentityHelper { private readonly XIdentityConfiguration configurations; private readonly JwtSecurityTokenHandler tokenHandler; private readonly XValidationProvider dataValidationHelper; public XIdentityHelper( XIdentityConfiguration configurations, XValidationProvider dataValidationHelper ) { // this.configurations = configurations; this.tokenHandler = new JwtSecurityTokenHandler(); this.dataValidationHelper = dataValidationHelper; } // #region Configuration Parser ... /// /// Generate a Key for Signing JWT Tokens /// /// public SymmetricSecurityKey GetTokenSecretKey() { // dataValidationHelper .NotEmpty(configurations.IdentitySecretKey); // var result = new SymmetricSecurityKey(configurations .IdentitySecretKey.ToBytes()); // return result; } /// /// Generate Security Token Signing Key /// /// public SigningCredentials GetTokenSigningCredentials() { // var key = GetTokenSecretKey(); dataValidationHelper .NotNull(key); // var result = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); // return result; } /// /// Get Token Validation Parameters /// /// public TokenValidationParameters GetTokenValidationParams() { // var key = GetTokenSecretKey(); var issuer = configurations.IdentityIssuer; var audience = configurations.IdentityAudience; // dataValidationHelper .NotNull(key); dataValidationHelper .NotEmpty(issuer, audience); // var result = new TokenValidationParameters { ValidIssuer = issuer, ValidAudience = audience, ValidateLifetime = true, IssuerSigningKey = key }; // return result; } /// /// Get Account Lockout Time Span after Max Fail Reached /// /// public TimeSpan GetLockoutTimeSpan() { // dataValidationHelper .NotNull(configurations.Policy, configurations.Policy.Lockout); // var timeSpanString = configurations.Policy.Lockout.LockoutTimeSpanProvider; dataValidationHelper .NotEmpty(timeSpanString); // var mExpireValue = 0; var mExpireValueStr = timeSpanString.GetDigits(); var mExpireUnit = timeSpanString.Replace(mExpireValueStr, ""); dataValidationHelper .NotEmpty(mExpireUnit); dataValidationHelper .NotEmpty(mExpireValueStr); // var isParsed = int.TryParse(mExpireValueStr, out mExpireValue); // switch (mExpireUnit) { case "d": return TimeSpan.FromDays(mExpireValue); case "h": return TimeSpan.FromHours(mExpireValue); case "m": return TimeSpan.FromMinutes(mExpireValue); case "s": return TimeSpan.FromSeconds(mExpireValue); case "ms": default: return TimeSpan.FromMilliseconds(mExpireValue); } } /// /// Generate Security Token Descriptor for Tokenize another /// /// public SecurityTokenDescriptor GetActionTokenDescriptor() { // dataValidationHelper .NotNull(configurations); // var issuer = configurations.IdentityIssuer; var audience = configurations.IdentityAudience; dataValidationHelper .NotEmpty(issuer, audience); // var expDate = GetActionTokenExpirationDate(); var signingCreds = GetTokenSigningCredentials(); dataValidationHelper .NotNull(expDate, signingCreds); // var descriptor = new SecurityTokenDescriptor { Issuer = issuer, Audience = audience, Expires = expDate, SigningCredentials = signingCreds }; // return descriptor; } /// /// Get Action Token Expiration Date /// /// public DateTime GetActionTokenExpirationDate() { // dataValidationHelper .NotNull(configurations); // var expDateProvider = configurations .ActionTokenExpirationDateProvider; dataValidationHelper .NotEmpty(expDateProvider); // var result = GetExpirationTime(expDateProvider); dataValidationHelper .NotNull(result); // return result; } #endregion // #region Action Token Handlers ... public bool ValidateToken(string token) { // // Validate Args ... dataValidationHelper .NotEmpty(token); dataValidationHelper .NotNull(tokenHandler); // // Prepare Requirements ... var tokenValidationParams = GetTokenValidationParams(); dataValidationHelper .NotNull(tokenValidationParams); // var result = token .ValidateToken(tokenHandler, tokenValidationParams); // return result; } /// /// Converts a Token string to SecurityToken instance /// /// /// public SecurityToken ToSecurityToken(string token) { // dataValidationHelper .NotEmpty(token); // // Validate token ... var isTokenValid = ValidateToken(token); if (!isTokenValid) { XException.InvalidToken.Throw(); } // // Prepare and Validate Requirements ... var tokenValidationParams = GetTokenValidationParams(); dataValidationHelper .NotNull(tokenHandler, tokenValidationParams); // var result = token .ToSecurityToken(tokenHandler, tokenValidationParams); dataValidationHelper .NotNull(result); // return result; } /// /// Convert an ActionRequest to Token Object /// /// /// public SecurityToken ToSecurityToken(XActionRequestToken request) { // var tokenDescriptor = GetActionTokenDescriptor(); // dataValidationHelper.NotNull(request, tokenHandler, tokenDescriptor); // var result = request.ToJwtToken(tokenHandler, tokenDescriptor); // return result; } /// /// Retrieve a Token Exiration Date /// /// /// public DateTime GetTokenExpirationDate(string token) { // var tokenObj = ToSecurityToken(token); dataValidationHelper.NotNull(tokenObj); // var result = tokenObj.ValidTo; // return result; } public XActionRequestToken ParseActionRequestToken(string token) { // dataValidationHelper .NotEmpty(token); // // Validate token ... var isTokenValid = ValidateToken(token); if (!isTokenValid) { XException.InvalidToken.Throw(); } // // Prepare and Validate Requirements ... var tokenValidationParams = GetTokenValidationParams(); dataValidationHelper .NotNull(tokenHandler, tokenValidationParams); // var result = token .ParseActionRequestToken(tokenHandler, tokenValidationParams); dataValidationHelper .NotNull(result); // return result; } /// /// Convert a JWT Security Token Object to /// it's String Representation /// /// /// public string ToTokenString(JwtSecurityToken token) { // dataValidationHelper.NotNull(token); // var result = tokenHandler .WriteToken(token); // return result; } /// /// Convert an Action Token Object to it's String Representation /// /// /// public string ToTokenString(SecurityToken token) { // // Validate Args ... dataValidationHelper .NotNull(token, tokenHandler); // // Generate and return Result ... var result = token.ToTokenString(tokenHandler); dataValidationHelper .NotEmpty(result); // return result; } #endregion // #region Private Actions ... /// /// Calculating Date Difference Provider String /// and Generate Date based on UTC Time /// /// /// private DateTime GetExpirationTime(string expirationProvider) { // dataValidationHelper .NotEmpty(expirationProvider); // var mExpireValue = 0; var mExpireValueStr = expirationProvider.GetDigits(); var mExpireUnit = expirationProvider.Replace(mExpireValueStr, ""); dataValidationHelper .NotEmpty(mExpireUnit); dataValidationHelper .NotEmpty(mExpireValueStr); // var isParsed = int.TryParse(mExpireValueStr, out mExpireValue); // switch (mExpireUnit) { case "d": return DateTime.UtcNow.AddDays(mExpireValue); case "h": return DateTime.UtcNow.AddHours(mExpireValue); case "m": return DateTime.UtcNow.AddMinutes(mExpireValue); case "s": return DateTime.UtcNow.AddSeconds(mExpireValue); case "ms": default: return DateTime.UtcNow.AddMilliseconds(mExpireValue); } } #endregion } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Interfaces\IXIdentityHelper.cs using System; using System.IdentityModel.Tokens.Jwt; using Microsoft.IdentityModel.Tokens; using xIdentityModels.Models; namespace xIds.Interfaces { public interface IXIdentityHelper { // #region Configuration Parser ... SymmetricSecurityKey GetTokenSecretKey(); SigningCredentials GetTokenSigningCredentials(); TokenValidationParameters GetTokenValidationParams(); TimeSpan GetLockoutTimeSpan(); #endregion // #region Action Token Handlers ... bool ValidateToken(string token); SecurityToken ToSecurityToken(string token); SecurityToken ToSecurityToken(XActionRequestToken request); string ToTokenString(SecurityToken token); string ToTokenString(JwtSecurityToken token); DateTime GetTokenExpirationDate(string token); XActionRequestToken ParseActionRequestToken(string token); #endregion } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Interfaces\IXIdentityManager.cs using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Security.Claims; using System.Threading.Tasks; using IdentityModel.Client; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Logging; using xCommons.Providers; using xIdentityModels; using xIdentityModels.Constants; using xIdentityModels.Descriptors; using xIdentityModels.Dtos; using xIdentityModels.Models; using xIdentityModels.Navigations; using xIds.DbContext; using xModels.Dtos; namespace xIds.Interfaces { public interface IXIdentityManager { XIdentityDbContext DbContext { get; } UserManager UserManager { get; } ILogger Logger { get; } SignInManager SignInManager { get; } IXSecurityProvider SecurityProvider { get; } RoleManager RoleManager { get; } XValidationProvider ValidationProvider { get; } // #region Class Getter (s) Methods ... IQueryable GetUsersDbSet( bool containsDetail = false ); IQueryable GetUsersFullDbSet(bool enableTracking = false); #endregion // #region Tools ... string GetUserSelectByParam( XActionRequest model, bool forceNotNull = true, ICollection excludes = null ); Task ValidateUserExistsAndRetrieve( string userSelectByParam, bool containsDetail = false, bool checkCanLoginPolicies = false, bool checkIsBanned = true, bool ignoreDisabledUser = false, bool forceAdmin = false, Exception exception = null ); #endregion // #region Default Identity Preparation Actions ... Task CreateIdentityRoles(); Task CreateUserAsync(XIdentityUserDescriptor user); #endregion // #region Identity Actions ... HttpClient GetHttpClient(); Task RequestScopeAccessToken(string scope); Task RequestDiscoveryDocument(); Task Authenticate(XLoginRequest model); Task Login(XLoginRequest model); Task RefreshTokens(XTokenResponse model); #endregion // #region Role Handlers ... Task IsRoleExistsAsync(string roleName); Task CreateRoleAsync(string roleName); Task GetRoleAsync(string roleName); Task AddUserToRoleAsync(XUser user, string roleName); Task GetRoleNameAsync(string roleId); Task> GetRoleNamesAsync( string userSelectByParam, bool checkCanLoginPolicies = true, bool checkIsBanned = true ); Task RemoveFromRoleAsync(XUser user, string roleName); Task RemoveFromRolesAsync(XUser user, IEnumerable roleNames); #endregion // #region User Handlers ... Task CanRegister(string userSelectByParam); Task IsUserExistsAsync(string userSelectByParam); Task GetUserAsync( string userSelectByParam, bool containsDetail = false); Task CreateUserAsync( XUser user, string password, bool checkCanLoginPolicies = true, bool checkIsBanned = true ); Task UpdateUserAsync( XUser user, bool checkCanLoginPolicies = true, bool checkIsBanned = true ); Task> GetUserNamesAsync( IEnumerable userIds ); Task> GetUserNameIdsAsync( XUserNameIdRequest model ); Task ToJwtClaims( XUser user, bool checkCanLoginPolicies = true, bool checkIsBanned = true ); Task CheckPasswordSignInAsync( XUser user, string password, XDevice device, string language, bool lockoutOnFailure, bool isForced = true ); #endregion // #region User Profile Handlers ... Task GetUserProfileAsync( string userSelectByParam, string requestedUserSelectByParam, bool forceCheckRequestedUser = true, bool checkCanLoginPolicies = true, bool checkIsBanned = true ); Task> QueryUsers( string requestedUserSelectByParam, XQuery query ); Task> QueryInRoleUsers( string requestedUserSelectByParam, string role, XQuery query, bool forceRole = false ); Task> GetUserProfilesAsync( ICollection ids, string requestedUserSelectByParam, bool forceCheckRequestedUser = true, bool checkCanLoginPolicies = true, bool checkIsBanned = true ); Task> QueryAvatars( string userSelectByParam, XQuery query ); Task ProfileUpdateAsync( string userSelectByParam, string requestedUserSelectByParam, XProfileUpdateRequest request ); Task FullProfileUpdateAsync( string userSelectByParam, string requestedUserSelectByParam, XProfileUpdateRequest request ); Task RequestConfirmMobile( string lang, XDevice device, string userSelectByParam, string password, string mobileNumber = null ); Task RequestConfirmEmail( string lang, XDevice device, string userSelectByParam, string password, string emailAddress = null ); Task RequestResetPassword( string lang, XDevice device, string userSelectByParam, string returnUrl ); Task RequestConfirmRegistration( string lang, XDevice device, string userSelectByParam, string password, string returnUrl ); Task ChangePassword( string lang, XDevice device, string userSelectByParam, string password, string newPassword, string returnUrl ); Task ResetPassword( string lang, XDevice device, string actionHash, string newPassword, string returnUrl ); Task AddAvatar( string userSelectByParam, IFormFile file ); Task AddAvatars( string userSelectByParam, IFormFileCollection files ); Task SetAvatar( string userSelectByParam, int profileImageId ); Task RemoveAvatar( string userSelectByParam, ICollection profileImageIds ); Task ConfirmRegistration( string lang, XDevice device, string actionHash, string returnUrl ); Task ConfirmMobileNumber( string lang, XDevice device, string registrationHash, string verificationCode ); Task ConfirmEmailAddress( string lang, XDevice device, string registrationHash, string verificationCode ); Task IsConfirmedEmail(string userSelectByParam); Task IsConfirmedMobile(string userSelectByParam); #endregion // #region Registration Handlers ... Task InviteUser( string lang, XDevice device, string email, string handlerUrl ); Task RequestRegistration( string lang, XDevice device, string invitationHash, string firstName, string lastName, DateTime dateOfBirth, string mobileNumber = null, string emailAddress = null ); Task AddAcountInfo( string lang, XDevice device, string registrationHash, string userName, string password ); Task AttachProfileImage( string tokenHash, IFormFile file ); Task FinishRegistration( string lang, XDevice device, string userSelectByParam, string password, string returnUrl ); #endregion // #region Friendship Handlers ... // #region Actions ... Task Follow( string userSelectByParam, string destUserSelectByParam ); Task Cancel( string userSelectByParam, string destUserSelectByParam ); Task UnFollowFollower( string userSelectByParam, string destUserSelectByParam ); Task UnFollowFollowing( string userSelectByParam, string destUserSelectByParam ); Task Block( string userSelectByParam, string destUserSelectByParam ); Task UnBlock( string userSelectByParam, string destUserSelectByParam ); #endregion // #region Request Handlers ... Task AcceptRequest( string userSelectByParam, string destUserSelectByParam ); Task RejectRequest( string userSelectByParam, string destUserSelectByParam ); #endregion // #region Getters ... Task IsFollower( string userSelectByParam, string destUserSelectByParam, bool checkIsBanned = true, bool checkCanLoginPolicies = true ); Task GetFollowerState( string userSelectByParam, string destUserSelectByParam, bool checkIsBanned = true, bool checkCanLoginPolicies = true ); Task GetFollower( string userSelectByParam, string destUserSelectByParam ); Task> GetFollowers(string userSelectByParam); Task> GetAllFollowers(string userSelectByParam); Task> GetFollowersList(string userSelectByParam); Task> QueryFollowers( XQuery query, string userSelectByParam ); Task IsFollowing( string userSelectByParam, string destUserSelectByParam, bool checkIsBanned = true, bool checkCanLoginPolicies = true ); Task GetFollowingState( string userSelectByParam, string destUserSelectByParam, bool checkIsBanned = true, bool checkCanLoginPolicies = true ); Task GetFollowing( string userSelectByParam, string destUserSelectByParam ); Task> GetFollowings(string userSelectByParam); Task> GetAllFollowings(string userSelectByParam); Task> GetFollowingList(string userSelectByParam); Task> QueryFollowings( XQuery query, string userSelectByParam ); #endregion // Task GetFriendshipInfo( string userSelectByParam, string destUserSelectByParam, bool checkCanLoginPolicies = true, bool checkIsBanned = true ); #endregion // #region Admin Actions ... Task> Ban( string userSelectByParam, XUserNameIdRequest model ); Task> UnBan( string userSelectByParam, XUserNameIdRequest model ); Task IsBanned( string userSelectByParam, string destUserSelectByParam ); #endregion // #region Open Actions ... // #region OpenGet ... Task OpenGet( XOpenActionInnerDto model ); Task OpenGet( string token, string actionRequest ); #endregion Task GetUserInfo( XOpenActionRequestDto dto ); Task> GetUserInfos( XOpenActionRequestDto dto ); #endregion // #region Search ... /// /// Query Open To Search User Profiles ... /// /// requested user's identifier /// how to filter results based on XQuery structure /// an instance of XQueryResult of XUserProfileDto Task> QueryOpenToSearchUsers( string requestedUserSelectByParam, XQuery query ); #endregion // #region Query Service ... /// /// Retrieve Users as Query Model for Query Service ... /// /// /// /// /// /// public Task> QueryUsers( string requestedUserSelectByParam, XQuery query, string role = null, bool forceRole = false ); #endregion } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Interfaces\IXIdentityMessageProvider.cs namespace xIds.Interfaces { public interface IXIdentityMessageProvider { string InviteMsg { get; } string RegistrationApproveMsg { get; } string RegisteredMsg { get; } string VerificationCodeMsg { get; } string ChangePasswordMsg { get; } string PasswordChangedMsg { get; } string NewDeviceLoggedInMsg { get; } bool IsReady(); void PrepareMessages(string lang); } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Interfaces\IXSecurityProvider.cs namespace xIds.Interfaces { public interface IXSecurityProvider { string Encrypt(string plainText); string Decrypt(string cipherText); string EncryptFromBytes(byte[] textBytes); string DecryptFromBytes(byte[] cipherBytes); } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Migrations\20260906032642_InitialConfigurationMigration.cs using System; using Microsoft.EntityFrameworkCore.Migrations; namespace xIds.Migrations { public partial class InitialConfigurationMigration : Migration { protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.CreateTable( name: "ApiResources", columns: table => new { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), Enabled = table.Column(type: "INTEGER", nullable: false), Name = table.Column(type: "TEXT", maxLength: 200, nullable: false), DisplayName = table.Column(type: "TEXT", maxLength: 200, nullable: true), Description = table.Column(type: "TEXT", maxLength: 1000, nullable: true), AllowedAccessTokenSigningAlgorithms = table.Column(type: "TEXT", maxLength: 100, nullable: true), ShowInDiscoveryDocument = table.Column(type: "INTEGER", nullable: false), Created = table.Column(type: "TEXT", nullable: false), Updated = table.Column(type: "TEXT", nullable: true), LastAccessed = table.Column(type: "TEXT", nullable: true), NonEditable = table.Column(type: "INTEGER", nullable: false) }, constraints: table => { table.PrimaryKey("PK_ApiResources", x => x.Id); }); migrationBuilder.CreateTable( name: "ApiScopes", columns: table => new { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), Enabled = table.Column(type: "INTEGER", nullable: false), Name = table.Column(type: "TEXT", maxLength: 200, nullable: false), DisplayName = table.Column(type: "TEXT", maxLength: 200, nullable: true), Description = table.Column(type: "TEXT", maxLength: 1000, nullable: true), Required = table.Column(type: "INTEGER", nullable: false), Emphasize = table.Column(type: "INTEGER", nullable: false), ShowInDiscoveryDocument = table.Column(type: "INTEGER", nullable: false) }, constraints: table => { table.PrimaryKey("PK_ApiScopes", x => x.Id); }); migrationBuilder.CreateTable( name: "Clients", columns: table => new { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), Enabled = table.Column(type: "INTEGER", nullable: false), ClientId = table.Column(type: "TEXT", maxLength: 200, nullable: false), ProtocolType = table.Column(type: "TEXT", maxLength: 200, nullable: false), RequireClientSecret = table.Column(type: "INTEGER", nullable: false), ClientName = table.Column(type: "TEXT", maxLength: 200, nullable: true), Description = table.Column(type: "TEXT", maxLength: 1000, nullable: true), ClientUri = table.Column(type: "TEXT", maxLength: 2000, nullable: true), LogoUri = table.Column(type: "TEXT", maxLength: 2000, nullable: true), RequireConsent = table.Column(type: "INTEGER", nullable: false), AllowRememberConsent = table.Column(type: "INTEGER", nullable: false), AlwaysIncludeUserClaimsInIdToken = table.Column(type: "INTEGER", nullable: false), RequirePkce = table.Column(type: "INTEGER", nullable: false), AllowPlainTextPkce = table.Column(type: "INTEGER", nullable: false), RequireRequestObject = table.Column(type: "INTEGER", nullable: false), AllowAccessTokensViaBrowser = table.Column(type: "INTEGER", nullable: false), FrontChannelLogoutUri = table.Column(type: "TEXT", maxLength: 2000, nullable: true), FrontChannelLogoutSessionRequired = table.Column(type: "INTEGER", nullable: false), BackChannelLogoutUri = table.Column(type: "TEXT", maxLength: 2000, nullable: true), BackChannelLogoutSessionRequired = table.Column(type: "INTEGER", nullable: false), AllowOfflineAccess = table.Column(type: "INTEGER", nullable: false), IdentityTokenLifetime = table.Column(type: "INTEGER", nullable: false), AllowedIdentityTokenSigningAlgorithms = table.Column(type: "TEXT", maxLength: 100, nullable: true), AccessTokenLifetime = table.Column(type: "INTEGER", nullable: false), AuthorizationCodeLifetime = table.Column(type: "INTEGER", nullable: false), ConsentLifetime = table.Column(type: "INTEGER", nullable: true), AbsoluteRefreshTokenLifetime = table.Column(type: "INTEGER", nullable: false), SlidingRefreshTokenLifetime = table.Column(type: "INTEGER", nullable: false), RefreshTokenUsage = table.Column(type: "INTEGER", nullable: false), UpdateAccessTokenClaimsOnRefresh = table.Column(type: "INTEGER", nullable: false), RefreshTokenExpiration = table.Column(type: "INTEGER", nullable: false), AccessTokenType = table.Column(type: "INTEGER", nullable: false), EnableLocalLogin = table.Column(type: "INTEGER", nullable: false), IncludeJwtId = table.Column(type: "INTEGER", nullable: false), AlwaysSendClientClaims = table.Column(type: "INTEGER", nullable: false), ClientClaimsPrefix = table.Column(type: "TEXT", maxLength: 200, nullable: true), PairWiseSubjectSalt = table.Column(type: "TEXT", maxLength: 200, nullable: true), Created = table.Column(type: "TEXT", nullable: false), Updated = table.Column(type: "TEXT", nullable: true), LastAccessed = table.Column(type: "TEXT", nullable: true), UserSsoLifetime = table.Column(type: "INTEGER", nullable: true), UserCodeType = table.Column(type: "TEXT", maxLength: 100, nullable: true), DeviceCodeLifetime = table.Column(type: "INTEGER", nullable: false), NonEditable = table.Column(type: "INTEGER", nullable: false) }, constraints: table => { table.PrimaryKey("PK_Clients", x => x.Id); }); migrationBuilder.CreateTable( name: "IdentityResources", columns: table => new { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), Enabled = table.Column(type: "INTEGER", nullable: false), Name = table.Column(type: "TEXT", maxLength: 200, nullable: false), DisplayName = table.Column(type: "TEXT", maxLength: 200, nullable: true), Description = table.Column(type: "TEXT", maxLength: 1000, nullable: true), Required = table.Column(type: "INTEGER", nullable: false), Emphasize = table.Column(type: "INTEGER", nullable: false), ShowInDiscoveryDocument = table.Column(type: "INTEGER", nullable: false), Created = table.Column(type: "TEXT", nullable: false), Updated = table.Column(type: "TEXT", nullable: true), NonEditable = table.Column(type: "INTEGER", nullable: false) }, constraints: table => { table.PrimaryKey("PK_IdentityResources", x => x.Id); }); migrationBuilder.CreateTable( name: "ApiResourceClaims", columns: table => new { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), ApiResourceId = table.Column(type: "INTEGER", nullable: false), Type = table.Column(type: "TEXT", maxLength: 200, nullable: false) }, constraints: table => { table.PrimaryKey("PK_ApiResourceClaims", x => x.Id); table.ForeignKey( name: "FK_ApiResourceClaims_ApiResources_ApiResourceId", column: x => x.ApiResourceId, principalTable: "ApiResources", principalColumn: "Id", onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateTable( name: "ApiResourceProperties", columns: table => new { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), ApiResourceId = table.Column(type: "INTEGER", nullable: false), Key = table.Column(type: "TEXT", maxLength: 250, nullable: false), Value = table.Column(type: "TEXT", maxLength: 2000, nullable: false) }, constraints: table => { table.PrimaryKey("PK_ApiResourceProperties", x => x.Id); table.ForeignKey( name: "FK_ApiResourceProperties_ApiResources_ApiResourceId", column: x => x.ApiResourceId, principalTable: "ApiResources", principalColumn: "Id", onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateTable( name: "ApiResourceScopes", columns: table => new { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), Scope = table.Column(type: "TEXT", maxLength: 200, nullable: false), ApiResourceId = table.Column(type: "INTEGER", nullable: false) }, constraints: table => { table.PrimaryKey("PK_ApiResourceScopes", x => x.Id); table.ForeignKey( name: "FK_ApiResourceScopes_ApiResources_ApiResourceId", column: x => x.ApiResourceId, principalTable: "ApiResources", principalColumn: "Id", onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateTable( name: "ApiResourceSecrets", columns: table => new { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), ApiResourceId = table.Column(type: "INTEGER", nullable: false), Description = table.Column(type: "TEXT", maxLength: 1000, nullable: true), Value = table.Column(type: "TEXT", maxLength: 4000, nullable: false), Expiration = table.Column(type: "TEXT", nullable: true), Type = table.Column(type: "TEXT", maxLength: 250, nullable: false), Created = table.Column(type: "TEXT", nullable: false) }, constraints: table => { table.PrimaryKey("PK_ApiResourceSecrets", x => x.Id); table.ForeignKey( name: "FK_ApiResourceSecrets_ApiResources_ApiResourceId", column: x => x.ApiResourceId, principalTable: "ApiResources", principalColumn: "Id", onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateTable( name: "ApiScopeClaims", columns: table => new { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), ScopeId = table.Column(type: "INTEGER", nullable: false), Type = table.Column(type: "TEXT", maxLength: 200, nullable: false) }, constraints: table => { table.PrimaryKey("PK_ApiScopeClaims", x => x.Id); table.ForeignKey( name: "FK_ApiScopeClaims_ApiScopes_ScopeId", column: x => x.ScopeId, principalTable: "ApiScopes", principalColumn: "Id", onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateTable( name: "ApiScopeProperties", columns: table => new { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), ScopeId = table.Column(type: "INTEGER", nullable: false), Key = table.Column(type: "TEXT", maxLength: 250, nullable: false), Value = table.Column(type: "TEXT", maxLength: 2000, nullable: false) }, constraints: table => { table.PrimaryKey("PK_ApiScopeProperties", x => x.Id); table.ForeignKey( name: "FK_ApiScopeProperties_ApiScopes_ScopeId", column: x => x.ScopeId, principalTable: "ApiScopes", principalColumn: "Id", onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateTable( name: "ClientClaims", columns: table => new { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), Type = table.Column(type: "TEXT", maxLength: 250, nullable: false), Value = table.Column(type: "TEXT", maxLength: 250, nullable: false), ClientId = table.Column(type: "INTEGER", nullable: false) }, constraints: table => { table.PrimaryKey("PK_ClientClaims", x => x.Id); table.ForeignKey( name: "FK_ClientClaims_Clients_ClientId", column: x => x.ClientId, principalTable: "Clients", principalColumn: "Id", onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateTable( name: "ClientCorsOrigins", columns: table => new { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), Origin = table.Column(type: "TEXT", maxLength: 150, nullable: false), ClientId = table.Column(type: "INTEGER", nullable: false) }, constraints: table => { table.PrimaryKey("PK_ClientCorsOrigins", x => x.Id); table.ForeignKey( name: "FK_ClientCorsOrigins_Clients_ClientId", column: x => x.ClientId, principalTable: "Clients", principalColumn: "Id", onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateTable( name: "ClientGrantTypes", columns: table => new { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), GrantType = table.Column(type: "TEXT", maxLength: 250, nullable: false), ClientId = table.Column(type: "INTEGER", nullable: false) }, constraints: table => { table.PrimaryKey("PK_ClientGrantTypes", x => x.Id); table.ForeignKey( name: "FK_ClientGrantTypes_Clients_ClientId", column: x => x.ClientId, principalTable: "Clients", principalColumn: "Id", onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateTable( name: "ClientIdPRestrictions", columns: table => new { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), Provider = table.Column(type: "TEXT", maxLength: 200, nullable: false), ClientId = table.Column(type: "INTEGER", nullable: false) }, constraints: table => { table.PrimaryKey("PK_ClientIdPRestrictions", x => x.Id); table.ForeignKey( name: "FK_ClientIdPRestrictions_Clients_ClientId", column: x => x.ClientId, principalTable: "Clients", principalColumn: "Id", onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateTable( name: "ClientPostLogoutRedirectUris", columns: table => new { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), PostLogoutRedirectUri = table.Column(type: "TEXT", maxLength: 2000, nullable: false), ClientId = table.Column(type: "INTEGER", nullable: false) }, constraints: table => { table.PrimaryKey("PK_ClientPostLogoutRedirectUris", x => x.Id); table.ForeignKey( name: "FK_ClientPostLogoutRedirectUris_Clients_ClientId", column: x => x.ClientId, principalTable: "Clients", principalColumn: "Id", onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateTable( name: "ClientProperties", columns: table => new { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), ClientId = table.Column(type: "INTEGER", nullable: false), Key = table.Column(type: "TEXT", maxLength: 250, nullable: false), Value = table.Column(type: "TEXT", maxLength: 2000, nullable: false) }, constraints: table => { table.PrimaryKey("PK_ClientProperties", x => x.Id); table.ForeignKey( name: "FK_ClientProperties_Clients_ClientId", column: x => x.ClientId, principalTable: "Clients", principalColumn: "Id", onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateTable( name: "ClientRedirectUris", columns: table => new { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), RedirectUri = table.Column(type: "TEXT", maxLength: 2000, nullable: false), ClientId = table.Column(type: "INTEGER", nullable: false) }, constraints: table => { table.PrimaryKey("PK_ClientRedirectUris", x => x.Id); table.ForeignKey( name: "FK_ClientRedirectUris_Clients_ClientId", column: x => x.ClientId, principalTable: "Clients", principalColumn: "Id", onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateTable( name: "ClientScopes", columns: table => new { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), Scope = table.Column(type: "TEXT", maxLength: 200, nullable: false), ClientId = table.Column(type: "INTEGER", nullable: false) }, constraints: table => { table.PrimaryKey("PK_ClientScopes", x => x.Id); table.ForeignKey( name: "FK_ClientScopes_Clients_ClientId", column: x => x.ClientId, principalTable: "Clients", principalColumn: "Id", onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateTable( name: "ClientSecrets", columns: table => new { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), ClientId = table.Column(type: "INTEGER", nullable: false), Description = table.Column(type: "TEXT", maxLength: 2000, nullable: true), Value = table.Column(type: "TEXT", maxLength: 4000, nullable: false), Expiration = table.Column(type: "TEXT", nullable: true), Type = table.Column(type: "TEXT", maxLength: 250, nullable: false), Created = table.Column(type: "TEXT", nullable: false) }, constraints: table => { table.PrimaryKey("PK_ClientSecrets", x => x.Id); table.ForeignKey( name: "FK_ClientSecrets_Clients_ClientId", column: x => x.ClientId, principalTable: "Clients", principalColumn: "Id", onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateTable( name: "IdentityResourceClaims", columns: table => new { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), IdentityResourceId = table.Column(type: "INTEGER", nullable: false), Type = table.Column(type: "TEXT", maxLength: 200, nullable: false) }, constraints: table => { table.PrimaryKey("PK_IdentityResourceClaims", x => x.Id); table.ForeignKey( name: "FK_IdentityResourceClaims_IdentityResources_IdentityResourceId", column: x => x.IdentityResourceId, principalTable: "IdentityResources", principalColumn: "Id", onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateTable( name: "IdentityResourceProperties", columns: table => new { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), IdentityResourceId = table.Column(type: "INTEGER", nullable: false), Key = table.Column(type: "TEXT", maxLength: 250, nullable: false), Value = table.Column(type: "TEXT", maxLength: 2000, nullable: false) }, constraints: table => { table.PrimaryKey("PK_IdentityResourceProperties", x => x.Id); table.ForeignKey( name: "FK_IdentityResourceProperties_IdentityResources_IdentityResourceId", column: x => x.IdentityResourceId, principalTable: "IdentityResources", principalColumn: "Id", onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateIndex( name: "IX_ApiResourceClaims_ApiResourceId", table: "ApiResourceClaims", column: "ApiResourceId"); migrationBuilder.CreateIndex( name: "IX_ApiResourceProperties_ApiResourceId", table: "ApiResourceProperties", column: "ApiResourceId"); migrationBuilder.CreateIndex( name: "IX_ApiResources_Name", table: "ApiResources", column: "Name", unique: true); migrationBuilder.CreateIndex( name: "IX_ApiResourceScopes_ApiResourceId", table: "ApiResourceScopes", column: "ApiResourceId"); migrationBuilder.CreateIndex( name: "IX_ApiResourceSecrets_ApiResourceId", table: "ApiResourceSecrets", column: "ApiResourceId"); migrationBuilder.CreateIndex( name: "IX_ApiScopeClaims_ScopeId", table: "ApiScopeClaims", column: "ScopeId"); migrationBuilder.CreateIndex( name: "IX_ApiScopeProperties_ScopeId", table: "ApiScopeProperties", column: "ScopeId"); migrationBuilder.CreateIndex( name: "IX_ApiScopes_Name", table: "ApiScopes", column: "Name", unique: true); migrationBuilder.CreateIndex( name: "IX_ClientClaims_ClientId", table: "ClientClaims", column: "ClientId"); migrationBuilder.CreateIndex( name: "IX_ClientCorsOrigins_ClientId", table: "ClientCorsOrigins", column: "ClientId"); migrationBuilder.CreateIndex( name: "IX_ClientGrantTypes_ClientId", table: "ClientGrantTypes", column: "ClientId"); migrationBuilder.CreateIndex( name: "IX_ClientIdPRestrictions_ClientId", table: "ClientIdPRestrictions", column: "ClientId"); migrationBuilder.CreateIndex( name: "IX_ClientPostLogoutRedirectUris_ClientId", table: "ClientPostLogoutRedirectUris", column: "ClientId"); migrationBuilder.CreateIndex( name: "IX_ClientProperties_ClientId", table: "ClientProperties", column: "ClientId"); migrationBuilder.CreateIndex( name: "IX_ClientRedirectUris_ClientId", table: "ClientRedirectUris", column: "ClientId"); migrationBuilder.CreateIndex( name: "IX_Clients_ClientId", table: "Clients", column: "ClientId", unique: true); migrationBuilder.CreateIndex( name: "IX_ClientScopes_ClientId", table: "ClientScopes", column: "ClientId"); migrationBuilder.CreateIndex( name: "IX_ClientSecrets_ClientId", table: "ClientSecrets", column: "ClientId"); migrationBuilder.CreateIndex( name: "IX_IdentityResourceClaims_IdentityResourceId", table: "IdentityResourceClaims", column: "IdentityResourceId"); migrationBuilder.CreateIndex( name: "IX_IdentityResourceProperties_IdentityResourceId", table: "IdentityResourceProperties", column: "IdentityResourceId"); migrationBuilder.CreateIndex( name: "IX_IdentityResources_Name", table: "IdentityResources", column: "Name", unique: true); } protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.DropTable( name: "ApiResourceClaims"); migrationBuilder.DropTable( name: "ApiResourceProperties"); migrationBuilder.DropTable( name: "ApiResourceScopes"); migrationBuilder.DropTable( name: "ApiResourceSecrets"); migrationBuilder.DropTable( name: "ApiScopeClaims"); migrationBuilder.DropTable( name: "ApiScopeProperties"); migrationBuilder.DropTable( name: "ClientClaims"); migrationBuilder.DropTable( name: "ClientCorsOrigins"); migrationBuilder.DropTable( name: "ClientGrantTypes"); migrationBuilder.DropTable( name: "ClientIdPRestrictions"); migrationBuilder.DropTable( name: "ClientPostLogoutRedirectUris"); migrationBuilder.DropTable( name: "ClientProperties"); migrationBuilder.DropTable( name: "ClientRedirectUris"); migrationBuilder.DropTable( name: "ClientScopes"); migrationBuilder.DropTable( name: "ClientSecrets"); migrationBuilder.DropTable( name: "IdentityResourceClaims"); migrationBuilder.DropTable( name: "IdentityResourceProperties"); migrationBuilder.DropTable( name: "ApiResources"); migrationBuilder.DropTable( name: "ApiScopes"); migrationBuilder.DropTable( name: "Clients"); migrationBuilder.DropTable( name: "IdentityResources"); } } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Migrations\20260906032642_InitialConfigurationMigration.Designer.cs // using System; using IdentityServer4.EntityFramework.DbContexts; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace xIds.Migrations { [DbContext(typeof(ConfigurationDbContext))] [Migration("20260906032642_InitialConfigurationMigration")] partial class InitialConfigurationMigration { protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder .HasAnnotation("ProductVersion", "5.0.2"); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResource", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("AllowedAccessTokenSigningAlgorithms") .HasMaxLength(100) .HasColumnType("TEXT"); b.Property("Created") .HasColumnType("TEXT"); b.Property("Description") .HasMaxLength(1000) .HasColumnType("TEXT"); b.Property("DisplayName") .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("Enabled") .HasColumnType("INTEGER"); b.Property("LastAccessed") .HasColumnType("TEXT"); b.Property("Name") .IsRequired() .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("NonEditable") .HasColumnType("INTEGER"); b.Property("ShowInDiscoveryDocument") .HasColumnType("INTEGER"); b.Property("Updated") .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("Name") .IsUnique(); b.ToTable("ApiResources"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ApiResourceId") .HasColumnType("INTEGER"); b.Property("Type") .IsRequired() .HasMaxLength(200) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("ApiResourceId"); b.ToTable("ApiResourceClaims"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceProperty", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ApiResourceId") .HasColumnType("INTEGER"); b.Property("Key") .IsRequired() .HasMaxLength(250) .HasColumnType("TEXT"); b.Property("Value") .IsRequired() .HasMaxLength(2000) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("ApiResourceId"); b.ToTable("ApiResourceProperties"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceScope", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ApiResourceId") .HasColumnType("INTEGER"); b.Property("Scope") .IsRequired() .HasMaxLength(200) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("ApiResourceId"); b.ToTable("ApiResourceScopes"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceSecret", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ApiResourceId") .HasColumnType("INTEGER"); b.Property("Created") .HasColumnType("TEXT"); b.Property("Description") .HasMaxLength(1000) .HasColumnType("TEXT"); b.Property("Expiration") .HasColumnType("TEXT"); b.Property("Type") .IsRequired() .HasMaxLength(250) .HasColumnType("TEXT"); b.Property("Value") .IsRequired() .HasMaxLength(4000) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("ApiResourceId"); b.ToTable("ApiResourceSecrets"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("Description") .HasMaxLength(1000) .HasColumnType("TEXT"); b.Property("DisplayName") .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("Emphasize") .HasColumnType("INTEGER"); b.Property("Enabled") .HasColumnType("INTEGER"); b.Property("Name") .IsRequired() .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("Required") .HasColumnType("INTEGER"); b.Property("ShowInDiscoveryDocument") .HasColumnType("INTEGER"); b.HasKey("Id"); b.HasIndex("Name") .IsUnique(); b.ToTable("ApiScopes"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ScopeId") .HasColumnType("INTEGER"); b.Property("Type") .IsRequired() .HasMaxLength(200) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("ScopeId"); b.ToTable("ApiScopeClaims"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeProperty", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("Key") .IsRequired() .HasMaxLength(250) .HasColumnType("TEXT"); b.Property("ScopeId") .HasColumnType("INTEGER"); b.Property("Value") .IsRequired() .HasMaxLength(2000) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("ScopeId"); b.ToTable("ApiScopeProperties"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.Client", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("AbsoluteRefreshTokenLifetime") .HasColumnType("INTEGER"); b.Property("AccessTokenLifetime") .HasColumnType("INTEGER"); b.Property("AccessTokenType") .HasColumnType("INTEGER"); b.Property("AllowAccessTokensViaBrowser") .HasColumnType("INTEGER"); b.Property("AllowOfflineAccess") .HasColumnType("INTEGER"); b.Property("AllowPlainTextPkce") .HasColumnType("INTEGER"); b.Property("AllowRememberConsent") .HasColumnType("INTEGER"); b.Property("AllowedIdentityTokenSigningAlgorithms") .HasMaxLength(100) .HasColumnType("TEXT"); b.Property("AlwaysIncludeUserClaimsInIdToken") .HasColumnType("INTEGER"); b.Property("AlwaysSendClientClaims") .HasColumnType("INTEGER"); b.Property("AuthorizationCodeLifetime") .HasColumnType("INTEGER"); b.Property("BackChannelLogoutSessionRequired") .HasColumnType("INTEGER"); b.Property("BackChannelLogoutUri") .HasMaxLength(2000) .HasColumnType("TEXT"); b.Property("ClientClaimsPrefix") .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("ClientId") .IsRequired() .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("ClientName") .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("ClientUri") .HasMaxLength(2000) .HasColumnType("TEXT"); b.Property("ConsentLifetime") .HasColumnType("INTEGER"); b.Property("Created") .HasColumnType("TEXT"); b.Property("Description") .HasMaxLength(1000) .HasColumnType("TEXT"); b.Property("DeviceCodeLifetime") .HasColumnType("INTEGER"); b.Property("EnableLocalLogin") .HasColumnType("INTEGER"); b.Property("Enabled") .HasColumnType("INTEGER"); b.Property("FrontChannelLogoutSessionRequired") .HasColumnType("INTEGER"); b.Property("FrontChannelLogoutUri") .HasMaxLength(2000) .HasColumnType("TEXT"); b.Property("IdentityTokenLifetime") .HasColumnType("INTEGER"); b.Property("IncludeJwtId") .HasColumnType("INTEGER"); b.Property("LastAccessed") .HasColumnType("TEXT"); b.Property("LogoUri") .HasMaxLength(2000) .HasColumnType("TEXT"); b.Property("NonEditable") .HasColumnType("INTEGER"); b.Property("PairWiseSubjectSalt") .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("ProtocolType") .IsRequired() .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("RefreshTokenExpiration") .HasColumnType("INTEGER"); b.Property("RefreshTokenUsage") .HasColumnType("INTEGER"); b.Property("RequireClientSecret") .HasColumnType("INTEGER"); b.Property("RequireConsent") .HasColumnType("INTEGER"); b.Property("RequirePkce") .HasColumnType("INTEGER"); b.Property("RequireRequestObject") .HasColumnType("INTEGER"); b.Property("SlidingRefreshTokenLifetime") .HasColumnType("INTEGER"); b.Property("UpdateAccessTokenClaimsOnRefresh") .HasColumnType("INTEGER"); b.Property("Updated") .HasColumnType("TEXT"); b.Property("UserCodeType") .HasMaxLength(100) .HasColumnType("TEXT"); b.Property("UserSsoLifetime") .HasColumnType("INTEGER"); b.HasKey("Id"); b.HasIndex("ClientId") .IsUnique(); b.ToTable("Clients"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ClientId") .HasColumnType("INTEGER"); b.Property("Type") .IsRequired() .HasMaxLength(250) .HasColumnType("TEXT"); b.Property("Value") .IsRequired() .HasMaxLength(250) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("ClientId"); b.ToTable("ClientClaims"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientCorsOrigin", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ClientId") .HasColumnType("INTEGER"); b.Property("Origin") .IsRequired() .HasMaxLength(150) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("ClientId"); b.ToTable("ClientCorsOrigins"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientGrantType", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ClientId") .HasColumnType("INTEGER"); b.Property("GrantType") .IsRequired() .HasMaxLength(250) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("ClientId"); b.ToTable("ClientGrantTypes"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientIdPRestriction", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ClientId") .HasColumnType("INTEGER"); b.Property("Provider") .IsRequired() .HasMaxLength(200) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("ClientId"); b.ToTable("ClientIdPRestrictions"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ClientId") .HasColumnType("INTEGER"); b.Property("PostLogoutRedirectUri") .IsRequired() .HasMaxLength(2000) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("ClientId"); b.ToTable("ClientPostLogoutRedirectUris"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientProperty", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ClientId") .HasColumnType("INTEGER"); b.Property("Key") .IsRequired() .HasMaxLength(250) .HasColumnType("TEXT"); b.Property("Value") .IsRequired() .HasMaxLength(2000) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("ClientId"); b.ToTable("ClientProperties"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientRedirectUri", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ClientId") .HasColumnType("INTEGER"); b.Property("RedirectUri") .IsRequired() .HasMaxLength(2000) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("ClientId"); b.ToTable("ClientRedirectUris"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientScope", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ClientId") .HasColumnType("INTEGER"); b.Property("Scope") .IsRequired() .HasMaxLength(200) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("ClientId"); b.ToTable("ClientScopes"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientSecret", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ClientId") .HasColumnType("INTEGER"); b.Property("Created") .HasColumnType("TEXT"); b.Property("Description") .HasMaxLength(2000) .HasColumnType("TEXT"); b.Property("Expiration") .HasColumnType("TEXT"); b.Property("Type") .IsRequired() .HasMaxLength(250) .HasColumnType("TEXT"); b.Property("Value") .IsRequired() .HasMaxLength(4000) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("ClientId"); b.ToTable("ClientSecrets"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResource", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("Created") .HasColumnType("TEXT"); b.Property("Description") .HasMaxLength(1000) .HasColumnType("TEXT"); b.Property("DisplayName") .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("Emphasize") .HasColumnType("INTEGER"); b.Property("Enabled") .HasColumnType("INTEGER"); b.Property("Name") .IsRequired() .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("NonEditable") .HasColumnType("INTEGER"); b.Property("Required") .HasColumnType("INTEGER"); b.Property("ShowInDiscoveryDocument") .HasColumnType("INTEGER"); b.Property("Updated") .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("Name") .IsUnique(); b.ToTable("IdentityResources"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResourceClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("IdentityResourceId") .HasColumnType("INTEGER"); b.Property("Type") .IsRequired() .HasMaxLength(200) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("IdentityResourceId"); b.ToTable("IdentityResourceClaims"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResourceProperty", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("IdentityResourceId") .HasColumnType("INTEGER"); b.Property("Key") .IsRequired() .HasMaxLength(250) .HasColumnType("TEXT"); b.Property("Value") .IsRequired() .HasMaxLength(2000) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("IdentityResourceId"); b.ToTable("IdentityResourceProperties"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") .WithMany("UserClaims") .HasForeignKey("ApiResourceId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("ApiResource"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceProperty", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") .WithMany("Properties") .HasForeignKey("ApiResourceId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("ApiResource"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceScope", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") .WithMany("Scopes") .HasForeignKey("ApiResourceId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("ApiResource"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceSecret", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") .WithMany("Secrets") .HasForeignKey("ApiResourceId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("ApiResource"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.ApiScope", "Scope") .WithMany("UserClaims") .HasForeignKey("ScopeId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("Scope"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeProperty", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.ApiScope", "Scope") .WithMany("Properties") .HasForeignKey("ScopeId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("Scope"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientClaim", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") .WithMany("Claims") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("Client"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientCorsOrigin", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") .WithMany("AllowedCorsOrigins") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("Client"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientGrantType", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") .WithMany("AllowedGrantTypes") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("Client"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientIdPRestriction", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") .WithMany("IdentityProviderRestrictions") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("Client"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") .WithMany("PostLogoutRedirectUris") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("Client"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientProperty", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") .WithMany("Properties") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("Client"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientRedirectUri", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") .WithMany("RedirectUris") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("Client"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientScope", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") .WithMany("AllowedScopes") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("Client"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientSecret", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") .WithMany("ClientSecrets") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("Client"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResourceClaim", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.IdentityResource", "IdentityResource") .WithMany("UserClaims") .HasForeignKey("IdentityResourceId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("IdentityResource"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResourceProperty", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.IdentityResource", "IdentityResource") .WithMany("Properties") .HasForeignKey("IdentityResourceId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("IdentityResource"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResource", b => { b.Navigation("Properties"); b.Navigation("Scopes"); b.Navigation("Secrets"); b.Navigation("UserClaims"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b => { b.Navigation("Properties"); b.Navigation("UserClaims"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.Client", b => { b.Navigation("AllowedCorsOrigins"); b.Navigation("AllowedGrantTypes"); b.Navigation("AllowedScopes"); b.Navigation("Claims"); b.Navigation("ClientSecrets"); b.Navigation("IdentityProviderRestrictions"); b.Navigation("PostLogoutRedirectUris"); b.Navigation("Properties"); b.Navigation("RedirectUris"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResource", b => { b.Navigation("Properties"); b.Navigation("UserClaims"); }); #pragma warning restore 612, 618 } } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Migrations\ConfigurationDbContextModelSnapshot.cs // using System; using IdentityServer4.EntityFramework.DbContexts; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace xIds.Migrations { [DbContext(typeof(ConfigurationDbContext))] partial class ConfigurationDbContextModelSnapshot : ModelSnapshot { protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder .HasAnnotation("ProductVersion", "5.0.2"); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResource", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("AllowedAccessTokenSigningAlgorithms") .HasMaxLength(100) .HasColumnType("TEXT"); b.Property("Created") .HasColumnType("TEXT"); b.Property("Description") .HasMaxLength(1000) .HasColumnType("TEXT"); b.Property("DisplayName") .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("Enabled") .HasColumnType("INTEGER"); b.Property("LastAccessed") .HasColumnType("TEXT"); b.Property("Name") .IsRequired() .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("NonEditable") .HasColumnType("INTEGER"); b.Property("ShowInDiscoveryDocument") .HasColumnType("INTEGER"); b.Property("Updated") .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("Name") .IsUnique(); b.ToTable("ApiResources"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ApiResourceId") .HasColumnType("INTEGER"); b.Property("Type") .IsRequired() .HasMaxLength(200) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("ApiResourceId"); b.ToTable("ApiResourceClaims"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceProperty", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ApiResourceId") .HasColumnType("INTEGER"); b.Property("Key") .IsRequired() .HasMaxLength(250) .HasColumnType("TEXT"); b.Property("Value") .IsRequired() .HasMaxLength(2000) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("ApiResourceId"); b.ToTable("ApiResourceProperties"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceScope", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ApiResourceId") .HasColumnType("INTEGER"); b.Property("Scope") .IsRequired() .HasMaxLength(200) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("ApiResourceId"); b.ToTable("ApiResourceScopes"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceSecret", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ApiResourceId") .HasColumnType("INTEGER"); b.Property("Created") .HasColumnType("TEXT"); b.Property("Description") .HasMaxLength(1000) .HasColumnType("TEXT"); b.Property("Expiration") .HasColumnType("TEXT"); b.Property("Type") .IsRequired() .HasMaxLength(250) .HasColumnType("TEXT"); b.Property("Value") .IsRequired() .HasMaxLength(4000) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("ApiResourceId"); b.ToTable("ApiResourceSecrets"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("Description") .HasMaxLength(1000) .HasColumnType("TEXT"); b.Property("DisplayName") .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("Emphasize") .HasColumnType("INTEGER"); b.Property("Enabled") .HasColumnType("INTEGER"); b.Property("Name") .IsRequired() .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("Required") .HasColumnType("INTEGER"); b.Property("ShowInDiscoveryDocument") .HasColumnType("INTEGER"); b.HasKey("Id"); b.HasIndex("Name") .IsUnique(); b.ToTable("ApiScopes"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ScopeId") .HasColumnType("INTEGER"); b.Property("Type") .IsRequired() .HasMaxLength(200) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("ScopeId"); b.ToTable("ApiScopeClaims"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeProperty", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("Key") .IsRequired() .HasMaxLength(250) .HasColumnType("TEXT"); b.Property("ScopeId") .HasColumnType("INTEGER"); b.Property("Value") .IsRequired() .HasMaxLength(2000) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("ScopeId"); b.ToTable("ApiScopeProperties"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.Client", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("AbsoluteRefreshTokenLifetime") .HasColumnType("INTEGER"); b.Property("AccessTokenLifetime") .HasColumnType("INTEGER"); b.Property("AccessTokenType") .HasColumnType("INTEGER"); b.Property("AllowAccessTokensViaBrowser") .HasColumnType("INTEGER"); b.Property("AllowOfflineAccess") .HasColumnType("INTEGER"); b.Property("AllowPlainTextPkce") .HasColumnType("INTEGER"); b.Property("AllowRememberConsent") .HasColumnType("INTEGER"); b.Property("AllowedIdentityTokenSigningAlgorithms") .HasMaxLength(100) .HasColumnType("TEXT"); b.Property("AlwaysIncludeUserClaimsInIdToken") .HasColumnType("INTEGER"); b.Property("AlwaysSendClientClaims") .HasColumnType("INTEGER"); b.Property("AuthorizationCodeLifetime") .HasColumnType("INTEGER"); b.Property("BackChannelLogoutSessionRequired") .HasColumnType("INTEGER"); b.Property("BackChannelLogoutUri") .HasMaxLength(2000) .HasColumnType("TEXT"); b.Property("ClientClaimsPrefix") .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("ClientId") .IsRequired() .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("ClientName") .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("ClientUri") .HasMaxLength(2000) .HasColumnType("TEXT"); b.Property("ConsentLifetime") .HasColumnType("INTEGER"); b.Property("Created") .HasColumnType("TEXT"); b.Property("Description") .HasMaxLength(1000) .HasColumnType("TEXT"); b.Property("DeviceCodeLifetime") .HasColumnType("INTEGER"); b.Property("EnableLocalLogin") .HasColumnType("INTEGER"); b.Property("Enabled") .HasColumnType("INTEGER"); b.Property("FrontChannelLogoutSessionRequired") .HasColumnType("INTEGER"); b.Property("FrontChannelLogoutUri") .HasMaxLength(2000) .HasColumnType("TEXT"); b.Property("IdentityTokenLifetime") .HasColumnType("INTEGER"); b.Property("IncludeJwtId") .HasColumnType("INTEGER"); b.Property("LastAccessed") .HasColumnType("TEXT"); b.Property("LogoUri") .HasMaxLength(2000) .HasColumnType("TEXT"); b.Property("NonEditable") .HasColumnType("INTEGER"); b.Property("PairWiseSubjectSalt") .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("ProtocolType") .IsRequired() .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("RefreshTokenExpiration") .HasColumnType("INTEGER"); b.Property("RefreshTokenUsage") .HasColumnType("INTEGER"); b.Property("RequireClientSecret") .HasColumnType("INTEGER"); b.Property("RequireConsent") .HasColumnType("INTEGER"); b.Property("RequirePkce") .HasColumnType("INTEGER"); b.Property("RequireRequestObject") .HasColumnType("INTEGER"); b.Property("SlidingRefreshTokenLifetime") .HasColumnType("INTEGER"); b.Property("UpdateAccessTokenClaimsOnRefresh") .HasColumnType("INTEGER"); b.Property("Updated") .HasColumnType("TEXT"); b.Property("UserCodeType") .HasMaxLength(100) .HasColumnType("TEXT"); b.Property("UserSsoLifetime") .HasColumnType("INTEGER"); b.HasKey("Id"); b.HasIndex("ClientId") .IsUnique(); b.ToTable("Clients"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ClientId") .HasColumnType("INTEGER"); b.Property("Type") .IsRequired() .HasMaxLength(250) .HasColumnType("TEXT"); b.Property("Value") .IsRequired() .HasMaxLength(250) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("ClientId"); b.ToTable("ClientClaims"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientCorsOrigin", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ClientId") .HasColumnType("INTEGER"); b.Property("Origin") .IsRequired() .HasMaxLength(150) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("ClientId"); b.ToTable("ClientCorsOrigins"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientGrantType", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ClientId") .HasColumnType("INTEGER"); b.Property("GrantType") .IsRequired() .HasMaxLength(250) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("ClientId"); b.ToTable("ClientGrantTypes"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientIdPRestriction", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ClientId") .HasColumnType("INTEGER"); b.Property("Provider") .IsRequired() .HasMaxLength(200) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("ClientId"); b.ToTable("ClientIdPRestrictions"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ClientId") .HasColumnType("INTEGER"); b.Property("PostLogoutRedirectUri") .IsRequired() .HasMaxLength(2000) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("ClientId"); b.ToTable("ClientPostLogoutRedirectUris"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientProperty", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ClientId") .HasColumnType("INTEGER"); b.Property("Key") .IsRequired() .HasMaxLength(250) .HasColumnType("TEXT"); b.Property("Value") .IsRequired() .HasMaxLength(2000) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("ClientId"); b.ToTable("ClientProperties"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientRedirectUri", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ClientId") .HasColumnType("INTEGER"); b.Property("RedirectUri") .IsRequired() .HasMaxLength(2000) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("ClientId"); b.ToTable("ClientRedirectUris"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientScope", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ClientId") .HasColumnType("INTEGER"); b.Property("Scope") .IsRequired() .HasMaxLength(200) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("ClientId"); b.ToTable("ClientScopes"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientSecret", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ClientId") .HasColumnType("INTEGER"); b.Property("Created") .HasColumnType("TEXT"); b.Property("Description") .HasMaxLength(2000) .HasColumnType("TEXT"); b.Property("Expiration") .HasColumnType("TEXT"); b.Property("Type") .IsRequired() .HasMaxLength(250) .HasColumnType("TEXT"); b.Property("Value") .IsRequired() .HasMaxLength(4000) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("ClientId"); b.ToTable("ClientSecrets"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResource", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("Created") .HasColumnType("TEXT"); b.Property("Description") .HasMaxLength(1000) .HasColumnType("TEXT"); b.Property("DisplayName") .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("Emphasize") .HasColumnType("INTEGER"); b.Property("Enabled") .HasColumnType("INTEGER"); b.Property("Name") .IsRequired() .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("NonEditable") .HasColumnType("INTEGER"); b.Property("Required") .HasColumnType("INTEGER"); b.Property("ShowInDiscoveryDocument") .HasColumnType("INTEGER"); b.Property("Updated") .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("Name") .IsUnique(); b.ToTable("IdentityResources"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResourceClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("IdentityResourceId") .HasColumnType("INTEGER"); b.Property("Type") .IsRequired() .HasMaxLength(200) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("IdentityResourceId"); b.ToTable("IdentityResourceClaims"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResourceProperty", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("IdentityResourceId") .HasColumnType("INTEGER"); b.Property("Key") .IsRequired() .HasMaxLength(250) .HasColumnType("TEXT"); b.Property("Value") .IsRequired() .HasMaxLength(2000) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("IdentityResourceId"); b.ToTable("IdentityResourceProperties"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") .WithMany("UserClaims") .HasForeignKey("ApiResourceId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("ApiResource"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceProperty", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") .WithMany("Properties") .HasForeignKey("ApiResourceId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("ApiResource"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceScope", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") .WithMany("Scopes") .HasForeignKey("ApiResourceId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("ApiResource"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceSecret", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") .WithMany("Secrets") .HasForeignKey("ApiResourceId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("ApiResource"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.ApiScope", "Scope") .WithMany("UserClaims") .HasForeignKey("ScopeId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("Scope"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeProperty", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.ApiScope", "Scope") .WithMany("Properties") .HasForeignKey("ScopeId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("Scope"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientClaim", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") .WithMany("Claims") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("Client"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientCorsOrigin", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") .WithMany("AllowedCorsOrigins") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("Client"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientGrantType", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") .WithMany("AllowedGrantTypes") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("Client"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientIdPRestriction", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") .WithMany("IdentityProviderRestrictions") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("Client"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") .WithMany("PostLogoutRedirectUris") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("Client"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientProperty", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") .WithMany("Properties") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("Client"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientRedirectUri", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") .WithMany("RedirectUris") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("Client"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientScope", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") .WithMany("AllowedScopes") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("Client"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientSecret", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") .WithMany("ClientSecrets") .HasForeignKey("ClientId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("Client"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResourceClaim", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.IdentityResource", "IdentityResource") .WithMany("UserClaims") .HasForeignKey("IdentityResourceId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("IdentityResource"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResourceProperty", b => { b.HasOne("IdentityServer4.EntityFramework.Entities.IdentityResource", "IdentityResource") .WithMany("Properties") .HasForeignKey("IdentityResourceId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("IdentityResource"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResource", b => { b.Navigation("Properties"); b.Navigation("Scopes"); b.Navigation("Secrets"); b.Navigation("UserClaims"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b => { b.Navigation("Properties"); b.Navigation("UserClaims"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.Client", b => { b.Navigation("AllowedCorsOrigins"); b.Navigation("AllowedGrantTypes"); b.Navigation("AllowedScopes"); b.Navigation("Claims"); b.Navigation("ClientSecrets"); b.Navigation("IdentityProviderRestrictions"); b.Navigation("PostLogoutRedirectUris"); b.Navigation("Properties"); b.Navigation("RedirectUris"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResource", b => { b.Navigation("Properties"); b.Navigation("UserClaims"); }); #pragma warning restore 612, 618 } } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Migrations\PersistedGrantDb\20260906032650_InitialPersistedGrantMigration.cs using System; using Microsoft.EntityFrameworkCore.Migrations; namespace xIds.Migrations.PersistedGrantDb { public partial class InitialPersistedGrantMigration : Migration { protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.CreateTable( name: "DeviceCodes", columns: table => new { UserCode = table.Column(type: "TEXT", maxLength: 200, nullable: false), DeviceCode = table.Column(type: "TEXT", maxLength: 200, nullable: false), SubjectId = table.Column(type: "TEXT", maxLength: 200, nullable: true), SessionId = table.Column(type: "TEXT", maxLength: 100, nullable: true), ClientId = table.Column(type: "TEXT", maxLength: 200, nullable: false), Description = table.Column(type: "TEXT", maxLength: 200, nullable: true), CreationTime = table.Column(type: "TEXT", nullable: false), Expiration = table.Column(type: "TEXT", nullable: false), Data = table.Column(type: "TEXT", maxLength: 50000, nullable: false) }, constraints: table => { table.PrimaryKey("PK_DeviceCodes", x => x.UserCode); }); migrationBuilder.CreateTable( name: "PersistedGrants", columns: table => new { Key = table.Column(type: "TEXT", maxLength: 200, nullable: false), Type = table.Column(type: "TEXT", maxLength: 50, nullable: false), SubjectId = table.Column(type: "TEXT", maxLength: 200, nullable: true), SessionId = table.Column(type: "TEXT", maxLength: 100, nullable: true), ClientId = table.Column(type: "TEXT", maxLength: 200, nullable: false), Description = table.Column(type: "TEXT", maxLength: 200, nullable: true), CreationTime = table.Column(type: "TEXT", nullable: false), Expiration = table.Column(type: "TEXT", nullable: true), ConsumedTime = table.Column(type: "TEXT", nullable: true), Data = table.Column(type: "TEXT", maxLength: 50000, nullable: false) }, constraints: table => { table.PrimaryKey("PK_PersistedGrants", x => x.Key); }); migrationBuilder.CreateIndex( name: "IX_DeviceCodes_DeviceCode", table: "DeviceCodes", column: "DeviceCode", unique: true); migrationBuilder.CreateIndex( name: "IX_DeviceCodes_Expiration", table: "DeviceCodes", column: "Expiration"); migrationBuilder.CreateIndex( name: "IX_PersistedGrants_Expiration", table: "PersistedGrants", column: "Expiration"); migrationBuilder.CreateIndex( name: "IX_PersistedGrants_SubjectId_ClientId_Type", table: "PersistedGrants", columns: new[] { "SubjectId", "ClientId", "Type" }); migrationBuilder.CreateIndex( name: "IX_PersistedGrants_SubjectId_SessionId_Type", table: "PersistedGrants", columns: new[] { "SubjectId", "SessionId", "Type" }); } protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.DropTable( name: "DeviceCodes"); migrationBuilder.DropTable( name: "PersistedGrants"); } } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Migrations\PersistedGrantDb\20260906032650_InitialPersistedGrantMigration.Designer.cs // using System; using IdentityServer4.EntityFramework.DbContexts; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace xIds.Migrations.PersistedGrantDb { [DbContext(typeof(PersistedGrantDbContext))] [Migration("20260906032650_InitialPersistedGrantMigration")] partial class InitialPersistedGrantMigration { protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder .HasAnnotation("ProductVersion", "5.0.2"); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.DeviceFlowCodes", b => { b.Property("UserCode") .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("ClientId") .IsRequired() .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("CreationTime") .HasColumnType("TEXT"); b.Property("Data") .IsRequired() .HasMaxLength(50000) .HasColumnType("TEXT"); b.Property("Description") .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("DeviceCode") .IsRequired() .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("Expiration") .IsRequired() .HasColumnType("TEXT"); b.Property("SessionId") .HasMaxLength(100) .HasColumnType("TEXT"); b.Property("SubjectId") .HasMaxLength(200) .HasColumnType("TEXT"); b.HasKey("UserCode"); b.HasIndex("DeviceCode") .IsUnique(); b.HasIndex("Expiration"); b.ToTable("DeviceCodes"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.PersistedGrant", b => { b.Property("Key") .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("ClientId") .IsRequired() .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("ConsumedTime") .HasColumnType("TEXT"); b.Property("CreationTime") .HasColumnType("TEXT"); b.Property("Data") .IsRequired() .HasMaxLength(50000) .HasColumnType("TEXT"); b.Property("Description") .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("Expiration") .HasColumnType("TEXT"); b.Property("SessionId") .HasMaxLength(100) .HasColumnType("TEXT"); b.Property("SubjectId") .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("Type") .IsRequired() .HasMaxLength(50) .HasColumnType("TEXT"); b.HasKey("Key"); b.HasIndex("Expiration"); b.HasIndex("SubjectId", "ClientId", "Type"); b.HasIndex("SubjectId", "SessionId", "Type"); b.ToTable("PersistedGrants"); }); #pragma warning restore 612, 618 } } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Migrations\PersistedGrantDb\PersistedGrantDbContextModelSnapshot.cs // using System; using IdentityServer4.EntityFramework.DbContexts; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace xIds.Migrations.PersistedGrantDb { [DbContext(typeof(PersistedGrantDbContext))] partial class PersistedGrantDbContextModelSnapshot : ModelSnapshot { protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder .HasAnnotation("ProductVersion", "5.0.2"); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.DeviceFlowCodes", b => { b.Property("UserCode") .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("ClientId") .IsRequired() .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("CreationTime") .HasColumnType("TEXT"); b.Property("Data") .IsRequired() .HasMaxLength(50000) .HasColumnType("TEXT"); b.Property("Description") .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("DeviceCode") .IsRequired() .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("Expiration") .IsRequired() .HasColumnType("TEXT"); b.Property("SessionId") .HasMaxLength(100) .HasColumnType("TEXT"); b.Property("SubjectId") .HasMaxLength(200) .HasColumnType("TEXT"); b.HasKey("UserCode"); b.HasIndex("DeviceCode") .IsUnique(); b.HasIndex("Expiration"); b.ToTable("DeviceCodes"); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.PersistedGrant", b => { b.Property("Key") .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("ClientId") .IsRequired() .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("ConsumedTime") .HasColumnType("TEXT"); b.Property("CreationTime") .HasColumnType("TEXT"); b.Property("Data") .IsRequired() .HasMaxLength(50000) .HasColumnType("TEXT"); b.Property("Description") .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("Expiration") .HasColumnType("TEXT"); b.Property("SessionId") .HasMaxLength(100) .HasColumnType("TEXT"); b.Property("SubjectId") .HasMaxLength(200) .HasColumnType("TEXT"); b.Property("Type") .IsRequired() .HasMaxLength(50) .HasColumnType("TEXT"); b.HasKey("Key"); b.HasIndex("Expiration"); b.HasIndex("SubjectId", "ClientId", "Type"); b.HasIndex("SubjectId", "SessionId", "Type"); b.ToTable("PersistedGrants"); }); #pragma warning restore 612, 618 } } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Migrations\XIdentityDb\20260906032659_InitialIdentityServerDbContext.cs using System; using Microsoft.EntityFrameworkCore.Migrations; namespace xIds.Migrations.XIdentityDb { public partial class InitialIdentityServerDbContext : Migration { protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.CreateTable( name: "AspNetRoles", columns: table => new { Id = table.Column(type: "TEXT", nullable: false), Name = table.Column(type: "TEXT", maxLength: 256, nullable: true), NormalizedName = table.Column(type: "TEXT", maxLength: 256, nullable: true), ConcurrencyStamp = table.Column(type: "TEXT", nullable: true) }, constraints: table => { table.PrimaryKey("PK_AspNetRoles", x => x.Id); }); migrationBuilder.CreateTable( name: "AspNetUsers", columns: table => new { Id = table.Column(type: "TEXT", nullable: false), Discriminator = table.Column(type: "TEXT", nullable: false), FirstName = table.Column(type: "TEXT", maxLength: 50, nullable: true), LastName = table.Column(type: "TEXT", maxLength: 100, nullable: true), IsEnable = table.Column(type: "INTEGER", nullable: true), IsBanned = table.Column(type: "INTEGER", nullable: true), DateOfBirth = table.Column(type: "TEXT", nullable: true), CreationDate = table.Column(type: "TEXT", nullable: true), LastLogin = table.Column(type: "TEXT", nullable: true), Avatar = table.Column(type: "TEXT", nullable: true), Gender = table.Column(type: "INTEGER", nullable: true), Bio = table.Column(type: "TEXT", nullable: true), CoverImage = table.Column(type: "TEXT", nullable: true), OpenToSearch = table.Column(type: "INTEGER", nullable: true), UserName = table.Column(type: "TEXT", maxLength: 256, nullable: true), NormalizedUserName = table.Column(type: "TEXT", maxLength: 256, nullable: true), Email = table.Column(type: "TEXT", maxLength: 256, nullable: true), NormalizedEmail = table.Column(type: "TEXT", maxLength: 256, nullable: true), EmailConfirmed = table.Column(type: "INTEGER", nullable: false), PasswordHash = table.Column(type: "TEXT", nullable: true), SecurityStamp = table.Column(type: "TEXT", nullable: true), ConcurrencyStamp = table.Column(type: "TEXT", nullable: true), PhoneNumber = table.Column(type: "TEXT", nullable: true), PhoneNumberConfirmed = table.Column(type: "INTEGER", nullable: false), TwoFactorEnabled = table.Column(type: "INTEGER", nullable: false), LockoutEnd = table.Column(type: "TEXT", nullable: true), LockoutEnabled = table.Column(type: "INTEGER", nullable: false), AccessFailedCount = table.Column(type: "INTEGER", nullable: false) }, constraints: table => { table.PrimaryKey("PK_AspNetUsers", x => x.Id); }); migrationBuilder.CreateTable( name: "BannedDevices", columns: table => new { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), BannedOn = table.Column(type: "TEXT", nullable: false), DeviceStr = table.Column(type: "TEXT", nullable: true), Deleted = table.Column(type: "INTEGER", nullable: false) }, constraints: table => { table.PrimaryKey("PK_BannedDevices", x => x.Id); }); migrationBuilder.CreateTable( name: "Tokens", columns: table => new { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), Token = table.Column(type: "TEXT", nullable: true), Hash = table.Column(type: "TEXT", nullable: true), UserSelectByParam = table.Column(type: "TEXT", nullable: true), DeviceStr = table.Column(type: "TEXT", nullable: true), Type = table.Column(type: "INTEGER", nullable: false), Deleted = table.Column(type: "INTEGER", nullable: false) }, constraints: table => { table.PrimaryKey("PK_Tokens", x => x.Id); }); migrationBuilder.CreateTable( name: "VerificationRequests", columns: table => new { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), VerificationCode = table.Column(type: "TEXT", nullable: false), NumberOfTries = table.Column(type: "INTEGER", nullable: false), LastTryOn = table.Column(type: "TEXT", nullable: false), RequestStr = table.Column(type: "TEXT", nullable: true), DeviceStr = table.Column(type: "TEXT", nullable: true), Deleted = table.Column(type: "INTEGER", nullable: false) }, constraints: table => { table.PrimaryKey("PK_VerificationRequests", x => x.Id); }); migrationBuilder.CreateTable( name: "AspNetRoleClaims", columns: table => new { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), RoleId = table.Column(type: "TEXT", nullable: false), ClaimType = table.Column(type: "TEXT", nullable: true), ClaimValue = table.Column(type: "TEXT", nullable: true) }, constraints: table => { table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id); table.ForeignKey( name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", column: x => x.RoleId, principalTable: "AspNetRoles", principalColumn: "Id", onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateTable( name: "AspNetUserClaims", columns: table => new { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), UserId = table.Column(type: "TEXT", nullable: false), ClaimType = table.Column(type: "TEXT", nullable: true), ClaimValue = table.Column(type: "TEXT", nullable: true) }, constraints: table => { table.PrimaryKey("PK_AspNetUserClaims", x => x.Id); table.ForeignKey( name: "FK_AspNetUserClaims_AspNetUsers_UserId", column: x => x.UserId, principalTable: "AspNetUsers", principalColumn: "Id", onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateTable( name: "AspNetUserLogins", columns: table => new { LoginProvider = table.Column(type: "TEXT", nullable: false), ProviderKey = table.Column(type: "TEXT", nullable: false), ProviderDisplayName = table.Column(type: "TEXT", nullable: true), UserId = table.Column(type: "TEXT", nullable: false) }, constraints: table => { table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey }); table.ForeignKey( name: "FK_AspNetUserLogins_AspNetUsers_UserId", column: x => x.UserId, principalTable: "AspNetUsers", principalColumn: "Id", onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateTable( name: "AspNetUserRoles", columns: table => new { UserId = table.Column(type: "TEXT", nullable: false), RoleId = table.Column(type: "TEXT", nullable: false) }, constraints: table => { table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId }); table.ForeignKey( name: "FK_AspNetUserRoles_AspNetRoles_RoleId", column: x => x.RoleId, principalTable: "AspNetRoles", principalColumn: "Id", onDelete: ReferentialAction.Cascade); table.ForeignKey( name: "FK_AspNetUserRoles_AspNetUsers_UserId", column: x => x.UserId, principalTable: "AspNetUsers", principalColumn: "Id", onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateTable( name: "AspNetUserTokens", columns: table => new { UserId = table.Column(type: "TEXT", nullable: false), LoginProvider = table.Column(type: "TEXT", nullable: false), Name = table.Column(type: "TEXT", nullable: false), Value = table.Column(type: "TEXT", nullable: true) }, constraints: table => { table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); table.ForeignKey( name: "FK_AspNetUserTokens_AspNetUsers_UserId", column: x => x.UserId, principalTable: "AspNetUsers", principalColumn: "Id", onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateTable( name: "Avatars", columns: table => new { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), UserId = table.Column(type: "TEXT", nullable: true), Name = table.Column(type: "TEXT", maxLength: 255, nullable: false), Thumb = table.Column(type: "TEXT", maxLength: 255, nullable: false), Path = table.Column(type: "TEXT", maxLength: 255, nullable: false), ThumbPath = table.Column(type: "TEXT", maxLength: 255, nullable: false), CreationDate = table.Column(type: "TEXT", nullable: false), Deleted = table.Column(type: "INTEGER", nullable: false) }, constraints: table => { table.PrimaryKey("PK_Avatars", x => x.Id); table.ForeignKey( name: "FK_Avatars_AspNetUsers_UserId", column: x => x.UserId, principalTable: "AspNetUsers", principalColumn: "Id", onDelete: ReferentialAction.Restrict); }); migrationBuilder.CreateTable( name: "Devices", columns: table => new { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), Os = table.Column(type: "TEXT", nullable: true), OsVersion = table.Column(type: "TEXT", nullable: true), Browser = table.Column(type: "TEXT", nullable: true), UserAgent = table.Column(type: "TEXT", nullable: true), DeviceType = table.Column(type: "INTEGER", nullable: false), UserId = table.Column(type: "TEXT", nullable: true), Deleted = table.Column(type: "INTEGER", nullable: false) }, constraints: table => { table.PrimaryKey("PK_Devices", x => x.Id); table.ForeignKey( name: "FK_Devices_AspNetUsers_UserId", column: x => x.UserId, principalTable: "AspNetUsers", principalColumn: "Id", onDelete: ReferentialAction.Restrict); }); migrationBuilder.CreateTable( name: "Followers", columns: table => new { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), State = table.Column(type: "INTEGER", nullable: false), UserId = table.Column(type: "TEXT", nullable: true), DestId = table.Column(type: "TEXT", nullable: true), Deleted = table.Column(type: "INTEGER", nullable: false) }, constraints: table => { table.PrimaryKey("PK_Followers", x => x.Id); table.ForeignKey( name: "FK_Followers_AspNetUsers_DestId", column: x => x.DestId, principalTable: "AspNetUsers", principalColumn: "Id", onDelete: ReferentialAction.Restrict); table.ForeignKey( name: "FK_Followers_AspNetUsers_UserId", column: x => x.UserId, principalTable: "AspNetUsers", principalColumn: "Id", onDelete: ReferentialAction.Restrict); }); migrationBuilder.CreateTable( name: "Followings", columns: table => new { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), State = table.Column(type: "INTEGER", nullable: false), UserId = table.Column(type: "TEXT", nullable: true), DestId = table.Column(type: "TEXT", nullable: true), Deleted = table.Column(type: "INTEGER", nullable: false) }, constraints: table => { table.PrimaryKey("PK_Followings", x => x.Id); table.ForeignKey( name: "FK_Followings_AspNetUsers_DestId", column: x => x.DestId, principalTable: "AspNetUsers", principalColumn: "Id", onDelete: ReferentialAction.Restrict); table.ForeignKey( name: "FK_Followings_AspNetUsers_UserId", column: x => x.UserId, principalTable: "AspNetUsers", principalColumn: "Id", onDelete: ReferentialAction.Restrict); }); migrationBuilder.CreateIndex( name: "IX_AspNetRoleClaims_RoleId", table: "AspNetRoleClaims", column: "RoleId"); migrationBuilder.CreateIndex( name: "RoleNameIndex", table: "AspNetRoles", column: "NormalizedName", unique: true); migrationBuilder.CreateIndex( name: "IX_AspNetUserClaims_UserId", table: "AspNetUserClaims", column: "UserId"); migrationBuilder.CreateIndex( name: "IX_AspNetUserLogins_UserId", table: "AspNetUserLogins", column: "UserId"); migrationBuilder.CreateIndex( name: "IX_AspNetUserRoles_RoleId", table: "AspNetUserRoles", column: "RoleId"); migrationBuilder.CreateIndex( name: "EmailIndex", table: "AspNetUsers", column: "NormalizedEmail"); migrationBuilder.CreateIndex( name: "UserNameIndex", table: "AspNetUsers", column: "NormalizedUserName", unique: true); migrationBuilder.CreateIndex( name: "IX_Avatars_UserId", table: "Avatars", column: "UserId"); migrationBuilder.CreateIndex( name: "IX_Devices_UserId", table: "Devices", column: "UserId"); migrationBuilder.CreateIndex( name: "IX_Followers_DestId", table: "Followers", column: "DestId"); migrationBuilder.CreateIndex( name: "IX_Followers_UserId", table: "Followers", column: "UserId"); migrationBuilder.CreateIndex( name: "IX_Followings_DestId", table: "Followings", column: "DestId"); migrationBuilder.CreateIndex( name: "IX_Followings_UserId", table: "Followings", column: "UserId"); } protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.DropTable( name: "AspNetRoleClaims"); migrationBuilder.DropTable( name: "AspNetUserClaims"); migrationBuilder.DropTable( name: "AspNetUserLogins"); migrationBuilder.DropTable( name: "AspNetUserRoles"); migrationBuilder.DropTable( name: "AspNetUserTokens"); migrationBuilder.DropTable( name: "Avatars"); migrationBuilder.DropTable( name: "BannedDevices"); migrationBuilder.DropTable( name: "Devices"); migrationBuilder.DropTable( name: "Followers"); migrationBuilder.DropTable( name: "Followings"); migrationBuilder.DropTable( name: "Tokens"); migrationBuilder.DropTable( name: "VerificationRequests"); migrationBuilder.DropTable( name: "AspNetRoles"); migrationBuilder.DropTable( name: "AspNetUsers"); } } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Migrations\XIdentityDb\20260906032659_InitialIdentityServerDbContext.Designer.cs // using System; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using xIds.DbContext; namespace xIds.Migrations.XIdentityDb { [DbContext(typeof(XIdentityDbContext))] [Migration("20260906032659_InitialIdentityServerDbContext")] partial class InitialIdentityServerDbContext { protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder .HasAnnotation("ProductVersion", "5.0.2"); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => { b.Property("Id") .HasColumnType("TEXT"); b.Property("ConcurrencyStamp") .IsConcurrencyToken() .HasColumnType("TEXT"); b.Property("Name") .HasMaxLength(256) .HasColumnType("TEXT"); b.Property("NormalizedName") .HasMaxLength(256) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("NormalizedName") .IsUnique() .HasDatabaseName("RoleNameIndex"); b.ToTable("AspNetRoles"); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ClaimType") .HasColumnType("TEXT"); b.Property("ClaimValue") .HasColumnType("TEXT"); b.Property("RoleId") .IsRequired() .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("RoleId"); b.ToTable("AspNetRoleClaims"); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("TEXT"); b.Property("AccessFailedCount") .HasColumnType("INTEGER"); b.Property("ConcurrencyStamp") .IsConcurrencyToken() .HasColumnType("TEXT"); b.Property("Discriminator") .IsRequired() .HasColumnType("TEXT"); b.Property("Email") .HasMaxLength(256) .HasColumnType("TEXT"); b.Property("EmailConfirmed") .HasColumnType("INTEGER"); b.Property("LockoutEnabled") .HasColumnType("INTEGER"); b.Property("LockoutEnd") .HasColumnType("TEXT"); b.Property("NormalizedEmail") .HasMaxLength(256) .HasColumnType("TEXT"); b.Property("NormalizedUserName") .HasMaxLength(256) .HasColumnType("TEXT"); b.Property("PasswordHash") .HasColumnType("TEXT"); b.Property("PhoneNumber") .HasColumnType("TEXT"); b.Property("PhoneNumberConfirmed") .HasColumnType("INTEGER"); b.Property("SecurityStamp") .HasColumnType("TEXT"); b.Property("TwoFactorEnabled") .HasColumnType("INTEGER"); b.Property("UserName") .HasMaxLength(256) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("NormalizedEmail") .HasDatabaseName("EmailIndex"); b.HasIndex("NormalizedUserName") .IsUnique() .HasDatabaseName("UserNameIndex"); b.ToTable("AspNetUsers"); b.HasDiscriminator("Discriminator").HasValue("IdentityUser"); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ClaimType") .HasColumnType("TEXT"); b.Property("ClaimValue") .HasColumnType("TEXT"); b.Property("UserId") .IsRequired() .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("UserId"); b.ToTable("AspNetUserClaims"); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { b.Property("LoginProvider") .HasColumnType("TEXT"); b.Property("ProviderKey") .HasColumnType("TEXT"); b.Property("ProviderDisplayName") .HasColumnType("TEXT"); b.Property("UserId") .IsRequired() .HasColumnType("TEXT"); b.HasKey("LoginProvider", "ProviderKey"); b.HasIndex("UserId"); b.ToTable("AspNetUserLogins"); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => { b.Property("UserId") .HasColumnType("TEXT"); b.Property("RoleId") .HasColumnType("TEXT"); b.HasKey("UserId", "RoleId"); b.HasIndex("RoleId"); b.ToTable("AspNetUserRoles"); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { b.Property("UserId") .HasColumnType("TEXT"); b.Property("LoginProvider") .HasColumnType("TEXT"); b.Property("Name") .HasColumnType("TEXT"); b.Property("Value") .HasColumnType("TEXT"); b.HasKey("UserId", "LoginProvider", "Name"); b.ToTable("AspNetUserTokens"); }); modelBuilder.Entity("xIdentityModels.Models.XBannedDevice", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("BannedOn") .HasColumnType("TEXT"); b.Property("Deleted") .HasColumnType("INTEGER"); b.Property("DeviceStr") .HasColumnType("TEXT"); b.HasKey("Id"); b.ToTable("BannedDevices"); }); modelBuilder.Entity("xIdentityModels.Models.XToken", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("Deleted") .HasColumnType("INTEGER"); b.Property("DeviceStr") .HasColumnType("TEXT"); b.Property("Hash") .HasColumnType("TEXT"); b.Property("Token") .HasColumnType("TEXT"); b.Property("Type") .HasColumnType("INTEGER"); b.Property("UserSelectByParam") .HasColumnType("TEXT"); b.HasKey("Id"); b.ToTable("Tokens"); }); modelBuilder.Entity("xIdentityModels.Models.XVerificationRequest", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("Deleted") .HasColumnType("INTEGER"); b.Property("DeviceStr") .HasColumnType("TEXT"); b.Property("LastTryOn") .HasColumnType("TEXT"); b.Property("NumberOfTries") .HasColumnType("INTEGER"); b.Property("RequestStr") .HasColumnType("TEXT"); b.Property("VerificationCode") .IsRequired() .HasColumnType("TEXT"); b.HasKey("Id"); b.ToTable("VerificationRequests"); }); modelBuilder.Entity("xIdentityModels.Navigations.XDevice", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("Browser") .HasColumnType("TEXT"); b.Property("Deleted") .HasColumnType("INTEGER"); b.Property("DeviceType") .HasColumnType("INTEGER"); b.Property("Os") .HasColumnType("TEXT"); b.Property("OsVersion") .HasColumnType("TEXT"); b.Property("UserAgent") .HasColumnType("TEXT"); b.Property("UserId") .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("UserId"); b.ToTable("Devices"); }); modelBuilder.Entity("xIdentityModels.Navigations.XFriendshipFollower", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("Deleted") .HasColumnType("INTEGER"); b.Property("DestId") .HasColumnType("TEXT"); b.Property("State") .HasColumnType("INTEGER"); b.Property("UserId") .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("DestId"); b.HasIndex("UserId"); b.ToTable("Followers"); }); modelBuilder.Entity("xIdentityModels.Navigations.XFriendshipFollowing", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("Deleted") .HasColumnType("INTEGER"); b.Property("DestId") .HasColumnType("TEXT"); b.Property("State") .HasColumnType("INTEGER"); b.Property("UserId") .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("DestId"); b.HasIndex("UserId"); b.ToTable("Followings"); }); modelBuilder.Entity("xIdentityModels.Navigations.XProfileImage", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("CreationDate") .HasColumnType("TEXT"); b.Property("Deleted") .HasColumnType("INTEGER"); b.Property("Name") .IsRequired() .HasMaxLength(255) .HasColumnType("TEXT"); b.Property("Path") .IsRequired() .HasMaxLength(255) .HasColumnType("TEXT"); b.Property("Thumb") .IsRequired() .HasMaxLength(255) .HasColumnType("TEXT"); b.Property("ThumbPath") .IsRequired() .HasMaxLength(255) .HasColumnType("TEXT"); b.Property("UserId") .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("UserId"); b.ToTable("Avatars"); }); modelBuilder.Entity("xIdentityModels.XUser", b => { b.HasBaseType("Microsoft.AspNetCore.Identity.IdentityUser"); b.Property("Avatar") .HasColumnType("TEXT"); b.Property("Bio") .HasColumnType("TEXT"); b.Property("CoverImage") .HasColumnType("TEXT"); b.Property("CreationDate") .HasColumnType("TEXT"); b.Property("DateOfBirth") .HasColumnType("TEXT"); b.Property("FirstName") .IsRequired() .HasMaxLength(50) .HasColumnType("TEXT"); b.Property("Gender") .HasColumnType("INTEGER"); b.Property("IsBanned") .HasColumnType("INTEGER"); b.Property("IsEnable") .HasColumnType("INTEGER"); b.Property("LastLogin") .HasColumnType("TEXT"); b.Property("LastName") .IsRequired() .HasMaxLength(100) .HasColumnType("TEXT"); b.Property("OpenToSearch") .HasColumnType("INTEGER"); b.HasDiscriminator().HasValue("XUser"); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) .WithMany() .HasForeignKey("RoleId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => { b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) .WithMany() .HasForeignKey("RoleId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.HasOne("xIdentityModels.XUser", null) .WithMany("Roles") .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); modelBuilder.Entity("xIdentityModels.Navigations.XDevice", b => { b.HasOne("xIdentityModels.XUser", "User") .WithMany("Devices") .HasForeignKey("UserId"); b.Navigation("User"); }); modelBuilder.Entity("xIdentityModels.Navigations.XFriendshipFollower", b => { b.HasOne("xIdentityModels.XUser", "Dest") .WithMany() .HasForeignKey("DestId"); b.HasOne("xIdentityModels.XUser", "User") .WithMany("Followers") .HasForeignKey("UserId"); b.Navigation("Dest"); b.Navigation("User"); }); modelBuilder.Entity("xIdentityModels.Navigations.XFriendshipFollowing", b => { b.HasOne("xIdentityModels.XUser", "Dest") .WithMany() .HasForeignKey("DestId"); b.HasOne("xIdentityModels.XUser", "User") .WithMany("Followings") .HasForeignKey("UserId"); b.Navigation("Dest"); b.Navigation("User"); }); modelBuilder.Entity("xIdentityModels.Navigations.XProfileImage", b => { b.HasOne("xIdentityModels.XUser", "User") .WithMany("Avatars") .HasForeignKey("UserId"); b.Navigation("User"); }); modelBuilder.Entity("xIdentityModels.XUser", b => { b.Navigation("Avatars"); b.Navigation("Devices"); b.Navigation("Followers"); b.Navigation("Followings"); b.Navigation("Roles"); }); #pragma warning restore 612, 618 } } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Migrations\XIdentityDb\XIdentityDbContextModelSnapshot.cs // using System; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using xIds.DbContext; namespace xIds.Migrations.XIdentityDb { [DbContext(typeof(XIdentityDbContext))] partial class XIdentityDbContextModelSnapshot : ModelSnapshot { protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder .HasAnnotation("ProductVersion", "5.0.2"); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => { b.Property("Id") .HasColumnType("TEXT"); b.Property("ConcurrencyStamp") .IsConcurrencyToken() .HasColumnType("TEXT"); b.Property("Name") .HasMaxLength(256) .HasColumnType("TEXT"); b.Property("NormalizedName") .HasMaxLength(256) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("NormalizedName") .IsUnique() .HasDatabaseName("RoleNameIndex"); b.ToTable("AspNetRoles"); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ClaimType") .HasColumnType("TEXT"); b.Property("ClaimValue") .HasColumnType("TEXT"); b.Property("RoleId") .IsRequired() .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("RoleId"); b.ToTable("AspNetRoleClaims"); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("TEXT"); b.Property("AccessFailedCount") .HasColumnType("INTEGER"); b.Property("ConcurrencyStamp") .IsConcurrencyToken() .HasColumnType("TEXT"); b.Property("Discriminator") .IsRequired() .HasColumnType("TEXT"); b.Property("Email") .HasMaxLength(256) .HasColumnType("TEXT"); b.Property("EmailConfirmed") .HasColumnType("INTEGER"); b.Property("LockoutEnabled") .HasColumnType("INTEGER"); b.Property("LockoutEnd") .HasColumnType("TEXT"); b.Property("NormalizedEmail") .HasMaxLength(256) .HasColumnType("TEXT"); b.Property("NormalizedUserName") .HasMaxLength(256) .HasColumnType("TEXT"); b.Property("PasswordHash") .HasColumnType("TEXT"); b.Property("PhoneNumber") .HasColumnType("TEXT"); b.Property("PhoneNumberConfirmed") .HasColumnType("INTEGER"); b.Property("SecurityStamp") .HasColumnType("TEXT"); b.Property("TwoFactorEnabled") .HasColumnType("INTEGER"); b.Property("UserName") .HasMaxLength(256) .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("NormalizedEmail") .HasDatabaseName("EmailIndex"); b.HasIndex("NormalizedUserName") .IsUnique() .HasDatabaseName("UserNameIndex"); b.ToTable("AspNetUsers"); b.HasDiscriminator("Discriminator").HasValue("IdentityUser"); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("ClaimType") .HasColumnType("TEXT"); b.Property("ClaimValue") .HasColumnType("TEXT"); b.Property("UserId") .IsRequired() .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("UserId"); b.ToTable("AspNetUserClaims"); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { b.Property("LoginProvider") .HasColumnType("TEXT"); b.Property("ProviderKey") .HasColumnType("TEXT"); b.Property("ProviderDisplayName") .HasColumnType("TEXT"); b.Property("UserId") .IsRequired() .HasColumnType("TEXT"); b.HasKey("LoginProvider", "ProviderKey"); b.HasIndex("UserId"); b.ToTable("AspNetUserLogins"); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => { b.Property("UserId") .HasColumnType("TEXT"); b.Property("RoleId") .HasColumnType("TEXT"); b.HasKey("UserId", "RoleId"); b.HasIndex("RoleId"); b.ToTable("AspNetUserRoles"); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { b.Property("UserId") .HasColumnType("TEXT"); b.Property("LoginProvider") .HasColumnType("TEXT"); b.Property("Name") .HasColumnType("TEXT"); b.Property("Value") .HasColumnType("TEXT"); b.HasKey("UserId", "LoginProvider", "Name"); b.ToTable("AspNetUserTokens"); }); modelBuilder.Entity("xIdentityModels.Models.XBannedDevice", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("BannedOn") .HasColumnType("TEXT"); b.Property("Deleted") .HasColumnType("INTEGER"); b.Property("DeviceStr") .HasColumnType("TEXT"); b.HasKey("Id"); b.ToTable("BannedDevices"); }); modelBuilder.Entity("xIdentityModels.Models.XToken", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("Deleted") .HasColumnType("INTEGER"); b.Property("DeviceStr") .HasColumnType("TEXT"); b.Property("Hash") .HasColumnType("TEXT"); b.Property("Token") .HasColumnType("TEXT"); b.Property("Type") .HasColumnType("INTEGER"); b.Property("UserSelectByParam") .HasColumnType("TEXT"); b.HasKey("Id"); b.ToTable("Tokens"); }); modelBuilder.Entity("xIdentityModels.Models.XVerificationRequest", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("Deleted") .HasColumnType("INTEGER"); b.Property("DeviceStr") .HasColumnType("TEXT"); b.Property("LastTryOn") .HasColumnType("TEXT"); b.Property("NumberOfTries") .HasColumnType("INTEGER"); b.Property("RequestStr") .HasColumnType("TEXT"); b.Property("VerificationCode") .IsRequired() .HasColumnType("TEXT"); b.HasKey("Id"); b.ToTable("VerificationRequests"); }); modelBuilder.Entity("xIdentityModels.Navigations.XDevice", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("Browser") .HasColumnType("TEXT"); b.Property("Deleted") .HasColumnType("INTEGER"); b.Property("DeviceType") .HasColumnType("INTEGER"); b.Property("Os") .HasColumnType("TEXT"); b.Property("OsVersion") .HasColumnType("TEXT"); b.Property("UserAgent") .HasColumnType("TEXT"); b.Property("UserId") .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("UserId"); b.ToTable("Devices"); }); modelBuilder.Entity("xIdentityModels.Navigations.XFriendshipFollower", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("Deleted") .HasColumnType("INTEGER"); b.Property("DestId") .HasColumnType("TEXT"); b.Property("State") .HasColumnType("INTEGER"); b.Property("UserId") .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("DestId"); b.HasIndex("UserId"); b.ToTable("Followers"); }); modelBuilder.Entity("xIdentityModels.Navigations.XFriendshipFollowing", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("Deleted") .HasColumnType("INTEGER"); b.Property("DestId") .HasColumnType("TEXT"); b.Property("State") .HasColumnType("INTEGER"); b.Property("UserId") .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("DestId"); b.HasIndex("UserId"); b.ToTable("Followings"); }); modelBuilder.Entity("xIdentityModels.Navigations.XProfileImage", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("INTEGER"); b.Property("CreationDate") .HasColumnType("TEXT"); b.Property("Deleted") .HasColumnType("INTEGER"); b.Property("Name") .IsRequired() .HasMaxLength(255) .HasColumnType("TEXT"); b.Property("Path") .IsRequired() .HasMaxLength(255) .HasColumnType("TEXT"); b.Property("Thumb") .IsRequired() .HasMaxLength(255) .HasColumnType("TEXT"); b.Property("ThumbPath") .IsRequired() .HasMaxLength(255) .HasColumnType("TEXT"); b.Property("UserId") .HasColumnType("TEXT"); b.HasKey("Id"); b.HasIndex("UserId"); b.ToTable("Avatars"); }); modelBuilder.Entity("xIdentityModels.XUser", b => { b.HasBaseType("Microsoft.AspNetCore.Identity.IdentityUser"); b.Property("Avatar") .HasColumnType("TEXT"); b.Property("Bio") .HasColumnType("TEXT"); b.Property("CoverImage") .HasColumnType("TEXT"); b.Property("CreationDate") .HasColumnType("TEXT"); b.Property("DateOfBirth") .HasColumnType("TEXT"); b.Property("FirstName") .IsRequired() .HasMaxLength(50) .HasColumnType("TEXT"); b.Property("Gender") .HasColumnType("INTEGER"); b.Property("IsBanned") .HasColumnType("INTEGER"); b.Property("IsEnable") .HasColumnType("INTEGER"); b.Property("LastLogin") .HasColumnType("TEXT"); b.Property("LastName") .IsRequired() .HasMaxLength(100) .HasColumnType("TEXT"); b.Property("OpenToSearch") .HasColumnType("INTEGER"); b.HasDiscriminator().HasValue("XUser"); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) .WithMany() .HasForeignKey("RoleId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => { b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) .WithMany() .HasForeignKey("RoleId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.HasOne("xIdentityModels.XUser", null) .WithMany("Roles") .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); modelBuilder.Entity("xIdentityModels.Navigations.XDevice", b => { b.HasOne("xIdentityModels.XUser", "User") .WithMany("Devices") .HasForeignKey("UserId"); b.Navigation("User"); }); modelBuilder.Entity("xIdentityModels.Navigations.XFriendshipFollower", b => { b.HasOne("xIdentityModels.XUser", "Dest") .WithMany() .HasForeignKey("DestId"); b.HasOne("xIdentityModels.XUser", "User") .WithMany("Followers") .HasForeignKey("UserId"); b.Navigation("Dest"); b.Navigation("User"); }); modelBuilder.Entity("xIdentityModels.Navigations.XFriendshipFollowing", b => { b.HasOne("xIdentityModels.XUser", "Dest") .WithMany() .HasForeignKey("DestId"); b.HasOne("xIdentityModels.XUser", "User") .WithMany("Followings") .HasForeignKey("UserId"); b.Navigation("Dest"); b.Navigation("User"); }); modelBuilder.Entity("xIdentityModels.Navigations.XProfileImage", b => { b.HasOne("xIdentityModels.XUser", "User") .WithMany("Avatars") .HasForeignKey("UserId"); b.Navigation("User"); }); modelBuilder.Entity("xIdentityModels.XUser", b => { b.Navigation("Avatars"); b.Navigation("Devices"); b.Navigation("Followers"); b.Navigation("Followings"); b.Navigation("Roles"); }); #pragma warning restore 612, 618 } } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Models\XDbInfo.cs using System; using xIds.Constants; namespace xIds.Models { public class XDbInfo { private string _migrationAssembly; public XDbProviders ProviderType { get; set; } public string MigrationsAssembly { get { return _migrationAssembly; } set { // _migrationAssembly = value; // OptionsBuilder = b => { b.MigrationsAssembly(value); }; } } public Action OptionsBuilder { get; set; } } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Models\XDbSeedDescriptor.cs using System.Collections.Generic; using IdentityServer4.Models; using xIdentityModels.Descriptors; namespace xIds.Models { /// /// the resource Descriptors for Using on DbSeed /// public class XDbSeedDescriptor { public bool UpdateExists { get; set; } public ICollection ApiScopes { get; set; } public ICollection ApiResources { get; set; } public ICollection IdentityResources { get; set; } public ICollection Clients { get; set; } public ICollection Users { get; set; } } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Providers\XIdentityManager.cs using System.Collections.Generic; using System.Linq; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using xCommons.Extensions; using xCommons.Providers; using xExceptions.Constants; using xIdentityModels; using xIdentityModels.Configurations; using xIdentityModels.Constants; using xIdentityModels.Models; using xMessageService.Interfaces; using xStorageService.Interfaces; using xIds.Configurations; using xIds.DbContext; using xIds.Interfaces; namespace xIds.Providers { public partial class XIdentityManager : IXIdentityManager { // private JsonSerializerSettings jsonSerializerSettings; // public XIdentityDbContext DbContext { get; } public UserManager UserManager { get; } public IXIdentityHelper IdentityHelper { get; } public ILogger Logger { get; } public IXMessageProvider MessageProvider { get; } public IXStorageProvider StorageProvider { get; } public SignInManager SignInManager { get; } public IXSecurityProvider SecurityProvider { get; } public XIdentityConfiguration Configuration { get; } public RoleManager RoleManager { get; } public XValidationProvider ValidationProvider { get; } public XDataServiceConfiguration DataConfiguration { get; } public IXIdentityMessageProvider IdentityMessageProvider { get; } public XIdentityResourceConfiguration IdentityResourceConfiguration { get; } public XIdentityManager( XIdentityDbContext dbContext, UserManager userManager, IXIdentityHelper identityHelper, ILogger logger, IXMessageProvider messageProvider, IXStorageProvider storageProvider, SignInManager signInManager, IXSecurityProvider securityProvider, XIdentityConfiguration configuration, RoleManager roleManager, XValidationProvider validationProvider, XDataServiceConfiguration dataConfiguration, IXIdentityMessageProvider identityMessageProvider, XIdentityResourceConfiguration identityResourceConfiguration ) { // Logger = logger; DbContext = dbContext; RoleManager = roleManager; UserManager = userManager; SignInManager = signInManager; SecurityProvider = securityProvider; Configuration = configuration; IdentityHelper = identityHelper; MessageProvider = messageProvider; StorageProvider = storageProvider; DataConfiguration = dataConfiguration; ValidationProvider = validationProvider; IdentityMessageProvider = identityMessageProvider; IdentityResourceConfiguration = identityResourceConfiguration; // this.jsonSerializerSettings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }; } // #region Class Getter (s) Methods ... /// /// Retrieve User DB Set /// /// specifies returned object contains all Navigation Properties or not, default is false /// public IQueryable GetUsersDbSet( bool containDetails = false ) { // var dbSet = containDetails ? GetUsersFullDbSet() : UserManager.Users; return dbSet; } /// /// Retrieve User Db Set Full Navigation Properties /// /// /// public IQueryable GetUsersFullDbSet(bool enableTracking = false) { // var dbSet = UserManager.Users .Include(u => u.Roles) .Include(u => u.Devices) .Include(u => u.Followers) .Include(u => u.Followings) .Include(u => u.Avatars); // return dbSet.AsSplitQuery(); } #endregion // #region Tools ... /// /// Get User SelectBy Param /// /// /// /// /// public string GetUserSelectByParam( XActionRequest model, bool forceNotNull = true, ICollection excludes = null ) { // // Validate Args ... ValidationProvider.NotNull(model); // var id = model.UserId; var userName = model.UserName; var email = model.Email; var phoneNumber = model.MobileNumber; // if (excludes != null) { // if (excludes.Contains(XUserSelectBy.ID)) { id = null; } if (excludes.Contains(XUserSelectBy.Email)) { email = null; } if (excludes.Contains(XUserSelectBy.MobileNumber)) { phoneNumber = null; } if (excludes.Contains(XUserSelectBy.Username)) { userName = null; } } var selectByParam = id.IsNullOrEmpty() ? userName.IsNullOrEmpty() ? email.IsNullOrEmpty() ? phoneNumber.IsNullOrEmpty() ? null : phoneNumber : email : userName : id; // // Check result ... if (forceNotNull && selectByParam.IsNullOrEmpty()) { XException.InvalidData.Throw(); } // return selectByParam; } #endregion } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Providers\XIdentityMessageProvider.cs using System.Linq; using Microsoft.Extensions.Logging; using xCommons.Extensions; using xExceptions.Constants; using xIdentityModels.Configurations; using xIds.Constants; using xIds.Interfaces; namespace xIds.Providers { public class XIdentityMessageProvider : IXIdentityMessageProvider { // public string InviteMsg { get; set; } public string RegistrationApproveMsg { get; set; } public string RegisteredMsg { get; set; } public string VerificationCodeMsg { get; set; } public string ChangePasswordMsg { get; set; } public string PasswordChangedMsg { get; set; } public string NewDeviceLoggedInMsg { get; set; } private readonly ILogger logger; private readonly XIdentityConfiguration identityConfiguration; public XIdentityMessageProvider( ILogger logger, XIdentityConfiguration identityConfiguration ) { this.logger = logger; this.identityConfiguration = identityConfiguration; } /// /// Determine All things is Ready or Not /// /// public bool IsReady() { return !InviteMsg.IsNullOrEmpty() && !RegistrationApproveMsg.IsNullOrEmpty() && !RegisteredMsg.IsNullOrEmpty() && !VerificationCodeMsg.IsNullOrEmpty() && !ChangePasswordMsg.IsNullOrEmpty() && !PasswordChangedMsg.IsNullOrEmpty() && !NewDeviceLoggedInMsg.IsNullOrEmpty(); } /// /// Retrieve a Translated Value Based on Given Lang /// /// /// /// private string GetStringResource(string resourceTitle, string lang) { // var item = identityConfiguration.IdentityMessages .FirstOrDefault(sr => sr.Language.ToNormalString() == lang.ToNormalString() && sr.ResourceTitle.ToNormalString() == resourceTitle.ToNormalString()); // if (item == null) { return null; } // return item.TranslatedValue; } /// /// Prepare Helper Class and Fill Messages /// with Specific Language /// /// public void PrepareMessages(string lang) { // InviteMsg = GetStringResource(IdentityMessagesKeys.InviteMsg, lang); RegisteredMsg = GetStringResource(IdentityMessagesKeys.RegisteredMsg, lang); ChangePasswordMsg = GetStringResource(IdentityMessagesKeys.ChangePasswordMsg, lang); PasswordChangedMsg = GetStringResource(IdentityMessagesKeys.PasswordChangedMsg, lang); VerificationCodeMsg = GetStringResource(IdentityMessagesKeys.VerificationCodeMsg, lang); NewDeviceLoggedInMsg = GetStringResource(IdentityMessagesKeys.NewDeviceLoggedInMsg, lang); RegistrationApproveMsg = GetStringResource(IdentityMessagesKeys.RegistrationApproveMsg, lang); // if (!IsReady()) { XException.InvalidArgs.Throw(); } } } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Providers\XIdentityProfileService.cs using System.Linq; using System.Threading.Tasks; using IdentityServer4.Extensions; using IdentityServer4.Models; using IdentityServer4.Services; using Microsoft.AspNetCore.Identity; using xCommons.Extensions; using xIdentityModels; using xIds.Interfaces; namespace xIds.Providers { public class XIdentityProfileService : IProfileService { private readonly IXIdentityManager identityManager; private readonly IUserClaimsPrincipalFactory userClaimsPrincipalFacotry; public XIdentityProfileService( IXIdentityManager identityManager, IUserClaimsPrincipalFactory userClaimsPrincipalFacotry ) { this.identityManager = identityManager; this.userClaimsPrincipalFacotry = userClaimsPrincipalFacotry; } public async Task GetProfileDataAsync(ProfileDataRequestContext context) { // var sub = context.Subject.GetSubjectId(); var user = await identityManager.GetUserAsync(sub, true); var principal = await userClaimsPrincipalFacotry.CreateAsync(user); // var claims = principal.Claims.ToList(); // context.IssuedClaims = claims; } public async Task IsActiveAsync(IsActiveContext context) { // var sub = context.Subject.GetSubjectId(); var user = await identityManager.GetUserAsync(sub); // context.IsActive = !user.IsNull() && user.IsEnable && !user.IsBanned; } } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Providers\XSecurityProvider.cs using System; using System.IO; using System.Security.Cryptography; using System.Text; using xCommons.Extensions; using xCommons.Providers; using xIds.Configurations; using xIds.Interfaces; namespace xIds.Providers { public class XSecurityProvider : IXSecurityProvider { // #region Props ... private readonly string secretKey; private readonly byte[] iv; private readonly byte[] key; private readonly XValidationProvider validationProvider; #endregion // #region Constructor ... public XSecurityProvider( XIdentityResourceConfiguration identityConfiguration, XValidationProvider validationProvider ) { // this.secretKey = identityConfiguration.XRevisionSecretKey.ToMd5String(); this.validationProvider = validationProvider; // var ivBytes = new byte[16]; var keyBytes = new byte[32]; var secretBytes = Encoding.UTF8.GetBytes(this.secretKey); // Array.Copy( secretBytes, ivBytes, secretBytes.Length < ivBytes.Length ? secretBytes.Length : ivBytes.Length ); this.iv = ivBytes; // Array.Copy( secretBytes, keyBytes, secretBytes.Length < keyBytes.Length ? secretBytes.Length : keyBytes.Length ); this.key = keyBytes; // Encoding.UTF8.GetBytes (this.secretKey); } #endregion // #region Actions ... public string Encrypt(string plainText) { // validationProvider.NotEmpty(plainText); // var textBytes = Encoding.UTF8.GetBytes(plainText); var result = EncryptFromBytes(textBytes); // return result; } public string Decrypt(string cipherText) { // validationProvider.NotEmpty(cipherText); // var cipherBytes = Convert.FromBase64String(cipherText); var result = DecryptFromBytes(cipherBytes); // return result; } public string EncryptFromBytes(byte[] textBytes) { // // Validate Args ... validationProvider.NotNull(textBytes); // Declare the string used to hold // the decrypted text. byte[] encryptedBytes = null; // Create an RijndaelManaged object // with the specified key and IV. using (var rijAlg = new RijndaelManaged()) { //Settings rijAlg.Mode = CipherMode.CBC; rijAlg.Padding = PaddingMode.PKCS7; // rijAlg.FeedbackSize = 128; rijAlg.Key = key; rijAlg.IV = iv; // using (var encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV)) { encryptedBytes = encryptor.TransformFinalBlock(textBytes, 0, textBytes.Length); } } // return Convert.ToBase64String(encryptedBytes); } public string DecryptFromBytes(byte[] cipherBytes) { // // Validate Args ... validationProvider.NotNull(cipherBytes); // Declare the string used to hold // the decrypted text. string plaintext = null; // Create an RijndaelManaged object // with the specified key and IV. using (var rijAlg = new RijndaelManaged()) { //Settings rijAlg.Mode = CipherMode.CBC; rijAlg.Padding = PaddingMode.PKCS7; // rijAlg.FeedbackSize = 128; rijAlg.Key = key; rijAlg.IV = iv; // Create a decrytor to perform the stream transform. var decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV); // Create the streams used for decryption. using (var msDecrypt = new MemoryStream(cipherBytes)) { using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) { using (var srDecrypt = new StreamReader(csDecrypt)) { // Read the decrypted bytes from the decrypting stream // and place them in a string. plaintext = srDecrypt.ReadToEnd(); } } } } // return plaintext; } #endregion } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+Admin.cs using System.Collections.Generic; using System.Threading.Tasks; using xCommons.Extensions; using xIdentityModels.Dtos; namespace xIds.Providers { public partial class XIdentityManager { #region Admin Actions ... /// /// Retrieve All UnBanned Users Identifiers /// /// caller user identifier /// a collection of user identifiers public async Task> GetAllUnbanned( ICollection userSelectByParam ) { // var result = new List(); if (!userSelectByParam.HasChild()) { return result; } // foreach (var uParam in userSelectByParam) { // var destUser = await ValidateUserExistsAndRetrieve(uParam, checkIsBanned: false); if (!destUser.IsBanned) { result.Add(uParam); } } // return result; } /// /// Get All Banned Users Identifiers /// /// caller user identifier /// a collection of user identifiers public async Task> GetAllBanned( ICollection userSelectByParam ) { // var result = new List(); if (!userSelectByParam.HasChild()) { return result; } // foreach (var uParam in userSelectByParam) { // var destUser = await ValidateUserExistsAndRetrieve(uParam, checkIsBanned: false); if (destUser.IsBanned) { result.Add(uParam); } } // return result; } /// /// Ban a Collection of Users /// /// caller user identifier /// an instance of XUserNameIdRequest which represents user identifier list to Ban /// a collection of user identifiers public async Task> Ban( string userSelectByParam, XUserNameIdRequest model ) { // // Validate Args ... ValidationProvider.NotEmpty(userSelectByParam); ValidationProvider.NotNull(model); ValidationProvider.NotZeroChilds(model.Ids); // var user = await ValidateUserExistsAndRetrieve( userSelectByParam, forceAdmin: true, checkIsBanned: true, containDetails: false, ignoreDisabledUser: false, checkCanLoginPolicies: true ); // var result = new List(); foreach (var uParam in model.Ids) { // var destUser = await ValidateUserExistsAndRetrieve(uParam, checkIsBanned: false); // var isBanned = destUser.IsBanned; if (!isBanned) { // destUser.IsBanned = true; // await UpdateUserAsync( user, checkCanLoginPolicies: false, checkIsBanned: false ); // result.Add(destUser.Id); } } // return result; } /// /// UnBan a Collection of Users /// /// caller user identifier /// an instance of XUserNameIdRequest which represents user identifier list to Ban /// a collection of user identifiers public async Task> UnBan( string userSelectByParam, XUserNameIdRequest model ) { // // Validate Args ... ValidationProvider.NotEmpty(userSelectByParam); ValidationProvider.NotNull(model); ValidationProvider.NotZeroChilds(model.Ids); // var user = await ValidateUserExistsAndRetrieve( userSelectByParam, forceAdmin: true, checkIsBanned: true, containDetails: false, ignoreDisabledUser: false, checkCanLoginPolicies: true ); // var result = new List(); foreach (var uParam in model.Ids) { // var destUser = await ValidateUserExistsAndRetrieve(uParam, checkIsBanned: false); // var isBanned = destUser.IsBanned; if (isBanned) { // destUser.IsBanned = false; // await UpdateUserAsync( user, checkCanLoginPolicies: false, checkIsBanned: false ); // result.Add(destUser.Id); } } // return result; } /// /// Detrmines a User is Banned or not /// /// caller user identifier /// destination user identifier which checked is banned or not /// a boolean value which represent user banned or not public async Task IsBanned( string userSelectByParam, string destUserSelectByParam ) { // // Validate Args ... ValidationProvider.NotEmpty( userSelectByParam, destUserSelectByParam ); // var user = await ValidateUserExistsAndRetrieve( userSelectByParam, forceAdmin: false, checkIsBanned: true, containDetails: false, ignoreDisabledUser: false, checkCanLoginPolicies: true ); var destUser = await ValidateUserExistsAndRetrieve(destUserSelectByParam, checkIsBanned: false); // var result = destUser.IsBanned; // return result; } #endregion } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+Device.cs using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using xCommons.Extensions; using xExceptions.Constants; using xIdentityModels; using xIdentityModels.Extensions; using xIdentityModels.Models; using xIdentityModels.Navigations; using xIds.Extensions; namespace xIds.Providers { public partial class XIdentityManager { // #region Device Actions ... /// /// Check a Device Exists or Not /// /// an instance of XDevice /// a boolean value public async Task IsDeviceExistsAsync( XDevice device ) { return await DbContext.Devices .AnyAsync(d => d.IsSameAs(device)); } /// /// Add new Device /// /// an instance of XDevice /// an instance of XDevice public async Task AddDeviceAsync( XDevice device ) { // var isDeviceExists = await IsDeviceExistsAsync(device); if (isDeviceExists) { return null; } // await DbContext.Devices .AddAsync(device); await DbContext.SaveChangesAsync(); return device; } /// /// Get a Device /// /// an instance of XDevice /// an instance of XDevice public Task GetDeviceAsync( XDevice device ) { // return DbContext.Devices .FirstOrDefaultAsync(d => d.IsSameAs(device)); } /// /// Retrieve a List of User Related Devices /// /// user identifier /// check a user can log in in system or not /// check user is banned or not /// a collection of XDevice instances which related to user public async Task> GetUserDevices( string userSelectByParam, bool checkCanLoginPolicies = true, bool checkIsBanned = true ) { // // Validate ARgs ... ValidationProvider.NotEmpty(userSelectByParam); // // Validate And Retrieve User ... var user = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: true, checkCanLoginPolicies: checkCanLoginPolicies, checkIsBanned: checkIsBanned ); // // Check User Devices ... if (!user.Devices.HasChild()) { return new List(); } // return user.Devices; } /// /// Determines a Device is Exists in User's Devices or not /// /// an instance of XUser /// an instance of XDevice /// a boolean value public bool IsDeviceRelateDToUser( XUser user, XDevice device ) { if (!user.Devices.HasChild()) { return false; } // var result = user.Devices.Any(d => d.IsSameAs(device)); // return result; } /// /// Determines a Device is Exists in User's Devices or not /// /// user identifier /// an instance of XDevice /// check a user can log in in system or not /// check user is banned or not /// a boolean value public async Task IsDeviceRelateDToUser( string userSelectByParam, XDevice device, bool checkCanLoginPolicies = true, bool checkIsBanned = true ) { // // Validate Args ... ValidationProvider.NotEmpty(userSelectByParam); ValidationProvider.NotNull(device); // var userDevices = await GetUserDevices( userSelectByParam, checkCanLoginPolicies: checkCanLoginPolicies, checkIsBanned: checkIsBanned ); if (!userDevices.HasChild()) { return false; } // var result = userDevices.Any(d => d.IsSameAs(device)); // return result; } /// /// Add a Device to a User Related Devices /// /// an instance of XUser /// an instance of XDevice /// a boolean value public async Task AddUserRelatedDevice( XUser user, XDevice device ) { // var isExists = user.Devices.Any(d => d.IsSameAs(device)); if (isExists) { return true; } // user.Devices.Add(device); try { var result = await UpdateUserAsync(user); return result.Succeeded; } catch { throw XException.ActionFailed.ToException(); } } /// /// Add a Device to a User /// /// user identifier /// an instance of XDevice /// check a user can log in in system or not /// check user is banned or not /// a boolean value public async Task AddUserRelatedDevice( string userSelectByParam, XDevice device, bool checkCanLoginPolicies = true, bool checkIsBanned = true ) { // // Validate Args ... ValidationProvider.NotEmpty(userSelectByParam); ValidationProvider.NotNull(device); // // Check Device Related ... var isDeviceRelatedToUser = await IsDeviceRelateDToUser( userSelectByParam, device, checkCanLoginPolicies: checkCanLoginPolicies, checkIsBanned: checkIsBanned); if (isDeviceRelatedToUser) { return true; } // // Retrieve User ... var user = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: true, checkCanLoginPolicies: checkCanLoginPolicies, checkIsBanned: checkIsBanned ); // // Add User Device ... user.Devices.Add(device); // var result = await UpdateUserAsync( user, checkCanLoginPolicies: false, checkIsBanned: false ); // return result.Succeeded; } /// /// Remove a Device from a User Related Devices List /// /// an instance of XUser /// an instance of XDevice /// a boolean value public async Task RemoveUserRelatedDevice( XUser user, XDevice device ) { // var isRelated = IsDeviceRelateDToUser(user, device); if (!isRelated) { return false; } // var instanse = user.Devices .FirstOrDefault(d => d.IsSameAs(device)); // user.Devices.Remove(instanse); // var result = await UpdateUserAsync( user, checkCanLoginPolicies: false, checkIsBanned: false ); // return result.Succeeded; } /// /// Remove a Device from a User Devices /// /// user identifier /// an instance of XDevice /// check a user can log in in system or not /// check user is banned or not /// a boolean value public async Task RemoveUserRelatedDevice( string userSelectByParam, XDevice device, bool checkCanLoginPolicies = true, bool checkIsBanned = true ) { // // Validate Args ... ValidationProvider.NotEmpty(userSelectByParam); ValidationProvider.NotNull(device); // // Validate user exists and Retrieve it based on userselectbyparam ... var user = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: true, checkCanLoginPolicies: checkCanLoginPolicies, checkIsBanned: checkIsBanned ); // return await RemoveUserRelatedDevice( user, device ); } #endregion // #region Banned Device Actions ... /// /// Check a Device is exists in Banned Devices or not /// /// an instance of XDevice /// a boolean value public async Task IsBannedDeviceExists( XDevice device ) { // var result = false; var bannedDeviceEnumerable = DbContext.BannedDevices.AsAsyncEnumerable(); await foreach (var bannedDevice in bannedDeviceEnumerable) { // if (bannedDevice.Device.IsSameAs(device)) { // result = true; break; } } // return result; } /// /// Find First Banned Device /// /// an instance of XDevice /// an instance of XDevice public async Task BannedDeviceFindOne( XDevice device ) { // var result = await DbContext.BannedDevices .FirstOrDefaultAsync(bd => bd.Device.IsSameAs(device) ); // return result; } /// /// Remove Banned Device /// /// an instance of XBannedDevice /// public async Task BannedDeviceRemove( XBannedDevice model ) { // var isExists = await IsBannedDeviceExists(model.Device); if (!isExists) { return; } // var item = await BannedDeviceFindOne(model.Device); if (item == null) { return; } // DbContext.BannedDevices.Remove(item); await DbContext.SaveChangesAsync(); } /// /// Check a Device is Banned or not /// /// an instance of XDevice /// a boolean value private async Task IsDeviceBanned( XDevice device ) { // var result = await IsBannedDeviceExists(device); return result; } /// /// Retrieve Specific Banned Device /// /// an instance of XDevice /// an instance of XBannedDevice private async Task GetBannedDevice( XDevice device ) { // var result = await BannedDeviceFindOne(device); return result; } /// /// Is a Banned Device passed Banning Time /// /// an instance of XBannedDevice /// a boolean value private bool IsDelayTimePassed( XBannedDevice bannedDevice ) { // // Validate Args ... if (bannedDevice == null || Configuration == null) { XException.InvalidArgs.Throw(); } // var isPassed = bannedDevice .IsDelayTimePassed(Configuration.BannedDeviceTimeout); // return isPassed; } /// /// Retrieve Passed Time from Banning Time of specific Device /// /// an instance of XBannedDevice /// an instance of DateTime which represent Passed Time private DateTime GetPassedTime( XBannedDevice bannedDevice ) { // var result = bannedDevice.BannedOn .AddSeconds(Configuration.BannedDeviceTimeout); // return result; } #endregion } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+Friendship.cs using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; using xCommons.Extensions; using xDataService.Extensions; using xExceptions.Constants; using xIdentityModels.Constants; using xIdentityModels.Dtos; using xIdentityModels.Navigations; using xModels.Dtos; namespace xIds.Providers { public partial class XIdentityManager { // #region Friendship Actions ... // #region Actions ... /// /// Send a Follow Request for userSelectByParam to /// destUserSelectByParam /// /// caller user identifier /// dest user identifier /// an instance of XFriendshipFollowing public async Task Follow( string userSelectByParam, string destUserSelectByParam ) { // // Validate Args ... ValidationProvider.NotEmpty( userSelectByParam, destUserSelectByParam ); // // Validate and Retrieve User ... var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, forceAdmin: false, checkIsBanned: true, containDetails: true, ignoreDisabledUser: false, checkCanLoginPolicies: true ); // // Validate and Retrieve Dest User ... var xDestUser = await ValidateUserExistsAndRetrieve( destUserSelectByParam, forceAdmin: false, checkIsBanned: true, containDetails: true, ignoreDisabledUser: false, checkCanLoginPolicies: true ); // // Validate Not Same Source and Dest Users ... ValidateNotSameUsers(xUser, xDestUser); // XFriendshipFollowing following = null; XFriendshipFollower follower = null; var isRequested = IsFollowRequested(xUser, xDestUser); // // Check Request Happens Or not ... if (!isRequested) { // following = new XFriendshipFollowing { UserId = xUser.Id, DestId = xDestUser.Id, State = XFriendshipState.Pending }; // follower = new XFriendshipFollower { UserId = xDestUser.Id, DestId = xUser.Id, State = XFriendshipState.Pending }; // xUser.Followings.Add(following); xDestUser.Followers.Add(follower); } else { // // if Request Done Before Must Check State ... following = xUser.Followings.FirstOrDefault(f => f.DestId == xDestUser.Id); follower = xDestUser.Followers.FirstOrDefault(f => f.DestId == xUser.Id); if (following.IsNull() || follower.IsNull()) { XException.NotFound.Throw(); } // switch (following.State) { case XFriendshipState.Accepted: case XFriendshipState.Blocked: throw XException.NotAllowed.ToException(); case XFriendshipState.Rejected: following.State = XFriendshipState.Pending; follower.State = XFriendshipState.Pending; break; } } // var canContinue = !following.IsNull() && !follower.IsNull(); if (!canContinue) { XException.ActionFailed.Throw(); } // await UpdateUserAsync(xUser); await UpdateUserAsync(xDestUser); // var result = following; // return result; } /// /// Cancel Following /// /// caller user identifier /// dest user identifier /// a boolean value public async Task Cancel( string userSelectByParam, string destUserSelectByParam ) { // // Validate Args ... ValidationProvider.NotEmpty( userSelectByParam, destUserSelectByParam ); // // Validate and Retrieve User ... var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, forceAdmin: false, checkIsBanned: true, containDetails: true, ignoreDisabledUser: false, checkCanLoginPolicies: true ); // // Validate and Retrieve Dest User ... var xDestUser = await ValidateUserExistsAndRetrieve( destUserSelectByParam, forceAdmin: false, checkIsBanned: true, containDetails: true, ignoreDisabledUser: false, checkCanLoginPolicies: true ); // // Validate Not Same Source and Dest Users ... ValidateNotSameUsers(xUser, xDestUser); // XFriendshipFollowing following = null; XFriendshipFollower follower = null; var isRequested = IsFollowRequested(xUser, xDestUser); // // Check Request Happens Or not ... if (!isRequested) { return false; } // // if Request Done Before Must Check State ... following = xUser.Followings.FirstOrDefault(f => f.DestId == xDestUser.Id); follower = xDestUser.Followers.FirstOrDefault(f => f.DestId == xUser.Id); if (following.IsNull() || follower.IsNull()) { XException.NotFound.Throw(); } // switch (following.State) { case XFriendshipState.Accepted: case XFriendshipState.Blocked: throw XException.NotAllowed.ToException(); case XFriendshipState.Rejected: case XFriendshipState.Pending: DbContext.Followers.Remove(follower); DbContext.Followings.Remove(following); break; } // var canContinue = !following.IsNull() && !follower.IsNull(); if (!canContinue) { XException.ActionFailed.Throw(); } // await DbContext.SaveChangesAsync(); // return true; } /// /// userSelectByParam remove friendship by it's Follower /// destUserSelectByParam /// /// caller user identifier /// dest user identifier /// public async Task UnFollowFollower( string userSelectByParam, string destUserSelectByParam ) { // // Validate Args ... ValidationProvider.NotEmpty( userSelectByParam, destUserSelectByParam ); // // Validate and Retrieve User ... var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, forceAdmin: false, checkIsBanned: true, containDetails: true, ignoreDisabledUser: false, checkCanLoginPolicies: true ); // // Validate and Retrieve Dest User ... var xDestUser = await ValidateUserExistsAndRetrieve( destUserSelectByParam, forceAdmin: false, checkIsBanned: true, containDetails: true, ignoreDisabledUser: false, checkCanLoginPolicies: true ); // // Validate Not Same Source and Dest Users ... ValidateNotSameUsers(xUser, xDestUser); ValidateIsFollowers(xUser, xDestUser); // var follower = xUser.Followers .FirstOrDefault(f => f.DestId == xDestUser.Id && f.State == XFriendshipState.Accepted); var following = xDestUser.Followings .FirstOrDefault(f => f.DestId == xUser.Id && f.State == XFriendshipState.Accepted); if (follower.IsNull() || following.IsNull()) { XException.NotFound.Throw(); } // DbContext.Followers.Remove(follower); DbContext.Followings.Remove(following); // await DbContext.SaveChangesAsync(); } /// /// userSelectByParam remove friendship by it's Followings /// destUserSelectByParam /// /// caller user identifier /// dest user identifier /// public async Task UnFollowFollowing( string userSelectByParam, string destUserSelectByParam ) { // // Validate Args ... ValidationProvider.NotEmpty( userSelectByParam, destUserSelectByParam ); // // Validate and Retrieve User ... var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, forceAdmin: false, checkIsBanned: true, containDetails: true, ignoreDisabledUser: false, checkCanLoginPolicies: true ); // // Validate and Retrieve Dest User ... var xDestUser = await ValidateUserExistsAndRetrieve( destUserSelectByParam, forceAdmin: false, checkIsBanned: true, containDetails: true, ignoreDisabledUser: false, checkCanLoginPolicies: true ); // // Validate Not Same Source and Dest Users ... ValidateNotSameUsers(xUser, xDestUser); ValidateIsFollowings(xUser, xDestUser); // var following = xUser.Followings .FirstOrDefault(f => f.DestId == xDestUser.Id && f.State == XFriendshipState.Accepted); var follower = xDestUser.Followers .FirstOrDefault(f => f.DestId == xUser.Id && f.State == XFriendshipState.Accepted); if (follower.IsNull() || following.IsNull()) { XException.NotAllowed.Throw(); } // DbContext.Followers.Remove(follower); DbContext.Followings.Remove(following); // await DbContext.SaveChangesAsync(); } /// /// userSelectByParam Block it's follower destUserSelectByParam /// /// caller user identifier /// dest user identifier /// an instance of XFriendshipFollowing public async Task Block( string userSelectByParam, string destUserSelectByParam ) { // // Validate Args ... ValidationProvider.NotEmpty( userSelectByParam, destUserSelectByParam ); // // Validate and Retrieve User ... var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, forceAdmin: false, checkIsBanned: true, containDetails: true, ignoreDisabledUser: false, checkCanLoginPolicies: true ); // // Validate and Retrieve Dest User ... var xDestUser = await ValidateUserExistsAndRetrieve( destUserSelectByParam, forceAdmin: false, checkIsBanned: true, containDetails: true, ignoreDisabledUser: false, checkCanLoginPolicies: true ); // // Validate Not Same Source and Dest Users ... ValidateNotSameUsers(xUser, xDestUser); // // Validate XDestUser is Accepted Follower of XUser ... ValidateIsFollowers(xUser, xDestUser); // // Retrieve FriendShip Models ... var following = xDestUser.Followings .FirstOrDefault(f => f.DestId == xUser.Id && ( f.State == XFriendshipState.Accepted ) ); var follower = xUser.Followers .FirstOrDefault(f => f.DestId == xDestUser.Id && ( f.State == XFriendshipState.Accepted ) ); if (following.IsNull() || follower.IsNull()) { XException.NotAllowed.Throw(); } // follower.State = XFriendshipState.Blocked; following.State = XFriendshipState.Blocked; // DbContext.Followers.Update(follower); DbContext.Followings.Update(following); // await DbContext.SaveChangesAsync(); // var result = following; // return result; } /// /// userSelectByParam UnBlock it's follower destUserSelectByParam /// /// caller user identifier /// dest user identifier /// an instance of XFriendshipFollowing public async Task UnBlock( string userSelectByParam, string destUserSelectByParam ) { // // Validate Args ... ValidationProvider.NotEmpty( userSelectByParam, destUserSelectByParam ); // // Validate and Retrieve User ... var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, forceAdmin: false, checkIsBanned: true, containDetails: true, ignoreDisabledUser: false, checkCanLoginPolicies: true ); // // Validate and Retrieve Dest User ... var xDestUser = await ValidateUserExistsAndRetrieve( destUserSelectByParam, forceAdmin: false, checkIsBanned: true, containDetails: true, ignoreDisabledUser: false, checkCanLoginPolicies: true ); // // Validate Not Same Source and Dest Users ... ValidateNotSameUsers(xUser, xDestUser); // // Validate XDestUser is Accepted Follower of XUser ... ValidateIsBlock(xUser, xDestUser); // // Retrieve FriendShip Models ... var following = xDestUser.Followings .FirstOrDefault(f => f.DestId == xUser.Id && ( f.State == XFriendshipState.Blocked ) ); var follower = xUser.Followers .FirstOrDefault(f => f.DestId == xDestUser.Id && ( f.State == XFriendshipState.Blocked ) ); if ( following.IsNull() || follower.IsNull() ) { XException.NotAllowed.Throw(); } // follower.State = XFriendshipState.Accepted; following.State = XFriendshipState.Accepted; // DbContext.Followers.Update(follower); DbContext.Followings.Update(following); // await DbContext.SaveChangesAsync(); // var result = following; // return result; } #endregion // #region Request Handlers ... /// /// userSelectByParam Accept Follow Request of /// destUserSelectByParam /// /// caller user identifier /// dest user identifier /// an instance of XFriendshipFollower public async Task AcceptRequest( string userSelectByParam, string destUserSelectByParam ) { // // Validate Args ... ValidationProvider.NotEmpty( userSelectByParam, destUserSelectByParam ); // // Validate and Retrieve User ... var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, forceAdmin: false, checkIsBanned: true, containDetails: true, ignoreDisabledUser: false, checkCanLoginPolicies: true ); // // Validate and Retrieve Dest User ... var xDestUser = await ValidateUserExistsAndRetrieve( destUserSelectByParam, forceAdmin: false, checkIsBanned: true, containDetails: true, ignoreDisabledUser: false, checkCanLoginPolicies: true ); // // Validate Not Same Source and Dest Users ... ValidateNotSameUsers(xUser, xDestUser); // // Validate Request Sent and in Pending State ... ValidateFollowingRequestForAccept(xUser, xDestUser); // // Retrieve FriendShip Models ... var following = xDestUser.Followings .FirstOrDefault(f => f.DestId == xUser.Id && ( f.State == XFriendshipState.Pending || f.State == XFriendshipState.Rejected ) ); var follower = xUser.Followers .FirstOrDefault(f => f.DestId == xDestUser.Id && ( f.State == XFriendshipState.Pending || f.State == XFriendshipState.Rejected ) ); if (following.IsNull() || follower.IsNull()) { XException.NotAllowed.Throw(); } // follower.State = XFriendshipState.Accepted; following.State = XFriendshipState.Accepted; // await UpdateUserAsync(xUser); await UpdateUserAsync(xDestUser); // var result = follower; // return result; } /// /// Reject a Follow Request of destUserSelectByParam /// with userSelectByParam /// /// caller user identifier /// dest user identifier /// an instance of XFriendshipFollower public async Task RejectRequest( string userSelectByParam, string destUserSelectByParam ) { // // Validate Args ... ValidationProvider.NotEmpty( userSelectByParam, destUserSelectByParam ); // // Validate and Retrieve User ... var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, forceAdmin: false, checkIsBanned: true, containDetails: true, ignoreDisabledUser: false, checkCanLoginPolicies: true ); // // Validate and Retrieve Dest User ... var xDestUser = await ValidateUserExistsAndRetrieve( destUserSelectByParam, forceAdmin: false, checkIsBanned: true, containDetails: true, ignoreDisabledUser: false, checkCanLoginPolicies: true ); // // Validate Not Same Source and Dest Users ... ValidateNotSameUsers(xUser, xDestUser); // // Validate Request Sent and in Pending State ... ValidateFollowingRequest(xUser, xDestUser); // // Retrieve Pending Specified User Request Friendship models ... var following = xDestUser.Followings .FirstOrDefault(f => f.DestId == xUser.Id && f.State == XFriendshipState.Pending); var follower = xUser.Followers .FirstOrDefault(f => f.DestId == xDestUser.Id && f.State == XFriendshipState.Pending); if (following.IsNull() || follower.IsNull()) { XException.NotFound.Throw(); } // follower.State = XFriendshipState.Rejected; following.State = XFriendshipState.Rejected; // DbContext.Followers.Update(follower); DbContext.Followings.Update(following); // await DbContext.SaveChangesAsync(); // var result = follower; // return result; } #endregion // #region Getters ... /// /// determines destUserSelectByParam is in followers of /// userSelectByParam or not /// /// caller user identifier /// dest user identifier /// check user is banned or not, default is true /// check a user can log in in system or not, default is true /// a boolean value public async Task IsFollower( string userSelectByParam, string destUserSelectByParam, bool checkIsBanned = true, bool checkCanLoginPolicies = true ) { // // Validate Args ... ValidationProvider.NotEmpty( userSelectByParam, destUserSelectByParam ); // // Validate and Retrieve User ... var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, forceAdmin: false, containDetails: true, ignoreDisabledUser: false, checkIsBanned: checkIsBanned, checkCanLoginPolicies: checkCanLoginPolicies ); // // Validate and Retrieve Dest User ... var xDestUser = await ValidateUserExistsAndRetrieve( destUserSelectByParam, forceAdmin: false, containDetails: true, ignoreDisabledUser: false, checkIsBanned: checkIsBanned, checkCanLoginPolicies: checkCanLoginPolicies ); // // Validate Not Same Source and Dest Users ... ValidateNotSameUsers(xUser, xDestUser); // var result = IsFollowRequested(xDestUser, xUser, XFriendshipState.Accepted); // return result; } /// /// retrieve Friendship state of destUserSelectByParam /// in Followers of userSelectByParam /// /// caller user identifier /// dest user identifier /// check user is banned or not, default is true /// check a user can log in in system or not, default is true /// a member of XFriendshipState public async Task GetFollowerState( string userSelectByParam, string destUserSelectByParam, bool checkIsBanned = true, bool checkCanLoginPolicies = true ) { // // Validate Args ... ValidationProvider.NotEmpty( userSelectByParam, destUserSelectByParam ); // // Validate and Retrieve User ... var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, forceAdmin: false, containDetails: true, ignoreDisabledUser: false, checkIsBanned: checkIsBanned, checkCanLoginPolicies: checkCanLoginPolicies ); // // Validate and Retrieve Dest User ... var xDestUser = await ValidateUserExistsAndRetrieve( destUserSelectByParam, forceAdmin: false, containDetails: true, ignoreDisabledUser: false, checkIsBanned: checkIsBanned, checkCanLoginPolicies: checkCanLoginPolicies ); // // Validate Not Same Source and Dest Users ... ValidateNotSameUsers(xUser, xDestUser); // var isFollow = IsFollowRequested(xDestUser, xUser); if (!isFollow) { return XFriendshipState.None; } // var follower = xUser.Followers.FirstOrDefault(f => f.DestId == xDestUser.Id); if (follower.IsNull()) { XException.NotFound.Throw(); } // return follower.State; } /// /// get follower friendship model of destUserSelectByParam /// in followers of userSelectByParam /// /// caller user identifier /// dest user identifier /// an instance of XFriendshipFollower public async Task GetFollower( string userSelectByParam, string destUserSelectByParam ) { // // Validate Args ... ValidationProvider.NotEmpty( userSelectByParam, destUserSelectByParam ); // // Validate and Retrieve User ... var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, forceAdmin: false, checkIsBanned: true, containDetails: true, ignoreDisabledUser: false, checkCanLoginPolicies: true ); // // Validate and Retrieve Dest User ... var xDestUser = await ValidateUserExistsAndRetrieve( destUserSelectByParam, forceAdmin: false, checkIsBanned: true, containDetails: true, ignoreDisabledUser: false, checkCanLoginPolicies: true ); // // Validate Not Same Source and Dest Users ... ValidateNotSameUsers(xUser, xDestUser); // var isFollow = IsFollowRequested(xDestUser, xUser); if (!isFollow) { return null; } // var follower = xUser.Followers .FirstOrDefault(f => f.DestId == xDestUser.Id); if (follower.IsNull()) { XException.NotFound.Throw(); } // var result = follower; // return result; } /// /// Retrieve Accepted Followers list of userSelectByParam /// /// caller user identifier /// a collection of XFriendshipFollower instances public async Task> GetFollowers( string userSelectByParam ) { // // Validate Args ... ValidationProvider.NotEmpty(userSelectByParam); // // Validate and Retrieve User ... var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, forceAdmin: false, checkIsBanned: true, containDetails: true, ignoreDisabledUser: false, checkCanLoginPolicies: true ); // var result = xUser.Followers .Where(f => f.State == XFriendshipState.Accepted); // return result; } /// /// Retrieve all Followers list of userSelectByParam /// /// caller user identifier /// a collection of XFriendshipFollower instances public async Task> GetAllFollowers( string userSelectByParam ) { // // Validate Args ... ValidationProvider.NotEmpty(userSelectByParam); // // Validate and Retrieve User ... var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, forceAdmin: false, checkIsBanned: true, containDetails: true, ignoreDisabledUser: false, checkCanLoginPolicies: true ); // var result = xUser.Followers; // return result; } /// /// Read Specified User's Follower's List based on Query Model ... /// /// /// /// public async Task> QueryFollowers( XQuery query, string userSelectByParam ) { // // Validate Args ... ValidationProvider.NotNull(query); ValidationProvider.NotEmpty(userSelectByParam); // // Validate and Retrieve User ... var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, forceAdmin: false, checkIsBanned: false, containDetails: false, ignoreDisabledUser: false, checkCanLoginPolicies: false ); // // Prepare Query ... // if (query.PageSize < DataConfiguration .PagingConfiguration .MinAvailablePageSize) { // query.PageSize = DataConfiguration .PagingConfiguration .DefaultPageSize; } // if (query.PageSize > DataConfiguration .PagingConfiguration .MaxAvailablePageSize) { // query.PageSize = DataConfiguration .PagingConfiguration .MaxAvailablePageSize; } // // Prepare Enumerator ... Expression> whereClause = x => x.UserId == xUser.Id; var enumerator = DbContext.Followers.AsAsyncEnumerable(); var resultItems = new List(); await foreach (var entity in enumerator) { // var isApproved = whereClause.Compile()(entity); if (isApproved) { // // Convert Approved Entity to Dto ... // then Validate it and Add it to Results ... var dto = await ToDto(entity); if (!dto.IsNull()) { resultItems.Add(dto); } } } // // Enumerable ... var result = resultItems.AsEnumerable(); // // Count Total Items ... var totalItemsCount = result.Count(); // // Apply Filter ... if (!query.Filter.IsNullOrEmpty()) { result = result.ApplyFilter(query.Filter); } // // Count Filtered Items ... var totalFilteredItemsCount = result.Count(); // // Apply Paging ... if (totalItemsCount > 0 && totalFilteredItemsCount > 0) { // // Apply Sorting ... if (!query.SortBy.IsNullOrEmpty()) { // // Since Sorting Based on Date is Very Important ... // we have to do Sorting at first Time then // try to apply Paging ... result = result .ApplySorting( query.SortBy, query.IsAscending) .ToList(); } // // Apply Paging ... result = result .ApplyPaging( query.Page, query.PageSize) .ToList(); } // // Calculating Page Count ... int pagesCount = totalItemsCount / query.PageSize; if (totalItemsCount % query.PageSize > 0) { pagesCount++; } // // Generate Result Object ... var queryResult = new XQueryResult { Page = query.Page, TotalPages = pagesCount, PageSize = query.PageSize, TotalItems = totalItemsCount, Items = result.AsEnumerable(), TotalFilteredItems = totalFilteredItemsCount }; // return queryResult; } /// /// determines destUserSelectByParam is in followings of /// userSelectByParam or not /// /// caller user identifier /// dest user identifier /// check user is banned or not, default is true /// check a user can log in in system or not, default is true /// a boolean value public async Task IsFollowing( string userSelectByParam, string destUserSelectByParam, bool checkIsBanned = true, bool checkCanLoginPolicies = true ) { // // Validate Args ... ValidationProvider.NotEmpty( userSelectByParam, destUserSelectByParam ); // // Validate and Retrieve User ... var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, forceAdmin: false, containDetails: true, ignoreDisabledUser: false, checkIsBanned: checkIsBanned, checkCanLoginPolicies: checkCanLoginPolicies ); // // Validate and Retrieve Dest User ... var xDestUser = await ValidateUserExistsAndRetrieve( destUserSelectByParam, forceAdmin: false, containDetails: true, ignoreDisabledUser: false, checkIsBanned: checkIsBanned, checkCanLoginPolicies: checkCanLoginPolicies ); // // Validate Not Same Source and Dest Users ... ValidateNotSameUsers(xUser, xDestUser); // var result = IsFollowRequested(xUser, xDestUser, XFriendshipState.Accepted); // return result; } /// /// retrieve Frindship State of destUserSelectByParam /// in Followings of userSelectByParam /// /// caller user identifier /// dest user identifier /// check user is banned or not, default is true /// check a user can log in in system or not, default is true /// a member of XFriendshipState public async Task GetFollowingState( string userSelectByParam, string destUserSelectByParam, bool checkIsBanned = true, bool checkCanLoginPolicies = true ) { // // Validate Args ... ValidationProvider.NotEmpty( userSelectByParam, destUserSelectByParam ); // // Validate and Retrieve User ... var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, forceAdmin: false, containDetails: true, ignoreDisabledUser: false, checkIsBanned: checkIsBanned, checkCanLoginPolicies: checkCanLoginPolicies ); // // Validate and Retrieve Dest User ... var xDestUser = await ValidateUserExistsAndRetrieve( destUserSelectByParam, forceAdmin: false, containDetails: true, ignoreDisabledUser: false, checkIsBanned: checkIsBanned, checkCanLoginPolicies: checkCanLoginPolicies ); // // Validate Not Same Source and Dest Users ... ValidateNotSameUsers(xUser, xDestUser); // var isFollow = IsFollowRequested(xUser, xDestUser); if (!isFollow) { return XFriendshipState.None; } // var following = xUser.Followings.FirstOrDefault(f => f.DestId == xDestUser.Id); if (following.IsNull()) { XException.NotFound.Throw(); } // return following.State; } /// /// get following friendship model of destUserSelectByParam /// in followings of userSelectByParam /// /// caller user identifier /// dest user identifier /// an instance of XFriendshipFollowing public async Task GetFollowing( string userSelectByParam, string destUserSelectByParam ) { // // Validate Args ... ValidationProvider.NotEmpty( userSelectByParam, destUserSelectByParam ); // // Validate and Retrieve User ... var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, forceAdmin: false, checkIsBanned: true, containDetails: true, ignoreDisabledUser: false, checkCanLoginPolicies: true ); // // Validate and Retrieve Dest User ... var xDestUser = await ValidateUserExistsAndRetrieve( destUserSelectByParam, forceAdmin: false, checkIsBanned: true, containDetails: true, ignoreDisabledUser: false, checkCanLoginPolicies: true ); // // Validate Not Same Source and Dest Users ... ValidateNotSameUsers(xUser, xDestUser); // var isFollow = IsFollowRequested(xUser, xDestUser); if (!isFollow) { return null; } // var following = xUser.Followings.FirstOrDefault(f => f.DestId == xDestUser.Id); if (following.IsNull()) { XException.NotFound.Throw(); } // var result = following; // return result; } /// /// Retrieve accepted Followings List of userSelectByParam /// /// caller user identifier /// a collection of XFriendshipFollowing instances public async Task> GetFollowings( string userSelectByParam ) { // // Validate Args ... ValidationProvider.NotEmpty(userSelectByParam); // // Validate and Retrieve User ... var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, forceAdmin: false, checkIsBanned: true, containDetails: true, ignoreDisabledUser: false, checkCanLoginPolicies: true ); // var result = xUser.Followings .Where(f => f.State == XFriendshipState.Accepted); // return result; } /// /// Retrieve all Followings List of userSelectByParam /// /// caller user identifier /// a collection of XFriendshipFollowing instances public async Task> GetAllFollowings(string userSelectByParam) { // // Validate Args ... ValidationProvider.NotEmpty(userSelectByParam); // // Validate and Retrieve User ... var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, forceAdmin: false, checkIsBanned: true, containDetails: true, ignoreDisabledUser: false, checkCanLoginPolicies: true ); // var result = xUser.Followings; // return result; } /// /// Read Specified User's Following's List based on Query Model ... /// /// /// /// public async Task> QueryFollowings( XQuery query, string userSelectByParam ) { // // Validate Args ... ValidationProvider.NotNull(query); ValidationProvider.NotEmpty(userSelectByParam); // // Validate and Retrieve User ... var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, forceAdmin: false, checkIsBanned: false, containDetails: false, ignoreDisabledUser: false, checkCanLoginPolicies: false ); // // Prepare Query ... // if (query.PageSize < DataConfiguration .PagingConfiguration .MinAvailablePageSize) { // query.PageSize = DataConfiguration .PagingConfiguration .DefaultPageSize; } // if (query.PageSize > DataConfiguration .PagingConfiguration .MaxAvailablePageSize) { // query.PageSize = DataConfiguration .PagingConfiguration .MaxAvailablePageSize; } // // Prepare Enumerator ... Expression> whereClause = x => x.UserId == xUser.Id; var enumerator = DbContext.Followings.AsAsyncEnumerable(); var resultItems = new List(); await foreach (var entity in enumerator) { // var isApproved = whereClause.Compile()(entity); if (isApproved) { // // Convert Approved Entity to Dto ... // then Validate it and Add it to Results ... var dto = await ToDto(entity); if (!dto.IsNull()) { resultItems.Add(dto); } } } // // Enumerable ... var result = resultItems.AsEnumerable(); // // Count Total Items ... var totalItemsCount = result.Count(); // // Apply Filter ... if (!query.Filter.IsNullOrEmpty()) { result = result.ApplyFilter(query.Filter); } // // Count Filtered Items ... var totalFilteredItemsCount = result.Count(); // // Apply Paging ... if (totalItemsCount > 0 && totalFilteredItemsCount > 0) { // // Apply Sorting ... if (!query.SortBy.IsNullOrEmpty()) { // // Since Sorting Based on Date is Very Important ... // we have to do Sorting at first Time then // try to apply Paging ... result = result .ApplySorting( query.SortBy, query.IsAscending) .ToList(); } // // Apply Paging ... result = result .ApplyPaging( query.Page, query.PageSize) .ToList(); } // // Calculating Page Count ... int pagesCount = totalItemsCount / query.PageSize; if (totalItemsCount % query.PageSize > 0) { pagesCount++; } // // Generate Result Object ... var queryResult = new XQueryResult { Page = query.Page, TotalPages = pagesCount, PageSize = query.PageSize, TotalItems = totalItemsCount, Items = result.AsEnumerable(), TotalFilteredItems = totalFilteredItemsCount }; // return queryResult; } #endregion // #region Others ... /// /// Retrieve List Of All Followings User Id's /// of userSelectByParam /// /// caller user identifier /// a collection of user identifiers public async Task> GetFollowingList( string userSelectByParam ) { // // Validate Args ... ValidationProvider.NotEmpty(userSelectByParam); // // Validate and Retrieve followings List ... var followings = await GetFollowings(userSelectByParam); // var result = followings.Select(f => f.DestId); // return result.ToList(); } /// /// Retrieve List Of All Followers User Id's /// of userSelectByParam /// /// caller user identifier /// a collection of user identifiers public async Task> GetFollowersList( string userSelectByParam ) { // // Validate Args ... ValidationProvider.NotEmpty(userSelectByParam); // // Validate and Retrieve followings List ... var followers = await GetFollowers(userSelectByParam); // var result = followers.Select(f => f.DestId); // return result.ToList(); } /// /// retrieve Friendship Info Model for Specific User /// /// caller user identifier /// dest user identifier /// check a user can log in in system or not, default is true /// check user is banned or not, default is true /// an instance of XFriendshipInfoDto public async Task GetFriendshipInfo( string userSelectByParam, string destUserSelectByParam, bool checkCanLoginPolicies = true, bool checkIsBanned = true ) { // // Validate Args ... ValidationProvider.NotEmpty( userSelectByParam, destUserSelectByParam ); // // Validate and Retrieve Dest User ... var xSourceUser = await ValidateUserExistsAndRetrieve( userSelectByParam, forceAdmin: false, containDetails: true, ignoreDisabledUser: false, checkIsBanned: checkIsBanned, checkCanLoginPolicies: checkCanLoginPolicies ); // // Validate and Retrieve Dest User ... var xDestUser = await ValidateUserExistsAndRetrieve( destUserSelectByParam, forceAdmin: false, containDetails: true, ignoreDisabledUser: false, checkIsBanned: checkIsBanned, checkCanLoginPolicies: checkCanLoginPolicies ); // var isSame = xSourceUser.Id == xDestUser.Id; var isFollower = false; var isFollowing = false; var followerState = XFriendshipState.None; var followingState = XFriendshipState.None; // if (!isSame) { // isFollower = await IsFollower( userSelectByParam, destUserSelectByParam, checkIsBanned: checkIsBanned, checkCanLoginPolicies: checkCanLoginPolicies ); // isFollowing = await IsFollowing( userSelectByParam, destUserSelectByParam, checkIsBanned: checkIsBanned, checkCanLoginPolicies: checkCanLoginPolicies ); // followerState = await GetFollowerState( userSelectByParam, destUserSelectByParam, checkIsBanned: checkIsBanned, checkCanLoginPolicies: checkCanLoginPolicies ); // followingState = await GetFollowingState( userSelectByParam, destUserSelectByParam, checkIsBanned: checkIsBanned, checkCanLoginPolicies: checkCanLoginPolicies ); } // var result = new XFriendshipInfoDto { UserId = xDestUser.Id, IsFollower = isFollower, IsFollowing = isFollowing, FollowerState = followerState, FollowingState = followingState, Followers = xDestUser.Followers .Count(f => f.State == XFriendshipState.Accepted), Followings = xDestUser.Followings .Count(f => f.State == XFriendshipState.Accepted) }; // return result; } #endregion #endregion } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+Identity.cs using System; using System.Net.Http; using System.Threading.Tasks; using IdentityModel.Client; using Microsoft.Extensions.Logging; using xCommons.Extensions; using xExceptions.Constants; using xExceptions.Models; using xIdentityModels.Extensions; using xIdentityModels.Models; using xIds.Extensions; using static IdentityModel.OidcConstants; namespace xIds.Providers { public partial class XIdentityManager { // #region Identity Actions ... /// /// Request for Discovery Document /// /// an instance of DiscoveryDocumentResponse public async Task RequestDiscoveryDocument() { // var httpClient = GetHttpClient(); var result = httpClient .GetDiscoveryDocumentAsync(IdentityResourceConfiguration.Authority) .ContinueWith(docTask => { // httpClient.Dispose(); return docTask.Result; }); // return await result; } /// /// Request AccessToken for Specific XApiScope /// /// a member of XApiScope /// an instance of TokenResponse public async Task RequestScopeAccessToken( string scope ) { // // Validate Args ... if (scope.IsNullOrEmpty()) { XException.InvalidArgs.Throw(); } // // Retrieve Disco Doc ... var discoDoc = await RequestDiscoveryDocument(); if (discoDoc.IsError) { XException.ActionFailed.Throw(); } // var request = new ClientCredentialsTokenRequest { Address = discoDoc.TokenEndpoint, GrantType = GrantTypes.ClientCredentials, ClientId = IdentityResourceConfiguration.ClientId, ClientSecret = IdentityResourceConfiguration.ClientSecret, Scope = scope }; // var httpClient = GetHttpClient(); var result = await httpClient .RequestClientCredentialsTokenAsync(request) .ContinueWith(response => { // httpClient.Dispose(); return response.Result; }); // return result; } /// /// Authenticate a User /// /// an instance of XLoginRequest class which represent Authentication requirements /// an instance of TokenResponse public async Task Authenticate( XLoginRequest model ) { // // Validate Args ... ValidationProvider .GroupValidationBuilder() .AddNotNull(model) .AddNotEmpty( model.UserSelectBy, model.Password ) .ValidateGroup(); // // Retrieve Disco Doc ... var discoDoc = await RequestDiscoveryDocument(); if (discoDoc.IsError) { XException.ActionFailed.Throw(); } // // Create Request ... var request = new PasswordTokenRequest { // Address = discoDoc.TokenEndpoint, // GrantType = GrantTypes.ClientCredentials, ClientId = IdentityResourceConfiguration.ClientId, ClientSecret = IdentityResourceConfiguration.ClientSecret, // UserName = model.UserSelectBy, Password = model.Password, // // Pass Device to Request ... Parameters = { { "force", false.ToJSON () } } }; // var httpClient = GetHttpClient(); var result = await httpClient .RequestPasswordTokenAsync(request) .ContinueWith(response => { // httpClient.Dispose(); return response.Result; }); // return result; } /// /// Do Login based on XLoginRequest /// /// an instance of XLoginRequest class which represent Authentication requirements /// an instance of XLoginResponse public async Task Login( XLoginRequest model ) { // // Validate Args ... ValidationProvider .GroupValidationBuilder() .AddNotNull(model, model.Device) .AddNotEmpty( model.UserSelectBy, model.Password ) .ValidateGroup(); // // Get Token Response ... // // Retrieve Disco Doc ... var discoDoc = await RequestDiscoveryDocument(); Logger.LogInformation($"discoDoc: {discoDoc.ToJSON()}"); if (discoDoc.IsError) { XException.ActionFailed.Throw(); } // // Create Request ... var request = new PasswordTokenRequest { // Address = discoDoc.TokenEndpoint, // GrantType = GrantTypes.ClientCredentials, ClientId = IdentityResourceConfiguration.ClientId, ClientSecret = IdentityResourceConfiguration.ClientSecret, // UserName = model.UserSelectBy, Password = model.Password, // // Pass Device to Request ... Parameters = { { "force", false.ToJSON () }, { "device", model.Device.ToJSON () }, { "language", model.Language } } }; // var httpClient = GetHttpClient(); var authResponse = await httpClient .RequestPasswordTokenAsync(request) .ContinueWith(response => { // httpClient.Dispose(); return response.Result; }); // // Check If Response Has Error ... Logger.LogInformation($"AuthResponse: {authResponse.ToJSON()}"); // if (authResponse.IsError) { throw authResponse.GetException(); } // // Create XLoginResponse Model ... var result = authResponse.CreateXLoginResponse(); // // Get ans Set User Profile ... result.Profile = await GetUserProfileAsync(model.UserSelectBy, model.UserSelectBy); // return result; } /// /// Refresh Tokens /// /// Authentication Tokens, instance of XTokenResponse /// an instance of XTokenResponse public async Task RefreshTokens( XTokenResponse model ) { // // Validate Args ... ValidationProvider .GroupValidationBuilder() .AddNotNull(model) .AddNotEmpty( model.AccessToken, model.RefreshToken ) .ValidateGroup(); // var authResponse = await RequestDiscoveryDocument() .ContinueWith((discoTask) => { // var discoDoc = discoTask.Result; if (discoDoc.IsError) { XException.ActionFailed.Throw(); } // using (var httpClient = GetHttpClient()) { return httpClient.RequestRefreshTokenAsync(new RefreshTokenRequest { // Address = discoDoc.TokenEndpoint, GrantType = GrantTypes.RefreshToken, ClientId = IdentityResourceConfiguration.ClientId, ClientSecret = IdentityResourceConfiguration.ClientSecret, RefreshToken = model.RefreshToken }).Result; } }); // // Check If Response Has Error ... if (authResponse.IsError) { // XError error = authResponse.ErrorDescription.FromJSON(); throw error.ToException(); } // // Create XLoginResponse Model ... var result = authResponse.CreateXTokenResponse(); // return result; } #endregion // #region Requirements ... /// /// Get an Instance of Http Client /// /// an instance of HttpClient public HttpClient GetHttpClient() { // HttpClient httpClient = null; httpClient = new HttpClient(); var httpClientHandler = new HttpClientHandler() { ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { // Logger.LogInformation( $"SSL Handler: {Environment.NewLine} sender: {sender}, {Environment.NewLine} cert: {cert}, {Environment.NewLine} chain: {chain}, {Environment.NewLine} sslPolicyErrors: {sslPolicyErrors}" ); // return true; }, ClientCertificateOptions = ClientCertificateOption.Manual, }; // httpClient = new HttpClient(httpClientHandler); // return httpClient; } #endregion } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+MessageProvider.cs using System; using xCommons.Extensions; using xExceptions.Constants; using xIdentityModels.Navigations; using xMessageService.Models; namespace xIds.Providers { public partial class XIdentityManager { // #region Message Provider ... /// /// Generate and Prepare an XMessage Instance for /// User Invite Action /// /// specify destination language /// reciever email address /// invitation token /// return url for invitation user to redirect /// an instance of XMessage private XMessage GetUserInviteMessage( string lang, string emailAddress, string inviteToken, string returnUrl ) { // ValidationProvider .NotEmpty(lang, emailAddress, inviteToken, returnUrl); ValidationProvider .EmailAddress(emailAddress); ValidationProvider .Url(returnUrl); // HandleMessageProviderPreperation(lang); // var msgStr = IdentityMessageProvider.InviteMsg + Environment.NewLine + returnUrl + "?t=" + inviteToken; // var message = new XMessage { Message = msgStr, }; message.Recievers.Add(emailAddress); // return message; } /// /// Generate and Prepare an XMessage Instance for /// New Device LoggedIn Action /// /// specify destination language /// reciever email address /// an instance of XDevice which represent user new Device /// an instance of XMessage private XMessage GetUserNewDeviceLoggedInMessage( string lang, string emailAddress, XDevice device ) { // ValidationProvider .NotEmpty(lang, emailAddress); ValidationProvider .EmailAddress(emailAddress); ValidationProvider .NotNull(device); // HandleMessageProviderPreperation(lang); // // Generate Specific Message ... var msgStr = IdentityMessageProvider.NewDeviceLoggedInMsg + Environment.NewLine + nameof(XDevice.Os) + ": " + device.Os + Environment.NewLine + nameof(XDevice.OsVersion) + ": " + device.OsVersion + Environment.NewLine + nameof(XDevice.Browser) + ": " + device.Browser + Environment.NewLine + nameof(XDevice.UserAgent) + ": " + device.UserAgent; // // Create XMessage Instance ... var message = new XMessage { Message = msgStr, }; message.Recievers.Add(emailAddress); // return message; } /// /// Generate and Prepare an XMessage Instance for /// Verification Code Action /// /// specify destination language /// an string which points to a user email address or mobile number /// user verification code /// an instance of XMessage private XMessage GetVerificationCodeMessage( string lang, string mobileNumberOrEmail, string verificationCode ) { // ValidationProvider .NotEmpty(lang, mobileNumberOrEmail, verificationCode); // HandleMessageProviderPreperation(lang); // mobileNumberOrEmail = mobileNumberOrEmail.ToNormalString(); // // Validate Mobile or Email ... var isValidEmail = mobileNumberOrEmail.IsValidEmail(); var isValidMobileNumber = mobileNumberOrEmail.IsValidMobileNumber(); if (!isValidEmail && !isValidMobileNumber) { XException.InvalidData.Throw(); } // // Prepare Message String ... var msgStr = IdentityMessageProvider.VerificationCodeMsg + Environment.NewLine + verificationCode; // // Create XMessage Instance ... var message = new XMessage { Message = msgStr, }; message.Recievers.Add(mobileNumberOrEmail); // return message; } /// /// Generate and Prepare an XMessage Instance for /// Registration Approve Action /// /// specify destination language /// reciever email address /// a token which approved user action /// return url for redirect /// an instance of XMessage private XMessage GetRegistrationConfirmMessage( string lang, string emailAddress, string actionToken, string returnUrl ) { // ValidationProvider .NotEmpty(lang, emailAddress, actionToken, returnUrl); ValidationProvider .EmailAddress(emailAddress); ValidationProvider .Url(returnUrl); // HandleMessageProviderPreperation(lang); // // Prepare Message Str ... var msgStr = IdentityMessageProvider.RegistrationApproveMsg + Environment.NewLine + returnUrl + "?t=" + actionToken; // var message = new XMessage { Message = msgStr, }; message.Recievers.Add(emailAddress); // return message; } /// /// Generate and Prepare an XMessage Instance for /// Registration Finished Action /// /// specify destination language /// reciever email address /// return url for redirect /// an instance of XMessage private XMessage GetRegistrationFinishedMessage( string lang, string emailAddress, string returnUrl ) { // ValidationProvider .NotEmpty(lang, emailAddress, returnUrl); ValidationProvider .EmailAddress(emailAddress); ValidationProvider .Url(returnUrl); // HandleMessageProviderPreperation(lang); // var msgStr = IdentityMessageProvider.RegisteredMsg + Environment.NewLine + returnUrl; // var message = new XMessage { Message = msgStr, }; message.Recievers.Add(emailAddress); // return message; } /// /// Generate and Prepare an XMessage Instance for /// Password Changed Action /// /// specify destination language /// reciever email address /// return url for redirect /// specify throw exceptions on failure or not, default is true /// an instance of XMessage private XMessage GetPasswordChangedMessage( string lang, string emailAddress, string returnUrl, bool throwException = true ) { // if (throwException) { ValidationProvider .NotEmpty(lang, emailAddress, returnUrl); ValidationProvider .EmailAddress(emailAddress); ValidationProvider .Url(returnUrl); } // HandleMessageProviderPreperation(lang); // var msgStr = IdentityMessageProvider.PasswordChangedMsg + (returnUrl.IsNullOrEmpty() ? "" : Environment.NewLine + returnUrl); // var message = new XMessage { Message = msgStr, }; message.Recievers.Add(emailAddress); // return message; } /// /// Generate and Prepare an XMessage Instance for /// Reset Password Action /// /// specify destination language /// reciever email address /// a token which approved user action /// return url for redirect /// an instance of XMessage private XMessage GetResetPasswordMessage( string lang, string emailAddress, string actionToken, string returnUrl ) { // ValidationProvider .NotEmpty(lang, emailAddress, actionToken, returnUrl); ValidationProvider .EmailAddress(emailAddress); ValidationProvider .Url(returnUrl); // HandleMessageProviderPreperation(lang); // // Prepare Message Str ... var msgStr = IdentityMessageProvider.ChangePasswordMsg + Environment.NewLine + returnUrl + "?t=" + actionToken; // var message = new XMessage { Message = msgStr, }; message.Recievers.Add(emailAddress); // return message; } #endregion } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+Open.cs using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using xCommons.Extensions; using xExceptions.Constants; using xIdentityModels.Dtos; namespace xIds.Providers { public partial class XIdentityManager { // #region OpenGet ... public async Task OpenGet( XOpenActionInnerDto model ) { // // Validate Args ... await ValidationProvider .GroupValidationBuilder() .AddNotNull(model) .AddNotEmpty(model.Token) .AddNotEmpty(model.Payload) .ValidateGroupAsync(); // return await OpenGet( token: model.Token, actionRequest: model.Payload ); } // public async Task OpenGet( string token, string actionRequest ) { // // Validatr Args ... await ValidationProvider .GroupValidationBuilder() .AddNotEmpty(token) .AddNotEmpty(actionRequest) .ValidateGroupAsync(); // // Try to Decrypt Request ... var requestModel = ParseModel( token: token, request: actionRequest ); if (requestModel.IsNull() || requestModel.Action.IsNullOrEmpty()) { XException.BadRequest.Throw(); } // var responseJson = string.Empty; switch (requestModel.Action) { // case XOpenActions.GetUserInfo: // ValidationProvider.NotEmpty(requestModel.Payload); var userInfo = await GetUserInfo(requestModel); if (userInfo.IsNull()) { XException.InvalidData.Throw(); } // responseJson = userInfo.ToJSON(); break; // case XOpenActions.GetUserInfos: ValidationProvider.NotEmpty(requestModel.Payload); var userInfos = await GetUserInfos(requestModel); if (userInfos.IsNull()) { XException.InvalidData.Throw(); } // responseJson = userInfos.ToJSON(); break; } // // Encrypt Json Str ... var responseStr = SecurityProvider.Encrypt(responseJson); requestModel.Payload = responseStr; requestModel.Timestamp = DateTime.UtcNow .AddMinutes(5) .ToTimestamp() .ToString(); // token = requestModel.ToOpenActionToken(); requestModel.Checksum = token; var result = new XOpenActionInnerDto { Token = token, Payload = requestModel.ToJSON() }; // // Check Result ... if (result.IsNull()) { XException.ActionFailed.Throw(); } // return result; } #endregion public async Task GetUserInfo( XOpenActionRequestDto model ) { // // Retrieve User Profile ... var userProfile = await GetUserProfileAsync( checkIsBanned: false, checkCanLoginPolicies: false, requestedUserSelectByParam: "", forceCheckRequestedUser: false, userSelectByParam: model.Payload ); // // Generate a Dynamic Object ... var result = new XOpenActionUserInfoDto { Username = userProfile.UserName, Firstname = userProfile.FirstName, Lastname = userProfile.LastName, Avatar = userProfile.Avatar }; // return result; } public async Task> GetUserInfos( XOpenActionRequestDto model ) { // var ids = model.Payload.ParseListString().ToList(); var profiles = await GetUserProfilesAsync( ids: ids, checkIsBanned: false, checkCanLoginPolicies: false, requestedUserSelectByParam: "", forceCheckRequestedUser: false ); var result = profiles.Select(x => new XOpenActionUserInfoDto { Avatar = x.Avatar, Username = x.UserName, Lastname = x.LastName, Firstname = x.FirstName, }); // return result; } // #region Private ... private XOpenActionRequestDto ParseModel( string token, string request ) { // // Decript request to get Json string of request object ... var result = new XOpenActionRequestDto(); // var jsonStr = SecurityProvider.Decrypt(request); result = jsonStr.FromJSON(); if (result.IsNull() || !result.Validate() || token != result.Checksum ) { // result = null; return result; } // var modelChecksum = result.ToOpenActionToken(); result = token == modelChecksum ? result : null; // return result; } #endregion } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+Private.cs using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using xCommons.Extensions; using xCommons.Helpers; using xExceptions.Constants; using xIdentityModels; using xIdentityModels.Constants; using xIdentityModels.Dtos; using xIdentityModels.Models; using xIdentityModels.Navigations; namespace xIds.Providers { public partial class XIdentityManager { // #region Generators ... /// /// Generate a Random Number ... /// /// a long value private long GenerateRandom() { return new Random().Next(100000, 999999); } #endregion // #region UserSelectBy Actions ... /// /// Retrieve UserSelectByType based on Given Info /// /// a user identifier /// a boolean value which specify the identifier /// must be specific and not empty, default is true /// a boolean value which specify the type /// must be specific, default is false /// a member of XUserSelectBy private XUserSelectBy GetUserSelectByType( string userSelectByParam, bool forceUserSelectByParamNotEmpty = true, bool forceUserSelectByTypeMustSpecified = false ) { // if (forceUserSelectByParamNotEmpty) { ValidationProvider.NotEmpty(userSelectByParam); } // var result = XUserSelectBy.NotSpecified; var normalizedString = userSelectByParam.ToNormalString(); if (userSelectByParam.IsValidEmail()) { // // Find User by Email ... result = XUserSelectBy.Email; } else if (userSelectByParam.IsValidMobileNumber()) { // // Find User by Mobile Number ... result = XUserSelectBy.MobileNumber; } else if (userSelectByParam.IsGuid()) { // // Find User By it's ID ... result = XUserSelectBy.ID; } else { // // UserName ... result = XUserSelectBy.Username; } // if (forceUserSelectByTypeMustSpecified && result == XUserSelectBy.NotSpecified) { XException.InvalidData.Throw(); } // return result; } /// /// Retrieve UserSelectByParam based on XUser Object /// /// an instance of XUser /// a boolean value which specify the identifier must nut empty, /// and throw exception if it is empty, default is true /// a collection of XUserSelectBy members which /// exclude them from result, default is null /// a user identifier private string GetUserSelectByParam( XUser user, bool forceNotNull = true, ICollection excludes = null ) { // // Validate Args ... ValidationProvider.NotNull(user); // var id = user.Id; var userName = user.UserName; var email = user.Email; var phoneNumber = user.PhoneNumber; // if (excludes != null) { if (excludes.Contains(XUserSelectBy.ID)) { id = null; } if (excludes.Contains(XUserSelectBy.Email)) { email = null; } if (excludes.Contains(XUserSelectBy.MobileNumber)) { phoneNumber = null; } if (excludes.Contains(XUserSelectBy.Username)) { userName = null; } } var selectByParam = id.IsNullOrEmpty() ? userName.IsNullOrEmpty() ? email.IsNullOrEmpty() ? phoneNumber.IsNullOrEmpty() ? null : phoneNumber : email : userName : id; // // Check result ... if (forceNotNull && selectByParam.IsNullOrEmpty()) { XException.InvalidData.Throw(); } // return selectByParam; } /// /// Retrieve UserSelectByParam based on XActionRequestContext instance /// /// an instance of XActionRequestContext /// a boolean value which specify the identifier must nut empty, /// and throw exception if it is empty, default is true /// a collection of XUserSelectBy members which /// exclude them from result, default is null /// a user identifier private string GetUserSelectByParam( XActionRequestContext context, bool forceNotNull = true, ICollection excludes = null ) { // // Validate Args ... ValidationProvider.NotNull(context); // // Generate User SelectBy ... var id = context.UserId; var userName = context.UserName; var email = context.Email; var phoneNumber = context.MobileNumber; // if (excludes != null) { // if (excludes.Contains(XUserSelectBy.ID)) { id = null; } if (excludes.Contains(XUserSelectBy.Email)) { email = null; } if (excludes.Contains(XUserSelectBy.MobileNumber)) { phoneNumber = null; } if (excludes.Contains(XUserSelectBy.Username)) { userName = null; } } var selectByParam = id.IsNullOrEmpty() ? userName.IsNullOrEmpty() ? email.IsNullOrEmpty() ? phoneNumber.IsNullOrEmpty() ? null : phoneNumber : email : userName : id; // // Check param ... if (forceNotNull && selectByParam.IsNullOrEmpty()) { XException.InvalidData.Throw(); } // return selectByParam; } /// /// Retrieve UserSelectByParam based on XActionRequestToken instance /// /// an instance of XActionRequestToken which /// provides required informations /// a boolean value which specify the identifier must nut empty, /// and throw exception if it is empty, default is true /// a collection of XUserSelectBy members which /// exclude them from result, default is null /// a user identifier private string GetUserSelectByParam( XActionRequestToken request, bool forceNotNull = true, ICollection excludes = null ) { // // Validate Args ... ValidationProvider.NotNull(request); // // Generate User SelectBy ... return GetUserSelectByParam( context: request.Context, forceNotNull: forceNotNull, excludes: excludes ); } /// /// Retrieve Available UserSelectByParams from given XUser /// /// an instance of XUser /// private ICollection GenerateUserSelectByParams( XUser user ) { // if (user == null) { return null; } // var result = new List { user.Id, user.UserName, user.PhoneNumber, user.Email, }; // return result; } /// /// Retrieve Required XUserSelectByTypes /// /// a collection of XUserSelectBy members which /// ignored in result /// a collection of available XUserSelectBy members private ICollection GenerateUserSelectByExcludes( ICollection ignores ) { // var result = ObjectHelper .ToEnumerableValues() .Except(ignores); // return result.ToList(); } #endregion // #region XAction Actions ... /// /// Retrieve Action Result Response based on XToken /// /// an instance of XToken /// an instance of XActionResponse private XActionResponse GetActionResultResponse( XToken xToken ) { // ValidationProvider.NotNull(xToken); ValidationProvider.NotEmpty(xToken.Hash, xToken.Token); // ValidateToken(xToken.Token); // var expDate = GetTokenExpirationDate(xToken.Token); ValidationProvider.NotNull(expDate); // // Generate Result class ... var result = new XActionResponse { Token = xToken.Hash, Expiration = expDate }; // return result; } #endregion // #region XIdentityMessage Actions ... /// /// Prepare Message Provider and Check it's State /// /// specify destination language private void HandleMessageProviderPreperation( string lang ) { // ValidationProvider .NotEmpty(lang); // // Prepare Identity Messages ... // the PrepareMessageMethod check IsReady of Helper automatically ... IdentityMessageProvider.PrepareMessages(lang); // // Check Message Provider ... var isMessageProviderReady = MessageProvider.IsReady(true); if (!isMessageProviderReady) { XException.MessageServiceInitialFailed.Throw(); } } #endregion // #region Friendship Actions ... /// /// Check Follow Request Sent Before /// from dest to source /// /// an instance of XUser /// an instance of XUser /// a boolean value private bool IsFollowRequested( XUser source, XUser dest ) { // // Validate Args ... ValidationProvider.NotNull(source, dest); // var result = source.Followings.Any(f => f.DestId == dest.Id); // return result; } /// /// Check Follow Request Sent Before /// from dest to source /// /// an instance of XUser /// an instance of XUser /// a member of XFriendshipState /// a boolean value private bool IsFollowRequested( XUser source, XUser dest, XFriendshipState state ) { // // Validate Args ... ValidationProvider.NotNull(source, dest); // var result = source.Followings .Any(f => f.DestId == dest.Id && f.State == state); // return result; } /// /// Converts to XFriendDto ... /// /// /// private async Task ToDto(XFriendshipFollower entity) { // XFriendDto result = null; // if (entity.IsNull()) { return result; } // // Reading Dest User Profile ... var profile = await GetUserProfileAsync( userSelectByParam: entity.DestId, requestedUserSelectByParam: entity.UserId, forceCheckRequestedUser: false, checkCanLoginPolicies: false, checkIsBanned: false ); // // Preparing Result ... result = new XFriendDto { UserId = profile.UserId, Avatar = profile.Avatar, Username = profile.UserName, Lastname = profile.LastName, Firstname = profile.FirstName, Type = XFriendshipType.Follower, State = profile.FriendshipInfo.FollowerState, }; // return result; } /// /// Converts to XFriendDto ... /// /// /// private async Task ToDto(XFriendshipFollowing entity) { // XFriendDto result = null; // if (entity.IsNull()) { return result; } // // Reading Dest User Profile ... var profile = await GetUserProfileAsync( checkIsBanned: false, checkCanLoginPolicies: false, forceCheckRequestedUser: false, userSelectByParam: entity.DestId, requestedUserSelectByParam: entity.UserId ); // // Preparing Result ... result = new XFriendDto { UserId = profile.UserId, Avatar = profile.Avatar, Username = profile.UserName, Lastname = profile.LastName, Firstname = profile.FirstName, Type = XFriendshipType.Following, State = profile.FriendshipInfo.FollowingState, }; // return result; } #endregion // #region User Profile ... /// /// Count User's Page /// /// an integer value which represent page size /// an inetger value which represent pages count public async Task UserPagesCount( int pageSize ) { // int count = await UserManager.Users.CountAsync(); int pagesCount = count / pageSize; // if (count % pageSize > 0) { pagesCount++; } // return pagesCount; } /// /// Count Avatar's Page /// /// an integer value which represent page size /// an inetger value which represent pages count public async Task ProfileImagePagesCount( int pageSize ) { // int count = await DbContext.Avatars.CountAsync(); int pagesCount = count / pageSize; // if (count % pageSize > 0) { pagesCount++; } // return pagesCount; } #endregion } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+Profile.cs using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using xCommons.Extensions; using xExceptions.Constants; using xIdentityModels.Constants; using xIdentityModels.Dtos; using xIdentityModels.Models; using xIdentityModels.Navigations; using xModels.Dtos; using xIds.Extensions; using xIdentityModels.Extensions; using xIdentityHelper; using xIdentityHelper.Extensions; using xDataService.Extensions; namespace xIds.Providers { public partial class XIdentityManager { // #region Retrieve Actions ... /// /// Retrieve User Profile /// /// a user identifier /// requested user's identifier /// specify check requested user's identifier not empty /// and throw exception if it is, default true /// check a user can log in in system or not, default is true /// check user is banned or not, default is true /// an instance of XUserProfileDto public async Task GetUserProfileAsync( string userSelectByParam, string requestedUserSelectByParam, bool forceCheckRequestedUser = true, bool checkCanLoginPolicies = true, bool checkIsBanned = true ) { // // Data Validation ... if (forceCheckRequestedUser) { ValidationProvider.NotEmpty( userSelectByParam, requestedUserSelectByParam); } else { ValidationProvider.NotEmpty(userSelectByParam); } // var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: true, checkCanLoginPolicies: false, checkIsBanned: false, ignoreDisabledUser: true, forceAdmin: false ); // var isAdmin = false; var isSameUser = false; if (forceCheckRequestedUser && !requestedUserSelectByParam.IsNullOrEmpty()) { // var xRequestedUser = await ValidateUserExistsAndRetrieve( requestedUserSelectByParam, containDetails: true, checkCanLoginPolicies: false, checkIsBanned: false, ignoreDisabledUser: true, forceAdmin: false ); // isSameUser = xUser.Id == xRequestedUser.Id; // var xRequestUserRoleNames = await GetRoleNamesAsync( userSelectByParam: requestedUserSelectByParam, checkCanLoginPolicies: false, checkIsBanned: false ); isAdmin = xRequestUserRoleNames.Contains(XUserRole.Admin.GetStringValue()); } // var roleNames = await GetRoleNamesAsync( userSelectByParam, checkIsBanned: checkIsBanned, checkCanLoginPolicies: checkCanLoginPolicies ); // var xFriendshipInfo = requestedUserSelectByParam.IsNullOrEmpty() ? null : await GetFriendshipInfo( requestedUserSelectByParam, userSelectByParam, checkIsBanned: checkIsBanned, checkCanLoginPolicies: checkCanLoginPolicies ); // var result = xUser.ToXProfileDto( isAdmin: isAdmin, roles: roleNames, isSameUser: isSameUser, friendship: xFriendshipInfo, profileConfig: Configuration.Policy.Profile ); // return result; } /// /// Retrieve a Collection of User Profiles /// /// a collection of user identifiers /// requested user's identifier /// specify check requested user's identifier not empty /// and throw exception if it is, default true /// check a user can log in in system or not, default is true /// check user is banned or not, default is true /// an collection of XUserProfileDto instances public async Task> GetUserProfilesAsync( ICollection ids, string requestedUserSelectByParam, bool forceCheckRequestedUser = true, bool checkCanLoginPolicies = true, bool checkIsBanned = true ) { // // Data Validation ... if (forceCheckRequestedUser) { ValidationProvider.NotEmpty(requestedUserSelectByParam); } ValidationProvider.NotZeroChilds(ids); // var result = new List(); foreach (var id in ids) { // var xProfile = await GetUserProfileAsync( id, requestedUserSelectByParam, checkIsBanned: checkIsBanned, checkCanLoginPolicies: checkCanLoginPolicies, forceCheckRequestedUser: forceCheckRequestedUser ); result.Add(xProfile); } // return result; } /// /// Query User Profiles /// /// requested user's identifier /// how to filter results based on XQuery structure /// an instance of XQueryResult of XUserProfileDto public async Task> QueryUsers( string requestedUserSelectByParam, XQuery query ) { // // Validation ... if (query.IsNull()) { XException.InvalidArgs.Throw(); } // // Normalize ... query = query.NormalizeQuery(DataConfiguration.ToXDataServiceConfig()); // // Since in Resourceable Entities we have to Search on Locales // we Must Implement Senario Custom ... var totalEntities = GetUsersDbSet() .ToList() .Where(u => !u.ContainsUserSelectByParam(requestedUserSelectByParam)) .Select(u => u.Id) .ToList(); // var items = await GetUserProfilesAsync( totalEntities, requestedUserSelectByParam, checkIsBanned: false, checkCanLoginPolicies: false, forceCheckRequestedUser: false ); // var totalItemsCount = items.Count(); // // Apply Filter ... if (!query.Filter.IsNullOrEmpty()) { // items = items .ApplyFilter(query.Filter); } int filteredItemsCount = items.Count(); // // Count Pages ... var totalPagesCount = query.CountPages(totalItemsCount); var filteredPagesCount = query.CountPages(filteredItemsCount); // // Apply Paging and Sorting ... if (totalItemsCount > 0 && filteredItemsCount > 0) { // // Apply Sorting ... items = items .ToList() .ApplySorting( query.SortBy, query.IsAscending ); // // Apply Paging ... items = items .ToList() .ApplyPaging( query.Page, query.PageSize ); } // // Generate Result Object ... // Query = query, var result = new XQueryResult { Items = items, Page = query.Page, PageSize = query.PageSize, TotalPages = totalPagesCount, TotalItems = totalItemsCount, TotalFilteredPages = filteredPagesCount, TotalFilteredItems = filteredItemsCount }; // return result; } /// /// Query In Roles User Profiles /// /// requested user's identifier /// an string which represent user role /// how to filter results based on XQuery structure /// if it's true the user must has exact role, otherwise top level users also listed, default is false /// an instance of XQueryResult of XUserProfileDto public async Task> QueryInRoleUsers( string requestedUserSelectByParam, string role, XQuery query, bool forceRole = false ) { // // Validation ... if (query.IsNull() || role.IsNullOrEmpty()) { XException.InvalidArgs.Throw(); } // // Check Role Exists ... var isExistsRole = await IsRoleExistsAsync(role); if (!isExistsRole) { XException.NotFound.Throw(); } // // Normalize ... query = query.NormalizeQuery(DataConfiguration.ToXDataServiceConfig()); // #region Select Users Based on Specific Roles ... var selectedUsers = new List(); var usersEnumerator = GetUsersDbSet(query.ContainsDetail).AsAsyncEnumerable(); await foreach (var user in usersEnumerator) { // if (user.ContainsUserSelectByParam(requestedUserSelectByParam)) { continue; } // // Set Default Value is True ... var isInRole = false; // // if Force Role ... if (forceRole) { isInRole = await UserManager.IsInRoleAsync(user, role); } else { // // Select User Top Role ... var userRoles = await GetRoleNamesAsync( checkIsBanned: false, userSelectByParam: user.Id, checkCanLoginPolicies: false ); isInRole = userRoles.HasRolePermissions(role); } // if (isInRole) { selectedUsers.Add(user.Id); } } #endregion // var items = await GetUserProfilesAsync( selectedUsers, requestedUserSelectByParam, checkIsBanned: false, checkCanLoginPolicies: false, forceCheckRequestedUser: false ); // var totalItemsCount = items.Count(); // // Apply Filter ... if (!query.Filter.IsNullOrEmpty()) { // items = items .ApplyFilter(query.Filter); } int filteredItemsCount = items.Count(); // // Count Pages ... var totalPagesCount = query.CountPages(totalItemsCount); var filteredPagesCount = query.CountPages(filteredItemsCount); // // Apply Paging and Sorting ... if (totalItemsCount > 0 && filteredItemsCount > 0) { // // Apply Sorting ... items = items .ToList() .ApplySorting( query.SortBy, query.IsAscending ); // // Apply Paging ... items = items .ToList() .ApplyPaging( query.Page, query.PageSize ); } // // Generate Result Object ... // Query = query, var result = new XQueryResult { Items = items, Page = query.Page, PageSize = query.PageSize, TotalPages = totalPagesCount, TotalItems = totalItemsCount, TotalFilteredPages = filteredPagesCount, TotalFilteredItems = filteredItemsCount }; // return result; } /// /// Query Specified User's Profile Images /// /// a user identifier /// how to filter results based on XQuery structure /// an instance of XQueryResult of XProfileImage public async Task> QueryAvatars( string userSelectByParam, XQuery query ) { // // Validation ... if (query.IsNull()) { XException.InvalidArgs.Throw(); } // // Normalize ... query = query.NormalizeQuery(DataConfiguration.ToXDataServiceConfig()); // var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: true, checkCanLoginPolicies: true, checkIsBanned: true ); // var items = query.ContainsDetail ? DbContext.Avatars .Include(pf => pf.User) .AsEnumerable() : DbContext.Avatars .AsEnumerable(); items = items .Where(pfi => pfi.UserId == xUser.Id); // var totalItemsCount = items.Count(); // // Apply Filter ... if (!query.Filter.IsNullOrEmpty()) { // items = items .ApplyFilter(query.Filter); } int filteredItemsCount = items.Count(); // // Count Pages ... var totalPagesCount = query.CountPages(totalItemsCount); var filteredPagesCount = query.CountPages(filteredItemsCount); // // Apply Paging and Sorting ... if (totalItemsCount > 0 && filteredItemsCount > 0) { // // Apply Sorting ... items = items .ToList() .ApplySorting( query.SortBy, query.IsAscending ); // // Apply Paging ... items = items .ToList() .ApplyPaging( query.Page, query.PageSize ); } // // Generate Result Object ... // Query = query, var result = new XQueryResult { Items = items, Page = query.Page, PageSize = query.PageSize, TotalPages = totalPagesCount, TotalItems = totalItemsCount, TotalFilteredPages = filteredPagesCount, TotalFilteredItems = filteredItemsCount }; // return result; } /// /// Check specific user Confirmed Email or not /// /// a user identifier /// a boolean value public async Task IsConfirmedEmail( string userSelectByParam ) { // // Validate Args ... ValidationProvider.NotEmpty(userSelectByParam); // var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: false, checkCanLoginPolicies: false, checkIsBanned: false, ignoreDisabledUser: true, forceAdmin: false ); // return xUser.EmailConfirmed; } /// /// Ceck specific user Confirmed Mobile or not /// /// a user identifier /// a boolean value public async Task IsConfirmedMobile( string userSelectByParam ) { // // Validate Args ... ValidationProvider.NotEmpty(userSelectByParam); // var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: false, checkCanLoginPolicies: false, checkIsBanned: false, ignoreDisabledUser: true, forceAdmin: false ); // return xUser.PhoneNumberConfirmed; } #endregion // #region Update Actions ... /// /// Update User Profile (FirstName/LastName/DateOfBirth) ... /// /// a user identifier /// requested user's identifier /// user update info, an instance of XProfileUpdateRequest /// an instance of XUserProfileDto public async Task ProfileUpdateAsync( string userSelectByParam, string requestedUserSelectByParam, XProfileUpdateRequest model ) { // // Data Validation ... ValidationProvider.NotEmpty( userSelectByParam, requestedUserSelectByParam); ValidationProvider.NotNull(model); // var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: true, checkCanLoginPolicies: false, checkIsBanned: false, ignoreDisabledUser: true, forceAdmin: false ); // var xRequestedUser = await ValidateUserExistsAndRetrieve( requestedUserSelectByParam, containDetails: true, checkCanLoginPolicies: false, checkIsBanned: false, ignoreDisabledUser: true, forceAdmin: false ); // await ValidateUserForDangerousAction(xUser, xRequestedUser); // // FirstName ... if (!model.FirstName.IsNullOrEmpty()) { xUser.FirstName = model.FirstName; } // // Last Name ... if (!model.LastName.IsNullOrEmpty()) { xUser.LastName = model.LastName; } // // Date of Birth ... if (model.DateOfBirth.HasValue) { xUser.DateOfBirth = model.DateOfBirth.Value; } // // Bio ... xUser.Bio = model.Bio; // // Cover Image ... xUser.CoverImage = model.CoverImage; // // Open To Search ... xUser.OpenToSearch = model.OpenToSearch; // var updateResult = await UpdateUserAsync(xUser); if (!updateResult.Succeeded) { XException.ActionFailed.Throw(); } // var result = await GetUserProfileAsync(userSelectByParam, requestedUserSelectByParam); return result; } /// /// Update User Profile /// /// a user identifier /// requested user's identifier /// user update info, an instance of XProfileUpdateRequest /// an instance of XUserProfileDto public async Task FullProfileUpdateAsync( string userSelectByParam, string requestedUserSelectByParam, XProfileUpdateRequest model ) { // // Data Validation ... ValidationProvider.NotEmpty( userSelectByParam, requestedUserSelectByParam); ValidationProvider.NotNull(model); // var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: true, checkCanLoginPolicies: false, checkIsBanned: false, ignoreDisabledUser: true, forceAdmin: false ); // var xRequestedUser = await ValidateUserExistsAndRetrieve( requestedUserSelectByParam, containDetails: true, checkCanLoginPolicies: false, checkIsBanned: false, ignoreDisabledUser: true, forceAdmin: false ); // await ValidateUserForDangerousAction(xUser, xRequestedUser); // #region Fill User with Models Value ... // // FirstName ... xUser.FirstName = !model.FirstName.IsNullOrEmpty() ? model.FirstName : xUser.FirstName; // // LastName ... xUser.LastName = !model.LastName.IsNullOrEmpty() ? model.LastName : xUser.LastName; // // Email ... xUser.Email = !model.Email.IsNullOrEmpty() ? model.Email : xUser.Email; // // EmailConfirmed ... if (model.EmailConfirmed.HasValue) { xUser.EmailConfirmed = model.EmailConfirmed.Value; } // // PhoneNumber ... xUser.PhoneNumber = !model.PhoneNumber.IsNullOrEmpty() ? model.PhoneNumber : xUser.PhoneNumber; // // PhoneNumberConfirmed ,,, if (model.PhoneNumberConfirmed.HasValue) { xUser.PhoneNumberConfirmed = model.PhoneNumberConfirmed.Value; } // // DateOfBirth ... if (model.DateOfBirth.HasValue) { xUser.DateOfBirth = model.DateOfBirth.Value; } // // CreationDate ... if (model.CreationDate.HasValue) { xUser.CreationDate = model.CreationDate.Value; } // // LastLogin ... if (model.LastLogin.HasValue) { xUser.LastLogin = model.LastLogin.Value; } // // Avatar ... xUser.Avatar = !model.Avatar.IsNullOrEmpty() ? model.Avatar : xUser.Avatar; // // Gender ... if (model.Gender.HasValue) { xUser.Gender = model.Gender.Value; } // // IsEnable ... if (model.IsEnable.HasValue) { xUser.IsEnable = model.IsEnable.Value; } // // IsBanned ... if (model.IsBanned.HasValue) { xUser.IsBanned = model.IsBanned.Value; } // // Bio ... xUser.Bio = model.Bio; // // Cover Image ... xUser.CoverImage = model.CoverImage; // // Open To Search ... xUser.OpenToSearch = model.OpenToSearch; #endregion // var updateResult = await UpdateUserAsync( xUser, checkCanLoginPolicies: false, checkIsBanned: false ); if (!updateResult.Succeeded) { XException.ActionFailed.Throw(); } // // Handle Roles ... // // Remove User from All Roles ... if (xUser.Roles.HasChild()) { // var roleNames = await GetRoleNamesAsync( xUser.Id, checkIsBanned: false, checkCanLoginPolicies: false ); // foreach (var role in roleNames) { // var isRoleExists = await IsRoleExistsAsync(role); if (isRoleExists) { // var isInRole = await UserManager.IsInRoleAsync(xUser, role); if (!isInRole) { // var removeRoleResult = await UserManager.RemoveFromRoleAsync(xUser, role); if (!removeRoleResult.Succeeded) { XException.ActionFailed.Throw(); } } } } } // // Check Roles and Add to Exists ... if (model.Roles.HasChild()) { // // Check Exists Roles for Add ... foreach (var role in model.Roles) { // var isRoleExists = await IsRoleExistsAsync(role); if (isRoleExists) { // var isInRole = await UserManager.IsInRoleAsync(xUser, role); if (!isInRole) { // var addToRoleResult = await UserManager.AddToRoleAsync(xUser, role); if (!addToRoleResult.Succeeded) { XException.ActionFailed.Throw(); } } } } } // var result = await GetUserProfileAsync( userSelectByParam, requestedUserSelectByParam, checkCanLoginPolicies: false, checkIsBanned: false ); return result; } #endregion // #region Request For Actions ... /// /// Request Mobile Confirm /// /// specify destination language /// an instance of XDevice /// a user identifier /// user's password /// mobile number which need to confirm /// an instance of XActionResponse public async Task RequestConfirmMobile( string lang, XDevice device, string userSelectByParam, string password, string mobileNumber = null ) { // // Validate Args ... await ValidationProvider .GroupValidationBuilder() .AddNotEmpty( lang, userSelectByParam, password) .AddNotNull(device) .ValidateGroupAsync(); // await ValidateDeviceForActions(device); // // Prepare Request Context ... var context = new XActionRequestContext { Lang = lang, Device = device, MobileNumber = mobileNumber }; // // Validate and Retrieve User ... var user = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: false, checkCanLoginPolicies: false, checkIsBanned: false); // context.UserName = user.UserName; // await ValidateUserAndPassword( userSelectByParam, password, false, XException.ActionFailed.ToException()); // ValidationProvider.MobileNumber(user.PhoneNumber); if (!mobileNumber.IsNullOrEmpty() && user.PhoneNumber == mobileNumber && user.PhoneNumberConfirmed) { XException.MobileInUsed.Throw(); } // if (mobileNumber.IsNullOrEmpty()) { mobileNumber = user.PhoneNumber; } // // Remove All Prevoius Requests ... await HandleRemoveExistsTokens(user.Id); // // Prepare New Token Result , // by Requesting an Action ... var request = await ActionRequest( lang, device, userSelectByParam, XAction.RequestMobileVerificationCode, context, forceRenewToken: true ); // Logger.LogInformation($"ActionRequest: {request.ToJSON()}"); // // Call Confirm Method of Registration ... var result = await RequestMobileVerificationCode( lang, device, request.Token, mobileNumber, checkMobileInUse: false); // return result; } /// /// Request Email Confirma /// /// specify destination language /// an instance of XDevice /// a user identifier /// user's password /// email address which need to confirm /// an instance of XActionResponse public async Task RequestConfirmEmail( string lang, XDevice device, string userSelectByParam, string password, string emailAddress = null ) { // // Validate Args ... await ValidationProvider .GroupValidationBuilder() .AddNotEmpty( lang, userSelectByParam, password) .AddNotNull(device) .ValidateGroupAsync(); // await ValidateDeviceForActions(device); // // Prepare Request Context ... var context = new XActionRequestContext { Lang = lang, Device = device, Email = emailAddress }; // // Validate and Retrieve User ... var user = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: false, checkCanLoginPolicies: false, checkIsBanned: false); // context.UserName = user.UserName; // // Remove All Prevoius Requests ... await HandleRemoveExistsTokens(user.Id); // await ValidateUserAndPassword( userSelectByParam, password, false, XException.ActionFailed.ToException()); // ValidationProvider.EmailAddress(user.Email); if (!emailAddress.IsNullOrEmpty() && user.Email == emailAddress && user.EmailConfirmed) { XException.EmailInUsed.Throw(); } // if (emailAddress.IsNullOrEmpty()) { emailAddress = user.Email; context.Email = user.Email; } // // Prepare New Token Result , // by Requesting an Action ... var request = await ActionRequest( lang, device, userSelectByParam, XAction.RequestEmailVerificationCode, context, forceRenewToken: true ); // // Call Confirm Method of Registration ... var result = await RequestEmailVerificationCode( lang, device, request.Token, emailAddress, checkEmailInUse: false); // return result; } /// /// Request Reset Password /// /// specify destination language /// an instance of XDevice /// a user identifier /// redirection url /// an instance of XActionResponse public async Task RequestResetPassword( string lang, XDevice device, string userSelectByParam, string returnUrl ) { // // Validate Args ... await ValidationProvider .GroupValidationBuilder() .AddNotEmpty( lang, userSelectByParam, returnUrl) .AddNotNull(device) .AddUrl(returnUrl) .ValidateGroupAsync(); // await ValidateDeviceForActions(device); // // Validate and Retrieve User ... var user = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: false, checkCanLoginPolicies: true, checkIsBanned: true); // // Prepare Request Context ... var context = new XActionRequestContext { Lang = lang, Device = device, Email = user.Email, UserName = user.UserName }; // // Remove All Prevoius Requests ... await HandleCleanUserTokens(user); // // Prepare New Token Result , // by Requesting an Action ... var result = await ActionRequest( lang, device, user.Email, XAction.RequestResetPassword, context ); // // Prepare Message ... var xMessage = GetResetPasswordMessage( lang, user.Email, result.Token, returnUrl); // try { await MessageProvider.SendMailAsync(xMessage); } catch { } // return result; } /// /// Request Registration Confrirm /// /// specify destination language /// an instance of XDevice /// a user identifier /// user's password /// redirection url /// public async Task RequestConfirmRegistration( string lang, XDevice device, string userSelectByParam, string password, string returnUrl ) { // // Validate Args ... await ValidationProvider .GroupValidationBuilder() .AddNotEmpty( lang, userSelectByParam, password, returnUrl) .AddNotNull(device) .AddUrl(returnUrl) .ValidateGroupAsync(); // // Validate user and Retrieve it ... var user = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: false, checkCanLoginPolicies: false, checkIsBanned: true, ignoreDisabledUser: true); // // Prepare Request Context ... var context = new XActionRequestContext { Lang = lang, Device = device, Email = user.Email }; // await ValidateUserAndPassword( userSelectByParam, password, false, XException.ActionFailed.ToException()); // // Remove All Prevoius Requests ... await HandleRemoveExistsTokens(user.Id); // // Prepare New Token Result , // by Requesting an Action ... var result = await ActionRequest( lang, device, user.Email, XAction.Finish, context ); // // Prepare XMessage Instance ... var xMessage = GetRegistrationConfirmMessage( lang, user.Email, result.Token, returnUrl); // // Send Message ... try { await MessageProvider.SendMailAsync(xMessage); } catch { } } #endregion // #region Password Actions ... /// /// Change Password /// /// specify destination language /// an instance of XDevice /// a user identifier /// user's password /// user's new password /// redirection url /// public async Task ChangePassword( string lang, XDevice device, string userSelectByParam, string password, string newPassword, string returnUrl ) { // // Validate Args ... await ValidationProvider .GroupValidationBuilder() .AddNotEmpty( lang, userSelectByParam, password, newPassword, returnUrl) .AddNotNull(device) .ValidateGroupAsync(); // // Password Unique ... if (password == newPassword) { XException.PasswordsSame.Throw(); } // // Validate and Retrieve User ... var user = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: false, checkCanLoginPolicies: true, checkIsBanned: true); // await ValidateUserAndPassword( userSelectByParam, password); // // Check Password Policies ... await ValidatePasswordPolicies(user, newPassword); // // Clean All User Tokens ... await HandleCleanUserTokens(user); // // Try to Change User Password ... var passwordResetResult = await UserManager .ChangePasswordAsync( user, password, newPassword); // // Check Result ... if (!passwordResetResult.Succeeded) { XException.ActionFailed.Throw(); } // // Prepare Message ... var xMessage = GetPasswordChangedMessage( lang, user.Email, returnUrl, throwException: false ); // // Send Message ... try { await MessageProvider.SendMailAsync(xMessage); } catch { } } /// /// Reset User Password /// /// specify destination language /// an instance of XDevice /// a token which approved user action /// user's new password /// redirection url /// public async Task ResetPassword( string lang, XDevice device, string actionToken, string newPassword, string returnUrl ) { // // Validate Args ... await ValidationProvider .GroupValidationBuilder() .AddNotEmpty( lang, actionToken, newPassword, returnUrl) .AddNotNull(device) .ValidateGroupAsync(); // // Get Related Token to Registration Hash and Validate it, // then Parse XActionRequest Instance from Token ... var request = await ValidateAndParseActionHash(actionToken); // // Get User Identifier ... var userSelectByParam = GetUserSelectByParam(request); // // Validate and Retrieve User ... var user = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: false, checkCanLoginPolicies: true, checkIsBanned: true); // // Check Password Policies ... await ValidatePasswordPolicies(user, newPassword); // // Clean All User Tokens ... await HandleCleanUserTokens(user); // // Try to Remove User Password ... var removePasswordResult = await UserManager.RemovePasswordAsync(user); if (!removePasswordResult.Succeeded) { XException.ActionFailed.Throw(); } // // try to Add New Password ... var passwordResetResult = await UserManager.AddPasswordAsync(user, newPassword); if (!passwordResetResult.Succeeded) { XException.ActionFailed.Throw(); } // // Prepare Message ... var xMessage = GetPasswordChangedMessage( lang, user.Email, returnUrl); // // Send Message ... try { await MessageProvider.SendMailAsync(xMessage); } catch { } } #endregion // #region Profile Image Actions ... /// /// Add Profile Image to a User /// /// a user identifier /// an specific File to upload, IFormFile /// an instance of XUserProfileDto public async Task AddAvatar( string userSelectByParam, IFormFile file ) { // var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: true, checkCanLoginPolicies: false, checkIsBanned: false, ignoreDisabledUser: true, exception: XException.NotFound.ToException() ); // // Handle Saving File and Attach it to User ... var saveResult = await StorageProvider.HandleProfileImageSave(file); // var xProfileImage = new XProfileImage { UserId = xUser.Id, Name = saveResult.FileName, Path = saveResult.FilePath, Thumb = saveResult.Thmbnail, ThumbPath = saveResult.ThmbnailPath, CreationDate = DateTime.UtcNow }; // xUser.Avatars.Add(xProfileImage); var updateResult = await UpdateUserAsync( xUser, checkCanLoginPolicies: false, checkIsBanned: false ); // if (!updateResult.Succeeded) { XException.ActionFailed.Throw(); } // xUser.Avatar = xProfileImage.ThumbPath; updateResult = await UpdateUserAsync( xUser, checkCanLoginPolicies: false, checkIsBanned: false ); // if (!updateResult.Succeeded) { XException.ActionFailed.Throw(); } // var result = await GetUserProfileAsync(userSelectByParam, userSelectByParam); return result; } /// /// Add a Collection of Profile Images to a User /// /// a user identifier /// a collection of Files to upload, IFormFileCollection /// an instance of XUserProfileDto public async Task AddAvatars( string userSelectByParam, IFormFileCollection files ) { // var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: true, checkCanLoginPolicies: false, checkIsBanned: false, ignoreDisabledUser: true, exception: XException.NotFound.ToException() ); // foreach (var file in files) { // // Handle Saving File and Attach it to User ... var saveResult = await StorageProvider.HandleProfileImageSave(file); // var xProfileImage = new XProfileImage { UserId = xUser.Id, Name = saveResult.FileName, Path = saveResult.FilePath, Thumb = saveResult.Thmbnail, ThumbPath = saveResult.ThmbnailPath, CreationDate = DateTime.UtcNow }; // xUser.Avatars.Add(xProfileImage); } // var updateResult = await UpdateUserAsync( xUser, checkCanLoginPolicies: false, checkIsBanned: false ); // if (!updateResult.Succeeded) { XException.ActionFailed.Throw(); } // var result = await GetUserProfileAsync(userSelectByParam, userSelectByParam); return result; } /// /// Set Specific Profie Image as Current Profile Image /// /// a user identifier /// an integer which reperesent AvatarId to set as current Avatar /// an instance of XUserProfileDto public async Task SetAvatar( string userSelectByParam, int id ) { // ValidationProvider.NotEmpty(userSelectByParam); // var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: true, checkCanLoginPolicies: false, checkIsBanned: false, ignoreDisabledUser: true, exception: XException.NotFound.ToException() ); // var xProfileImage = xUser.Avatars.FirstOrDefault(pf => pf.Id == id); if (xProfileImage.IsNull()) { XException.NotFound.Throw(); } // xUser.Avatar = xProfileImage.ThumbPath; var updateResult = await UpdateUserAsync( xUser, checkCanLoginPolicies: false, checkIsBanned: false ); // if (!updateResult.Succeeded) { XException.ActionFailed.Throw(); } // var result = await GetUserProfileAsync(userSelectByParam, userSelectByParam); return result; } /// /// Remove a Collection of User's Profile Images /// /// a user identifier /// a comma seperated list of avatarIds to remove /// an instance of XUserProfileDto public async Task RemoveAvatar( string userSelectByParam, ICollection ids ) { // ValidationProvider.NotEmpty(userSelectByParam); // var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: true, checkCanLoginPolicies: false, checkIsBanned: false, ignoreDisabledUser: true, exception: XException.NotFound.ToException() ); // var xProfileImages = xUser.Avatars .Where(pf => ids.Contains(pf.Id)); if (xProfileImages.HasChild()) { // xUser.Avatars = xUser.Avatars .Except(xProfileImages) .ToList(); // // Creat a List of Physical Files to Remove ... var xFilePathsForRemove = xProfileImages.Select(pf => pf.Thumb).ToList(); xFilePathsForRemove.AddRange(xProfileImages.Select(pf => pf.Name)); // StorageProvider.DeleteFiles( xFilePathsForRemove, forceFileExists: false); // var isCurrentProfileImage = xProfileImages.Any(pfi => pfi.ThumbPath == xUser.Avatar); if (isCurrentProfileImage) { xUser.Avatar = ""; } // await UpdateUserAsync(xUser); } // var result = await GetUserProfileAsync(userSelectByParam, userSelectByParam); return result; } #endregion // #region Confirmations ... /// /// Confirm Registration /// /// specify destination language /// an instance of XDevice /// a token which approved user action /// redirection url /// public async Task ConfirmRegistration( string lang, XDevice device, string actionToken, string returnUrl ) { // // Validate Args ... await ValidationProvider .GroupValidationBuilder() .AddNotEmpty( lang, actionToken, returnUrl) .AddNotNull(device) .ValidateGroupAsync(); // // Check Device Validation ... await ValidateDeviceForActions(device); // // Get Related Token to Registration Hash and Validate it, // then Parse XActionRequest Instance from Token ... var request = await ValidateAndParseActionHash(actionToken); if (request.Action != XAction.Finish) { XException.ActionFailed.Throw(); } // // Extract UserSelectByParam from XActionRequest ... var userSelectByParam = GetUserSelectByParam( request, forceNotNull: true); // // Validate user and Retrieve it ... var user = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: false, checkCanLoginPolicies: false, ignoreDisabledUser: true, checkIsBanned: true); // // Make User Enabled ... var xMessage = GetRegistrationFinishedMessage( lang, user.Email, returnUrl); // user.IsEnable = true; user.EmailConfirmed = true; // await UpdateUserAsync( user, checkCanLoginPolicies: false, checkIsBanned: false ); // // Remove Token ... await RemoveTokenByHash(actionToken); // // Remove All Prevoius Requests ... await HandleRemoveExistsTokens(user.Id); // await RemoveVerificationCodeRequestByDevice(device); // // Send Mail ... try { await MessageProvider.SendMailAsync(xMessage); } catch { } } /// /// Confirm Mobile Number /// /// specify destination language /// an instance of XDevice /// a token which approved user action /// recieved verification code /// an instance of XActionResponse public async Task ConfirmMobileNumber( string lang, XDevice device, string actionToken, string verificationCode ) { // // Validate Args ... await ValidationProvider .GroupValidationBuilder() .AddNotEmpty(lang, actionToken, verificationCode) .AddNotNull(device) .ValidateGroupAsync(); // // Check Device Validation ... await ValidateDeviceForActions(device); // // Get Related Token to Registration Hash and Validate it, // then Parse XActionRequest Instance from Token ... var request = await ValidateAndParseActionHash(actionToken); ValidationProvider.MobileNumber(request.Context.MobileNumber); // // Validate two Device Must Same ... ValidateRequestAndGiveDevices(device, request.Context.Device); // // Check XActionRequest Action Must be Request Mobile Validation ... if (request.Action != XAction.RequestMobileVerificationCode) { XException.InvalidData.Throw(); } // // Extract UserSelectByParam from XActionRequest ... var userSelectByParam = GetUserSelectByParam(request); // // since device must Requested before, // Retrieve XVerification instance by Verification Code from Db // and Validate it ... XVerificationRequest xVerificationRequest = await ValidateAndRetrieveVerificationRequest(verificationCode); // // Check User Added To Db or Not ... // var isUserExists = await IsUserExistsAsync(userSelectByParam); var isAddedUser = !request.Context.UserId.IsNullOrEmpty(); if (isAddedUser) { // // Validate User Exists and Retireve User Object ... var user = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: false, checkCanLoginPolicies: false, checkIsBanned: false); // // Update Exists User's Mobile Confirmation ... user.PhoneNumberConfirmed = true; // // Save Changes to Db ... await UpdateUserAsync(user, checkCanLoginPolicies: false, checkIsBanned: false); // request.Context.UserId = user.Id; } // // Update Request Context MobileNumber Verification Code // and it's Confirmation Status ... request.Context.MobileVerificationCode = verificationCode; request.Context.MobileVerified = true; // // Prepare New Token Result , // by Requesting an Action ... var result = await ActionRequest( lang, device, userSelectByParam, XAction.ConfirmMobileNumber, request.Context, forceCheckUserExists: isAddedUser ); // // Remove Previous Token ... await RemoveTokenByHash(actionToken); try { // // Remove XVerificationRequest instance from Db ... await RemoveVerificationRequest(verificationCode); } catch { } // // Return Result ... return result; } /// /// Confirm Email Address /// /// specify destination language /// an instance of XDevice /// a token which approved user action /// recieved verification code /// an instance of XActionResponse public async Task ConfirmEmailAddress( string lang, XDevice device, string actionToken, string verificationCode ) { // // Validate Args ... await ValidationProvider .GroupValidationBuilder() .AddNotEmpty(lang, actionToken, verificationCode) .AddNotNull(device) .ValidateGroupAsync(); // // Check Device Validation ... await ValidateDeviceForActions(device); // // Get Related Token to Registration Hash and Validate it, // then Parse XActionRequest Instance from Token ... var request = await ValidateAndParseActionHash(actionToken); ValidationProvider.EmailAddress(request.Context.Email); // // Validate two Device Must Same ... ValidateRequestAndGiveDevices(device, request.Context.Device); // // Check XActionRequest Action Must be Request Mobile Validation ... if (request.Action != XAction.RequestEmailVerificationCode) { XException.InvalidData.Throw(); } // // Extract UserSelectByParam from XActionRequest ... var userSelectByParam = GetUserSelectByParam(request); // // since device must Requested before, // Retrieve XVerification instance by Verification Code from Db // and Validate it ... XVerificationRequest xVerificationRequest = await ValidateAndRetrieveVerificationRequest(verificationCode); // // Check User Added To Db or Not ... var isAddedUser = !request.Context.UserId.IsNullOrEmpty(); if (isAddedUser) { // // Validate User Exists and Retireve User Object ... var user = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: false, checkCanLoginPolicies: false, checkIsBanned: false); // // Update Exists User's Email Confirmation ... user.EmailConfirmed = true; // // Save Changes to Db ... await UpdateUserAsync(user, checkCanLoginPolicies: false, checkIsBanned: false); // request.Context.UserId = user.Id; } // // Update Request Context Email Address Verification Code // and it's Confirmation Status ... request.Context.EmailVerificationCode = verificationCode; request.Context.EmailVerified = true; // // Prepare New Token Result , // by Requesting an Action ... var result = await ActionRequest( lang, device, userSelectByParam, XAction.ConfirmEmailAddress, request.Context, forceCheckUserExists: isAddedUser ); // // Remove Previous Token ... await RemoveTokenByHash(actionToken); // // Remove XVerificationRequest instance from Db ... await RemoveVerificationRequest(verificationCode); // // Return Result ... return result; } #endregion } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+Query.cs using System.Linq; using System.Threading.Tasks; using xCommons.Extensions; using xDataService.Extensions; using xExceptions.Constants; using xIdentityModels.Extensions; using xIds.Extensions; using xModels.Dtos; namespace xIds.Providers { public partial class XIdentityManager { /// /// Retrieve Users as Query Model for Query Service ... /// /// /// /// /// /// public async Task> QueryUsers( string requestedUserSelectByParam, XQuery query, string role = null, bool forceRole = false ) { // // Validation ... if (query.IsNull()) { XException.InvalidArgs.Throw(); } // // Normalize ... query = query.NormalizeQuery(DataConfiguration.ToXDataServiceConfig()); // // Since in Resourceable Entities we have to Search on Locales // we Must Implement Senario Custom ... var items = GetUsersDbSet() .ToList() .Where(u => !u.ContainsUserSelectByParam(requestedUserSelectByParam)) .ToList() .AsEnumerable(); // var totalItemsCount = items.Count(); // // Apply Filter ... if (!query.Filter.IsNullOrEmpty()) { // items = items .ApplyFilter(query.Filter); } int filteredItemsCount = items.Count(); // // Count Pages ... var totalPagesCount = query.CountPages(totalItemsCount); var filteredPagesCount = query.CountPages(filteredItemsCount); // // Apply Paging and Sorting ... if (totalItemsCount > 0 && filteredItemsCount > 0) { // // Apply Sorting ... items = items .ToList() .ApplySorting( query.SortBy, query.IsAscending ); // // Apply Paging ... items = items .ToList() .ApplyPaging( query.Page, query.PageSize ); } // // Generate Result Object ... // Query = query, var result = new XQueryResult { Items = items .Select(u => u.Id), Page = query.Page, PageSize = query.PageSize, TotalPages = totalPagesCount, TotalItems = totalItemsCount, TotalFilteredPages = filteredPagesCount, TotalFilteredItems = filteredItemsCount }; // return await Task.Run(() => result); } } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+Registration.cs using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using xCommons.Extensions; using xExceptions.Constants; using xIdentityModels; using xIdentityModels.Constants; using xIdentityModels.Models; using xIdentityModels.Navigations; namespace xIds.Providers { public partial class XIdentityManager { // #region Registration Actions ... /// /// Invite a User to Register on Dashboard /// /// specify destination language /// an instance of XDevice /// which email address is going to invite /// return url for invitation user to redirect /// an instance of XActionResponse public async Task InviteUser( string lang, XDevice device, string email, string returnUrl ) { // // Validate Args ... await ValidationProvider .GroupValidationBuilder() .AddNotEmpty( lang, email, returnUrl ) .AddNotNull(device) .AddEmailAddress(email) .ValidateGroupAsync(); // // Check Email is Unique ... await ValidateUserNotExists(email); // // Get Request Result ... var result = await ActionRequest( lang, device, email, XAction.Invite, forceCheckContext: false, forceCheckUserExists: false); // // Prepare Propper Message ... var xMessage = GetUserInviteMessage(lang, email, result.Token, returnUrl); // // Send Message ... try { await MessageProvider.SendMailAsync(xMessage); } catch { } // // Send Result ... return result; } /// /// Recieve some Basic Informations and Start Registration Proccess /// if they Valid /// /// Registration Proccess Starts with Invoking this Action /// /// specify destination language /// an instance of XDevice /// optional, if user invited, this is the invitation token /// user's FirstName /// user's LastName /// user's dob date /// user's Mobile Number /// user's Email address /// an instance of XActionResponse public async Task RequestRegistration( string lang, XDevice device, string invitationHash, string firstName, string lastName, DateTime dateOfBirth, string mobileNumber = null, string emailAddress = null ) { // // Validate Args ... await ValidationProvider .GroupValidationBuilder() .AddNotEmpty( lang, firstName, lastName ) .AddNotNull( device, dateOfBirth ) .ValidateGroupAsync(); // // Validate Mobile Number if Exists ... if (!mobileNumber.IsNullOrEmpty()) { // ValidationProvider.MobileNumber(mobileNumber); // // Check Mobile is Uniqsue ... await ValidateUserNotExists(mobileNumber); } // // Validate Email Address if Exists ... if (!emailAddress.IsNullOrEmpty()) { // ValidationProvider.EmailAddress(emailAddress); // // Check Email is Unique ... await ValidateUserNotExists(emailAddress); } // // Get Related Token and Validate it and // Check Related Configurations ... await ValidateInvitationHash(invitationHash); // // Check Device Validation ... await ValidateDeviceForActions(device); // // Validate DateOfBirth ... ValidateDateOfBirth(dateOfBirth); // // Define Empty Objects for Using ... var userSelectByParam = ""; var context = new XActionRequestContext(); // context.Lang = lang; context.Device = device; context.LastName = lastName; context.FirstName = firstName; context.DateOfBirth = dateOfBirth; context.MobileNumber = mobileNumber ?? ""; context.Email = !emailAddress.IsNullOrEmpty() ? emailAddress.ToNormalString() : ""; // userSelectByParam = GetUserSelectByParam(context); // // Token Data Parsing ... if (!invitationHash.IsNullOrEmpty()) { // // Get Related Token, Validate it and Parse Contains // XAction Request and Validate the Request itself and // Return it ... var inviteRequest = await ValidateAndParseActionHash(invitationHash); // // Extract User Select By Param and Type ... userSelectByParam = GetUserSelectByParam(inviteRequest); var userSelectBy = GetUserSelectByType(userSelectByParam); // // Check Invitation Only done with Email Address ... if (userSelectBy != XUserSelectBy.Email) { XException.InvalidData.Throw(); } // // Check Invited Email and Given Email to be Same ... if (emailAddress.IsNullOrEmpty() || (!emailAddress.IsNullOrEmpty() && !emailAddress.IsValidEmail())) { XException.InvalidEmailAddress.Throw(); } var isSameEmail = inviteRequest.Context.Email.ToNormalString() == emailAddress.ToNormalString(); if (!isSameEmail) { XException.EmailsSame.Throw(); } // // Update Context Email for Request Action ... context.Email = userSelectByParam.ToNormalString(); context.EmailVerified = true; } // var result = await ActionRequest( lang, device, userSelectByParam, XAction.Registration, context, forceCheckUserExists: false ); // // Remove Invitation Token ... if (!invitationHash.IsNullOrEmpty()) { await RemoveTokenByHash(invitationHash); } // // Return Result ... return result; } /// /// Add User Account Info /// /// specify destination language /// an instance of XDevice /// a token which approved user action /// user name /// assigne password /// an instance of XActionResponse public async Task AddAcountInfo( string lang, XDevice device, string actionToken, string userName, string password ) { // // Validate Args ... await ValidationProvider .GroupValidationBuilder() .AddNotEmpty( lang, actionToken, userName, password) .AddNotNull(device) .ValidateGroupAsync(); // // Check Device Validation ... await ValidateDeviceForActions(device); // // Validate a UserSelector is Available or not ... await ValidateCanRegister(userName); // // Check UserName is Unique ... await ValidateUserNotExists(userName); // // Get Related Token to Registration Hash and Validate it, // then Parse XActionRequest Instance from Token ... var request = await ValidateAndParseActionHash(actionToken); // // Validate Requeired Data for Register User must be in Action Context ... await ValidationProvider .GroupValidationBuilder() .AddNotNull( request.Context, request.Context.Device, request.Context.DateOfBirth) .AddNotEmpty( request.Context.Email, request.Context.MobileNumber, request.Context.FirstName, request.Context.LastName) .AddEmailAddress(request.Context.Email) .AddMobileNumber(request.Context.MobileNumber) .ValidateGroupAsync(); // // Validate two Device Must Same ... ValidateRequestAndGivenDevices(device, request.Context.Device); // // Extract UserSelectByParam from XActionRequest ... var userSelectByParam = GetUserSelectByParam(request); // // Validate Request Pointer User doesn't Exists ... await ValidateUserNotExists(userSelectByParam); // // Create an Empty Instance of XUser ... var xUser = new XUser(); // // Start Filling User Fields ... xUser.UserName = userName; xUser.Email = request.Context.Email; xUser.PhoneNumber = request.Context.MobileNumber; // xUser.FirstName = request.Context.FirstName; xUser.LastName = request.Context.LastName; xUser.DateOfBirth = request.Context.DateOfBirth; // xUser.EmailConfirmed = request.Context.EmailVerified; xUser.PhoneNumberConfirmed = request.Context.MobileVerified; // xUser.CreationDate = DateTime.UtcNow; xUser.LastLogin = null; // #region Handling New User IsEnable State ... // // By Default New Users will Enables ... xUser.IsEnable = true; xUser.IsBanned = false; // // Check Auto Enable Users ... if (Configuration.RequireRegistrationConfirm) { xUser.IsEnable = false; } // // Check Auto Confirm Email Users ... if (Configuration.AutoConfirmNewUsersEmail) { xUser.EmailConfirmed = true; } #endregion // // Check Auto Confirm Phone Number Users ... if (Configuration.AutoConfirmNewUsersPhoneNumber) { xUser.PhoneNumberConfirmed = true; } // // Validating given Password ... await ValidatePasswordPolicies(xUser, password); // // Now add new User to Database ... var createUserResult = await CreateUserAsync(xUser, password); if (!createUserResult.Succeeded) { XException.ActionFailed.Throw(); } // // Update Request UserId Value ... request.Context.UserId = xUser.Id; request.Context.UserName = xUser.UserName; // #region Handling New User Role ... // // Now Try to Assign Default User role ... var isContainsDefaultUserRole = !Configuration.NewUsersRole.IsNullOrEmpty(); if (isContainsDefaultUserRole) { // var newUserRoleName = Configuration.NewUsersRole; var isNewUserRoleExists = await IsRoleExistsAsync(newUserRoleName); // // Make Sure New User role Exists ... if (!isNewUserRoleExists) { // // Create Default Roles ... await CreateIdentityRoles(); } // // Assign User to Role ... var assignNewUserToRoleResult = await AddUserToRoleAsync(xUser, newUserRoleName); if (!assignNewUserToRoleResult.Succeeded) { // // Delete User if Role Assignment Faild ... await UserManager.DeleteAsync(xUser); // // Thrown ActionFailed Error ... XException.ActionFailed.Throw(); } } #endregion // #region Handle Profile Image ... // Save and Attach Profile Image to User if it's Added Before ... if (!request.Context.UserId.IsNullOrEmpty() && !request.Context.Thubmnail.IsNull()) { // xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: true, checkCanLoginPolicies: false, checkIsBanned: false, ignoreDisabledUser: true, exception: XException.NotFound.ToException() ); // // Handle Saving File and Attach it to User ... var saveResult = await StorageProvider .HandleProfileImageSave(request.Context.Thubmnail); // var xProfileImage = new XProfileImage { UserId = request.Context.UserId, Name = saveResult.FileName, Path = saveResult.FilePath, Thumb = saveResult.Thmbnail, ThumbPath = saveResult.ThmbnailPath }; // xUser.Avatars.Add(xProfileImage); var updateResult = await UpdateUserAsync( xUser, checkCanLoginPolicies: false, checkIsBanned: false ); // if (updateResult.Succeeded) { // xUser.Avatar = xProfileImage.ThumbPath; await UpdateUserAsync( xUser, checkCanLoginPolicies: false, checkIsBanned: false ); } } #endregion // // Handle Attaching User device ... var xUserDevice = await AddUserRelatedDevice( userSelectByParam, device, checkCanLoginPolicies: false); // // Prepare New Token Result Resource, // by Requesting an Action ... var result = await ActionRequest( lang, device, userSelectByParam, XAction.Finish, request.Context, forceCheckUserExists: false ); // // Remove Previous Token ... await RemoveTokenByHash(actionToken); // // Return Result ... return result; } /// /// Attach Profile Image /// /// a token which approved user action /// an instance of IFormFile for user's Avatar /// an instance of XActionResponse public async Task AttachProfileImage( string actionToken, IFormFile file ) { // // Validate Args ... await ValidationProvider .GroupValidationBuilder() .AddNotEmpty(actionToken) .AddNotNull(file) .ValidateGroupAsync(); // // Get Related Token to Registration Hash and Validate it, // then Parse XActionRequest Instance from Token ... var request = await ValidateAndParseActionHash(actionToken); // // Extract UserSelectByParam from XActionRequest ... var userSelectByParam = GetUserSelectByParam(request); if (userSelectByParam.IsNullOrEmpty()) { XException.InvalidData.Throw(); } // // Validate Given FormFile as Profile Image ... StorageProvider.ValidateProfileImage(file); // request.Context.Thubmnail = file; // // Save and Attach Profile Image to User if it's Added Before ... if (!request.Context.UserId.IsNullOrEmpty()) { // var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: true, checkCanLoginPolicies: false, checkIsBanned: false, ignoreDisabledUser: true, exception: XException.NotFound.ToException() ); // // Handle Saving File and Attach it to User ... var saveResult = await StorageProvider.HandleProfileImageSave(file); // var xProfileImage = new XProfileImage { UserId = request.Context.UserId, Name = saveResult.FileName, Path = saveResult.FilePath, Thumb = saveResult.Thmbnail, ThumbPath = saveResult.ThmbnailPath }; // xUser.Avatars.Add(xProfileImage); var updateResult = await UpdateUserAsync( xUser, checkCanLoginPolicies: false, checkIsBanned: false ); // if (updateResult.Succeeded) { // xUser.Avatar = xProfileImage.ThumbPath; await UpdateUserAsync( xUser, checkCanLoginPolicies: false, checkIsBanned: false ); } } // // Remove Invitation Token ... if (!actionToken.IsNullOrEmpty()) { await RemoveTokenByHash(actionToken); } // var result = await ActionRequest( request.Context.Lang, request.Context.Device, userSelectByParam, XAction.ProfileAction, request.Context, forceCheckUserExists: false ); // // Return Result ... return result; } /// /// Finishing Registration /// /// specify destination language /// an instance of XDevice /// user identifier /// assigne password /// return url for invitation user to redirect /// public async Task FinishRegistration( string lang, XDevice device, string userSelectByParam, string password, string returnUrl ) { // // Validate Args ... await ValidationProvider .GroupValidationBuilder() .AddNotEmpty(lang, userSelectByParam, password, returnUrl) .AddNotNull(device) .AddUrl(returnUrl) .ValidateGroupAsync(); // // Validate User Exists And Retrieve it ... var xUser = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: false, checkCanLoginPolicies: false, checkIsBanned: false, ignoreDisabledUser: true, forceAdmin: false ); // #region Handling New User Email Notification Senario ... // // Here we Check if User is Enable and Approved Email // send RegisteredMsg and if User is not Enable and // Verify Registration value in Configuration is True // send Verify Registration mail to user and handle it ... if (Configuration.RequireRegistrationConfirm) { // if (xUser.IsEnable) { // // Send Registration Finished Message ... // since in this step we need to prevent errors from // going forward. add this try catch here ... try { // var xMessage = GetRegistrationFinishedMessage(lang, xUser.Email, returnUrl); // await MessageProvider.SendMailAsync(xMessage); } catch { } } else { // // Send Registration Confirm Message ... // since in this step we need to prevent errors from // going forward. add this try catch here ... try { // var request = await ActionRequest( lang, device, userSelectByParam, XAction.Finish, forceCheckContext: false, forceCheckUserExists: true); // var xMessage = GetRegistrationConfirmMessage(lang, xUser.Email, request.Token, returnUrl); // await MessageProvider.SendMailAsync(xMessage); } catch { } } } // // // await RemoveTokenByDevice (device); #endregion } #endregion } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+Request.cs using System.Collections.Generic; using System.Threading.Tasks; using xCommons.Extensions; using xExceptions.Constants; using xIdentityModels.Constants; using xIdentityModels.Extensions; using xIdentityModels.Models; using xIdentityModels.Navigations; namespace xIds.Providers { public partial class XIdentityManager { // #region Action Handlers ... /// /// Request an Action /// /// specify destination language /// an instance of XDevice /// specified user's identifier /// a member of XAction which represent Action Step /// an instance of XActionRequestContext which provides required informations for specified step /// specify checking context, default is false /// specify check user exists, default is true /// specify check user and device relation, default is false /// specifies force renew Action Token if it's expired, default is false /// an instance of XActionResponse private async Task ActionRequest( string lang, XDevice device, string userSelectByParam, XAction step, XActionRequestContext context = null, bool forceCheckContext = false, bool forceCheckUserExists = true, bool forceCheckUserDevice = false, bool forceRenewToken = false ) { // // Validate Args ... ValidationProvider.NotEmpty(lang); ValidationProvider.NotNull(device); // // Check Device not Banned ... await ValidateDeviceForActions(device); // // Check User Exists and Device Relation ... if (forceCheckUserExists) { if (forceCheckUserDevice) { // if (context.Device != null && !device.IsSameAs(context.Device)) { XException.InvalidDevice.Throw(); } // await ValidateUserAndDeviceRelation(userSelectByParam, device); } else { await ValidateUserExistsAsync(userSelectByParam); } } // XToken xToken = null; XActionResponse result = null; XActionRequestToken xRequest = null; // var isExists = false; var forceUserSelectByParamNotEmpty = true; switch (step) { case XAction.Registration: // forceUserSelectByParamNotEmpty = false; isExists = await IsTokenExistsByDeviceAndType(device, step); // if (isExists) { xToken = await ValidateAndRetieveTokenByDeviceAndType(device, step); } break; default: // isExists = await IsTokenExistsByUserAndType(userSelectByParam, step); // if (isExists) { xToken = await ValidateAndRetieveTokenByUserAndType(userSelectByParam, step); } break; } // if (isExists) { // var isValidToken = IsValidToken(xToken.Token); if (!isValidToken && !forceRenewToken) { switch (step) { case XAction.Registration: case XAction.Invite: forceRenewToken = true; break; default: throw XException.InvalidToken.ToException(); } } // if (!isValidToken && forceRenewToken) { await ValidateAndHandleToken(xToken.Token); return await ActionRequest( lang, device, userSelectByParam, step, context, forceCheckContext, forceCheckUserExists, forceCheckUserDevice, forceRenewToken); } // xRequest = ValidateAndParseActionToken(xToken.Token); // // Check Exists Context ... if (forceCheckContext) { // var isSameContext = xRequest.Context.IsSameAs(context); if (!isSameContext) { XException.InvalidData.Throw(); } } } else { // if (context != null) { // var contextUserSelectByParam = GetUserSelectByParam( context, false, new List { XUserSelectBy.ID, XUserSelectBy.Email, XUserSelectBy.MobileNumber }); var contextLang = context.Lang; var contextDevice = context.Device; // // prevent from issues on Registration Request ... if (forceUserSelectByParamNotEmpty) { var userSelectByType = GetUserSelectByType(userSelectByParam); var contextUserSelectByType = GetUserSelectByType(contextUserSelectByParam); if (contextUserSelectByType != userSelectByType) { // var excludesList = GenerateUserSelectByExcludes(new List { userSelectByType }); // contextUserSelectByParam = GetUserSelectByParam(context, false, excludesList); } } // // Fix Device Not Same on Invitation and Request if (step == XAction.Registration) { // context.Device = device; contextDevice = context.Device; } // // Validate Context Data must be Same as Request Data ... if ((!contextUserSelectByParam.IsNullOrEmpty() && contextUserSelectByParam != userSelectByParam) || (!contextLang.IsNullOrEmpty() && contextLang != lang) || (contextDevice != null && !contextDevice.IsSameAs(device))) { XException.InvalidData.Throw(); } } else { // context = new XActionRequestContext { Lang = lang, Device = device }; // // Add Content ... var userSelectByType = GetUserSelectByType( userSelectByParam, forceUserSelectByParamNotEmpty); switch (userSelectByType) { case XUserSelectBy.MobileNumber: context.MobileNumber = userSelectByParam; break; case XUserSelectBy.Email: context.Email = userSelectByParam; break; case XUserSelectBy.Username: context.UserName = userSelectByParam; break; case XUserSelectBy.ID: context.UserId = userSelectByParam; break; case XUserSelectBy.NotSpecified: default: if (forceCheckUserExists) { XException.InvalidArgs.Throw(); } break; } } // // Generate Registration Request ... xRequest = new XActionRequestToken { Action = step, Context = context }; // // Add User Id if Exists to Context ... var isUserExists = await IsUserExistsAsync(userSelectByParam); if (isUserExists) { // var user = await GetUserAsync(userSelectByParam); if (user != null) { xRequest.Context.UserId = user.Id; } } // xRequest.Prepare(Configuration.IdentitySecretKey); // xToken = await HashRequest( xRequest, forceUserSelectByParamNotEmpty); } // // When XToken Exists Passed XToken ... result = GetActionResultResponse(xToken); // if (result == null) { XException.ActionFailed.Throw(); } // return result; } /// /// Request a Mobile Verification Code /// /// specify destination language /// an instance of XDevice /// a token which approved user action /// the mobile number which is going to request a verification code /// check mobile number is in use or not, default is true /// an instance of XActionResponse private async Task RequestMobileVerificationCode( string lang, XDevice device, string actionToken, string mobileNumber, bool checkMobileInUse = true ) { // // Validate Args ... await ValidationProvider .GroupValidationBuilder() .AddNotEmpty(lang, actionToken, mobileNumber) .AddMobileNumber(mobileNumber) .AddNotNull(device) .ValidateGroupAsync(); // // Check Device Validation ... await ValidateDeviceForActions(device); // // Check Mobile is Unique ... if (checkMobileInUse) { var isUserExists = await IsUserExistsAsync(mobileNumber); if (isUserExists) { // var xUser = await GetUserAsync(mobileNumber); // if (xUser.PhoneNumberConfirmed) { XException.MobileInUsed.Throw(); } } } // // Get Related Token to Registration Hash and Validate it, // then Parse XActionRequest Instance from Token ... var request = await ValidateAndParseActionHash(actionToken); // // Validate two Device Must Same ... ValidateRequestAndGiveDevices(device, request.Context.Device); // // Extract UserSelectByParam from XActionRequest ... var userSelectByParam = GetUserSelectByParam( request, forceNotNull: false, excludes: new List { XUserSelectBy.ID, XUserSelectBy.Email, XUserSelectBy.MobileNumber }); // // if it's null, means user doesn't have Invitation Token // and there is no User Selector ... if (userSelectByParam.IsNullOrEmpty()) { // // Since Mobile is Unique so it can act as a // UserSelector ... userSelectByParam = mobileNumber; } // // Define empty Verification Code // and Empty Verification Request ... var verificationCode = ""; XVerificationRequest xVerificationRequest = null; // // Check Device Request Verification Code before or Not ... var isDeviceRequested = await IsDeviceRequestedForVerificationCodeBefor(device); if (isDeviceRequested) { // // if Requested before, Retrieve XVerification instance by Device from Db // and Validate it ... xVerificationRequest = await ValidateAndRetrieveVerificationRequest(device); // if (xVerificationRequest.VerificationCode.IsNullOrEmpty()) { // verificationCode = GenerateRandom().ToString(); xVerificationRequest.VerificationCode = verificationCode; // await RemoveVerificationCodeRequestByDevice( device, saveChanges: false ); await AddVerificationRequest( xVerificationRequest, saveChanges: false ); // await DbContext.SaveChangesAsync(); } // // if XVerificationRequest is Valid, it must Contain an Alive Verification Code // so retrieve it and assign it ... verificationCode = xVerificationRequest.VerificationCode; } else { // verificationCode = GenerateRandom().ToString(); } // // if it's First Verification Request of given Device // Generate a new Verification Code ... if (verificationCode.IsNullOrEmpty()) { verificationCode = GenerateRandom().ToString(); } // // Check Context Mobile and given Mobile ... if (!request.Context.MobileNumber.IsNullOrEmpty() && mobileNumber != request.Context.MobileNumber) { XException.InvalidMobileNumber.Throw(); } // // Check User Added To Db or Not ... var isAddedUser = !request.Context.UserId.IsNullOrEmpty(); if (isAddedUser) { // // Validate User Exists and Retireve User Object ... var user = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: false, checkCanLoginPolicies: false, checkIsBanned: false); // // Check Mobiles Same ... if (user.PhoneNumber == mobileNumber && user.PhoneNumberConfirmed) { XException.MobilesSame.Throw(); } // // Update User Object's Mobile Number and // Confirmation Status ... user.PhoneNumber = mobileNumber; user.PhoneNumberConfirmed = false; // // Save Changes to Db ... await UpdateUserAsync(user, checkCanLoginPolicies: false, checkIsBanned: false); } // // Prepare Verification Request by Checking Next Tries, // Device Status, and etc, Update or Add XVerificationRequest to db // and Retrieve the added Entity ... xVerificationRequest = await HandleVerificationRequestPreparation(verificationCode, request); // // Update Request Context MobileNumber // and it's Confirmation Status ... request.Context.MobileNumber = mobileNumber; request.Context.MobileVerified = false; // // Remove Previous Token ... await RemoveTokenByHash(actionToken); // // Prepare New Token Result Resource, // by Requesting an Action ... var result = await ActionRequest( lang, device, userSelectByParam, XAction.RequestMobileVerificationCode, request.Context, forceCheckUserExists: isAddedUser ); // // Prepare Message ... var xMessage = GetVerificationCodeMessage(lang, mobileNumber, verificationCode); // // Send Verification Code Message to User Using SMS Provider ... await MessageProvider.SendSmsAsync(xMessage, throwException: false); // // Return Result ... return result; } /// /// Request a Email Verification Code /// /// specify destination language /// an instance of XDevice /// a token which approved user action /// the email address which is going to request a verification code /// check email address is in use or not, default is true /// an instance of XActionResponse public async Task RequestEmailVerificationCode( string lang, XDevice device, string actionToken, string emailAddress, bool checkEmailInUse = true ) { // // Validate Args ... await ValidationProvider .GroupValidationBuilder() .AddNotEmpty(lang, actionToken, emailAddress) .AddEmailAddress(emailAddress) .AddNotNull(device) .ValidateGroupAsync(); // // Check Device Validation ... await ValidateDeviceForActions(device); // // Check Email is Unique ... if (checkEmailInUse) { var isUserExists = await IsUserExistsAsync(emailAddress); if (isUserExists) { // var xUser = await GetUserAsync(emailAddress); // if (xUser.EmailConfirmed) { XException.EmailInUsed.Throw(); } } } // // Get Related Token to Registration Hash and Validate it, // then Parse XActionRequest Instance from Token ... var request = await ValidateAndParseActionHash(actionToken); // // Validate two Device Must Same ... ValidateRequestAndGiveDevices(device, request.Context.Device); // // Extract UserSelectByParam from XActionRequest ... var userSelectByParam = GetUserSelectByParam( request, forceNotNull: false, excludes: new List { XUserSelectBy.ID, XUserSelectBy.Email, XUserSelectBy.MobileNumber }); // // if it's null, means user doesn't have Invitation Token // and there is no User Selector ... if (userSelectByParam.IsNullOrEmpty()) { // // Since Email is Unique so it can act as a // UserSelector ... userSelectByParam = emailAddress; } // // Define empty Verification Code // and Empty Verification Request ... var verificationCode = ""; XVerificationRequest xVerificationRequest = null; // // Check Device Request Verification Code before or Not ... var isDeviceRequested = await IsDeviceRequestedForVerificationCodeBefor(device); if (isDeviceRequested) { // // if Requested before, Retrieve XVerification instance by Device from Db // and Validate it ... xVerificationRequest = await ValidateAndRetrieveVerificationRequest(device); // if (xVerificationRequest.VerificationCode.IsNullOrEmpty()) { // verificationCode = GenerateRandom().ToString(); xVerificationRequest.VerificationCode = verificationCode; // await RemoveVerificationCodeRequestByDevice( device, saveChanges: false ); await AddVerificationRequest( xVerificationRequest, saveChanges: true ); } // // if XVerificationRequest is Valid, it must Contain an Alive Verification Code // so retrieve it and assign it ... verificationCode = xVerificationRequest.VerificationCode; } else { // verificationCode = GenerateRandom().ToString(); } // // Check Context Email and given Email ... if (!request.Context.Email.IsNullOrEmpty() && emailAddress != request.Context.Email) { XException.InvalidEmailAddress.Throw(); } // // Check User Added To Db or Not ... var isAddedUser = !request.Context.UserId.IsNullOrEmpty(); if (isAddedUser) { // // Validate User Exists and Retireve User Object ... var user = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: false, checkCanLoginPolicies: false, checkIsBanned: false); // // Check Email Same ... if (user.Email == emailAddress && user.EmailConfirmed) { XException.MobilesSame.Throw(); } // // Update User Object's Email and // Confirmation Status ... user.Email = emailAddress; user.EmailConfirmed = false; // // Save Changes to Db ... await UpdateUserAsync( user, checkCanLoginPolicies: false, checkIsBanned: false ); } // // Prepare Verification Request by Checking Next Tries, // Device Status, and etc, Update or Add XVerificationRequest to db // and Retrieve the added Entity ... xVerificationRequest = await HandleVerificationRequestPreparation(verificationCode, request); // // Update Request Context Email // and it's Confirmation Status ... request.Context.Email = emailAddress; request.Context.EmailVerified = false; // // Prepare New Token Result Resource, // by Requesting an Action ... var result = await ActionRequest( lang, device, userSelectByParam, XAction.RequestEmailVerificationCode, request.Context, forceCheckUserExists: isAddedUser ); // // Remove Hash ... await RemoveTokenByHash(actionToken); // // Prepare Message ... var xMessage = GetVerificationCodeMessage(lang, emailAddress, verificationCode); // // Send Verification Code Message to User Using Mail Provider ... await MessageProvider.SendMailAsync(xMessage, throwException: false); // // Return Result ... return result; } #endregion } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+Role.cs using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; using xCommons.Extensions; using xExceptions.Constants; using xIdentityModels; namespace xIds.Providers { public partial class XIdentityManager { // #region Role Actions ... /// /// Check a Role exists or not /// /// role name /// a boolean value public async Task IsRoleExistsAsync( string roleName ) { // if (roleName.IsNullOrEmpty()) { XException.InvalidArgs.Throw(); } // return await RoleManager.RoleExistsAsync(roleName); } /// /// Create a new Role /// /// role name /// an instance of IdentityResult public async Task CreateRoleAsync( string roleName ) { // var isExists = await RoleManager .RoleExistsAsync(roleName); if (isExists) { XException.Duplicate.Throw(); } // var result = await RoleManager .CreateAsync(new IdentityRole(roleName)); // return result; } /// /// Get a Role /// /// role name /// an instance of IdentityRole public async Task GetRoleAsync( string roleName ) { // var isExists = await IsRoleExistsAsync(roleName); if (!isExists) { XException.NotFound.Throw(); } // var result = await RoleManager .FindByNameAsync(roleName); // return result; } /// /// Remove a User From Role /// /// an instance of XUser /// role name /// an instance of IdentityResult public async Task RemoveFromRoleAsync( XUser user, string roleName ) { return await UserManager.RemoveFromRoleAsync(user, roleName); } /// /// Remove a User From Roles /// /// an instance of XUser /// a collection of role names /// an instance of IdentityResult public async Task RemoveFromRolesAsync( XUser user, IEnumerable roleNames ) { return await UserManager.RemoveFromRolesAsync(user, roleNames); } /// /// Assign a User to Specific Role /// /// an instance of XUser /// role name /// an instance of IdentityResult public async Task AddUserToRoleAsync( XUser user, string roleName ) { // if (user == null || roleName.IsNullOrEmpty()) { XException.InvalidArgs.Throw(); } // var userSelectByParam = GetUserSelectByParam(user); var isExistsUser = await IsUserExistsAsync(userSelectByParam); var isExistsRole = await IsRoleExistsAsync(roleName); if (!isExistsUser || !isExistsRole) { XException.NotFound.Throw(); } // var result = await UserManager .AddToRoleAsync(user, roleName); // return result; } /// /// Retrieve Role Name by it's ID /// /// role id /// role name as string public async Task GetRoleNameAsync( string roleId ) { // // Validate Args ... if (roleId.IsNullOrEmpty()) { XException.InvalidArgs.Throw(); } // var role = await RoleManager .FindByIdAsync(roleId); // return role.Name.ToNormalString(); } /// /// Get a List Of User Roles /// /// user identifier /// /// /// a collection of role names public async Task> GetRoleNamesAsync( string userSelectByParam, bool checkCanLoginPolicies = true, bool checkIsBanned = true ) { // // Validate Args ... if (userSelectByParam.IsNullOrEmpty()) { XException.InvalidArgs.Throw(); } // var user = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: true, checkCanLoginPolicies: checkCanLoginPolicies, checkIsBanned: checkIsBanned ); // var result = new List(); foreach (var role in user.Roles) { // var roleName = await GetRoleNameAsync(role.RoleId); roleName = roleName.ToNormalString(); // result.Add(roleName); } // return result; } /// /// Check a User is Adminr not /// /// user identifier /// a boolean value public async Task IsAdmin( string userSelectByParam ) { // // Validate Args ... ValidationProvider.NotEmpty(userSelectByParam); // var user = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: true, checkCanLoginPolicies: true); // var result = await IsAdmin(user); // return result; } /// /// Check a User is Adminr not /// /// an instance of XUser /// a boolean value public async Task IsAdmin( XUser user ) { // // Validate Args ... ValidationProvider.NotNull(user); ValidationProvider.NotEmpty(user.Id); // // Retrieve Admin Role ... // TODO: Fix this ... var adminRole = "admin"; // XUserRole.Admin // .GetStringValue () // .ToNormalString (); // // Check Admin Role Exists in User Roles or not ... var userRoleNames = await GetRoleNamesAsync(user.Id); var isContainsAdminRole = userRoleNames.Contains(adminRole); // // Return Result ... return isContainsAdminRole; } #endregion } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+Search.cs using System.Threading.Tasks; using xCommons.Extensions; using xExceptions.Constants; using xIdentityModels.Dtos; using xModels.Dtos; using xDataService.Extensions; using xIds.Extensions; using System.Linq; using xIdentityModels.Extensions; namespace xIds.Providers { public partial class XIdentityManager { // #region Actions ... /// /// Query User Profiles /// /// requested user's identifier /// how to filter results based on XQuery structure /// an instance of XQueryResult of XUserProfileDto public async Task> QueryOpenToSearchUsers( string requestedUserSelectByParam, XQuery query ) { // // Validation ... if (query.IsNull()) { XException.InvalidArgs.Throw(); } // // Normalize ... query = query.NormalizeQuery(DataConfiguration.ToXDataServiceConfig()); // // Since in Resourceable Entities we have to Search on Locales // we Must Implement Senario Custom ... var totalEntities = GetUsersDbSet() .Where(u => u.OpenToSearch) .ToList() .Where(u => !u.ContainsUserSelectByParam(requestedUserSelectByParam)) .Select(u => u.Id) .ToList(); // var items = await GetUserProfilesAsync( totalEntities, requestedUserSelectByParam, checkIsBanned: false, checkCanLoginPolicies: false, forceCheckRequestedUser: false ); // var totalItemsCount = items.Count(); // // Apply Filter ... if (!query.Filter.IsNullOrEmpty()) { // items = items .ApplyFilter(query.Filter); } int filteredItemsCount = items.Count(); // // Count Pages ... var totalPagesCount = query.CountPages(totalItemsCount); var filteredPagesCount = query.CountPages(filteredItemsCount); // // Apply Paging and Sorting ... if (totalItemsCount > 0 && filteredItemsCount > 0) { // // Apply Sorting ... items = items .ToList() .ApplySorting( query.SortBy, query.IsAscending ); // // Apply Paging ... items = items .ToList() .ApplyPaging( query.Page, query.PageSize ); } // // Generate Result Object ... // Query = query, var result = new XQueryResult { Items = items, Page = query.Page, PageSize = query.PageSize, TotalPages = totalPagesCount, TotalItems = totalItemsCount, TotalFilteredPages = filteredPagesCount, TotalFilteredItems = filteredItemsCount }; // return result; } #endregion } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+Seed.cs using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; using xCommons.Extensions; using xExceptions.Constants; using xIdentityModels.Descriptors; using xIdentityModels.Extensions; namespace xIds.Providers { public partial class XIdentityManager { // #region Default Identity Preparation Actions ... /// /// Create Default Roles based on Identity Configuration /// /// public async Task CreateIdentityRoles() { // if (Configuration == null || Configuration.IdentityRoles == null || Configuration.IdentityRoles.Count == 0) { return; } // // Check New Users Role exists in IdentityRole or not ... if (!Configuration.NewUsersRole.IsNullOrEmpty()) { // // Ensure NewUsersRole Exists in IdentityRoles ... var isNewUserRoleExistsInIdentityRoles = Configuration .IdentityRoles .Contains(Configuration.NewUsersRole); if (!isNewUserRoleExistsInIdentityRoles) { XException.InvalidArgs.Throw(); } } // // loop through all roles and create them one by one ... foreach (var roleName in Configuration.IdentityRoles) { // var isRoleExists = await RoleManager.RoleExistsAsync(roleName); if (!isRoleExists) { // var result = await RoleManager.CreateAsync(new IdentityRole(roleName)); } } } /// /// Create a user Based on User Descriptor /// /// an instance of XIdentityUserDescriptor /// public async Task CreateUserAsync( XIdentityUserDescriptor user ) { // // Validate Args ... ValidationProvider.NotNull(user); // var isExistsRole = await RoleManager.RoleExistsAsync(user.Role); if (!isExistsRole) { // // Check Assigned role to user exists in app roles ... if (!Configuration .IdentityRoles .Contains(user.Role)) { XException.InvalidArgs.Throw(); } // // Ensure All Roles Created ... await CreateIdentityRoles(); } // // Check User Exists ... var isExistsUser = await IsUserExistsAsync(user.UserName); if (!isExistsUser) { // // Create a DashboardUser instance based on Configuration Data ... var userEntity = user.ToXUser(); // // Try to Create User ... var userCreateResult = await CreateUserAsync( userEntity, user.Password ); if (!userCreateResult.Succeeded) { XException.ActionFailed.Throw(); } // // Assign Admin User to it's Role ... var roleAssignResult = await UserManager.AddToRoleAsync(userEntity, user.Role); if (!roleAssignResult.Succeeded) { XException.ActionFailed.Throw(); } // var claims = await ToJwtClaims( userEntity, checkCanLoginPolicies: true, checkIsBanned: true); // var addClaimsResult = await UserManager.AddClaimsAsync(userEntity, claims); if (!addClaimsResult.Succeeded) { XException.ActionFailed.Throw(); } } } #endregion } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+Token.cs using System; using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.IdentityModel.Tokens; using xCommons.Extensions; using xCommons.Helpers; using xExceptions.Constants; using xIdentityModels; using xIdentityModels.Constants; using xIdentityModels.Extensions; using xIdentityModels.Models; using xIdentityModels.Navigations; namespace xIds.Providers { public partial class XIdentityManager { // #region Token Actions ... /// /// Check a Token Entity Exists or not /// /// an instance of XDevice /// specifies Action Step by a member of XAction /// a boolean value private async Task IsTokenExistsByDeviceAndType( XDevice device, XAction type ) { // ValidationProvider.NotNull(device); // var isExists = false; var enumerator = DbContext.Tokens.AsAsyncEnumerable(); await foreach (var token in enumerator) { // if (token.Type == type && token.Device.IsSameAs(device)) { isExists = true; break; } } // return isExists; } /// /// Check a Token Entity Exists or not /// /// specified user's identifier /// specifies Action Step by a member of XAction /// a boolean value private async Task IsTokenExistsByUserAndType( string userSelectByParam, XAction type ) { // ValidationProvider.NotEmpty(userSelectByParam); // var isExists = false; var tokensEnumerator = DbContext.Tokens.AsAsyncEnumerable(); await foreach (var token in tokensEnumerator) { // if (token.Type == type && token.UserSelectByParam .ToNormalString() == userSelectByParam .ToNormalString()) { // isExists = true; break; } } // return isExists; } /// /// Check a Token Entity Exists or not /// /// represent specified action token /// a boolean value private async Task IsTokenExistsByToken( string token ) { // var result = await DbContext.Tokens .AnyAsync(xt => xt.Token == token); // return result; } /// /// Check a Token Entity Exists or not /// /// represent specified action token hash /// a boolean value private async Task IsTokenExistsByHash( string hash ) { // var result = await DbContext.Tokens .AnyAsync(xt => xt.Hash == hash); // return result; } /// /// Check a Token Entity Exists or not /// /// an instance of XToken /// a boolean value private async Task IsTokenExistsByToken( XToken item ) { // var result = false; var tokenEnumerator = DbContext.Tokens .AsAsyncEnumerable(); await foreach (var token in tokenEnumerator) { // if (token.Hash == item.Hash && token.Token == item.Token && token.Type == item.Type && token.UserSelectByParam .ToNormalString() == item.UserSelectByParam .ToNormalString() && token.Device.IsSameAs(item.Device)) { // result = true; break; } } // return result; } /// /// Check a Token Entity Exists or not /// /// specifies token id /// a boolean value private async Task IsTokenExistsById( int id ) { return await DbContext.Tokens.AnyAsync(t => t.Id == id); } /// /// Retrieve Token Entity /// /// an instance of XDevice /// specifies Action Step by a member of XAction /// an instance of XToken private async Task GetTokenByDeviceAndType( XDevice device, XAction type ) { // var isExists = await IsTokenExistsByDeviceAndType(device, type); if (!isExists) { return null; } // XToken item = null; var enumerator = DbContext.Tokens.AsAsyncEnumerable(); await foreach (var token in enumerator) { // if (token.Type == type && token.Device.IsSameAs(device)) { // item = token; break; } } // return item; } /// /// Retrieve Token Entity /// /// specified user's identifier /// specifies Action Step by a member of XAction /// an instance of XToken private async Task GetTokenByUserAndType( string userSelectByParam, XAction type ) { // var isExists = await IsTokenExistsByUserAndType(userSelectByParam, type); if (!isExists) { return null; } // XToken item = null; var enumerator = DbContext.Tokens.AsAsyncEnumerable(); await foreach (var token in enumerator) { // if (token.Type == type && token.UserSelectByParam .ToNormalString() == userSelectByParam .ToNormalString()) { // item = token; break; } } // return item; } /// /// Retrieve a Token Entity /// /// represent specified action token /// an instance of XToken private async Task GetTokenByToken( string token ) { // var isExists = await IsTokenExistsByToken(token); if (!isExists) { return null; } // var result = await DbContext.Tokens .FirstOrDefaultAsync(xt => xt.Token == token); // return result; } /// /// Retrieve Related Hash to a Token /// /// represent specified action token /// hash string private async Task GetRelatedHashByToken( string token ) { // var item = await GetTokenByToken(token); if (item == null) { return null; } // return item.Hash; } /// /// Retrieve a Token Entity /// /// represent specified action token hash /// an instance of XToken private async Task GetTokenByHash( string hash ) { // // Validate Args ... ValidationProvider.NotEmpty(hash); // var isExists = await IsTokenExistsByHash(hash); if (!isExists) { return null; } // var item = await DbContext.Tokens .FirstOrDefaultAsync(t => t.Hash == hash); // return item; } /// /// Retrieve Related Token to a Hash string /// /// represent specified action token hash /// token string private async Task GetRelatedTokenByHash( string hash ) { // var item = await GetTokenByHash(hash); if (item == null) { return null; } // return item.Token; } /// /// Retrieve a Token Expiration Date /// /// represent specified action token /// an instance of DateTime private DateTime GetTokenExpirationDate( string token ) { // ValidationProvider.NotEmpty(token); // var result = IdentityHelper.GetTokenExpirationDate(token); // return result; } /// /// Remove a Token Entity /// /// represent specified action token /// private async Task RemoveTokenByToken( string token ) { // // Validate Args ... ValidationProvider.NotEmpty(token); // var isExists = await IsTokenExistsByToken(token); if (!isExists) { return; } // var item = await GetTokenByToken(token); if (item == null) { return; } // DbContext.Tokens.Remove(item); await DbContext.SaveChangesAsync(); } /// /// Remove a Token Entity /// /// represent specified action token hash /// private async Task RemoveTokenByHash( string hash ) { // // Validate Args ... ValidationProvider.NotEmpty(hash); // var isExists = await IsTokenExistsByHash(hash); if (!isExists) { return; } // var item = await GetTokenByHash(hash); if (item == null) { return; } // DbContext.Tokens.Remove(item); await DbContext.SaveChangesAsync(); } /// /// Remove a Token Entity /// /// an instance of XDevice /// private async Task RemoveTokenByDevice( XDevice device ) { // // Validate Args ... ValidationProvider.NotNull(device); // XToken items = null; var enumerator = DbContext.Tokens.AsAsyncEnumerable(); await foreach (var token in enumerator) { // if (token.Device.IsSameAs(device)) { // items = token; break; } } // if (!items.IsNull()) { DbContext.Tokens.RemoveRange(items); await DbContext.SaveChangesAsync(); } } /// /// add a token Entity /// /// an instance of XToken /// an instance of XToken private async Task AddTokenAsync( XToken item ) { // var isExist = await IsTokenExistsByToken(item); if (isExist) { return await GetTokenByHash(item.Hash); } // var entry = await DbContext.Tokens.AddAsync(item); await DbContext.SaveChangesAsync(); // return entry.Entity; } /// /// Hash a Request Token /// /// an instance of XActionRequestToken /// /// /// an instance of XToken private async Task HashRequest( XActionRequestToken request, bool forceNotNullUserSelectByParam = true, bool forceDeviceNotNull = true ) { // // Validate Args ... var secretKey = Configuration.IdentitySecretKey; ValidationProvider.NotNull(request); ValidationProvider.NotEmpty(secretKey); // ValidateActionRequest(request); // var type = request.Action; var device = request.Context.Device; var tokenObject = ToSecurityToken(request); var tokenString = ToTokenString(tokenObject); var tokenHash = ToHash(tokenString); var userSelectByParam = GetUserSelectByParam(request, forceNotNullUserSelectByParam); // if (forceNotNullUserSelectByParam) { ValidationProvider.NotEmpty(userSelectByParam); } // ValidationProvider.NotEmpty(tokenString, tokenHash); // if (forceDeviceNotNull) { ValidationProvider.NotNull(device); } // ValidationProvider.NotNull(tokenObject); // var xToken = new XToken { Type = type, Device = device, Hash = tokenHash, Token = tokenString, UserSelectByParam = userSelectByParam }; // var addedToken = await AddTokenAsync(xToken); // return addedToken; } /// /// Generate Token Hash string /// /// represent specified action token /// check token validation parameters, default is true /// hash string private string ToHash( string token, bool checkValidation = true ) { // ValidationProvider.NotEmpty(token); // if (checkValidation) { ValidateToken(token); } // var result = token.ToMd5String().ToNormalString(); // return result; } /// /// Generate Token string /// /// represent specified action token /// token string private string ToTokenString( SecurityToken token ) { // ValidationProvider.NotNull(token, IdentityHelper); // var result = IdentityHelper.ToTokenString(token); // return result; } /// /// Generate Token string /// /// represent specified action token /// token string private string ToTokenString( JwtSecurityToken token ) { // ValidationProvider.NotNull(token, IdentityHelper); // var result = IdentityHelper.ToTokenString(token); // return result; } /// /// Generate Security Token /// /// represent specified action token /// an instance of SecurityToken private SecurityToken ToSecurityToken( string token ) { // ValidationProvider.NotEmpty(token); // var result = IdentityHelper.ToSecurityToken(token); // return result; } /// /// Generate Security Token /// /// an instance of XActionRequestToken /// an instance of SecurityToken private SecurityToken ToSecurityToken( XActionRequestToken request ) { // ValidationProvider.NotNull(request); // ValidateActionRequest(request); // var result = IdentityHelper.ToSecurityToken(request); if (result == null) { XException.InvalidToken.Throw(); } // return result; } /// /// Cleanup all exists tokens related to specified User /// /// specified user's identifier /// private async Task HandleRemoveExistsTokens( string userSelectByParam ) { // // Validate Args ... ValidationProvider.NotEmpty(userSelectByParam); // var xTokens = new List(); var xTokenEnumerator = DbContext.Tokens.AsAsyncEnumerable(); await foreach (var xToken in xTokenEnumerator) { // if (xToken.UserSelectByParam == userSelectByParam && ObjectHelper.ToEnumerableValues().Contains(xToken.Type)) { xTokens.Add(xToken); } } // if (xTokens.HasChild()) { DbContext.Tokens.RemoveRange(xTokens); await DbContext.SaveChangesAsync(); } } /// /// Cleanup all tokens related to specified User /// /// a collection of user identifiers /// private async Task HandleCleanUserTokens( ICollection userSelectByParams ) { // // Validate Args ... if (!userSelectByParams.HasChild()) { return; } // foreach (var userSelectByParam in userSelectByParams) { await HandleRemoveExistsTokens(userSelectByParam); } } /// /// Cleanup all tokens related to specified User /// /// an instance of XUser /// private async Task HandleCleanUserTokens( XUser user ) { // if (user == null) { return; } // var userSelectByParams = GenerateUserSelectByParams(user); // await HandleCleanUserTokens(userSelectByParams); } #endregion } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+User.cs using System; using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; using System.Linq; using System.Security.Claims; using System.Threading.Tasks; using IdentityModel; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using xCommons.Constants; using xCommons.Extensions; using xExceptions.Constants; using xIdentityModels; using xIdentityModels.Constants; using xIdentityModels.Dtos; using xIdentityModels.Extensions; using xIdentityModels.Navigations; namespace xIds.Providers { public partial class XIdentityManager { // #region User Handlers ... /// /// Check a User Exists or not /// /// specified user's identifier /// a boolean value public async Task IsUserExistsAsync( string userSelectByParam ) { // // Validate Args ... if (userSelectByParam.IsNullOrEmpty()) { return false; } // var selectType = GetUserSelectByType(userSelectByParam); // var result = false; XUser user = null; switch (selectType) { case XUserSelectBy.MobileNumber: user = await GetUsersDbSet() .Where(ur => ur.PhoneNumber == userSelectByParam) .FirstOrDefaultAsync(); break; case XUserSelectBy.Email: user = await UserManager .FindByEmailAsync(userSelectByParam); break; case XUserSelectBy.Username: user = await UserManager .FindByNameAsync(userSelectByParam); break; case XUserSelectBy.ID: default: user = await UserManager .FindByIdAsync(userSelectByParam); break; } // result = user != null; // return result; } /// /// Check a User Selector is Available for Registration or Not /// /// specified user's identifier /// a boolean value public async Task CanRegister( string userSelectByParam ) { // // Validate ARgs ... ValidationProvider.NotEmpty(userSelectByParam); // var selectByType = GetUserSelectByType(userSelectByParam); // if (selectByType == XUserSelectBy.Username && !ValidateUserName(userSelectByParam)) { return false; } // var isExists = await IsUserExistsAsync(userSelectByParam); if (isExists) { return false; } // return true; } /// /// Get a User object /// /// specified user's identifier /// specifies returned object contains all Navigation Properties or not, default is false /// an instance of XUser public async Task GetUserAsync( string userSelectByParam, bool containDetails = false ) { // var isExists = await IsUserExistsAsync(userSelectByParam); if (!isExists) { XException.NotFound.Throw(); } // // Fill User ... var selectType = GetUserSelectByType(userSelectByParam); XUser user = null; var usersStore = GetUsersDbSet(containDetails); // // Select Type ... switch (selectType) { case XUserSelectBy.MobileNumber: user = await usersStore .FirstOrDefaultAsync(ur => ur.PhoneNumber == userSelectByParam); break; case XUserSelectBy.Email: user = await usersStore .FirstOrDefaultAsync(ur => ur.Email == userSelectByParam); break; case XUserSelectBy.Username: user = await usersStore .FirstOrDefaultAsync(ur => ur.UserName == userSelectByParam); break; case XUserSelectBy.ID: default: user = await usersStore .FirstOrDefaultAsync(ur => ur.Id == userSelectByParam); break; } // return user; } /// /// Retrieve User Names based on UserIds /// /// a collection of user identifiers /// a collection of Usernames public async Task> GetUserNamesAsync( IEnumerable userIds ) { // // Validate Args ... if (userIds == null || userIds.Count() == 0) { return null; } // var result = await GetUsersDbSet() .Where( xu => userIds .Contains(xu.Id)) .Select(xt => xt.UserName) .ToListAsync(); // return result; } /// /// get user ids and retrieve corresponding user names /// /// an instance of XUserNameIdRequest which represent required UserIds collection /// a collection of XUserNameIdResponse instances public async Task> GetUserNameIdsAsync( XUserNameIdRequest model ) { // // Validate Args ... if (model.IsNull() || !model.Ids.HasChild()) { return null; } // var result = await GetUsersDbSet() .Where( xu => model.Ids.Contains(xu.Id) || model.Ids.Contains(xu.Email) || model.Ids.Contains(xu.UserName) || model.Ids.Contains(xu.PhoneNumber)) .Select(xt => new XUserNameIdResponse { Id = xt.Id, UserName = xt.UserName, }) .ToListAsync(); // return result; } /// /// Create a User /// /// an instance of XUser /// user's password /// check a user can log in in system or not, default is false /// check user is banned or not, default is false /// an instance of IdentityResult public async Task CreateUserAsync( XUser user, string password, bool checkCanLoginPolicies = false, bool checkIsBanned = false ) { // if (user == null || password.IsNullOrEmpty()) { XException.InvalidArgs.Throw(); } // // Get User Select By param var userSelectByParam = GetUserSelectByParam(user, excludes: new List { XUserSelectBy.ID }); // // Check User Created before or not ... var isExists = await IsUserExistsAsync(userSelectByParam); if (isExists) { XException.Duplicate.Throw(); } // var result = await UserManager.CreateAsync(user, password); if (result.Succeeded) { // var claims = await ToJwtClaims( user, checkCanLoginPolicies: checkCanLoginPolicies, checkIsBanned: checkIsBanned); // var addClaimsResult = await UserManager.AddClaimsAsync(user, claims); // return addClaimsResult; } // return result; } /// /// Update a User Information /// /// an instance of XUser /// check a user can log in in system or not, default is true /// check user is banned or not, default is true /// an instance of IdentityResult public async Task UpdateUserAsync( XUser user, bool checkCanLoginPolicies = true, bool checkIsBanned = true ) { // var updateResult = await this.UserManager.UpdateAsync(user); if (updateResult.Succeeded) { // var claims = await ToJwtClaims( user, checkCanLoginPolicies: checkCanLoginPolicies, checkIsBanned: checkIsBanned ); var existsClaims = await UserManager.GetClaimsAsync(user); // await UserManager.RemoveClaimsAsync(user, existsClaims); var addClaimsResult = await UserManager.AddClaimsAsync(user, claims); // return addClaimsResult; } // return updateResult; } /// /// Generate JWT Claims froma DashboardUser object /// /// an instance of XUser /// check a user can log in in system or not, default is true /// check user is banned or not, default is true /// a collection of Claim instances public async Task ToJwtClaims( XUser user, bool checkCanLoginPolicies = true, bool checkIsBanned = true ) { // // Get New Instance of Claims ... var claims = new List { // // Mapping to User.Identity.Name ... new Claim (JwtClaimTypes.Name, user.UserName), // // Mapping to User.Identity.Name ... new Claim (JwtRegisteredClaimNames.UniqueName, user.UserName), // // Other Usefull User Related Data ... new Claim (JwtClaimTypes.GivenName, user.FirstName), new Claim (JwtClaimTypes.FamilyName, user.LastName), // // User Gendre ... new Claim (JwtClaimTypes.Gender, user.Gender.ToString (), ClaimValueTypes.Integer), // // User Profile Picture ... new Claim (JwtClaimTypes.Picture, !user.Avatar.IsNullOrEmpty () ? user.Avatar.ToString () : ""), // // The Unique Identifier for Each Token ... new Claim (JwtRegisteredClaimNames.Jti, Guid.NewGuid ().ToString ()), // // Add isEnable and isBanned feature ... new Claim ( XCustomClaims.IsEnabled, user.IsEnable.ToString (), ClaimValueTypes.Boolean ), new Claim ( XCustomClaims.IsBanned, user.IsBanned.ToString (), ClaimValueTypes.Boolean ), }; // #region Set Claims based on Profile Policies ... // if (Configuration.Policy.Profile.ContainsDateOfBirth) { claims.Add(new Claim(JwtRegisteredClaimNames.Birthdate, user.DateOfBirth.ToString())); } // if (Configuration.Policy.Profile.ContainsEmail) { claims.Add(new Claim(JwtClaimTypes.Email, user.Email)); claims.Add(new Claim( JwtClaimTypes.EmailVerified, user.EmailConfirmed.ToString(), ClaimValueTypes.Boolean)); } // if (Configuration.Policy.Profile.ContainsPhoneNumber) { claims.Add(new Claim(JwtClaimTypes.PhoneNumber, user.PhoneNumber)); claims.Add(new Claim( JwtClaimTypes.PhoneNumberVerified, user.PhoneNumberConfirmed.ToString(), ClaimValueTypes.Boolean)); } // if (Configuration.Policy.Profile.ContainsRoles) { var roleNames = await GetRoleNamesAsync( user.UserName, checkCanLoginPolicies: checkCanLoginPolicies, checkIsBanned: checkIsBanned); roleNames.ToList() .ForEach(rn => { claims.Add(new Claim(JwtClaimTypes.Role, rn)); }); } // if (Configuration.Policy.Profile.ContainsLastLogin) { claims.Add(new Claim( JwtClaimTypes.AuthenticationTime, user.LastLogin.ToString(), ClaimValueTypes.DateTime)); } #endregion // // Return Result ... return claims.ToArray(); } /// /// Check User and Password relation /// /// an instance of XUser /// user's password /// an instance of XDevice /// specify destination language /// specify account lockout on failure log in /// specify log in force without checking XDevice and lang relation /// an instance of SignInResult public async Task CheckPasswordSignInAsync( XUser user, string password, XDevice device, string language, bool lockoutOnFailure, bool isForced = true ) { // var result = await SignInManager.CheckPasswordSignInAsync( user, password, lockoutOnFailure ); // if (result.Succeeded && isForced) { // var isExistsDevice = user.Devices.Any(d => d.IsSameAs(device)); if (!isExistsDevice && !user.Email.IsNullOrEmpty() && user.EmailConfirmed) { // user.Devices.Add(device); // var updateUserResult = await UpdateUserAsync(user); if (updateUserResult.Succeeded) { // try { // var xMessage = GetUserNewDeviceLoggedInMessage( language, user.Email, device ); // await MessageProvider.SendMailAsync(xMessage); } catch { } } } } // return result; } #endregion } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+Validators.cs using System; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; using xCommons.Extensions; using xExceptions.Constants; using xIdentityModels; using xIdentityModels.Constants; using xIdentityModels.Extensions; using xIdentityModels.Models; using xIdentityModels.Navigations; namespace xIds.Providers { public partial class XIdentityManager { // #region User Validators ... /// /// Validate User Name for Registration based on Policies /// /// provided user name /// a boolean value private bool ValidateUserName( string userName ) { // // Check min/max Length ... if (userName.IsNullOrEmpty() || userName.Length < Configuration.Policy.User.MinLength || userName.Length > Configuration.Policy.User.MaxLength) { return false; } // // Check Allowed UserName Characters ... if (!UserManager.Options.User.AllowedUserNameCharacters.IsNullOrEmpty() && userName.Any(c => !UserManager.Options.User.AllowedUserNameCharacters.Contains(c))) { return false; } // // Check invalid UserNames ... if (Configuration.Policy.User.InvalidUserNames .HasChild() && Configuration.Policy.User.InvalidUserNames .Any(u => userName .ToNormalString() .Contains(u.ToNormalString()))) { return false; } // return true; } /// /// Validate a User Exists /// /// specifies user identifier /// specify Excetion to thrown on failure /// private async Task ValidateUserExistsAsync( string userSelectByParam, Exception exception = null ) { // ValidationProvider .NotEmpty(userSelectByParam); // if (exception == null) { exception = XException.NotFound.ToException(); } // // Check User Exists ... var isExists = await IsUserExistsAsync(userSelectByParam); if (!isExists) { throw exception; } } /// /// Validate a User Not Exists /// /// specifies user identifier /// specify Excetion to thrown on failure /// private async Task ValidateUserNotExists( string userSelectByParam, Exception exception = null ) { // ValidationProvider .NotEmpty(userSelectByParam); // if (exception == null) { exception = XException.UserRegisteredBefore.ToException(); } // // Check User Exists ... var isExists = await IsUserExistsAsync(userSelectByParam); if (isExists) { throw exception; } } /// /// Validate User Exists and Some Usefull Checks /// /// specifies user identifier /// specifies returned object contains all Navigation Properties or not, default is false /// check a user can log in in system or not, default is false /// check user is banned or not, default is true /// specify do not thrown Exception if user is Disabled, default is false /// specify requested person is Admin role, default is false /// specify Excetion to thrown on failure /// an instance of XUser public async Task ValidateUserExistsAndRetrieve( string userSelectByParam, bool containDetails = false, bool checkCanLoginPolicies = false, bool checkIsBanned = true, bool ignoreDisabledUser = false, bool forceAdmin = false, Exception exception = null ) { // ValidationProvider .NotEmpty(userSelectByParam); ValidationProvider.NotNull( Configuration, Configuration.Policy, Configuration.Policy.SignIn); // // Prepare Default Exception ... if (exception == null) { exception = XException.InvalidData.ToException(); } // // Check User Exists ... await ValidateUserExistsAsync(userSelectByParam); // // Retrieve User ... var result = await GetUserAsync(userSelectByParam, containDetails); if (result == null) { throw exception; } // // Check Force Admin ... if (forceAdmin) { // var isAdmin = await IsAdmin(result); if (!isAdmin) { XException.NotAuthorized.Throw(); } } // // Check User not Bann ... if (checkIsBanned && result.IsBanned) { XException.UserBanned.Throw(); } // var requireConfirmedEmail = Configuration.Policy.SignIn.RequireConfirmedEmail; var requireConfirmedPhoneNumber = Configuration.Policy.SignIn.RequireConfirmedPhoneNumber; var requireEnabled = Configuration.Policy.SignIn.RequiredEnabled; // var isEnabled = result.IsEnable; var isMobileConfirmed = result.PhoneNumberConfirmed; var isEmailConfirmed = result.EmailConfirmed; // if (checkCanLoginPolicies) { // // Check IsEnabled ... if (!ignoreDisabledUser && requireEnabled && !isEnabled) { XException.UserDisabled.Throw(); } // // Check Email Confirmed ... if (requireConfirmedEmail && !isEmailConfirmed) { XException.EmailNotConfirmed.Throw(); } // // Check Mobile Confirmed ... if (requireConfirmedPhoneNumber && !isMobileConfirmed) { XException.MobileNotConfirmed.Throw(); } } // // Return Result ... return result; } /// /// Validate a Device for User Actions /// /// an instance of XDevice /// private async Task ValidateDeviceForActions( XDevice device ) { // ValidationProvider .NotNull(device); // // Check is Device Banned or not ... var isDeviceBanned = await IsDeviceBanned(device); if (isDeviceBanned) { // // Retrieve Banned Device ... var xBannedDevice = await GetBannedDevice(device); if (xBannedDevice == null) { XException.InvalidArgs.Throw(); } // // Check Banned Device Time out Passed or not ... var isDelayTimePassed = IsDelayTimePassed(xBannedDevice); if (!isDelayTimePassed) { // var passedTime = GetPassedTime(xBannedDevice); // XException.DeviceBanned .AddContentToException(passedTime.ToString()); } // // if Delay Passed of Banned Device // the device must Removed ... await BannedDeviceRemove(xBannedDevice); } } /// /// Validate a DateOfBirth for Registration /// /// users dob date, an instance of DateTime /// specify Excetion to thrown on failure /// private void ValidateDateOfBirth( DateTime dateOfBirth, Exception exception = null ) { // // Validate Args ... ValidationProvider.NotNull(dateOfBirth); // if (exception.IsNull()) { exception = XException.InvalidDate.ToException(); } // var currentDate = DateTime.UtcNow; if (dateOfBirth >= currentDate) { throw exception; } // var zeroDate = (new DateTime(1, 1, 1)).ToUniversalTime(); var minAge = Configuration.Policy.User.MinAgeForRegistration; var maxAge = Configuration.Policy.User.MaxAgeForRegistration; // var timeSpan = currentDate - dateOfBirth; var age = (zeroDate + timeSpan).Year - 1; // if (age > maxAge || age < minAge) { throw exception; } } /// /// Validate a Given User Can Registere /// /// specifies user identifier /// private async Task ValidateCanRegister( string userSelectByParam ) { // // Validate Args ... ValidationProvider.NotEmpty(userSelectByParam); // var canRegister = await CanRegister(userSelectByParam); if (!canRegister) { XException.Unavailable.Throw(); } } /// /// Validate Password by Gicen Policies /// /// an instance of XUser /// user's password /// specify Excetion to thrown on failure /// private async Task ValidatePasswordPolicies( XUser user, string password, Exception exception = null ) { // // Validate Args ... ValidationProvider.NotNull(user); ValidationProvider.NotEmpty(password); // // Prepare Default Exception ... if (exception == null) { exception = XException.InvalidPassword.ToException(); } // // Check new Password Validation ... var passwordValidator = new PasswordValidator(); var checkPasswordResult = await passwordValidator.ValidateAsync(UserManager, user, password); if (!checkPasswordResult.Succeeded) { throw exception; } } /// /// Validate a User for Dangerous Actions /// /// an instance of XUser /// specified which user request Action by an instance of XUser /// private async Task ValidateUserForDangerousAction( XUser user, XUser requester ) { // // Validate ARgs ... ValidationProvider.NotNull(user, requester); // var requesterRoleNames = await GetRoleNamesAsync(requester.Id); // var isSame = user.Id == requester.Id; var isRequesterAdmin = requesterRoleNames.Any(r => r.ToNormalString() == "admin"); if (!isSame && !isRequesterAdmin) { XException.NotAllowed.Throw(); } } #endregion // #region Device Validators ... /// /// Validate a Device for Specified User /// /// specifies user identifier /// an instance of XDevice /// specify Excetion to thrown on failure /// private async Task ValidateUserAndDeviceRelation( string userSelectByParam, XDevice device, Exception exception = null ) { // ValidationProvider.NotEmpty(userSelectByParam); ValidationProvider.NotNull(device); // if (exception == null) { exception = XException.InvalidDevice.ToException(); } // var user = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: true); // var result = await IsDeviceRelateDToUser( userSelectByParam, device ); if (!result) { throw exception; } } #endregion // #region Token Validators ... /// /// Validate a Token /// /// token string /// specify Excetion to thrown on failure private void ValidateToken( string token, Exception exception = null ) { // ValidationProvider.NotEmpty(token); // if (exception == null) { exception = XException.InvalidToken.ToException(); } // var result = IdentityHelper.ValidateToken(token); if (!result) { throw exception; } } /// /// Validate a Token is Specified to a Device and User /// /// an instance of XDevice /// specifies Action type by a member of XAction /// specify Excetion to thrown on failure /// an instance of XToken private async Task ValidateAndRetieveTokenByDeviceAndType( XDevice device, XAction type, Exception exception = null ) { // ValidationProvider.NotNull(device); // // Prepare Default Exception ... if (exception == null) { exception = XException.NotFound.ToException(); } // var isExists = await IsTokenExistsByDeviceAndType(device, type); if (!isExists) { throw exception; } // var item = await GetTokenByDeviceAndType(device, type); if (item == null) { throw exception; } // return item; } /// /// Validate a Token By User and Specified Type /// /// specifies user identifier /// specifies Action type by a member of XAction /// specify Excetion to thrown on failure /// an instance of XToken private async Task ValidateAndRetieveTokenByUserAndType( string userSelectByParam, XAction type, Exception exception = null ) { // ValidationProvider.NotEmpty(userSelectByParam); // // Prepare Default Exception ... if (exception == null) { exception = XException.InvalidData.ToException(); } // var isExists = await IsTokenExistsByUserAndType(userSelectByParam, type); if (!isExists) { throw exception; } // var item = await GetTokenByUserAndType(userSelectByParam, type); if (item == null) { throw exception; } // return item; } /// /// Check Token Validation /// /// token string /// a boolean value private bool IsValidToken( string token ) { // ValidationProvider.NotEmpty(token); // var result = IdentityHelper.ValidateToken(token); // return result; } /// /// Retrieve Action Request Based on Action Token /// /// token string /// specify Excetion to thrown on failure /// an instance of XActionRequestToken private XActionRequestToken ValidateAndParseActionToken( string token, Exception exception = null ) { // ValidationProvider.NotEmpty(token); // // Prepare Default Exception ... if (exception == null) { exception = XException.InvalidToken.ToException(); } // ValidateToken(token); // var result = IdentityHelper.ParseActionRequestToken(token); if (result == null) { throw exception; } // ValidateActionRequest(result); // return result; } /// /// Parse Action Request from Token /// /// token string /// an instance of XActionRequestToken private XActionRequestToken ParseActionRequest( string token ) { // // Validate Args ... ValidationProvider.NotEmpty(token); // var result = IdentityHelper .ParseActionRequestToken(token); // return result; } /// /// Parse Action Hash by Corresponding Token /// /// token hash string /// an instance of XActionRequestToken private async Task ParseActionHash( string hash ) { // ValidationProvider.NotEmpty(hash); // var isHashExists = await IsTokenExistsByHash(hash); if (!isHashExists) { return null; } // var xToken = await GetTokenByHash(hash); if (xToken == null) { return null; } // var isValidToken = IsValidToken(xToken.Token); if (!isValidToken) { return null; } // var result = ParseActionRequest(xToken.Token); // return result; } /// /// Validate and Parse Action Hash /// /// token hash string /// specifies chack token Validation Parameter, default is true /// specifies check action Validations, default is true /// specify Excetion to thrown on failure /// an instance of XActionRequestToken private async Task ValidateAndParseActionHash( string hash, bool forceTokenValidation = true, bool forceActionValidation = true, Exception exception = null ) { // ValidationProvider.NotEmpty(hash); // // Prepare Default Exception ... if (exception == null) { exception = XException.InvalidToken.ToException(); } // var token = await ValidateAndRetrieveRelatedToken(hash, forceTokenValidation); // var result = await ParseActionHash(hash); if (result == null) { throw exception; } // if (forceActionValidation) { ValidateActionRequest(result); } // return result; } /// /// Validate Action Request /// /// an instance of XActionRequestToken /// specify Excetion to thrown on failure private void ValidateActionRequest( XActionRequestToken request, Exception exception = null ) { // ValidationProvider .NotNull(request); // // Prepare Default Exception ... if (exception == null) { exception = XException.InvalidData.ToException(); } // var isValid = IsValidActionRequest(request); if (!isValid) { throw exception; } } /// /// Check Action Request Validation /// /// an instance of XActionRequestToken /// a boolean value private bool IsValidActionRequest( XActionRequestToken request ) { // // Validate Args ... if (request == null || Configuration.IdentitySecretKey.IsNullOrEmpty()) { XException.InvalidArgs.Throw(); } // var result = request.Validate(Configuration.IdentitySecretKey); // return result; } /// /// Check Token and Act Based on it /// /// token string /// specify Excetion to thrown on Issue failure /// specify Excetion to thrown on failure /// private async Task ValidateAndHandleToken( string token, bool issueExcepion = false, Exception exception = null ) { // // Validate Args ... ValidationProvider.NotEmpty(token); // // Prepare Default Exception ... if (exception == null) { exception = XException.InvalidToken.ToException(); } // var isValidToken = IsValidToken(token); // if (!isValidToken) { // await RemoveTokenByToken(token); // if (issueExcepion) { throw exception; } } } /// /// Validate a Hash Exists or not /// /// token hash string /// specify Excetion to thrown on failure /// private async Task ValidateHashExists( string hash, Exception exception = null ) { // // Validate Args ... ValidationProvider.NotEmpty(hash); // // Prepare Default Exception ... if (exception == null) { exception = XException.InvalidToken.ToException(); } // var isExists = await IsTokenExistsByHash(hash); if (!isExists) { throw exception; } } /// /// Validate a Token Exists /// /// token string /// specify Excetion to thrown on failure /// private async Task ValidateTokenExists( string token, Exception exception = null ) { // // Validate Args ... ValidationProvider.NotEmpty(token); // // Prepare Default Exception ... if (exception == null) { exception = XException.InvalidToken.ToException(); } // var isExists = await IsTokenExistsByToken(token); if (!isExists) { throw exception; } } /// /// Validate a Hash and Retrieve it's Corresponding Token /// /// token hash string /// specifies chack token Validation Parameter, default is true /// specify Excetion to thrown on Issue failure /// specify Excetion to thrown on failure /// token string private async Task ValidateAndRetrieveRelatedToken( string hash, bool forceTokenValidation = true, bool issueExcepion = false, Exception exception = null ) { // // Validate Args ... ValidationProvider.NotEmpty(hash); // // Prepare Default Exception ... if (exception == null) { exception = XException.InvalidToken.ToException(); } // await ValidateHashExists(hash); // var token = await GetRelatedTokenByHash(hash); if (token.IsNullOrEmpty()) { throw exception; } // if (forceTokenValidation) { await ValidateAndHandleToken(token, issueExcepion); } // return token; } /// /// Validate a Token and Retrieve it's Corresponding Hash /// /// token string /// specifies chack token Validation Parameter, default is true /// specify Excetion to thrown on failure /// hash string private async Task ValidateAndRetrieveRelatedHash( string token, bool forceTokenValidation = true, Exception exception = null ) { // // Validate Args ... ValidationProvider.NotEmpty(token); // // Prepare Default Exception ... if (exception == null) { exception = XException.InvalidToken.ToException(); } // if (forceTokenValidation) { await ValidateAndHandleToken(token); } // await ValidateTokenExists(token); // var hash = await GetRelatedHashByToken(token); if (hash.IsNullOrEmpty()) { throw exception; } // return hash; } /// /// Validate Invitation Hash /// /// registration invitation hash string /// thrown Exception if user Exists, default is true /// private async Task ValidateInvitationHash( string invitationHash, bool forceUserExists = true ) { // // Validate Args ... ValidationProvider.NotNull(Configuration); // if (Configuration.RegistrationJustWithInvite && invitationHash.IsNullOrEmpty()) { XException.NotAllowed.Throw(); } // // Validate Invitation Token if it isn't null ... if (!invitationHash.IsNullOrEmpty()) { // await ValidateHashExists(invitationHash); // // Token Validation also done in this task ... var relatedToken = await ValidateAndRetrieveRelatedToken(invitationHash); // var inviteAction = ValidateAndParseActionToken(relatedToken); ValidationProvider.NotNull(inviteAction); // var inviteUerSelectByParam = GetUserSelectByParam(inviteAction); var inviteUserSelectBy = GetUserSelectByType(inviteUerSelectByParam); if (inviteUserSelectBy != XUserSelectBy.Email) { XException.InvalidToken.Throw(); } // if (forceUserExists) { // await ValidateUserNotExists( inviteUerSelectByParam, XException.EmailInUsed.ToException()); } } } #endregion // #region Profile Validators ... /// /// Validate a Request is Corresponding to Specific Device /// /// an instance of XDevice /// specify requested device by an instance of XDevice /// specify Excetion to thrown on failure private void ValidateRequestAndGiveDevices( XDevice device, XDevice requestDevice, Exception exception = null ) { // // Validate Args ... ValidationProvider.NotNull(device, requestDevice); // // Prepare Default Exception ... if (exception == null) { exception = XException.InvalidDevice.ToException(); } // var isDevicesSame = device.IsSameAs(requestDevice); // if (!isDevicesSame) { throw exception; } } /// /// Check Validation of a User SelectBy Param and Password /// /// specifies user identifier /// user's password /// check a user can log in in system or not, default is true /// specify Excetion to thrown on failure /// private async Task ValidateUserAndPassword( string userSelectByParam, string password, bool checkCanLoginPolicies = true, Exception exception = null ) { // // Validate Args ... ValidationProvider.NotEmpty( userSelectByParam, password ); // // Prepare Default Exception ... if (exception == null) { exception = XException.LoginFailed.ToException(); } // // Retrieve User and Validate User Exists ... var user = await ValidateUserExistsAndRetrieve( userSelectByParam, containDetails: false, checkCanLoginPolicies: checkCanLoginPolicies, ignoreDisabledUser: false, checkIsBanned: true, exception: exception); // // Check Given Password Follows Policies ... await ValidatePasswordPolicies(user, password, exception); // // Check Password for User ... var checkPasswordResult = await UserManager.CheckPasswordAsync(user, password); if (!checkPasswordResult) { throw exception; } } #endregion // #region Friendship Validators ... /// /// Validate Friendship Requested Before or not /// /// specifies a user to check as source by an instance of XUser /// specifies a user to check as dest by an instance of XUser private void ValidateRequestBefore( XUser source, XUser dest ) { // // Validate Args ... ValidationProvider.NotNull(source, dest); // var isRequested = IsFollowRequested(source, dest); if (!isRequested) { XException.NotFound.Throw(); } } /// /// Validate a Friendship Not Requested Before /// /// specifies a user to check as source by an instance of XUser /// specifies a user to check as dest by an instance of XUser private void ValidateNotRequestBefore( XUser source, XUser dest ) { // // Validate Args ... ValidationProvider.NotNull(source, dest); // var isRequested = IsFollowRequested(source, dest); if (isRequested) { XException.Duplicate.Throw(); } } /// /// Validate User Can Send Following Request to Dest User /// /// specifies a user to check as dest by an instance of XUser /// specifies a user to check as source by an instance of XUser private void ValidateFollowingRequest( XUser accepterUser, XUser requesterUser ) { // // Validate Args ... ValidationProvider.NotNull(accepterUser, requesterUser); // var isRequest = IsFollowRequested(requesterUser, accepterUser, XFriendshipState.Pending); if (!isRequest) { XException.NotFound.Throw(); } } /// /// Validate a User can Accept a Following Request or Not /// /// specifies a user to check as dest by an instance of XUser /// specifies a user to check as source by an instance of XUser private void ValidateFollowingRequestForAccept( XUser accepterUser, XUser requesterUser ) { // // Validate Args ... ValidationProvider.NotNull(accepterUser, requesterUser); // var isRequestPending = IsFollowRequested(requesterUser, accepterUser, XFriendshipState.Pending); var isRequestRejected = IsFollowRequested(requesterUser, accepterUser, XFriendshipState.Rejected); if (!isRequestPending && !isRequestRejected) { XException.NotFound.Throw(); } } /// /// Validate a Request is not Passed for Same Users /// /// specifies a user to check as source by an instance of XUser /// specifies a user to check as dest by an instance of XUser private void ValidateNotSameUsers( XUser source, XUser dest ) { // // Validate ARgs ... ValidationProvider.NotNull(source, dest); // var isSame = source.Id == dest.Id; if (isSame) { XException.ActionFailed.Throw(); } } /// /// Check a user is in Followers of another /// /// specifies a user to check as source by an instance of XUser /// specifies a user to check as dest by an instance of XUser private void ValidateIsFollowers( XUser source, XUser dest ) { // // Validate Args ... ValidationProvider.NotNull(source, dest); // ValidateNotSameUsers(source, dest); ValidateRequestBefore(dest, source); // var isFollower = IsFollowRequested(dest, source, XFriendshipState.Accepted) || IsFollowRequested(dest, source, XFriendshipState.Blocked); if (!isFollower) { XException.NotFound.Throw(); } } /// /// Check a user is in Followings of another /// /// specifies a user to check as source by an instance of XUser /// specifies a user to check as dest by an instance of XUser private void ValidateIsFollowings( XUser source, XUser dest ) { // // Validate Args ... ValidationProvider.NotNull(source, dest); // ValidateNotSameUsers(source, dest); ValidateRequestBefore(source, dest); // var isFollowing = IsFollowRequested(source, dest, XFriendshipState.Accepted); if (!isFollowing) { XException.NotFound.Throw(); } } /// /// Validate a User Blocked another /// /// specifies a user to check as source by an instance of XUser /// specifies a user to check as dest by an instance of XUser private void ValidateIsBlock( XUser source, XUser dest ) { // // Validate Args ... ValidationProvider.NotNull(source, dest); // ValidateNotSameUsers(source, dest); ValidateRequestBefore(dest, source); // var isFollower = IsFollowRequested(dest, source, XFriendshipState.Blocked); if (!isFollower) { XException.NotFound.Throw(); } } #endregion // #region XActionRequest Validators ... /// /// Validate a Device for Request /// /// an instance of XDevice /// specify requested device by an instance of XDevice /// specify Excetion to thrown on failure private void ValidateRequestAndGivenDevices( XDevice device, XDevice requestDevice, Exception exception = null ) { // // Validate Args ... ValidationProvider.NotNull(device, requestDevice); // // Prepare Default Exception ... if (exception == null) { exception = XException.InvalidDevice.ToException(); } // var isDevicesSame = device.IsSameAs(requestDevice); // if (!isDevicesSame) { throw exception; } } #endregion // #region XVerification Request ... /// /// Validate Verification Request Exists by Device /// /// an instance of XDevice /// specify Excetion to thrown on failure /// private async Task ValidateVerificationRequestExists( XDevice device, Exception exception = null ) { // ValidationProvider.NotNull(device); // if (exception == null) { exception = XException.InvalidDevice.ToException(); } // var isExists = await IsDeviceRequestedForVerificationCodeBefor(device); if (!isExists) { throw exception; } } /// /// Validate Verification Request Exists by VerificationCode /// /// Confirm Verification Code /// specify Excetion to thrown on failure /// private async Task ValidateVerificationRequestExists( string verificationCode, Exception exception = null ) { // ValidationProvider.NotEmpty(verificationCode); // if (exception == null) { exception = XException.InvalidVerificationCode.ToException(); } // var isExists = await IsVerificationCodeRequested(verificationCode); if (!isExists) { throw exception; } } /// /// Validate and Retrive Verification Request for Given Device /// /// an instance of XDevice /// specify Excetion to thrown on failure /// an instance of XVerificationRequest private async Task ValidateAndRetrieveVerificationRequest( XDevice device, Exception exception = null ) { // ValidationProvider.NotNull(device); // if (exception == null) { exception = XException.InvalidDevice.ToException(); } // await ValidateVerificationRequestExists(device); // var result = await GetVerificationRequest(device); if (result == null) { throw exception; } // return result; } /// /// Validate and Retrieve Verification Request for Given VerificationCode /// /// Confirm Verification Code /// specify Excetion to thrown on failure /// an instance of XVerificationRequest private async Task ValidateAndRetrieveVerificationRequest( string verificationCode, Exception exception = null ) { // ValidationProvider.NotEmpty(verificationCode); // if (exception == null) { exception = XException.InvalidVerificationCode.ToException(); } // await ValidateVerificationRequestExists(verificationCode); // var result = await GetVerificationRequest(verificationCode); if (result == null) { throw exception; } // return result; } /// /// Handle Prepare Verification Request /// /// Confirm Verification Code /// an instance of XActionRequestToken /// an instance of XVerificationRequest private async Task HandleVerificationRequestPreparation( string verificationCode, XActionRequestToken request ) { // ValidationProvider .NotEmpty(verificationCode); // // Check Action Request Validation ... ValidateActionRequest(request); // var device = request.Context.Device; // // Check is Device Requested Before or not ... XVerificationRequest xVerificationRequest = null; var isDeviceRequested = await IsDeviceRequestedForVerificationCodeBefor(device); if (!isDeviceRequested) { // xVerificationRequest = new XVerificationRequest { VerificationCode = verificationCode, NumberOfTries = 1, LastTryOn = DateTime.UtcNow, Device = device, Request = request }; // await AddVerificationRequest(xVerificationRequest); } else { // // Get Verification Request ... xVerificationRequest = await ValidateAndRetrieveVerificationRequest(device); } // return xVerificationRequest; } #endregion } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+VerificationCode.cs using System.Threading.Tasks; using xCommons.Extensions; using xIdentityModels.Extensions; using xIdentityModels.Models; using xIdentityModels.Navigations; namespace xIds.Providers { public partial class XIdentityManager { // #region Verification Code Actions ... /// /// Check a Device Requeste for Verification Code before or not /// /// an instance of XDevice /// a boolean value private async Task IsDeviceRequestedForVerificationCodeBefor( XDevice device ) { // var result = false; var enumerator = DbContext.VerificationRequests .AsAsyncEnumerable(); await foreach (var entity in enumerator) { // if (entity.Device.IsSameAs(device)) { // result = true; break; } } // return result; } /// /// Check a Verification Code Requested before or not /// /// Confirm Verification Code /// a boolean value private async Task IsVerificationCodeRequested( string verificationCode ) { // // Validate Args ... if (verificationCode.IsNullOrEmpty()) { return false; } // var result = false; var enumerator = DbContext.VerificationRequests .AsAsyncEnumerable(); await foreach (var entity in enumerator) { // if (entity.VerificationCode == verificationCode) { // result = true; break; } } // return result; } /// /// Retrieve Verification Request /// /// an instance of XDevice /// an instance of XVerificationRequest private async Task GetVerificationRequest( XDevice device ) { // XVerificationRequest result = null; var enumerator = DbContext.VerificationRequests .AsAsyncEnumerable(); await foreach (var entity in enumerator) { // if (entity.Device.IsSameAs(device)) { // result = entity; break; } } // return result; } /// /// Retrieve Verification Request /// /// Confirm Verification Code /// an instance of XVerificationRequest private async Task GetVerificationRequest( string verificationCode ) { // XVerificationRequest result = null; var enumerator = DbContext.VerificationRequests .AsAsyncEnumerable(); await foreach (var entity in enumerator) { // if (entity.VerificationCode == verificationCode) { // result = entity; break; } } // return result; } /// /// Remove Exists Verification Code Request /// /// an instance of XDevice /// save changes on DbContext, default is true /// private async Task RemoveVerificationCodeRequestByDevice( XDevice device, bool saveChanges = true ) { // if (!await IsDeviceRequestedForVerificationCodeBefor(device)) { return; } // var xvr = await GetVerificationRequest(device); DbContext.VerificationRequests.Remove(xvr); // if (saveChanges) { await DbContext.SaveChangesAsync(); } } /// /// Remove Exists Verification Code Request /// /// Confirm Verification Code /// save changes on DbContext, default is true /// private async Task RemoveVerificationRequest( string verificationCode, bool saveChanges = true ) { // ValidationProvider.NotEmpty(verificationCode); // var request = await GetVerificationRequest(verificationCode); DbContext.VerificationRequests.Remove(request); // if (saveChanges) { await DbContext.SaveChangesAsync(); } } /// /// Add Verification Code Request /// /// an instance of XVerificationRequest /// save changes on DbContext, default is true /// an instance of XVerificationRequest private async Task AddVerificationRequest( XVerificationRequest request, bool saveChanges = true ) { // if (await IsDeviceRequestedForVerificationCodeBefor(request.Device)) { await RemoveVerificationCodeRequestByDevice(request.Device); } // var entry = await DbContext.VerificationRequests.AddAsync(request); // if (saveChanges) { await DbContext.SaveChangesAsync(); } // return entry.Entity; } #endregion } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Stores\XPersistedGrantStore.cs using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using IdentityServer4.EntityFramework.DbContexts; using IdentityServer4.EntityFramework.Mappers; using IdentityServer4.Models; using IdentityServer4.Stores; using Microsoft.EntityFrameworkCore; namespace xIds.Stores { public class XPersistedGrantStore : IPersistedGrantStore { private readonly PersistedGrantDbContext dbContext; public XPersistedGrantStore(PersistedGrantDbContext dbContext) { this.dbContext = dbContext; } public async Task> GetAllAsync(string subjectId) { // var result = (await dbContext.PersistedGrants .Where(g => g.SubjectId == subjectId) .AsNoTracking() .Select(res => res.ToModel()) .ToListAsync()).AsEnumerable(); // return result; } public async Task GetAsync(string key) { // var result = await dbContext.PersistedGrants .FirstOrDefaultAsync(g => g.Key == key); // return result.ToModel(); } public async Task RemoveAllAsync(string subjectId, string clientId) { // var items = await dbContext.PersistedGrants .Where(g => g.SubjectId == subjectId && g.ClientId == clientId) .ToListAsync(); // dbContext.PersistedGrants.RemoveRange(items); // await dbContext.SaveChangesAsync(); } public async Task RemoveAllAsync(string subjectId, string clientId, string type) { // var items = await dbContext.PersistedGrants .Where(g => g.SubjectId == subjectId && g.ClientId == clientId && g.Type == type) .ToListAsync(); // dbContext.PersistedGrants.RemoveRange(items); // await dbContext.SaveChangesAsync(); } public async Task RemoveAsync(string key) { // var items = await dbContext.PersistedGrants .Where(g => g.Key == key) .ToListAsync(); // dbContext.PersistedGrants.RemoveRange(items); // await dbContext.SaveChangesAsync(); } public async Task IsExistsAsync(string key) { return await this.dbContext.PersistedGrants.AnyAsync(g => g.Key == key); } public async Task IsExistsAsync(PersistedGrant grant) { return await IsExistsAsync(grant.Key); } public async Task AddOrUpdateAsync(PersistedGrant grant) { // var isExists = await IsExistsAsync(grant); if (isExists) { await UpdateAsync(grant); } else { await AddAsync(grant); } } public async Task AddAsync(PersistedGrant grant) { // var item = grant.ToEntity(); await dbContext.PersistedGrants.AddAsync(item); await dbContext.SaveChangesAsync(); } public async Task UpdateAsync(PersistedGrant grant) { // var item = grant.ToEntity(); var entity = dbContext.Attach(item); entity.State = EntityState.Modified; await dbContext.SaveChangesAsync(); } public async Task StoreAsync(PersistedGrant grant) { await AddOrUpdateAsync(grant); } // // TODO: Complete this ... public Task> GetAllAsync(PersistedGrantFilter filter) { throw new System.NotImplementedException(); } // // TODO: Complete this ... public Task RemoveAllAsync(PersistedGrantFilter filter) { throw new System.NotImplementedException(); } } } ### FILE: C:\Users\hkhazaeeasl\Documents\Projets\XProjects\xSaherelmWorkspace\xIds\Validators\XResourceOwnerPasswordValidator.cs using System; using System.Threading.Tasks; using IdentityServer4.Events; using IdentityServer4.Models; using IdentityServer4.Services; using IdentityServer4.Validation; using Microsoft.Extensions.Logging; using xCommons.Extensions; using xExceptions.Constants; using xIdentityModels.Navigations; using xIds.Interfaces; using static IdentityModel.OidcConstants; namespace xIds.Validators { public class XResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator { private readonly IXIdentityManager identityManager; private readonly IEventService events; private readonly ILogger logger; public XResourceOwnerPasswordValidator( IXIdentityManager identityProvider, IEventService events, ILogger logger ) { this.identityManager = identityProvider; this.events = events; this.logger = logger; } /// /// Validates the resource owner password credential /// by providing UserName/Email or PhoneNumber /// /// The context. /// public virtual async Task ValidateAsync(ResourceOwnerPasswordValidationContext context) { // var clientId = context.Request?.Client?.ClientId; var xUser = await identityManager.GetUserAsync(context.UserName, true); // // Check Force Data ... var isForced = true; var isForcedStr = context.Request?.Raw["force"]; if (!isForcedStr.IsNullOrEmpty()) { isForced = isForcedStr.FromJSON(); } // XDevice device = null; var language = context.Request?.Raw["language"]; var deviceStr = context.Request?.Raw["device"]; if (deviceStr.IsNullOrEmpty() && isForced) { // logger.LogError($"Device not Found ..."); // await events .RaiseAsync( new UserLoginFailureEvent( xUser.UserName, XException.InvalidDevice.ToXError().Message, false, clientId )); return; } device = isForced ? deviceStr.FromJSON() : null; // XException exception; if (!xUser.IsNull()) { // var result = await identityManager .CheckPasswordSignInAsync( xUser, context.Password, device, language, true, isForced ); if (result.Succeeded) { // logger.LogInformation("Credentials validated for username: {username}", xUser.UserName); // // Update User Last Login ... xUser.LastLogin = DateTime.UtcNow; await identityManager.UpdateUserAsync(xUser); // await events.RaiseAsync( new UserLoginSuccessEvent( xUser.UserName, xUser.Id, xUser.UserName, false, clientId )); // context.Result = new GrantValidationResult(xUser.Id, AuthenticationMethods.Password); return; } else if (result.IsLockedOut) { // logger.LogInformation("Authentication failed for username: {username}, reason: locked out", xUser.UserName); // exception = XException.AccountLockedOut; await events .RaiseAsync( new UserLoginFailureEvent( xUser.UserName, exception.ToXError().Message, false, clientId )); } else if (result.IsNotAllowed) { // logger.LogInformation("Authentication failed for username: {username}, reason: not allowed", xUser.UserName); // exception = XException.NotAllowed; await events .RaiseAsync( new UserLoginFailureEvent( xUser.UserName, exception.ToXError().Message, false, clientId )); } else { // logger.LogInformation("Authentication failed for username: {username}, reason: invalid credentials", xUser.UserName); // exception = XException.LoginFailed; await events .RaiseAsync( new UserLoginFailureEvent( xUser.UserName, exception.ToXError().Message, false, clientId )); // } } else { // logger.LogInformation("No user found matching username: {username}", xUser.UserName); // exception = XException.InvalidUserName; await events .RaiseAsync( new UserLoginFailureEvent( xUser.UserName, exception.ToXError().Message, false, clientId )); } // Exception ecs = exception.ToException(); if (exception == XException.AccountLockedOut && xUser.LockoutEnd.HasValue) { // var passedTime = xUser.LockoutEnd.Value.UtcDateTime; ecs = XException.AccountLockedOut .AddContentToException(passedTime.ToString()); } // context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, ecs.Message); } } }