Initial commit - Auth

This commit is contained in:
2026-08-05 21:15:14 +03:00
commit dda4d9e63f
1490 changed files with 53289 additions and 0 deletions
+212
View File
@@ -0,0 +1,212 @@
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Threading.Tasks;
using Auth.Contracts.DTOs.Auth;
using Auth.Contracts.DTOs.Users;
using Auth.Core;
using Auth.Domain;
using Auth.Domain.Entities;
using Auth.Domain.Entities.HR;
using Generic.Contracts.Generics;
using Generic.Services;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
namespace Auth.Core.Services.Auth;
public class AuthService
{
private readonly UserManager<AppUser> userManager;
private readonly TokenGenerator tokenGenerator;
private readonly Context context;
private readonly EmailService emailService;
public AuthService(
UserManager<AppUser> userManager,
TokenGenerator tokenGenerator,
Context appDbContext,
EmailService emailService
)
{
this.emailService = emailService;
this.tokenGenerator = tokenGenerator;
this.context = appDbContext;
this.userManager = userManager;
}
public async Task<TokenModel> Login(LoginModel loginModel)
{
var user = await userManager.Users.FirstOrDefaultAsync(x => x.Email == loginModel.Email);
if (user != null)
{
if (await userManager.CheckPasswordAsync(user, loginModel.Password))
{
user.RefreshToken = tokenGenerator.CreateRefreshToken();
user.RefreshTokenExpiryDate = DateTime.UtcNow.AddDays(30);
await userManager.UpdateAsync(user);
var newAccessToken = await tokenGenerator.CreateJWT(user);
return new TokenModel
{
AccessToken = new JwtSecurityTokenHandler().WriteToken(newAccessToken),
RefreshToken = user.RefreshToken,
Expiry = newAccessToken.ValidTo,
};
}
}
return null;
}
public async Task<string> SignUp(RegisterModel registerModel)
{
var user = new AppUser()
{
UserName = registerModel.Email,
Email = registerModel.Email,
Name = registerModel.FullName,
};
var userWithSameEmail = await userManager.FindByEmailAsync(registerModel.Email);
if (userWithSameEmail is null)
{
var result = await userManager.CreateAsync(user, registerModel.Password);
if (!result.Succeeded)
return $"Error registering user: {user.UserName} ({result.Errors.First().Description})";
await userManager.AddToRoleAsync(user, "User");
var confirmToken = await userManager.GenerateEmailConfirmationTokenAsync(user);
await emailService.SendConfirmationEmail(user.Email, user, confirmToken);
return "";
}
return $"Email {user.Email} is already registered.";
}
public async Task<TokenModel> RefreshToken(TokenModel tokenModel)
{
var principle = tokenGenerator.GetPrincipalFromExpiredToken(tokenModel.AccessToken);
if (principle != null)
{
var user = await userManager.FindByEmailAsync(
principle.Claims.First(x => x.Type == "UserName").Value
);
if (
user != null
&& user.RefreshToken == tokenModel.RefreshToken
&& user.RefreshTokenExpiryDate > DateTime.Now
)
{
var newAccessToken = await tokenGenerator.CreateJWT(user);
return new TokenModel()
{
AccessToken = new JwtSecurityTokenHandler().WriteToken(newAccessToken),
RefreshToken = tokenModel.RefreshToken,
Expiry = newAccessToken.ValidTo,
};
}
}
return null;
}
public async Task SendChangePhoneNumberToken(string id, string phoneNumber)
{
var user = await userManager.FindByIdAsync(id);
if (await userManager.IsEmailConfirmedAsync(user))
throw new Exception();
var token = await userManager.GenerateChangePhoneNumberTokenAsync(user, phoneNumber);
await emailService.SendChangePhoneNumberToken(user.Email, user, token);
}
public async Task<IdentityResult> ChangePhoneNumber(
string userId,
UpdatePhoneNumber updatePhoneNumber
)
{
var user = await userManager.FindByIdAsync(userId);
var result = await userManager.ChangePhoneNumberAsync(
user,
updatePhoneNumber.PhoneNumber,
updatePhoneNumber.Token
);
return result;
}
public async Task SendEmailConfirmationToken(string id)
{
var user = await userManager.FindByIdAsync(id);
if (await userManager.IsEmailConfirmedAsync(user))
throw new Exception();
var token = await userManager.GenerateEmailConfirmationTokenAsync(user);
await emailService.SendConfirmationEmail(user.Email, user, token);
}
public async Task<bool> ConfirmEmail(string id, string token)
{
var user = await userManager.FindByIdAsync(id);
var result = await userManager.ConfirmEmailAsync(user, token);
return result.Succeeded;
}
public async Task SendPasswordResetToken(string email)
{
var user = await userManager.FindByEmailAsync(email);
var token = await userManager.GeneratePasswordResetTokenAsync(user);
await emailService.SendResetPasswordEmail(user.Email, user, token);
}
public async Task ResetPassword(PasswordResetModel passwordResetModel)
{
var user = await userManager.FindByEmailAsync(passwordResetModel.Email);
await userManager.ResetPasswordAsync(
user,
passwordResetModel.Token,
passwordResetModel.Password
);
}
public async Task SendChangeEmailToken(RequestChangeEmail changeEmailModel, string userId)
{
var user = await userManager.FindByIdAsync(userId);
var isValid = await userManager.CheckPasswordAsync(user, changeEmailModel.Password);
if (isValid)
{
var token = await userManager.GenerateChangeEmailTokenAsync(
user,
changeEmailModel.NewEmail
);
await emailService.SendConfirmationEmail(user.Email, user, token);
}
}
public async Task<bool> ChangeEmail(string userId, ChangeEmailModel changeEmailModel)
{
var user = await userManager.FindByIdAsync(userId);
var result = await userManager.ChangeEmailAsync(
user,
changeEmailModel.NewEmail,
changeEmailModel.Token
);
return result.Succeeded;
}
public async Task<bool> RevokeRefreshToken(string userName)
{
var user = await userManager.FindByNameAsync(userName);
if (user == null) return false;
user.RefreshToken = null;
await userManager.UpdateAsync(user);
return true;
}
}
+57
View File
@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Auth.Contracts.DTOs.Auth;
using Auth.Contracts.DTOs.Users;
using Auth.Core;
using Auth.Domain;
using Auth.Domain.Entities;
using Auth.Domain.Entities.HR;
using Bogus;
using FluentEmail.Core;
namespace Auth.Core.Services.Auth;
public class EmailService
{
private readonly IFluentEmail fluentEmail;
public EmailService(IFluentEmail fluentEmail)
{
this.fluentEmail = fluentEmail;
}
public async Task SendConfirmationEmail(string to, AppUser user, string token)
{
await fluentEmail
.To(to)
.Subject("Confirm Your Email.")
.UsingTemplateFromFile("../Auth.Contracts/EmailTemplates/ConfirmEmail.cshtml", (user, token))
.SendAsync();
}
public async Task SendResetPasswordEmail(string to, AppUser user, string token)
{
await fluentEmail
.To(to)
.Subject("Reset Your Password.")
.UsingTemplateFromFile(
"../Auth.Contracts/EmailTemplates/ResetPassword.cshtml",
(user, token)
)
.SendAsync();
}
public async Task SendChangePhoneNumberToken(string to, AppUser user, string token)
{
await fluentEmail
.To(to)
.Subject("Reset Your Password.")
.UsingTemplateFromFile(
"../Auth.Contracts/EmailTemplates/SendPhoneNumber.cshtml",
(user, token)
)
.SendAsync();
}
}
+13
View File
@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Auth.Contracts.DTOs.Auth;
using Auth.Contracts.DTOs.Users;
using Auth.Core;
using Auth.Domain;
using Auth.Domain.Entities;
namespace Auth.Core.Services.Auth;
public class RoleService { }
+127
View File
@@ -0,0 +1,127 @@
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Auth.Contracts.DTOs.Auth;
using Auth.Contracts.DTOs.Users;
using Auth.Core;
using Auth.Domain;
using Auth.Domain.Entities;
using Auth.Domain.Entities.HR;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
namespace Auth.Core.Services.Auth;
public class TokenGenerator
{
private readonly RoleManager<IdentityRole> roleManager;
private readonly UserManager<AppUser> userManager;
private readonly JWT jwt;
private readonly IConfiguration configuration;
public TokenGenerator(
UserManager<AppUser> userManager,
RoleManager<IdentityRole> roleManager,
IOptions<JWT> jwt,
IConfiguration configuration
)
{
this.configuration = configuration;
this.jwt = jwt.Value;
this.userManager = userManager;
this.roleManager = roleManager;
}
public async Task<JwtSecurityToken> CreateJWT(AppUser user)
{
var userClaims = await userManager.GetClaimsAsync(user);
var roles = await userManager.GetRolesAsync(user);
var roleClaims = new List<Claim>();
foreach (var roleName in roles)
{
roleClaims.Add(new Claim(ClaimTypes.Role, roleName));
var role = await roleManager.FindByNameAsync(roleName);
if (role != null)
{
var currentRoleClaims = await roleManager.GetClaimsAsync(role);
roleClaims.AddRange(currentRoleClaims);
}
}
var claims = new[]
{
new Claim(ClaimTypes.Name, user.UserName ?? ""),
new Claim(JwtRegisteredClaimNames.Sub, user.UserName ?? ""),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.Email, user.Email ?? ""),
new Claim("Name", user.Name ?? ""),
new Claim("UserName", user.Email ?? ""),
new Claim("confirmed", user.EmailConfirmed.ToString()),
new Claim("uid", user.Id),
new Claim("Holidays", user.Holidays.ToString()),
new Claim("PhotoPath", user.PhotoPath ?? ""),
}
.Union(userClaims)
.Union(roleClaims);
var bytes = Encoding.UTF8.GetBytes(jwt.Key);
var symmetricSecurityKey = new SymmetricSecurityKey(bytes);
var signingCredentials = new SigningCredentials(
symmetricSecurityKey,
SecurityAlgorithms.HmacSha256
);
var jwtSecurityToken = new JwtSecurityToken(
issuer: jwt.Issuer,
audience: jwt.Audience,
claims: claims,
expires: DateTime.UtcNow.AddMinutes(jwt.DurationInMinutes),
signingCredentials: signingCredentials
);
return jwtSecurityToken;
}
public string CreateRefreshToken()
{
var token = Convert.ToBase64String(RandomNumberGenerator.GetBytes(64));
return token;
}
public ClaimsPrincipal? GetPrincipalFromExpiredToken(string? token)
{
var tokenValidationParameters = new TokenValidationParameters
{
ValidateAudience = false,
ValidateIssuer = false,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwt.Key)),
ValidateLifetime = false,
};
var tokenHandler = new JwtSecurityTokenHandler();
var principal = tokenHandler.ValidateToken(
token,
tokenValidationParameters,
out SecurityToken securityToken
);
if (
securityToken is not JwtSecurityToken jwtSecurityToken
|| !jwtSecurityToken.Header.Alg.Equals(
SecurityAlgorithms.HmacSha256,
StringComparison.InvariantCultureIgnoreCase
)
)
throw new SecurityTokenException("Invalid token");
return principal;
}
}
@@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Core.Services.Email;
public class EmailTemplateService
{
}
@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Auth.Domain;
namespace Auth.Core.Services.HR.Users;
public class GroupService
{
private readonly Context context;
public GroupService(Context context)
{
this.context = context;
}
// public async Task CreateGroup(GroupVM groupVM) { }
// public async Task ChangeUserGroup(GroupVM groupVM) { }
// public async Task GetAllGroups(GroupVM groupVM) { }
// public async Task GetGroup(GroupVM groupVM) { }
}
@@ -0,0 +1,25 @@
// using System;
// using System.Collections.Generic;
// using System.Linq;
// using System.Threading.Tasks;
// using Domain;
// namespace Auth.Core.Services.HR.Users;
// public class HolidayService
// {
// private readonly Context context;
// public HolidayService(Context context)
// {
// this.context = context;
// }
// public async Task AddHolidaysToUser(string userId, int holidays)
// {
// var user = await context.AppUsers.FindAsync(userId);
// user.Holidays += holidays;
// context.Update(user);
// await context.SaveChangesAsync();
// }
// }
@@ -0,0 +1,44 @@
// using System;
// using System.Collections.Generic;
// using System.Linq;
// using System.Threading.Tasks;
// using Domain;
// namespace Auth.Core.Services.HR.Users;
// public class PunchService
// {
// private readonly Context context;
// public PunchService(Context context)
// {
// this.context = context;
// }
// // public async Task CreateSinglePunch(PunchVM punchVM)
// // {
// // await context.Punches.AddAsync(punchVM);
// // await context.SaveChangesAsync();
// // }
// // public async Task UpdatePunch(PunchVM punchVM)
// // {
// // context.Update(punchVM);
// // await context.SaveChangesAsync();
// // }
// // public async Task AddBulkPunches(PunchVM[] punchVMs)
// // {
// // await context.AddRangeAsync(punchVMs);
// // await context.SaveChangesAsync();
// // }
// // public async Task DetermineIfPunchAttendOrLeave() { }
// // public async Task GetPunchesInADay()
// // {
// // // Get Correct Punches ... determine if it should be attendant or leave, how many punches and get first and last , if not after midnight
// // }
// // public async Task GetAllPunches() { }
// }
@@ -0,0 +1,19 @@
// using System;
// using System.Collections.Generic;
// using System.Linq;
// using System.Threading.Tasks;
// using Domain;
// namespace Auth.Core.Services.HR.Users;
// public class RulesService
// {
// private readonly Context context;
// public RulesService(Context context)
// {
// this.context = context;
// }
// public async Task CreateRule() { }
// }
@@ -0,0 +1,23 @@
// using System;
// using System.Collections.Generic;
// using System.Linq;
// using System.Threading.Tasks;
// namespace Auth.Core.Services.HR.Users;
// public class SalaryPaymentService
// {
// public SalaryPaymentService() { }
// // GetPunches()
// // GetHolidaysFromPunches()
// // PutPunchesToPunchesRules()
// // PutDaysToDaysRules()
// // CalculateHolidays()
// // CalculateSalary()
// // PaySalary()
// }
@@ -0,0 +1,26 @@
// using System;
// using System.Collections.Generic;
// using System.Linq;
// using System.Threading.Tasks;
// using Contracts.DTOs.HR;
// using Domain;
// using Domain.Entities.HR;
// using Microsoft.EntityFrameworkCore;
// namespace Auth.Core.Services.HR.Users;
// public class SalaryService
// {
// private readonly Context context;
// public SalaryService(Context context)
// {
// this.context = context;
// }
// public async Task AddNewSalaryToUser(SalaryVM salaryVM)
// {
// await context.Salaries.AddAsync(Salary.ToEntity(salaryVM));
// await context.SaveChangesAsync();
// }
// }
+154
View File
@@ -0,0 +1,154 @@
using System.Security.Cryptography.X509Certificates;
using Auth.Contracts.DTOs.Auth;
using Auth.Contracts.DTOs.Users;
using Auth.Core;
using Auth.Core.Services.Auth;
using Auth.Domain;
using Auth.Domain.Entities;
using Auth.Domain.Entities.HR;
using Generic.Services;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
namespace Auth.Core.Services.HR.Users;
public class UserService
{
private readonly UserManager<AppUser> userManager;
private readonly TokenGenerator tokenGenerator;
private readonly Context context;
private readonly EmailService emailService;
// private readonly OrderService orderService;
public UserService(
UserManager<AppUser> userManager,
TokenGenerator tokenGenerator,
Context appDbContext,
EmailService emailService
)
{
this.emailService = emailService;
this.tokenGenerator = tokenGenerator;
context = appDbContext;
this.userManager = userManager;
}
public async Task<UserView> GetUser(string id)
{
try
{
var user = await context.AppUsers.Where(x => x.Id == id).FirstOrDefaultAsync();
return new UserView()
{
Name = user.Name,
PhotoPath = user.PhotoPath,
PhoneNumber = user.PhoneNumber,
Email = user.Email,
};
}
catch
{
throw new Exception();
}
}
public async Task<List<UserVM>> GetAllUsers()
{
var users = await userManager.Users.ToListAsync();
// foreach (var user in users)
// {
// user.Roles = (await userManager.GetRolesAsync(user)).ToList();
// }
return users.Select(x => AppUser.ToVM(x)).ToList();
}
public async Task UpdateUserInfo(UserInfoUpdate userVM, string userId)
{
var user = await userManager.FindByIdAsync(userId);
if (user is not null)
{
user.Name = userVM.Name;
user.PhotoPath = userVM.PhotoPath;
await userManager.UpdateAsync(user);
}
}
// public async Task<Location> GetLocation(string userId)
// {
// var user = await userManager.FindByIdAsync(userId);
// if (user != null)
// {
// return new Location()
// {
// Address = user.Address,
// Building = user.Building,
// Flat = user.Flat,
// Floor = user.Floor,
// Lat = user.locationLati,
// Lng = user.locationLong,
// };
// }
// return null;
// }
// public async Task<Location> UpdateLocation(Location location, string userId)
// {
// var user = await userManager.FindByIdAsync(userId);
// if (user != null)
// {
// user.Address = location.Address;
// user.Building = location.Building;
// user.Flat = location.Flat;
// user.Floor = location.Floor;
// user.locationLati = location.Lat;
// user.locationLong = location.Lng;
// }
// context.Update(user);
// await context.SaveChangesAsync();
// return location;
// }
// public async Task<IQueryable<AppUser>> FilterUsers(IQueryable<AppUser> query, UserFilter userFilter)
// {
// var list = query.ToList();
// if (!string.IsNullOrEmpty(userFilter.Role))
// query = await userManager.GetUsersInRoleAsync(userFilter.Role);
// if (userFilter.UserFilterBy == UserFilterBy.Name)
// query = query.Where(x => x.Name == userFilter.Search);
// if (userFilter.UserFilterBy == UserFilterBy.Email)
// query = query.Where(x => x.Email == userFilter.Search);
// if (userFilter.UserFilterBy == UserFilterBy.PhoneNumber)
// query = query.Where(x => x.PhoneNumber == userFilter.Search);
// query.Where(x => true).Include(x => x.Role)
// return query;
// }
// public async Task UpdateUser(string id, AppUser user)
// {
// //change Email
// //change Password
// //change
// }
// public async Task SignUp(AppUser user)
// {
// await userManager.CreateAsync(user);
// }
// public async Task Login()
// {
// }
}
@@ -0,0 +1,130 @@
// using System;
// using System.Collections.Generic;
// using System.Linq;
// using System.Threading.Tasks;
// using Contracts;
// using Contracts.DTOs.Generic;
// using Contracts.DTOs.Requests;
// using Core.Utils;
// using Domain;
// using Domain.Entities;
// using Microsoft.EntityFrameworkCore;
// namespace Auth.Core.Services.Requests;
// public class RequestService
// {
// private readonly Context context;
// public RequestService(Context context)
// {
// this.context = context;
// }
// public async Task CreateRequest(RequestVM requestVM, string userId)
// {
// requestVM.IssuerId = userId;
// requestVM = CreateTitleAndDescription(requestVM);
// var request = Request.ToEntity(requestVM);
// await context.Requests.AddAsync(request);
// await context.SaveChangesAsync();
// }
// public async Task<(List<Request>, int)> GetRequests(
// RequestFilter requestFilter,
// Pagination pagination
// )
// {
// var query = context.Requests.AsQueryable();
// query = query.ApplyFilter(requestFilter);
// // query = query.ApplySorting(sortBy);
// var count = query.Count();
// query = query.Paginate(pagination);
// query = query.Include(x => x.AcceptedBy).Include(x => x.Issuer);
// return (await query.ToListAsync(), count);
// }
// public async Task<List<Request>> GetRequestsAsUser(RequestFilter requestFilter, string id)
// {
// return await context.Requests.Where(x => x.IssuerId == id).ToListAsync();
// }
// public async Task TreatRequest(RequestVM requestVM, string id)
// {
// var request = await context.Requests.FirstOrDefaultAsync(x =>
// x.Id == requestVM.Id && requestVM.AcceptedById == id
// );
// var user = await context.AppUsers.FindAsync(id);
// if (request != null)
// {
// request.AcceptedBy = user;
// request.DateRequestTreated = DateTime.UtcNow;
// request.RequestStatus = requestVM.RequestStatus;
// context.Requests.Update(request);
// }
// await context.SaveChangesAsync();
// }
// public RequestVM CreateTitleAndDescription(RequestVM requestVM)
// {
// if (requestVM.RequestType == AppEnum.RequestType.LeavePermission)
// {
// if (requestVM.IsLeaveEarly == true)
// {
// requestVM.Title = "خروج مبكر";
// requestVM.Description =
// $"طلب موافقة على الخروج المبكر يوم {requestVM.PermissionDate} الساعة {requestVM.PermissionTime}.";
// }
// else
// {
// requestVM.Title = "دخول متأخر";
// requestVM.Description =
// $"طلب موافقة على الدخول المتأخر يوم {requestVM.PermissionDate} الساعة {requestVM.PermissionTime}.";
// }
// }
// else if (requestVM.RequestType == AppEnum.RequestType.Punches)
// {
// if (requestVM.IsAttend == true)
// {
// requestVM.Title = "تسجيل دخول";
// requestVM.Description =
// $"طلب موافقة على تسجيل الدخول بتاريخ {requestVM.PunchDate} والساعة {requestVM.PunchTime}.";
// }
// else
// {
// requestVM.Title = "تسجيل خروج";
// requestVM.Description =
// $"طلب موافقة على تسجيل الخروج بتاريخ {requestVM.PunchDate} والساعة {requestVM.PunchTime}.";
// }
// }
// else if (requestVM.RequestType == AppEnum.RequestType.AbsencePermission)
// {
// if (requestVM.IsFromHolidays == true)
// {
// requestVM.Title = "طلب أجازة";
// requestVM.Description =
// $"طلب إذن بالغياب يوم {requestVM.AbsenceDate} و يحسب من رصيد الأجازات السنوية.";
// }
// else
// {
// requestVM.Title = "إذن بالغياب";
// requestVM.Description = $"طلب إذن بالغياب يوم {requestVM.AbsenceDate}.";
// }
// }
// else if (requestVM.RequestType == AppEnum.RequestType.Financial)
// {
// if (requestVM.FinancialType == AppEnum.FinancialType.Loan)
// {
// requestVM.Title = "طلب سلفة";
// requestVM.Description = $"طلب سلفة بقيمة {requestVM.Amount}.";
// }
// else if (requestVM.FinancialType == AppEnum.FinancialType.Incentive)
// {
// requestVM.Title = "طلب تسوية مالية";
// requestVM.Description = $"طلب تسوية مالية قيمتها {requestVM.Amount}.";
// }
// }
// return requestVM;
// }
// }