From b7265f3b74a87b4fd17781bf152da2353ac8517d Mon Sep 17 00:00:00 2001 From: Mahdi Jafari <126339078+mahdijafariii@users.noreply.github.com> Date: Tue, 13 Aug 2024 15:36:02 +0330 Subject: [PATCH] fix(User):fix login (#3) --- .../AnalysisData.sln.DotSettings.user | 3 + .../Controllers/UserController.cs | 22 ++++++ .../CookieService/CookieService.cs | 45 ++++++++++++ .../abstractions/ICookieService.cs | 8 +++ .../AnalysisData/JwtService/JwtService.cs | 2 +- .../JwtService/abstractions/IJwtService.cs | 6 ++ .../AnalysisData/Resources.Designer.cs | 71 +++++++++++++++++++ AnalysisData/AnalysisData/Resources.resx | 24 +++++++ .../AnalysisData/Services/IUserService.cs | 8 +++ .../AnalysisData/Services/UserService.cs | 34 +++++---- 10 files changed, 207 insertions(+), 16 deletions(-) create mode 100644 AnalysisData/AnalysisData.sln.DotSettings.user create mode 100644 AnalysisData/AnalysisData/Controllers/UserController.cs create mode 100644 AnalysisData/AnalysisData/CookieService/CookieService.cs create mode 100644 AnalysisData/AnalysisData/CookieService/abstractions/ICookieService.cs create mode 100644 AnalysisData/AnalysisData/JwtService/abstractions/IJwtService.cs create mode 100644 AnalysisData/AnalysisData/Resources.Designer.cs create mode 100644 AnalysisData/AnalysisData/Resources.resx create mode 100644 AnalysisData/AnalysisData/Services/IUserService.cs diff --git a/AnalysisData/AnalysisData.sln.DotSettings.user b/AnalysisData/AnalysisData.sln.DotSettings.user new file mode 100644 index 0000000..d864046 --- /dev/null +++ b/AnalysisData/AnalysisData.sln.DotSettings.user @@ -0,0 +1,3 @@ + + True + True \ No newline at end of file diff --git a/AnalysisData/AnalysisData/Controllers/UserController.cs b/AnalysisData/AnalysisData/Controllers/UserController.cs new file mode 100644 index 0000000..8071e3f --- /dev/null +++ b/AnalysisData/AnalysisData/Controllers/UserController.cs @@ -0,0 +1,22 @@ +using AnalysisData.Services; +using AnalysisData.UserManage.LoginModel; +using Microsoft.AspNetCore.Mvc; + +namespace AnalysisData.Controllers; +[ApiController] +[Route("api/[controller]")] +public class UserController : ControllerBase +{ + private readonly IUserService _userService; + + public UserController(IUserService userService) + { + _userService = userService; + } + [HttpPost("login")] + public IActionResult Login([FromBody] UserLoginModel userLoginModel) + { + var userRoles = _userService.Login(userLoginModel); + return Ok(new { roles = userRoles }); + } +} \ No newline at end of file diff --git a/AnalysisData/AnalysisData/CookieService/CookieService.cs b/AnalysisData/AnalysisData/CookieService/CookieService.cs new file mode 100644 index 0000000..5719a64 --- /dev/null +++ b/AnalysisData/AnalysisData/CookieService/CookieService.cs @@ -0,0 +1,45 @@ +using AnalysisData.CookieSevice.abstractions; + +namespace AnalysisData.CookieSevice; + +public class CookieService : ICookieService +{ + private readonly IHttpContextAccessor _httpContextAccessor; + + public CookieService(IHttpContextAccessor httpContextAccessor) + { + _httpContextAccessor = httpContextAccessor; + } + + public void SetCookie(string name, string token,bool rememberMe) + { + var options = new CookieOptions + { + HttpOnly = true, + Secure = true, + SameSite = SameSiteMode.Strict + }; + + if (rememberMe) + { + options.Expires = DateTimeOffset.UtcNow.AddDays(7); + } + else + { + options.IsEssential = true; + } + + _httpContextAccessor.HttpContext.Response.Cookies.Append(name, token, options); + } + + public string GetCookie(string name) + { + _httpContextAccessor.HttpContext.Request.Cookies.TryGetValue(name, out var value); + return value; + } + + public void RemoveCookie(string name) + { + _httpContextAccessor.HttpContext.Response.Cookies.Delete(name); + } +} \ No newline at end of file diff --git a/AnalysisData/AnalysisData/CookieService/abstractions/ICookieService.cs b/AnalysisData/AnalysisData/CookieService/abstractions/ICookieService.cs new file mode 100644 index 0000000..701f4e6 --- /dev/null +++ b/AnalysisData/AnalysisData/CookieService/abstractions/ICookieService.cs @@ -0,0 +1,8 @@ +namespace AnalysisData.CookieSevice.abstractions; + +public interface ICookieService +{ + void RemoveCookie(string name); + string GetCookie(string name); + void SetCookie(string name, string token,bool rememberMe); +} \ No newline at end of file diff --git a/AnalysisData/AnalysisData/JwtService/JwtService.cs b/AnalysisData/AnalysisData/JwtService/JwtService.cs index 93ec7ca..160df06 100644 --- a/AnalysisData/AnalysisData/JwtService/JwtService.cs +++ b/AnalysisData/AnalysisData/JwtService/JwtService.cs @@ -7,7 +7,7 @@ namespace Authentication; -public class JwtService +public class JwtService : IJwtService { private readonly IConfiguration _configuration; private readonly IUserRepository _userRepository; diff --git a/AnalysisData/AnalysisData/JwtService/abstractions/IJwtService.cs b/AnalysisData/AnalysisData/JwtService/abstractions/IJwtService.cs new file mode 100644 index 0000000..c18da56 --- /dev/null +++ b/AnalysisData/AnalysisData/JwtService/abstractions/IJwtService.cs @@ -0,0 +1,6 @@ +namespace AnalysisData.JwtService; + +public interface IJwtService +{ + Task GenerateJwtToken(string userName); +} \ No newline at end of file diff --git a/AnalysisData/AnalysisData/Resources.Designer.cs b/AnalysisData/AnalysisData/Resources.Designer.cs new file mode 100644 index 0000000..959f03e --- /dev/null +++ b/AnalysisData/AnalysisData/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace AnalysisData { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AnalysisData.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to user not found ! . + /// + internal static string NotFoundUserException { + get { + return ResourceManager.GetString("NotFoundUserException", resourceCulture); + } + } + } +} diff --git a/AnalysisData/AnalysisData/Resources.resx b/AnalysisData/AnalysisData/Resources.resx new file mode 100644 index 0000000..ec6f011 --- /dev/null +++ b/AnalysisData/AnalysisData/Resources.resx @@ -0,0 +1,24 @@ + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + user not found ! + + \ No newline at end of file diff --git a/AnalysisData/AnalysisData/Services/IUserService.cs b/AnalysisData/AnalysisData/Services/IUserService.cs new file mode 100644 index 0000000..04cf146 --- /dev/null +++ b/AnalysisData/AnalysisData/Services/IUserService.cs @@ -0,0 +1,8 @@ +using AnalysisData.UserManage.LoginModel; + +namespace AnalysisData.Services; + +public interface IUserService +{ + Task> Login(UserLoginModel userLoginModel); +} \ No newline at end of file diff --git a/AnalysisData/AnalysisData/Services/UserService.cs b/AnalysisData/AnalysisData/Services/UserService.cs index e0eab5f..32282f5 100644 --- a/AnalysisData/AnalysisData/Services/UserService.cs +++ b/AnalysisData/AnalysisData/Services/UserService.cs @@ -1,4 +1,7 @@ +using AnalysisData.CookieSevice.abstractions; using AnalysisData.Data; +using AnalysisData.JwtService; +using AnalysisData.Repository.RoleRepository.Abstraction; using AnalysisData.Repository.UserRepository.Abstraction; using AnalysisData.UserManage.LoginModel; using Microsoft.AspNetCore.Http.HttpResults; @@ -6,35 +9,36 @@ namespace AnalysisData.Services; -public class UserService : ControllerBase +public class UserService : IUserService { private readonly IUserRepository _userRepository; + private readonly ICookieService _cookieService; + private readonly IJwtService _jwtService; - public UserService(IUserRepository userRepository) + public UserService(IUserRepository userRepository, ICookieService cookieService,IJwtService jwtService) { _userRepository = userRepository; + _cookieService = cookieService; + _jwtService = jwtService; } - public async Task Login([FromBody] UserLoginModel userLoginModel) + public async Task> Login(UserLoginModel userLoginModel) { - var user = await _userRepository.GetUser(userLoginModel.userName); - if (user is null) + if (userLoginModel.userName.Length > 255) { - return NotFound($"Unable to load user with username '{userLoginModel.userName}'"); + return null; } - - if (user.Password != userLoginModel.password) + var user = await _userRepository.GetUser(userLoginModel.userName); + if (user == null || user.Password != userLoginModel.password) { - return Unauthorized("Invalid username or password."); + return null; } + var token = await _jwtService.GenerateJwtToken(userLoginModel.userName); - return Ok(new - { - Massage = "welcome", - Token = "سشی" - }); - + _cookieService.SetCookie("AuthToken", token, userLoginModel.rememberMe); + var roles = user.UserRoles.Select(ur => ur.Role.RoleName).ToList(); + return roles; } } \ No newline at end of file