From ec1b969a9af03d0da8983d2f5fe163ad93b149aa Mon Sep 17 00:00:00 2001 From: VahidN Date: Sun, 15 Sep 2024 20:14:23 +0330 Subject: [PATCH] Move scripts for wwwroot folder --- .config/dotnet-tools.json | 2 +- .template.config/template.json | 8 +- Directory.Packages.props | 51 +++++---- README.md | 2 +- global.json | 2 +- .../ASPNETCoreIdentitySample.Common.csproj | 1 - .../GuardToolkit/ImagesGuardExt.cs | 63 ----------- .../WebOptimizerRegistry.cs | 10 +- .../Identity/ApplicationUserManager.cs | 105 +++++++++--------- .../ConfirmEmailDataProtectorTokenProvider.cs | 9 +- .../Controllers/UserProfileController.cs | 101 ++++++++++------- src/ASPNETCoreIdentitySample/Program.cs | 56 +++++----- .../{Content => wwwroot/content}/custom.css | 0 .../{Scripts => wwwroot/scripts}/custom.js | 0 .../jquery.bootstrap-modal-ajax-form.js | 0 .../scripts}/jquery.bootstrap-modal-alert.js | 0 .../jquery.bootstrap-modal-confirm.js | 0 tag-it.bat | 2 +- update-dependencies.bat | 3 +- 19 files changed, 179 insertions(+), 236 deletions(-) delete mode 100644 src/ASPNETCoreIdentitySample.Common/GuardToolkit/ImagesGuardExt.cs rename src/ASPNETCoreIdentitySample/{Content => wwwroot/content}/custom.css (100%) rename src/ASPNETCoreIdentitySample/{Scripts => wwwroot/scripts}/custom.js (100%) rename src/ASPNETCoreIdentitySample/{Scripts => wwwroot/scripts}/jquery.bootstrap-modal-ajax-form.js (100%) rename src/ASPNETCoreIdentitySample/{Scripts => wwwroot/scripts}/jquery.bootstrap-modal-alert.js (100%) rename src/ASPNETCoreIdentitySample/{Scripts => wwwroot/scripts}/jquery.bootstrap-modal-confirm.js (100%) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 029fe3f..290cc36 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "dotnet-ef": { - "version": "8.0.2", + "version": "8.0.8", "commands": [ "dotnet-ef" ] diff --git a/.template.config/template.json b/.template.config/template.json index 0d6f557..9ee5dee 100644 --- a/.template.config/template.json +++ b/.template.config/template.json @@ -17,12 +17,12 @@ "datatype": "choice", "choices": [ { - "choice": "net7.0", - "description": "Target .NET 7" + "choice": "net8.0", + "description": "Target .NET 8" } ], - "defaultValue": "net7.0", - "replaces": "net7.0" + "defaultValue": "net8.0", + "replaces": "net8.0" } } } diff --git a/Directory.Packages.props b/Directory.Packages.props index 0b4dbb1..5ccf53d 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -1,41 +1,40 @@ - - + + - + - - - - + + + + - - - - - - - - - + + + + + + + + - + - - - + + + - - - - - - + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index 4224606..b6c0a72 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ 
-# سفارشی سازی ASP.NET Core Identity SDK-8.0.200 +# سفارشی سازی ASP.NET Core Identity SDK-8.0.400

diff --git a/global.json b/global.json index 7bd16fd..f6ee1ca 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.200", + "version": "8.0.400", "rollForward": "latestMajor", "allowPrerelease": false } diff --git a/src/ASPNETCoreIdentitySample.Common/ASPNETCoreIdentitySample.Common.csproj b/src/ASPNETCoreIdentitySample.Common/ASPNETCoreIdentitySample.Common.csproj index 6f9bc8f..3817496 100644 --- a/src/ASPNETCoreIdentitySample.Common/ASPNETCoreIdentitySample.Common.csproj +++ b/src/ASPNETCoreIdentitySample.Common/ASPNETCoreIdentitySample.Common.csproj @@ -4,7 +4,6 @@ - diff --git a/src/ASPNETCoreIdentitySample.Common/GuardToolkit/ImagesGuardExt.cs b/src/ASPNETCoreIdentitySample.Common/GuardToolkit/ImagesGuardExt.cs deleted file mode 100644 index 82facd9..0000000 --- a/src/ASPNETCoreIdentitySample.Common/GuardToolkit/ImagesGuardExt.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System.Drawing; -using System.Runtime.Versioning; -using Microsoft.AspNetCore.Http; - -namespace ASPNETCoreIdentitySample.Common.GuardToolkit; - -public static class ImagesGuardExt -{ - [SupportedOSPlatform("windows")] - public static bool IsImageFile(this byte[] photoFile) - { - if (photoFile == null || photoFile.Length == 0) - { - return false; - } - - using (var memoryStream = new MemoryStream(photoFile)) - { - using (var img = Image.FromStream(memoryStream)) - { - return img.Width > 0; - } - } - } - - [SupportedOSPlatform("windows")] - public static bool IsImageFile(this IFormFile photoFile) - { - if (photoFile == null || photoFile.Length == 0) - { - return false; - } - - using (var img = Image.FromStream(photoFile.OpenReadStream())) - { - return img.Width > 0; - } - } - - [SupportedOSPlatform("windows")] - public static bool IsValidImageFile(this IFormFile photoFile, int maxWidth = 150, int maxHeight = 150) - { - if (photoFile == null || photoFile.Length == 0) - { - return false; - } - - using (var img = Image.FromStream(photoFile.OpenReadStream())) - { - if (img.Width > maxWidth) - { - return false; - } - - if (img.Height > maxHeight) - { - return false; - } - } - - return true; - } -} \ No newline at end of file diff --git a/src/ASPNETCoreIdentitySample.IocConfig/WebOptimizerRegistry.cs b/src/ASPNETCoreIdentitySample.IocConfig/WebOptimizerRegistry.cs index 830e58b..6990972 100644 --- a/src/ASPNETCoreIdentitySample.IocConfig/WebOptimizerRegistry.cs +++ b/src/ASPNETCoreIdentitySample.IocConfig/WebOptimizerRegistry.cs @@ -14,7 +14,7 @@ public static void AddWebOptimizerServices(this IServiceCollection services) "wwwroot/lib/bootstrap4-rtl/bootstrap-rtl.css", "wwwroot/lib/components-font-awesome/css/solid.min.css", "wwwroot/lib/components-font-awesome/css/fontawesome.min.css", - "Content/custom.css" + "wwwroot/content/custom.css" ) .UseContentRoot() .AdjustRelativePaths(); @@ -25,10 +25,10 @@ public static void AddWebOptimizerServices(this IServiceCollection services) "wwwroot/lib/jquery-validation-unobtrusive/dist/jquery.validate.unobtrusive.min.js", "wwwroot/lib/jquery-ajax-unobtrusive/dist/jquery.unobtrusive-ajax.min.js", "wwwroot/lib/bootstrap/dist/js/bootstrap.min.js", - "scripts/jquery.bootstrap-modal-confirm.js", - "scripts/jquery.bootstrap-modal-alert.js", - "scripts/jquery.bootstrap-modal-ajax-form.js", - "scripts/custom.js" + "wwwroot/scripts/jquery.bootstrap-modal-confirm.js", + "wwwroot/scripts/jquery.bootstrap-modal-alert.js", + "wwwroot/scripts/jquery.bootstrap-modal-ajax-form.js", + "wwwroot/scripts/custom.js" ) .UseContentRoot(); diff --git a/src/ASPNETCoreIdentitySample.Services/Identity/ApplicationUserManager.cs b/src/ASPNETCoreIdentitySample.Services/Identity/ApplicationUserManager.cs index 6d3585d..f857d83 100644 --- a/src/ASPNETCoreIdentitySample.Services/Identity/ApplicationUserManager.cs +++ b/src/ASPNETCoreIdentitySample.Services/Identity/ApplicationUserManager.cs @@ -1,5 +1,4 @@ -using System.Runtime.Versioning; -using ASPNETCoreIdentitySample.DataLayer.Context; +using ASPNETCoreIdentitySample.DataLayer.Context; using ASPNETCoreIdentitySample.Entities.Identity; using ASPNETCoreIdentitySample.Services.Contracts.Identity; using ASPNETCoreIdentitySample.ViewModels.Identity; @@ -17,9 +16,7 @@ namespace ASPNETCoreIdentitySample.Services.Identity; ///

/// More info: http://www.dntips.ir/post/2578 /// -public class ApplicationUserManager : - UserManager, - IApplicationUserManager +public class ApplicationUserManager : UserManager, IApplicationUserManager { private readonly IHttpContextAccessor _contextAccessor; private readonly IdentityErrorDescriber _errors; @@ -37,8 +34,7 @@ public class ApplicationUserManager : private readonly IEnumerable> _userValidators; private User _currentUserInScope; - public ApplicationUserManager( - IApplicationUserStore store, + public ApplicationUserManager(IApplicationUserStore store, IOptions optionsAccessor, IPasswordHasher passwordHasher, IEnumerable> userValidators, @@ -49,12 +45,9 @@ public ApplicationUserManager( ILogger logger, IHttpContextAccessor contextAccessor, IUnitOfWork uow, - IUsedPasswordsService usedPasswordsService) - : base( - (UserStore) - store, - optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, - logger) + IUsedPasswordsService usedPasswordsService) : base( + (UserStore)store, + optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger) { _userStore = store ?? throw new ArgumentNullException(nameof(store)); _optionsAccessor = optionsAccessor ?? throw new ArgumentNullException(nameof(optionsAccessor)); @@ -74,20 +67,17 @@ public ApplicationUserManager( #region BaseClass - string IApplicationUserManager.CreateTwoFactorRecoveryCode() - { - return base.CreateTwoFactorRecoveryCode(); - } + string IApplicationUserManager.CreateTwoFactorRecoveryCode() => base.CreateTwoFactorRecoveryCode(); Task IApplicationUserManager.VerifyPasswordAsync(IUserPasswordStore store, - User user, string password) - { - return base.VerifyPasswordAsync(store, user, password); - } + User user, + string password) + => base.VerifyPasswordAsync(store, user, password); public override async Task CreateAsync(User user) { var result = await base.CreateAsync(user); + if (result.Succeeded) { await _usedPasswordsService.AddToUsedPasswordsListAsync(user); @@ -99,6 +89,7 @@ public override async Task CreateAsync(User user) public override async Task CreateAsync(User user, string password) { var result = await base.CreateAsync(user, password); + if (result.Succeeded) { await _usedPasswordsService.AddToUsedPasswordsListAsync(user); @@ -107,10 +98,12 @@ public override async Task CreateAsync(User user, string passwor return result; } - public override async Task ChangePasswordAsync(User user, string currentPassword, + public override async Task ChangePasswordAsync(User user, + string currentPassword, string newPassword) { var result = await base.ChangePasswordAsync(user, currentPassword, newPassword); + if (result.Succeeded) { await _usedPasswordsService.AddToUsedPasswordsListAsync(user); @@ -122,6 +115,7 @@ public override async Task ChangePasswordAsync(User user, string public override async Task ResetPasswordAsync(User user, string token, string newPassword) { var result = await base.ResetPasswordAsync(user, token, newPassword); + if (result.Succeeded) { await _usedPasswordsService.AddToUsedPasswordsListAsync(user); @@ -134,20 +128,12 @@ public override async Task ResetPasswordAsync(User user, string #region CustomMethods - public User FindById(int userId) - { - return _users.Find(userId); - } + public User FindById(int userId) => _users.Find(userId); public Task FindByIdIncludeUserRolesAsync(int userId) - { - return _users.Include(x => x.Roles).FirstOrDefaultAsync(x => x.Id == userId); - } + => _users.Include(x => x.Roles).FirstOrDefaultAsync(x => x.Id == userId); - public Task> GetAllUsersAsync() - { - return Users.ToListAsync(); - } + public Task> GetAllUsersAsync() => Users.ToListAsync(); public User GetCurrentUser() { @@ -157,12 +143,14 @@ public User GetCurrentUser() } var currentUserId = GetCurrentUserId(); + if (string.IsNullOrWhiteSpace(currentUserId)) { return null; } var userId = int.Parse(currentUserId, NumberStyles.Number, CultureInfo.InvariantCulture); + return _currentUserInScope = FindById(userId); } @@ -176,22 +164,18 @@ public async Task GetCurrentUserAsync() return _currentUserInScope ??= await GetUserAsync(_contextAccessor.HttpContext.User); } - public string GetCurrentUserId() - { - return _contextAccessor.HttpContext?.User.Identity?.GetUserId(); - } + public string GetCurrentUserId() => _contextAccessor.HttpContext?.User.Identity?.GetUserId(); public int? GetCurrentIntUserId() { var userId = _contextAccessor.HttpContext?.User.Identity?.GetUserId(); + if (string.IsNullOrEmpty(userId)) { return null; } - return !int.TryParse(userId, NumberStyles.Number, CultureInfo.InvariantCulture, out var result) - ? null - : result; + return !int.TryParse(userId, NumberStyles.Number, CultureInfo.InvariantCulture, out var result) ? null : result; } IPasswordHasher IApplicationUserManager.PasswordHasher @@ -206,24 +190,22 @@ IPasswordHasher IApplicationUserManager.PasswordHasher IQueryable IApplicationUserManager.Users => base.Users; - public string GetCurrentUserName() - { - return _contextAccessor.HttpContext?.User.Identity?.GetUserName(); - } + public string GetCurrentUserName() => _contextAccessor.HttpContext?.User.Identity?.GetUserName(); public async Task HasPasswordAsync(int userId) { var user = await FindByIdAsync(userId.ToString(CultureInfo.InvariantCulture)); + return user?.PasswordHash != null; } public async Task HasPhoneNumberAsync(int userId) { var user = await FindByIdAsync(userId.ToString(CultureInfo.InvariantCulture)); + return user?.PhoneNumber != null; } - [SupportedOSPlatform("windows")] public async Task GetEmailImageAsync(int? userId) { if (userId == null) @@ -232,6 +214,7 @@ public async Task GetEmailImageAsync(int? userId) } var user = await FindByIdAsync(userId.Value.ToString(CultureInfo.InvariantCulture)); + if (user == null) { return "?".TextToImage(new TextToImageOptions()); @@ -314,6 +297,7 @@ public async Task GetPagedUsersListAsync(SearchUsersVie } query = query.OrderBy(x => x.Id); + return new PagedUsersListViewModel { Paging = @@ -325,9 +309,10 @@ public async Task GetPagedUsersListAsync(SearchUsersVie }; } - public async Task GetPagedUsersListAsync( - int pageNumber, int recordsPerPage, - string sortByField, SortOrder sortOrder, + public async Task GetPagedUsersListAsync(int pageNumber, + int recordsPerPage, + string sortByField, + SortOrder sortOrder, bool showAllUsers) { var skipRecords = pageNumber * recordsPerPage; @@ -344,6 +329,7 @@ public async Task GetPagedUsersListAsync( query = sortOrder == SortOrder.Descending ? query.OrderByDescending(x => x.Id) : query.OrderBy(x => x.Id); + break; } @@ -361,6 +347,7 @@ public async Task GetPagedUsersListAsync( public async Task UpdateUserAndSecurityStampAsync(int userId, Action action) { var user = await FindByIdIncludeUserRolesAsync(userId); + if (user == null) { return IdentityResult.Failed(new IdentityError @@ -373,6 +360,7 @@ public async Task UpdateUserAndSecurityStampAsync(int userId, Ac action?.Invoke(user); var result = await UpdateAsync(user); + if (!result.Succeeded) { return result; @@ -381,10 +369,12 @@ public async Task UpdateUserAndSecurityStampAsync(int userId, Ac return await UpdateSecurityStampAsync(user); } - public async Task AddOrUpdateUserRolesAsync(int userId, IList selectedRoleIds, + public async Task AddOrUpdateUserRolesAsync(int userId, + IList selectedRoleIds, Action action = null) { var user = await FindByIdIncludeUserRolesAsync(userId); + if (user == null) { return IdentityResult.Failed(new IdentityError @@ -399,15 +389,22 @@ public async Task AddOrUpdateUserRolesAsync(int userId, IList(); var newRolesToAdd = selectedRoleIds.Except(currentUserRoleIds).ToList(); + foreach (var roleId in newRolesToAdd) { - user.Roles.Add(new UserRole { RoleId = roleId, UserId = user.Id }); + user.Roles.Add(new UserRole + { + RoleId = roleId, + UserId = user.Id + }); } var removedRoles = currentUserRoleIds.Except(selectedRoleIds).ToList(); + foreach (var roleId in removedRoles) { var userRole = user.Roles.SingleOrDefault(ur => ur.RoleId == roleId); + if (userRole != null) { user.Roles.Remove(userRole); @@ -417,6 +414,7 @@ public async Task AddOrUpdateUserRolesAsync(int userId, IList AddOrUpdateUserRolesAsync(int userId, IList IApplicationUserManager.UpdatePasswordHash(User user, string newPassword, + Task IApplicationUserManager.UpdatePasswordHash(User user, + string newPassword, bool validatePassword) - { - return base.UpdatePasswordHash(user, newPassword, validatePassword); - } + => base.UpdatePasswordHash(user, newPassword, validatePassword); #endregion } \ No newline at end of file diff --git a/src/ASPNETCoreIdentitySample.Services/Identity/ConfirmEmailDataProtectorTokenProvider.cs b/src/ASPNETCoreIdentitySample.Services/Identity/ConfirmEmailDataProtectorTokenProvider.cs index 9d0492d..afaf6cc 100644 --- a/src/ASPNETCoreIdentitySample.Services/Identity/ConfirmEmailDataProtectorTokenProvider.cs +++ b/src/ASPNETCoreIdentitySample.Services/Identity/ConfirmEmailDataProtectorTokenProvider.cs @@ -8,13 +8,12 @@ namespace ASPNETCoreIdentitySample.Services.Identity; /// /// How to override the default (1 day) TokenLifeSpan for the email confirmations. /// -public class ConfirmEmailDataProtectorTokenProvider : DataProtectorTokenProvider where TUser : class +public class ConfirmEmailDataProtectorTokenProvider : DataProtectorTokenProvider + where TUser : class { - public ConfirmEmailDataProtectorTokenProvider( - IDataProtectionProvider dataProtectionProvider, + public ConfirmEmailDataProtectorTokenProvider(IDataProtectionProvider dataProtectionProvider, IOptions options, - ILogger> logger) - : base(dataProtectionProvider, options, logger) + ILogger> logger) : base(dataProtectionProvider, options, logger) { // NOTE: DataProtectionTokenProviderOptions.TokenLifespan is set to TimeSpan.FromDays(1) // which is low for the `ConfirmEmail` task. diff --git a/src/ASPNETCoreIdentitySample/Areas/Identity/Controllers/UserProfileController.cs b/src/ASPNETCoreIdentitySample/Areas/Identity/Controllers/UserProfileController.cs index 8bbb200..3e4e521 100644 --- a/src/ASPNETCoreIdentitySample/Areas/Identity/Controllers/UserProfileController.cs +++ b/src/ASPNETCoreIdentitySample/Areas/Identity/Controllers/UserProfileController.cs @@ -1,6 +1,4 @@ -using System.Runtime.Versioning; -using ASPNETCoreIdentitySample.Common.GuardToolkit; -using ASPNETCoreIdentitySample.Common.IdentityToolkit; +using ASPNETCoreIdentitySample.Common.IdentityToolkit; using ASPNETCoreIdentitySample.Entities.Identity; using ASPNETCoreIdentitySample.Services.Contracts.Identity; using ASPNETCoreIdentitySample.Services.Identity; @@ -17,7 +15,9 @@ namespace ASPNETCoreIdentitySample.Areas.Identity.Controllers; -[Authorize, Area(AreaConstants.IdentityArea), BreadCrumb(Title = "مشخصات کاربری", UseDefaultRouteUrl = true, Order = 0)] +[Authorize] +[Area(AreaConstants.IdentityArea)] +[BreadCrumb(Title = "مشخصات کاربری", UseDefaultRouteUrl = true, Order = 0)] public class UserProfileController : Controller { private readonly IEmailSender _emailSender; @@ -31,8 +31,7 @@ public class UserProfileController : Controller private readonly IUsersPhotoService _usersPhotoService; private readonly IUserValidator _userValidator; - public UserProfileController( - IApplicationUserManager userManager, + public UserProfileController(IApplicationUserManager userManager, IApplicationRoleManager roleManager, IApplicationSignInManager signInManager, IProtectionProviderService protectionProviderService, @@ -46,8 +45,10 @@ public UserProfileController( _userManager = userManager ?? throw new ArgumentNullException(nameof(userManager)); _roleManager = roleManager ?? throw new ArgumentNullException(nameof(roleManager)); _signInManager = signInManager ?? throw new ArgumentNullException(nameof(signInManager)); + _protectionProviderService = protectionProviderService ?? throw new ArgumentNullException(nameof(protectionProviderService)); + _userValidator = userValidator ?? throw new ArgumentNullException(nameof(userValidator)); _usedPasswordsService = usedPasswordsService ?? throw new ArgumentNullException(nameof(usedPasswordsService)); _usersPhotoService = usersPhotoService ?? throw new ArgumentNullException(nameof(usersPhotoService)); @@ -56,52 +57,59 @@ public UserProfileController( _logger = logger ?? throw new ArgumentNullException(nameof(logger)); } - [Authorize(Roles = ConstantRoles.Admin), BreadCrumb(Title = "ایندکس", Order = 1)] + [Authorize(Roles = ConstantRoles.Admin)] + [BreadCrumb(Title = "ایندکس", Order = 1)] public async Task AdminEdit(int? id) { if (!id.HasValue) { - return View("Error"); + return View(viewName: "Error"); } var user = await _userManager.FindByIdAsync(id.Value.ToString(CultureInfo.InvariantCulture)); - return await RenderForm(user, true); + + return await RenderForm(user, isAdminEdit: true); } [BreadCrumb(Title = "ایندکس", Order = 1)] public async Task Index() { var user = await _userManager.GetCurrentUserAsync(); - return await RenderForm(user, false); + + return await RenderForm(user, isAdminEdit: false); } - [SupportedOSPlatform("windows"), HttpPost, ValidateAntiForgeryToken] + [HttpPost] + [ValidateAntiForgeryToken] public async Task Index(UserProfileViewModel model) { if (model is null) { - return View("Error"); + return View(viewName: "Error"); } if (ModelState.IsValid) { var pid = _protectionProviderService.Decrypt(model.Pid); + if (string.IsNullOrWhiteSpace(pid)) { - return View("Error"); + return View(viewName: "Error"); } if (!string.Equals(pid, _userManager.GetCurrentUserId(), StringComparison.Ordinal) && !_roleManager.IsCurrentUserInRole(ConstantRoles.Admin)) { _logger.LogWarningMessage($"سعی در دسترسی غیرمجاز به ویرایش اطلاعات کاربر {pid}"); - return View("Error"); + + return View(viewName: "Error"); } var user = await _userManager.FindByIdAsync(pid); + if (user == null) { - return View("NotFound"); + return View(viewName: "NotFound"); } user.FirstName = model.FirstName; @@ -128,6 +136,7 @@ public async Task Index(UserProfileViewModel model) } var updateResult = await _userManager.UpdateAsync(user); + if (updateResult.Succeeded) { if (!model.IsAdminEdit) @@ -136,10 +145,8 @@ public async Task Index(UserProfileViewModel model) await _signInManager.RefreshSignInAsync(user); } - await _emailSender.SendEmailAsync( - user.Email, - "اطلاع رسانی به روز رسانی مشخصات کاربری", - "~/Areas/Identity/Views/EmailTemplates/_UserProfileUpdateNotification.cshtml", + await _emailSender.SendEmailAsync(user.Email, subject: "اطلاع رسانی به روز رسانی مشخصات کاربری", + viewNameOrPath: "~/Areas/Identity/Views/EmailTemplates/_UserProfileUpdateNotification.cshtml", new UserProfileUpdateNotificationViewModel { User = user, @@ -147,10 +154,13 @@ await _emailSender.SendEmailAsync( MessageDateTime = DateTime.UtcNow.ToLongPersianDateTimeString() }); - return RedirectToAction(nameof(Index), "UserCard", new { id = user.Id }); + return RedirectToAction(nameof(Index), controllerName: "UserCard", new + { + id = user.Id + }); } - ModelState.AddModelError("", updateResult.DumpErrors(true)); + ModelState.AddModelError(key: "", updateResult.DumpErrors(useHtmlNewLine: true)); } return View(nameof(Index), model); @@ -159,13 +169,17 @@ await _emailSender.SendEmailAsync( /// /// For [Remote] validation /// - [AjaxOnly, HttpPost, ValidateAntiForgeryToken, ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)] + [AjaxOnly] + [HttpPost] + [ValidateAntiForgeryToken] + [ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)] public async Task ValidateUsername(string username, string email, string pid) { pid = _protectionProviderService.Decrypt(pid); + if (string.IsNullOrWhiteSpace(pid)) { - return Json("اطلاعات وارد شده معتبر نیست."); + return Json(data: "اطلاعات وارد شده معتبر نیست."); } var user = await _userManager.FindByIdAsync(pid); @@ -173,18 +187,18 @@ public async Task ValidateUsername(string username, string email, user.Email = email; var result = await _userValidator.ValidateAsync((UserManager)_userManager, user); - return Json(result.Succeeded ? "true" : result.DumpErrors(true)); + + return Json(result.Succeeded ? "true" : result.DumpErrors(useHtmlNewLine: true)); } private static void UpdateUserBirthDate(UserProfileViewModel model, User user) { - if (model.DateOfBirthYear.HasValue && - model.DateOfBirthMonth.HasValue && - model.DateOfBirthDay.HasValue) + if (model.DateOfBirthYear.HasValue && model.DateOfBirthMonth.HasValue && model.DateOfBirthDay.HasValue) { var date = - $"{model.DateOfBirthYear.Value.ToString(CultureInfo.InvariantCulture)}/{model.DateOfBirthMonth.Value.ToString("00", CultureInfo.InvariantCulture)}/{model.DateOfBirthDay.Value.ToString("00", CultureInfo.InvariantCulture)}"; - user.BirthDate = date.ToGregorianDateTime(true); + $"{model.DateOfBirthYear.Value.ToString(CultureInfo.InvariantCulture)}/{model.DateOfBirthMonth.Value.ToString(format: "00", CultureInfo.InvariantCulture)}/{model.DateOfBirthDay.Value.ToString(format: "00", CultureInfo.InvariantCulture)}"; + + user.BirthDate = date.ToGregorianDateTime(convertToUtc: true); } else { @@ -222,27 +236,31 @@ private async Task RenderForm(User user, bool isAdminEdit) return View(nameof(Index), userProfile); } - [SupportedOSPlatform("windows")] private async Task UpdateUserAvatarImage(UserProfileViewModel model, User user) { _usersPhotoService.SetUserDefaultPhoto(user); var photoFile = model.Photo; + if (photoFile is not null && photoFile.Length > 0) { var imageOptions = _siteOptions.Value.UserAvatarImageOptions; + if (!photoFile.IsValidImageFile(imageOptions.MaxWidth, imageOptions.MaxHeight)) { - ModelState.AddModelError("", + ModelState.AddModelError(key: "", Invariant( $"حداکثر اندازه تصویر قابل ارسال {imageOptions.MaxHeight} در {imageOptions.MaxWidth} پیکسل است")); + model.PhotoFileName = user.PhotoFileName; + return false; } var uploadsRootFolder = _usersPhotoService.GetUsersAvatarsFolderPath(); var photoFileName = Invariant($"{user.Id}{Path.GetExtension(photoFile.FileName)}"); var filePath = Path.Combine(uploadsRootFolder, photoFileName); + using (var fileStream = new FileStream(filePath, FileMode.Create)) { await photoFile.CopyToAsync(fileStream); @@ -259,21 +277,21 @@ private async Task UpdateUserEmail(UserProfileViewModel model, User user) if (!string.Equals(user.Email, model.Email, StringComparison.Ordinal)) { user.Email = model.Email; - var userValidator = - await _userValidator.ValidateAsync((UserManager)_userManager, user); + var userValidator = await _userValidator.ValidateAsync((UserManager)_userManager, user); + if (!userValidator.Succeeded) { - ModelState.AddModelError("", userValidator.DumpErrors(true)); + ModelState.AddModelError(key: "", userValidator.DumpErrors(useHtmlNewLine: true)); + return false; } user.EmailConfirmed = false; var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); - await _emailSender.SendEmailAsync( - user.Email, - "لطفا اکانت خود را تائید کنید", - "~/Areas/Identity/Views/EmailTemplates/_RegisterEmailConfirmation.cshtml", + + await _emailSender.SendEmailAsync(user.Email, subject: "لطفا اکانت خود را تائید کنید", + viewNameOrPath: "~/Areas/Identity/Views/EmailTemplates/_RegisterEmailConfirmation.cshtml", new RegisterEmailConfirmationViewModel { User = user, @@ -291,11 +309,12 @@ private async Task UpdateUserName(UserProfileViewModel model, User user) if (!string.Equals(user.UserName, model.UserName, StringComparison.Ordinal)) { user.UserName = model.UserName; - var userValidator = - await _userValidator.ValidateAsync((UserManager)_userManager, user); + var userValidator = await _userValidator.ValidateAsync((UserManager)_userManager, user); + if (!userValidator.Succeeded) { - ModelState.AddModelError("", userValidator.DumpErrors(true)); + ModelState.AddModelError(key: "", userValidator.DumpErrors(useHtmlNewLine: true)); + return false; } } diff --git a/src/ASPNETCoreIdentitySample/Program.cs b/src/ASPNETCoreIdentitySample/Program.cs index 3c52138..dcb0b7c 100644 --- a/src/ASPNETCoreIdentitySample/Program.cs +++ b/src/ASPNETCoreIdentitySample/Program.cs @@ -11,14 +11,14 @@ ConfigureMiddlewares(webApp, webApp.Environment); ConfigureEndpoints(webApp); ConfigureDatabase(webApp); -webApp.Run(); +await webApp.RunAsync(); void ConfigureServices(IServiceCollection services, IConfiguration configuration, IWebHostEnvironment env) { services.Configure(options => configuration.Bind(options)); - services.Configure(options => - configuration.GetSection("ContentSecurityPolicyConfig") - .Bind(options)); + + services.Configure(options + => configuration.GetSection(key: "ContentSecurityPolicyConfig").Bind(options)); // Adds all of the ASP.NET Core Identity related services and configurations at once. services.AddCustomIdentityServices(configuration); @@ -26,14 +26,16 @@ void ConfigureServices(IServiceCollection services, IConfiguration configuration services.AddMvc(options => options.UseYeKeModelBinder()); services.AddDNTCommonWeb(); + services.AddDNTCaptcha(options => - { - options.UseCookieStorageProvider() - .AbsoluteExpiration(7) - .ShowExceptionsInResponse(env.IsDevelopment()) - .ShowThousandsSeparators(false) - .WithEncryptionKey("This is my secure key!"); - }); + { + options.UseCookieStorageProvider() + .AbsoluteExpiration(minutes: 7) + .ShowExceptionsInResponse(env.IsDevelopment()) + .ShowThousandsSeparators(show: false) + .WithEncryptionKey(key: "This is my secure key!"); + }); + services.AddCloudscribePagination(); services.AddWebOptimizerServices(); @@ -51,7 +53,7 @@ void ConfigureLogging(ILoggingBuilder logging, IHostEnvironment env, IConfigurat logging.AddConsole(); } - logging.AddConfiguration(configuration.GetSection("Logging")); + logging.AddConfiguration(configuration.GetSection(key: "Logging")); logging.AddDbLogger(); // You can change its Log Level using the `appsettings.json` file -> Logging -> LogLevel -> Default } @@ -65,8 +67,8 @@ void ConfigureMiddlewares(IApplicationBuilder app, IHostEnvironment env) app.UseWebOptimizer(); app.UseHttpsRedirection(); - app.UseExceptionHandler("/error/index/500"); - app.UseStatusCodePagesWithReExecute("/error/index/{0}"); + app.UseExceptionHandler(errorHandlingPath: "/error/index/500"); + app.UseStatusCodePagesWithReExecute(pathFormat: "/error/index/{0}"); app.UseContentSecurityPolicy(); @@ -80,24 +82,16 @@ void ConfigureMiddlewares(IApplicationBuilder app, IHostEnvironment env) } void ConfigureEndpoints(IApplicationBuilder app) -{ - app.UseEndpoints(endpoints => - { - endpoints.MapControllers(); + => app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); - endpoints.MapControllerRoute( - "areaRoute", - "{area:exists}/{controller=Account}/{action=Index}/{id?}"); + endpoints.MapControllerRoute(name: "areaRoute", + pattern: "{area:exists}/{controller=Account}/{action=Index}/{id?}"); - endpoints.MapControllerRoute( - "default", - "{controller=Home}/{action=Index}/{id?}"); + endpoints.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); - endpoints.MapRazorPages(); - }); -} + endpoints.MapRazorPages(); + }); -void ConfigureDatabase(IApplicationBuilder app) -{ - app.ApplicationServices.InitializeDb(); -} \ No newline at end of file +void ConfigureDatabase(IApplicationBuilder app) => app.ApplicationServices.InitializeDb(); \ No newline at end of file diff --git a/src/ASPNETCoreIdentitySample/Content/custom.css b/src/ASPNETCoreIdentitySample/wwwroot/content/custom.css similarity index 100% rename from src/ASPNETCoreIdentitySample/Content/custom.css rename to src/ASPNETCoreIdentitySample/wwwroot/content/custom.css diff --git a/src/ASPNETCoreIdentitySample/Scripts/custom.js b/src/ASPNETCoreIdentitySample/wwwroot/scripts/custom.js similarity index 100% rename from src/ASPNETCoreIdentitySample/Scripts/custom.js rename to src/ASPNETCoreIdentitySample/wwwroot/scripts/custom.js diff --git a/src/ASPNETCoreIdentitySample/Scripts/jquery.bootstrap-modal-ajax-form.js b/src/ASPNETCoreIdentitySample/wwwroot/scripts/jquery.bootstrap-modal-ajax-form.js similarity index 100% rename from src/ASPNETCoreIdentitySample/Scripts/jquery.bootstrap-modal-ajax-form.js rename to src/ASPNETCoreIdentitySample/wwwroot/scripts/jquery.bootstrap-modal-ajax-form.js diff --git a/src/ASPNETCoreIdentitySample/Scripts/jquery.bootstrap-modal-alert.js b/src/ASPNETCoreIdentitySample/wwwroot/scripts/jquery.bootstrap-modal-alert.js similarity index 100% rename from src/ASPNETCoreIdentitySample/Scripts/jquery.bootstrap-modal-alert.js rename to src/ASPNETCoreIdentitySample/wwwroot/scripts/jquery.bootstrap-modal-alert.js diff --git a/src/ASPNETCoreIdentitySample/Scripts/jquery.bootstrap-modal-confirm.js b/src/ASPNETCoreIdentitySample/wwwroot/scripts/jquery.bootstrap-modal-confirm.js similarity index 100% rename from src/ASPNETCoreIdentitySample/Scripts/jquery.bootstrap-modal-confirm.js rename to src/ASPNETCoreIdentitySample/wwwroot/scripts/jquery.bootstrap-modal-confirm.js diff --git a/tag-it.bat b/tag-it.bat index fbeb9be..0998146 100644 --- a/tag-it.bat +++ b/tag-it.bat @@ -1,3 +1,3 @@ -git tag -a 7.0.100.1401.08.19 -m "V 7.0.100.1401.08.19" +git tag -a 8.0.400.1404.06.25 -m "V 8.0.400.1404.06.25" git push --follow-tags pause \ No newline at end of file diff --git a/update-dependencies.bat b/update-dependencies.bat index 203ee26..36da7e6 100644 --- a/update-dependencies.bat +++ b/update-dependencies.bat @@ -1,5 +1,4 @@ dotnet restore -dotnet tool update --global dotnet-outdated-tool -dotnet outdated +dotnet list package --outdated dotnet restore pause \ No newline at end of file