Parcourir la source

city_country Seeding
ForgetPass_OTP

zinab_elgendy il y a 8 mois
Parent
commit
8f9a0d0fe8
34 fichiers modifiés avec 16843 ajouts et 40 suppressions
  1. 6 5
      MTWorkHR.API/Controllers/AuthController.cs
  2. 6 6
      MTWorkHR.API/Controllers/LookupController.cs
  3. 2 1
      MTWorkHR.API/Controllers/UserController.cs
  4. 8 0
      MTWorkHR.API/appsettings.json
  5. 1 0
      MTWorkHR.Application/ApplicationServiceRegistration.cs
  6. 1 0
      MTWorkHR.Application/Dtos/Identity/ForgetPasswordDto.cs
  7. 4 4
      MTWorkHR.Application/Dtos/Identity/UserAddressDto.cs
  8. 1 0
      MTWorkHR.Application/Mapper/MappingProfile.cs
  9. 1 1
      MTWorkHR.Application/Services/Base/FileService.cs
  10. 117 0
      MTWorkHR.Application/Services/Base/OTPService.cs
  11. 16 0
      MTWorkHR.Application/Services/Interfaces/IOTPService.cs
  12. 1 1
      MTWorkHR.Application/Services/Interfaces/IUserService.cs
  13. 5 4
      MTWorkHR.Application/Services/User/LookupService.cs
  14. 68 9
      MTWorkHR.Application/Services/User/UserService.cs
  15. 0 1
      MTWorkHR.Core/Email/IMailSender.cs
  16. 15 0
      MTWorkHR.Core/Entities/Base/LoginOTP.cs
  17. 28 0
      MTWorkHR.Core/Entities/User/City.cs
  18. 1 0
      MTWorkHR.Core/Entities/User/CountryLookup.cs
  19. 16 0
      MTWorkHR.Core/IRepositories/Auth/ILoginOTPRepository.cs
  20. 15 0
      MTWorkHR.Core/IRepositories/Lookups/ICityRepository.cs
  21. 2 0
      MTWorkHR.Core/IUnitOfWork/IUnitOfWork.cs
  22. 2 0
      MTWorkHR.Infrastructure/DBContext/HRDataContext.cs
  23. 4 4
      MTWorkHR.Infrastructure/Entities/UserAddress.cs
  24. 2 0
      MTWorkHR.Infrastructure/InfrastructureServiceRegistration.cs
  25. 2934 0
      MTWorkHR.Infrastructure/Migrations/20240520154627_altrForget.Designer.cs
  26. 90 0
      MTWorkHR.Infrastructure/Migrations/20240520154627_altrForget.cs
  27. 3014 0
      MTWorkHR.Infrastructure/Migrations/20240520183928_altrcity.Designer.cs
  28. 80 0
      MTWorkHR.Infrastructure/Migrations/20240520183928_altrcity.cs
  29. 3014 0
      MTWorkHR.Infrastructure/Migrations/20240520214358_CountryCityConfiguration.Designer.cs
  30. 7246 0
      MTWorkHR.Infrastructure/Migrations/20240520214358_CountryCityConfiguration.cs
  31. 81 4
      MTWorkHR.Infrastructure/Migrations/HRDataContextModelSnapshot.cs
  32. 37 0
      MTWorkHR.Infrastructure/Repositories/Auth/LoginOTPRepository.cs
  33. 19 0
      MTWorkHR.Infrastructure/Repositories/Lookups/CityRepository.cs
  34. 6 0
      MTWorkHR.Infrastructure/UnitOfWork/UnitOfWork.cs

+ 6 - 5
MTWorkHR.API/Controllers/AuthController.cs

@@ -26,7 +26,8 @@ namespace MTWorkHR.API.Controllers
             return Ok( await _authenticationService.Login(request));
         }
         [HttpPost("register")]
-        public async Task<ActionResult<UserDto>> Register([FromBody] UserDto input)
+        [Consumes("multipart/form-data")]
+        public async Task<ActionResult<UserDto>> Register([FromForm] UserDto input)
         {
             return await _userService.Create(input);
         }
@@ -39,11 +40,11 @@ namespace MTWorkHR.API.Controllers
         //    return await _userService.IsExpiredToken(model);
         //}
 
-        [HttpPost("forgetPasswordMail")]
-        [ProducesResponseType(StatusCodes.Status200OK)]
-        public async Task ForgetPasswordMail(string email)
+        [HttpGet("forgetPasswordMail")]
+        //[ProducesResponseType(StatusCodes.Status200OK)]
+        public async Task<string> ForgetPasswordMail(string email)
         {
-            await _userService.ForgetPasswordMail(email);
+            return await _userService.ForgetPasswordMail(email);
         }
 
         [HttpPost("forgetPassword")]

+ 6 - 6
MTWorkHR.API/Controllers/LookupController.cs

@@ -82,12 +82,12 @@ namespace MTWorkHR.API.Controllers
             return await _LookupService.GetAllQualifications();
         }
 
-        [HttpGet("CreateCountries")]
-        [ProducesResponseType(StatusCodes.Status200OK)]
+        //[HttpGet("CreateCountries")]
+        //[ProducesResponseType(StatusCodes.Status200OK)]
 
-        public async Task<ActionResult<List<CountryDto>>> CreateCountries()
-        {
-            return await _LookupService.CreateCountries();
-        }
+        //public async Task<ActionResult<List<CountryDto>>> CreateCountries()
+        //{
+        //    return await _LookupService.CreateCountries();
+        //}
     }
 }

+ 2 - 1
MTWorkHR.API/Controllers/UserController.cs

@@ -31,7 +31,8 @@ namespace MTWorkHR.API.Controllers
 
         [HttpPost("Create")]
         [ProducesResponseType(StatusCodes.Status200OK)]
-        public async Task<ActionResult<UserDto>> Create([FromBody] UserDto input)
+        [Consumes("multipart/form-data")]
+        public async Task<ActionResult<UserDto>> Create([FromForm] UserDto input)
         {
             return await _userService.Create(input);
         }

+ 8 - 0
MTWorkHR.API/appsettings.json

@@ -36,5 +36,13 @@
     "Port": 587,
     "TemplatePath": "C:\\Attachment\\MailTemp\\EmailTemplate.html"
   },
+  "OTPSettings": {
+    "Length": 6,
+    "ExpirePeriodInMinutes": 30,
+    "SendEmail": true,
+    "AllowZeros": true,
+    "MessageBody": "Dear User, Your OTP is {0}. Use this passcode to proceed.",
+    "MessageSubject": "OTP"
+  },
   "AllowedHosts": "*"
 }

+ 1 - 0
MTWorkHR.Application/ApplicationServiceRegistration.cs

@@ -33,6 +33,7 @@ namespace MTWorkHR.Application
             services.AddScoped<IOrderRequestService, OrderRequestService>();
             services.AddScoped<ILookupService, LookupService>();
             services.AddScoped<ICompanyService, CompanyService>();
+            services.AddScoped<IOTPService, OTPService>();
 
             return services;
         }

+ 1 - 0
MTWorkHR.Application/Dtos/Identity/ForgetPasswordDto.cs

@@ -9,6 +9,7 @@ namespace MTWorkHR.Application.Models
         
         public string? Password { get; set; }
         public string? Email { get; set; }
+        public string? OTP { get; set; }
 
     }
 }

+ 4 - 4
MTWorkHR.Application/Dtos/Identity/UserAddressDto.cs

@@ -5,9 +5,9 @@ namespace MTWorkHR.Application.Models
 {
     public class UserAddressDto : EntityDto
     {
-        public int CountryId { get; set; }
-        public string City { get; set; }
-        public string PostalCode { get; set; }
-        public string AddressDesc { get; set; }
+        public int? CountryId { get; set; }
+        public string? City { get; set; }
+        public string? PostalCode { get; set; }
+        public string? AddressDesc { get; set; }
     }
 }

+ 1 - 0
MTWorkHR.Application/Mapper/MappingProfile.cs

@@ -85,6 +85,7 @@ namespace MTWorkHR.Application.Mapper
             CreateMap<JobTitle, JobTitleDto>().ReverseMap();
             CreateMap<University, UniversityDto>().ReverseMap();
             CreateMap<Qualification, QualificationDto>().ReverseMap();
+            CreateMap<City, CityDto>().ReverseMap();
 
         }
     }

+ 1 - 1
MTWorkHR.Application/Services/Base/FileService.cs

@@ -90,7 +90,7 @@ namespace MTWorkHR.Application.Services
                 {
                     if (formFile.Length > 0)
                     {
-                        var filePath = Path.GetTempFileName();
+                        var filePath = Path.Combine(GetTempAttachmentPath(), attachment.FileName);// Path.GetTempFileName();
 
                         using (var stream = System.IO.File.Create(filePath))
                         {

+ 117 - 0
MTWorkHR.Application/Services/Base/OTPService.cs

@@ -0,0 +1,117 @@
+using Microsoft.AspNetCore.Mvc;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.Design;
+using System.IO;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading.Tasks;
+using System.Drawing.Drawing2D;
+using System.Drawing.Imaging;
+using System.Drawing.Text;
+using System.Drawing;
+using NeomtechERP.Auth.Core.Global;
+using NeomtechERP.Auth.Core;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using MTWorkHR.Core.Global;
+using MTWorkHR.Core.Email;
+using MTWorkHR.Core.UnitOfWork;
+using MTWorkHR.Application.Services.Interfaces;
+using MTWorkHR.Core.Entities;
+
+namespace MTWorkHR.Application.Services
+{
+	public class OTPService : IOTPService
+	{
+		private readonly AppSettingsConfiguration appSettings;
+		private readonly IMailSender mailSender;
+		private readonly IUnitOfWork unitOfWork;
+		private readonly IWebHostEnvironment env;
+
+
+		public OTPService(AppSettingsConfiguration appSettings, IUnitOfWork unitOfWork, IMailSender mailSender,
+			 IWebHostEnvironment env)
+		{
+			this.appSettings = appSettings;
+			this.mailSender = mailSender;
+			this.unitOfWork = unitOfWork;
+			this.env = env;
+		}
+		public async Task<string> RandomOneTimePassword(string userId)
+		{
+			string oneTimePassword = default;
+
+			for (var index = 0; index < appSettings.OTPSettings.Length; index++)
+			{
+				oneTimePassword += $"{new Random().Next(0, 10)}";
+			}
+
+			var loginOTP = new LoginOTP()
+			{
+				OTP = oneTimePassword,
+				UserId = userId,
+				CreateDate = DateTime.Now,
+				ExpireDate = DateTime.Now.AddMinutes(appSettings.OTPSettings.ExpirePeriodInMinutes)
+			};
+			await unitOfWork.LoginOTP.AddAsync(loginOTP);
+			await unitOfWork.CompleteAsync();
+			return oneTimePassword;
+		}
+		public async Task<bool> VerifyOTP(string userId, string oneTimePassword)
+		{
+			if (appSettings.OTPSettings.AllowZeros)
+			{
+				var dummyOTP = "";
+                for (var index = 0; index < appSettings.OTPSettings.Length; index++)
+                {
+                    dummyOTP += "1";
+                }
+                return oneTimePassword == dummyOTP;
+            }
+				
+			else
+				return await unitOfWork.LoginOTP.VerifyOTP(userId, oneTimePassword);
+		}
+
+		//public async Task SentOTPBySMS(string phoneNumber, string oneTimePassword, SMSMethod method)
+		//{
+		//	if (appSettings.OTPSettings.SendSMS)
+		//	{
+		//		string message = string.Format(appSettings.OTPSettings.MessageBody, oneTimePassword);
+		//		var smsModel = new SMSDTO
+		//		{
+		//			PhoneNumber = phoneNumber,
+		//			MessageBody = message,
+		//			Method = method.ToString(),
+		//			Module = "Auth",
+		//		};
+		//		var smsOutput = await smsProvider.SendSmsBySMSProviderSettings(smsModel);
+		//	}
+  //      }
+		public async Task SentOTPByMail(string userId, string email, string oneTimePassword)
+		{
+			if (appSettings.OTPSettings.SendEmail)
+			{
+				string subject = appSettings.OTPSettings.MessageSubject;
+				string message = string.Format(appSettings.OTPSettings.MessageBody , oneTimePassword);
+                await mailSender.SendEmail(new EmailMessage
+                {
+                    Subject = subject,
+                    To = email,
+                    Body = message,
+                    url = "",
+                    userId = userId
+                });
+			}
+		}
+
+
+
+	}
+
+}
+
+

+ 16 - 0
MTWorkHR.Application/Services/Interfaces/IOTPService.cs

@@ -0,0 +1,16 @@
+using Microsoft.AspNetCore.Identity;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MTWorkHR.Application.Services.Interfaces
+{
+    public interface IOTPService
+    {
+        Task<string> RandomOneTimePassword(string userId);
+        Task<bool> VerifyOTP(string userId, string oneTimePassword);
+        Task SentOTPByMail(string userId, string email, string oneTimePassword);
+    }
+}

+ 1 - 1
MTWorkHR.Application/Services/Interfaces/IUserService.cs

@@ -18,7 +18,7 @@ namespace MTWorkHR.Application.Identity
         Task Delete(string id);
         Task<UserDto> Create(UserDto input);
         Task<UserDto> Update(UserDto input);
-        Task ForgetPasswordMail(string input);
+        Task<string> ForgetPasswordMail(string input);
         Task<bool> ResetPassword(ResetPasswordDto input);
 
         Task<bool> ForgetPassword(ForgetPasswordDto model);

+ 5 - 4
MTWorkHR.Application/Services/User/LookupService.cs

@@ -50,10 +50,11 @@ namespace MTWorkHR.Application.Services
 
         public async Task<List<CityDto>> GetCityByCountry(long CountryId)
         {
-            List<CityDto> city = new List<CityDto> { new CityDto { NameEn = "Riyadh", NameAr = "الرياض", CountryId=1, Id = 1 }, new CityDto { NameEn = "Giddah", CountryId = 1, NameAr = "جده", Id = 2 }};
-            //var entity = await _unitOfWork.CountryLookup.GetAllAsync();
-            //var response = MapperObject.Mapper.Map<List<CountryDto>>(entity.Item1);
-            return city;
+           // List<CityDto> city = new List<CityDto> { new CityDto { NameEn = "Riyadh", NameAr = "الرياض", CountryId=1, Id = 1 }, new CityDto { NameEn = "Giddah", CountryId = 1, NameAr = "جده", Id = 2 }};
+            var cityList = await _unitOfWork.City.GetAllAsync();
+            var filterList = cityList.Item1.Where(c=> c.CountryId == CountryId);
+            var response = MapperObject.Mapper.Map<List<CityDto>>(filterList);
+            return response;
         }
         
         public async Task<List<IndustryDto>> GetAllIndustries()

+ 68 - 9
MTWorkHR.Application/Services/User/UserService.cs

@@ -19,6 +19,8 @@ using System.Data;
 using MTWorkHR.Core.IDto;
 using System.Linq.Dynamic.Core;
 using MTWorkHR.Core.Entities.Base;
+using MTWorkHR.Infrastructure.EmailService;
+using Countries.NET.Database;
 
 namespace MTWorkHR.Application.Services
 {
@@ -32,10 +34,11 @@ namespace MTWorkHR.Application.Services
         private readonly IMailSender _emailSender;
         private readonly GlobalInfo _globalInfo;
         private readonly IFileService _fileService;
+        private readonly IOTPService _oTPService;
 
         public UserService(ApplicationUserManager userManager, IUnitOfWork unitOfWork
              , RoleManager<ApplicationRole> roleManager, GlobalInfo globalInfo, AppSettingsConfiguration configuration, IMailSender emailSender
-            , IUserRoleRepository<IdentityUserRole<string>> userRole, IFileService fileService)
+            , IUserRoleRepository<IdentityUserRole<string>> userRole, IFileService fileService, IOTPService oTPService)
         {
             _userManager = userManager;
             _unitOfWork = unitOfWork;
@@ -45,7 +48,8 @@ namespace MTWorkHR.Application.Services
             _emailSender = emailSender;
             _globalInfo = globalInfo;
             _fileService = fileService;
-        }
+            _oTPService = oTPService;
+        }   
 
 
         public async Task<UserDto> GetById(string id)
@@ -199,14 +203,22 @@ namespace MTWorkHR.Application.Services
             //saving user
             var result = await _userManager.CreateAsync(user, input.Password);
             if (!result.Succeeded)
+            {
+                if(result.Errors != null && result.Errors.Count() > 0)
+                {
+                    var msg = result.Errors.Select(a => a.Description ).Aggregate((a,b) => a + " /r/n " + b);
+                    throw new AppException(msg);
+                }
                 throw new AppException(ExceptionEnum.RecordCreationFailed);
+            }
+                
             input.Id = user.Id;
 
             //saving userRoles
             if(input.UserRoles == null || input.UserRoles.Count == 0)
             {
                 var employeeRole = await _roleManager.FindByNameAsync("Employee");
-                if (employeeRole == null)
+                if (employeeRole != null)
                 {
                     await _userManager.AddToRoleAsync(user, "Employee");
                 }
@@ -354,7 +366,7 @@ namespace MTWorkHR.Application.Services
             var result = await _userManager.VerifyUserTokenAsync(user, "Default", purpose, input.Token);
             return !result;
         }
-        public async Task<bool> ForgetPassword(ForgetPasswordDto model)
+        public async Task<bool> ForgetPassword1(ForgetPasswordDto model)
         {
             var user = await _userManager.Users.IgnoreQueryFilters().FirstOrDefaultAsync(x => x.Id == model.UserId);
             if (user == null)
@@ -382,20 +394,26 @@ namespace MTWorkHR.Application.Services
 
             return true;
         }
-        public async Task ForgetPasswordMail(string email)
+        public async Task ForgetPasswordMail1(string email)
         {
 
             var foundUser = await _userManager.FindByEmailAsync(email);
             if (foundUser != null)
             {
-                var resultPassReset = await GetResetPasswordURL(foundUser.Id);
+                var user = await _userManager.Users.FirstOrDefaultAsync(x => !x.IsDeleted && x.Id.Equals(foundUser.Id));
+                if (user == null)
+                    throw new AppException(ExceptionEnum.RecordNotExist);
+
+                string resetToken = await _userManager.GeneratePasswordResetTokenAsync(user);
+
+              //  var resultPassReset = await GetResetPasswordURL(foundUser.Id);
 
                 await _emailSender.SendEmail(new EmailMessage
                 {
                     Subject = "Register Confirmation",
-                    To = resultPassReset.Item2,
-                    Body = "Forget Your Password, link will expired after 24 hours",
-                    url = resultPassReset.Item1,
+                    To = foundUser.Email,
+                    Body = "Forget Your Password, your OTP is " + "1111" ,
+                    url = "",
                     userId = foundUser.Id
                 });
             }
@@ -405,6 +423,47 @@ namespace MTWorkHR.Application.Services
             }
         }
 
+
+        public async Task<string> ForgetPasswordMail(string email) //Begin forget password
+        {
+            var foundUser = await _userManager.FindByEmailAsync(email);
+            if (foundUser != null)
+            {
+                string oneTimePassword = await _oTPService.RandomOneTimePassword(foundUser.Id);
+                await _oTPService.SentOTPByMail(foundUser.Id,foundUser.Email, oneTimePassword);
+                return foundUser.Id;
+            }
+            else
+            {
+                throw new AppException(ExceptionEnum.RecordNotExist);
+            }
+        }
+       
+
+        public async Task<bool> ForgetPassword(ForgetPasswordDto input)
+        {
+            var user = await _userManager.Users.IgnoreQueryFilters().FirstOrDefaultAsync(x => x.Id == input.UserId);
+            if (user == null)
+                throw new AppException(ExceptionEnum.RecordNotExist);
+
+            if (!_oTPService.VerifyOTP(user.Id, input.OTP).Result)
+                throw new AppException(ExceptionEnum.WrongOTP);
+            string resetToken = await _userManager.GeneratePasswordResetTokenAsync(user);
+
+            var result = await _userManager.ResetPasswordAsync(user, resetToken, input.Password);
+            if (!result.Succeeded)
+            {
+                if (result.Errors != null && result.Errors.Count() > 0)
+                {
+                    var msg = result.Errors.Select(a => a.Description).Aggregate((a, b) => a + " /r/n " + b);
+                    throw new AppException(msg);
+                }
+                throw new AppException(ExceptionEnum.RecordCreationFailed);
+            }
+            return result.Succeeded;
+        }
+
+
         public async Task StopUser(string userId)
         {
             var entity = await _userManager.Users.FirstOrDefaultAsync(x => x.Id == userId);

+ 0 - 1
MTWorkHR.Core/Email/IMailSender.cs

@@ -11,6 +11,5 @@ namespace MTWorkHR.Core.Email
     public interface IMailSender
     {
         Task<bool> SendEmail(EmailMessage email);
-
     }
 }

+ 15 - 0
MTWorkHR.Core/Entities/Base/LoginOTP.cs

@@ -0,0 +1,15 @@
+using MTWorkHR.Core.Entities.Base;
+using System;
+using System.ComponentModel.DataAnnotations.Schema;
+
+namespace MTWorkHR.Core.Entities
+{
+    public partial class LoginOTP : Entity
+    {
+		public string OTP { get; set; }
+		public string UserId { get; set; }
+		public DateTime CreateDate { get; set; }
+		public DateTime ExpireDate { get; set; }
+
+	}
+}

+ 28 - 0
MTWorkHR.Core/Entities/User/City.cs

@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using MTWorkHR.Core.Entities.Base;
+
+namespace MTWorkHR.Core.Entities
+{
+    public class City : Entity
+    {
+        [Required]
+        [MaxLength(250)]
+        [Filter]
+        public string NameAr { get; set; }
+        [Required]
+        [MaxLength(250)]
+        [Filter]
+        public string NameEn { get; set; }
+        public string NameFr { get; set; }
+        public long CountryId { get; set; }
+        [ForeignKey("CountryId")]
+        public CountryLookup? Country { get; set; }
+        public string Code { get; set; }
+    }
+}

+ 1 - 0
MTWorkHR.Core/Entities/User/CountryLookup.cs

@@ -18,6 +18,7 @@ namespace MTWorkHR.Core.Entities
         [MaxLength(250)]
         [Filter]
         public string NameEn { get; set; }
+        public string NameFr { get; set; }
         public string Code { get; set; }
     }
 }

+ 16 - 0
MTWorkHR.Core/IRepositories/Auth/ILoginOTPRepository.cs

@@ -0,0 +1,16 @@
+using MTWorkHR.Core.Entities;
+using MTWorkHR.Core.IRepositories.Base;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MTWorkHR.Core.IRepositories
+{
+    public interface ILoginOTPRepository : IRepository<LoginOTP>
+	{
+        Task<bool> VerifyOTP(string userId, string oTP);
+        Task<string> LastOpt();
+    }
+}

+ 15 - 0
MTWorkHR.Core/IRepositories/Lookups/ICityRepository.cs

@@ -0,0 +1,15 @@
+using MTWorkHR.Core.Entities;
+using MTWorkHR.Core.IRepositories.Base;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MTWorkHR.Core.IRepositories
+{
+    public interface ICityRepository : IRepository<City>
+    {
+
+    }
+}

+ 2 - 0
MTWorkHR.Core/IUnitOfWork/IUnitOfWork.cs

@@ -26,7 +26,9 @@ namespace MTWorkHR.Core.UnitOfWork
         IIndustryRepository Industry { get; }
         IJobTitleRepository JobTitle { get; }
         IUniversityRepository University { get; }
+        ICityRepository City{ get; }
         IQualificationRepository Qualification { get; }
+        ILoginOTPRepository LoginOTP { get; }
         Task<int> CompleteAsync();
 
         void BeginTran();

+ 2 - 0
MTWorkHR.Infrastructure/DBContext/HRDataContext.cs

@@ -47,6 +47,8 @@ namespace MTWorkHR.Infrastructure.DBContext
         public DbSet<University> Universities { get; set; }
         public DbSet<Industry> Industries { get; set; }
         public DbSet<JobTitle> JobTitles { get; set; }
+        public DbSet<LoginOTP> LoginOTPs { get; set; }
+        public DbSet<City> Cities { get; set; }
 
         
         //------------------------Logs------------------------

+ 4 - 4
MTWorkHR.Infrastructure/Entities/UserAddress.cs

@@ -11,9 +11,9 @@ namespace MTWorkHR.Infrastructure.Entities
         [ForeignKey("UserId")]
         public ApplicationUser User { get; set; }
 
-        public int CountryId { get; set; }
-        public string City{ get; set; }
-        public string PostalCode { get; set; }
-        public string AddressDesc{ get; set; }
+        public int? CountryId { get; set; }
+        public string? City{ get; set; }
+        public string? PostalCode { get; set; }
+        public string? AddressDesc{ get; set; }
     }
 }

+ 2 - 0
MTWorkHR.Infrastructure/InfrastructureServiceRegistration.cs

@@ -77,6 +77,8 @@ namespace MTWorkHR.Infrastructure
             services.AddScoped(typeof(IJobTitleRepository), typeof(JobTitleRepository));
             services.AddScoped(typeof(IQualificationRepository), typeof(QualificationRepository));
             services.AddScoped(typeof(IUniversityRepository), typeof(UniversityRepository));
+            services.AddScoped(typeof(ILoginOTPRepository), typeof(LoginOTPRepository));
+            services.AddScoped(typeof(ICityRepository), typeof(CityRepository));
 
 
 

Fichier diff supprimé car celui-ci est trop grand
+ 2934 - 0
MTWorkHR.Infrastructure/Migrations/20240520154627_altrForget.Designer.cs


+ 90 - 0
MTWorkHR.Infrastructure/Migrations/20240520154627_altrForget.cs

@@ -0,0 +1,90 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace MTWorkHR.Infrastructure.Migrations
+{
+    /// <inheritdoc />
+    public partial class altrForget : Migration
+    {
+        /// <inheritdoc />
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.AlterColumn<string>(
+                name: "PostalCode",
+                table: "UserAddress",
+                type: "nvarchar(max)",
+                nullable: true,
+                oldClrType: typeof(string),
+                oldType: "nvarchar(max)");
+
+            migrationBuilder.AlterColumn<int>(
+                name: "CountryId",
+                table: "UserAddress",
+                type: "int",
+                nullable: true,
+                oldClrType: typeof(int),
+                oldType: "int");
+
+            migrationBuilder.AlterColumn<string>(
+                name: "City",
+                table: "UserAddress",
+                type: "nvarchar(max)",
+                nullable: true,
+                oldClrType: typeof(string),
+                oldType: "nvarchar(max)");
+
+            migrationBuilder.AlterColumn<string>(
+                name: "AddressDesc",
+                table: "UserAddress",
+                type: "nvarchar(max)",
+                nullable: true,
+                oldClrType: typeof(string),
+                oldType: "nvarchar(max)");
+        }
+
+        /// <inheritdoc />
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.AlterColumn<string>(
+                name: "PostalCode",
+                table: "UserAddress",
+                type: "nvarchar(max)",
+                nullable: false,
+                defaultValue: "",
+                oldClrType: typeof(string),
+                oldType: "nvarchar(max)",
+                oldNullable: true);
+
+            migrationBuilder.AlterColumn<int>(
+                name: "CountryId",
+                table: "UserAddress",
+                type: "int",
+                nullable: false,
+                defaultValue: 0,
+                oldClrType: typeof(int),
+                oldType: "int",
+                oldNullable: true);
+
+            migrationBuilder.AlterColumn<string>(
+                name: "City",
+                table: "UserAddress",
+                type: "nvarchar(max)",
+                nullable: false,
+                defaultValue: "",
+                oldClrType: typeof(string),
+                oldType: "nvarchar(max)",
+                oldNullable: true);
+
+            migrationBuilder.AlterColumn<string>(
+                name: "AddressDesc",
+                table: "UserAddress",
+                type: "nvarchar(max)",
+                nullable: false,
+                defaultValue: "",
+                oldClrType: typeof(string),
+                oldType: "nvarchar(max)",
+                oldNullable: true);
+        }
+    }
+}

Fichier diff supprimé car celui-ci est trop grand
+ 3014 - 0
MTWorkHR.Infrastructure/Migrations/20240520183928_altrcity.Designer.cs


+ 80 - 0
MTWorkHR.Infrastructure/Migrations/20240520183928_altrcity.cs

@@ -0,0 +1,80 @@
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace MTWorkHR.Infrastructure.Migrations
+{
+    /// <inheritdoc />
+    public partial class altrcity : Migration
+    {
+        /// <inheritdoc />
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.AddColumn<string>(
+                name: "NameFr",
+                table: "CountryLookups",
+                type: "nvarchar(max)",
+                nullable: false,
+                defaultValue: "");
+
+            migrationBuilder.CreateTable(
+                name: "Cities",
+                columns: table => new
+                {
+                    Id = table.Column<long>(type: "bigint", nullable: false)
+                        .Annotation("SqlServer:Identity", "1, 1"),
+                    NameAr = table.Column<string>(type: "nvarchar(250)", maxLength: 250, nullable: false),
+                    NameEn = table.Column<string>(type: "nvarchar(250)", maxLength: 250, nullable: false),
+                    NameFr = table.Column<string>(type: "nvarchar(max)", nullable: false),
+                    CountryId = table.Column<long>(type: "bigint", nullable: false),
+                    Code = table.Column<string>(type: "nvarchar(max)", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Cities", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_Cities_CountryLookups_CountryId",
+                        column: x => x.CountryId,
+                        principalTable: "CountryLookups",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "LoginOTPs",
+                columns: table => new
+                {
+                    Id = table.Column<long>(type: "bigint", nullable: false)
+                        .Annotation("SqlServer:Identity", "1, 1"),
+                    OTP = table.Column<string>(type: "nvarchar(max)", nullable: false),
+                    UserId = table.Column<string>(type: "nvarchar(max)", nullable: false),
+                    CreateDate = table.Column<DateTime>(type: "datetime2", nullable: false),
+                    ExpireDate = table.Column<DateTime>(type: "datetime2", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_LoginOTPs", x => x.Id);
+                });
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Cities_CountryId",
+                table: "Cities",
+                column: "CountryId");
+        }
+
+        /// <inheritdoc />
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.DropTable(
+                name: "Cities");
+
+            migrationBuilder.DropTable(
+                name: "LoginOTPs");
+
+            migrationBuilder.DropColumn(
+                name: "NameFr",
+                table: "CountryLookups");
+        }
+    }
+}

Fichier diff supprimé car celui-ci est trop grand
+ 3014 - 0
MTWorkHR.Infrastructure/Migrations/20240520214358_CountryCityConfiguration.Designer.cs


Fichier diff supprimé car celui-ci est trop grand
+ 7246 - 0
MTWorkHR.Infrastructure/Migrations/20240520214358_CountryCityConfiguration.cs


+ 81 - 4
MTWorkHR.Infrastructure/Migrations/HRDataContextModelSnapshot.cs

@@ -281,6 +281,43 @@ namespace MTWorkHR.Infrastructure.Migrations
                         });
                 });
 
+            modelBuilder.Entity("MTWorkHR.Core.Entities.City", b =>
+                {
+                    b.Property<long>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("bigint")
+                        .HasColumnOrder(0);
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
+
+                    b.Property<string>("Code")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<long>("CountryId")
+                        .HasColumnType("bigint");
+
+                    b.Property<string>("NameAr")
+                        .IsRequired()
+                        .HasMaxLength(250)
+                        .HasColumnType("nvarchar(250)");
+
+                    b.Property<string>("NameEn")
+                        .IsRequired()
+                        .HasMaxLength(250)
+                        .HasColumnType("nvarchar(250)");
+
+                    b.Property<string>("NameFr")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("CountryId");
+
+                    b.ToTable("Cities");
+                });
+
             modelBuilder.Entity("MTWorkHR.Core.Entities.Company", b =>
                 {
                     b.Property<long>("Id")
@@ -360,6 +397,10 @@ namespace MTWorkHR.Infrastructure.Migrations
                         .HasMaxLength(250)
                         .HasColumnType("nvarchar(250)");
 
+                    b.Property<string>("NameFr")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
                     b.HasKey("Id");
 
                     b.ToTable("CountryLookups");
@@ -981,6 +1022,34 @@ namespace MTWorkHR.Infrastructure.Migrations
                         });
                 });
 
+            modelBuilder.Entity("MTWorkHR.Core.Entities.LoginOTP", b =>
+                {
+                    b.Property<long>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("bigint")
+                        .HasColumnOrder(0);
+
+                    SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
+
+                    b.Property<DateTime>("CreateDate")
+                        .HasColumnType("datetime2");
+
+                    b.Property<DateTime>("ExpireDate")
+                        .HasColumnType("datetime2");
+
+                    b.Property<string>("OTP")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.Property<string>("UserId")
+                        .IsRequired()
+                        .HasColumnType("nvarchar(max)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("LoginOTPs");
+                });
+
             modelBuilder.Entity("MTWorkHR.Core.Entities.Meeting", b =>
                 {
                     b.Property<long>("Id")
@@ -2423,14 +2492,12 @@ namespace MTWorkHR.Infrastructure.Migrations
                     SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
 
                     b.Property<string>("AddressDesc")
-                        .IsRequired()
                         .HasColumnType("nvarchar(max)");
 
                     b.Property<string>("City")
-                        .IsRequired()
                         .HasColumnType("nvarchar(max)");
 
-                    b.Property<int>("CountryId")
+                    b.Property<int?>("CountryId")
                         .HasColumnType("int");
 
                     b.Property<DateTime>("CreateDate")
@@ -2443,7 +2510,6 @@ namespace MTWorkHR.Infrastructure.Migrations
                         .HasColumnOrder(1);
 
                     b.Property<string>("PostalCode")
-                        .IsRequired()
                         .HasColumnType("nvarchar(max)");
 
                     b.Property<DateTime?>("UpdateDate")
@@ -2653,6 +2719,17 @@ namespace MTWorkHR.Infrastructure.Migrations
                         .IsRequired();
                 });
 
+            modelBuilder.Entity("MTWorkHR.Core.Entities.City", b =>
+                {
+                    b.HasOne("MTWorkHR.Core.Entities.CountryLookup", "Country")
+                        .WithMany()
+                        .HasForeignKey("CountryId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Country");
+                });
+
             modelBuilder.Entity("MTWorkHR.Core.Entities.MeetingUser", b =>
                 {
                     b.HasOne("MTWorkHR.Core.Entities.Meeting", "Meeting")

+ 37 - 0
MTWorkHR.Infrastructure/Repositories/Auth/LoginOTPRepository.cs

@@ -0,0 +1,37 @@
+using Microsoft.AspNetCore.Identity;
+using Microsoft.EntityFrameworkCore;
+using MTWorkHR.Core.Entities;
+using MTWorkHR.Core.IRepositories;
+using MTWorkHR.Infrastructure.DBContext;
+using Org.BouncyCastle.Math.EC.Rfc7748;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Dynamic.Core;
+using System.Text;
+using System.Threading.Tasks;
+namespace MTWorkHR.Infrastructure.Repositories
+{
+	public class LoginOTPRepository : Repository<LoginOTP>, ILoginOTPRepository
+	{
+		private readonly DbSet<LoginOTP> dbSet;
+		public LoginOTPRepository(HRDataContext context) : base(context)
+		{
+			dbSet = context.Set<LoginOTP>();
+		}
+		public async Task<bool> VerifyOTP(string userId, string oTP)
+		{
+			bool result = false;
+			var loginOTP = await dbSet.AsQueryable().OrderByDescending(x => x.CreateDate).FirstOrDefaultAsync(x => x.UserId == userId && x.ExpireDate >= DateTime.Now);
+			if (loginOTP.OTP == oTP)
+				result = true;
+			return result;
+		}
+		public async Task<string> LastOpt()
+		{
+			var res= await dbSet.OrderByDescending(x=>x.CreateDate).FirstOrDefaultAsync();
+
+			return res.OTP;
+		}
+    }
+}

+ 19 - 0
MTWorkHR.Infrastructure/Repositories/Lookups/CityRepository.cs

@@ -0,0 +1,19 @@
+using Microsoft.EntityFrameworkCore;
+using MTWorkHR.Core.Entities;
+using MTWorkHR.Core.IDto;
+using MTWorkHR.Core.IRepositories;
+using MTWorkHR.Infrastructure.Entities;
+using MTWorkHR.Infrastructure.DBContext;
+
+namespace MTWorkHR.Infrastructure.Repositories
+{
+    public class CityRepository : Repository<City>, ICityRepository
+    {
+        private readonly DbSet<City> dbSet;
+        public CityRepository(HRDataContext context) : base(context)
+        {
+            dbSet = context.Set<City>();
+        }
+        
+    }
+}

+ 6 - 0
MTWorkHR.Infrastructure/UnitOfWork/UnitOfWork.cs

@@ -33,6 +33,8 @@ namespace MTWorkHR.Infrastructure.UnitOfWorks
         public IJobTitleRepository JobTitle { get; }
         public IQualificationRepository Qualification { get; }
         public IUniversityRepository University { get; }
+        public ILoginOTPRepository LoginOTP { get; }
+        public ICityRepository City { get; }
 
         public UnitOfWork(HRDataContext _context
             , IPermissionRepository permission
@@ -54,6 +56,8 @@ namespace MTWorkHR.Infrastructure.UnitOfWorks
             , IJobTitleRepository jobTitle
             , IQualificationRepository qualification
             , IUniversityRepository university
+            , ILoginOTPRepository loginOTP
+            , ICityRepository city
 
             )
         {
@@ -77,6 +81,8 @@ namespace MTWorkHR.Infrastructure.UnitOfWorks
             this.JobTitle = jobTitle;
             this.Qualification = qualification;
             this.University = university;
+            LoginOTP = loginOTP;
+            City = city;
         }
 
         public async Task<int> CompleteAsync()