Fix admin route access and backend configuration
- Added /admin redirect to login page in nginx config - Fixed backend server.js route ordering for proper admin handling - Updated authentication middleware and routes - Added user management routes - Configured PostgreSQL integration - Updated environment configuration
This commit is contained in:
134
Services/AuthService.cs
Normal file
134
Services/AuthService.cs
Normal file
@@ -0,0 +1,134 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading.Tasks;
|
||||
using SkyArtShop.Models;
|
||||
|
||||
namespace SkyArtShop.Services;
|
||||
|
||||
public class AuthService
|
||||
{
|
||||
private readonly MongoDBService _mongoService;
|
||||
|
||||
public AuthService(MongoDBService mongoService)
|
||||
{
|
||||
_mongoService = mongoService;
|
||||
}
|
||||
|
||||
public string HashPassword(string password)
|
||||
{
|
||||
using RandomNumberGenerator randomNumberGenerator = RandomNumberGenerator.Create();
|
||||
byte[] array = new byte[16];
|
||||
randomNumberGenerator.GetBytes(array);
|
||||
using Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, array, 10000, HashAlgorithmName.SHA256);
|
||||
byte[] bytes = rfc2898DeriveBytes.GetBytes(32);
|
||||
byte[] array2 = new byte[48];
|
||||
Array.Copy(array, 0, array2, 0, 16);
|
||||
Array.Copy(bytes, 0, array2, 16, 32);
|
||||
return Convert.ToBase64String(array2);
|
||||
}
|
||||
|
||||
public bool VerifyPassword(string password, string hashedPassword)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] array = Convert.FromBase64String(hashedPassword);
|
||||
byte[] array2 = new byte[16];
|
||||
Array.Copy(array, 0, array2, 0, 16);
|
||||
using Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, array2, 10000, HashAlgorithmName.SHA256);
|
||||
byte[] bytes = rfc2898DeriveBytes.GetBytes(32);
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
if (array[i + 16] != bytes[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<AdminUser?> AuthenticateAsync(string email, string password)
|
||||
{
|
||||
AdminUser user = (await _mongoService.GetAllAsync<AdminUser>("AdminUsers")).FirstOrDefault((AdminUser u) => u.Email.ToLower() == email.ToLower() && u.IsActive);
|
||||
if (user == null || !VerifyPassword(password, user.PasswordHash))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
user.LastLogin = DateTime.UtcNow;
|
||||
await _mongoService.UpdateAsync("AdminUsers", user.Id, user);
|
||||
return user;
|
||||
}
|
||||
|
||||
public ClaimsPrincipal CreateClaimsPrincipal(AdminUser user)
|
||||
{
|
||||
List<Claim> list = new List<Claim>
|
||||
{
|
||||
new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", user.Id),
|
||||
new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress", user.Email),
|
||||
new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", user.Name),
|
||||
new Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/role", user.Role)
|
||||
};
|
||||
foreach (string permission in user.Permissions)
|
||||
{
|
||||
list.Add(new Claim("Permission", permission));
|
||||
}
|
||||
ClaimsIdentity identity = new ClaimsIdentity(list, "Cookies");
|
||||
return new ClaimsPrincipal(identity);
|
||||
}
|
||||
|
||||
public async Task<AdminUser?> GetUserByIdAsync(string userId)
|
||||
{
|
||||
return await _mongoService.GetByIdAsync<AdminUser>("AdminUsers", userId);
|
||||
}
|
||||
|
||||
public async Task<AdminUser?> GetUserByEmailAsync(string email)
|
||||
{
|
||||
return (await _mongoService.GetAllAsync<AdminUser>("AdminUsers")).FirstOrDefault((AdminUser u) => u.Email.ToLower() == email.ToLower());
|
||||
}
|
||||
|
||||
public async Task<AdminUser> CreateUserAsync(string email, string password, string name, string role = "Admin")
|
||||
{
|
||||
AdminUser user = new AdminUser
|
||||
{
|
||||
Email = email,
|
||||
PasswordHash = HashPassword(password),
|
||||
Name = name,
|
||||
Role = role,
|
||||
IsActive = true,
|
||||
CreatedAt = DateTime.UtcNow
|
||||
};
|
||||
await _mongoService.InsertAsync("AdminUsers", user);
|
||||
return user;
|
||||
}
|
||||
|
||||
public async Task<bool> ChangePasswordAsync(string userId, string oldPassword, string newPassword)
|
||||
{
|
||||
AdminUser adminUser = await GetUserByIdAsync(userId);
|
||||
if (adminUser == null || !VerifyPassword(oldPassword, adminUser.PasswordHash))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
adminUser.PasswordHash = HashPassword(newPassword);
|
||||
await _mongoService.UpdateAsync("AdminUsers", userId, adminUser);
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<bool> ResetPasswordAsync(string userId, string newPassword)
|
||||
{
|
||||
AdminUser adminUser = await GetUserByIdAsync(userId);
|
||||
if (adminUser == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
adminUser.PasswordHash = HashPassword(newPassword);
|
||||
await _mongoService.UpdateAsync("AdminUsers", userId, adminUser);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user