You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
870 lines
30 KiB
C#
870 lines
30 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using System.IdentityModel.Tokens.Jwt;
|
|
using System.Security.Claims;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
using Microsoft.Extensions.Options;
|
|
using Microsoft.IdentityModel.Tokens;
|
|
using Haoliang.Models.User;
|
|
using Haoliang.Data.Repositories;
|
|
using Haoliang.Core.Services;
|
|
|
|
namespace Haoliang.Core.Services
|
|
{
|
|
public interface IAuthService
|
|
{
|
|
Task<AuthResult> LoginAsync(LoginRequest request);
|
|
Task<bool> LogoutAsync(int userId);
|
|
Task<bool> ValidateTokenAsync(string token);
|
|
Task<UserClaims> GetUserClaimsAsync(int userId);
|
|
Task<string> GenerateRefreshTokenAsync(int userId);
|
|
Task<bool> ValidateRefreshTokenAsync(int userId, string refreshToken);
|
|
Task<AuthResult> RefreshTokenAsync(string refreshToken);
|
|
}
|
|
|
|
public interface IUserService
|
|
{
|
|
Task<UserViewModel> CreateUserAsync(User user);
|
|
Task<UserViewModel> UpdateUserAsync(int userId, User user);
|
|
Task<bool> DeleteUserAsync(int userId);
|
|
Task<UserViewModel> GetUserByIdAsync(int userId);
|
|
Task<IEnumerable<UserViewModel>> GetAllUsersAsync();
|
|
Task<IEnumerable<UserViewModel>> GetUsersByRoleAsync(string roleName);
|
|
Task<bool> ActivateUserAsync(int userId);
|
|
Task<bool> DeactivateUserAsync(int userId);
|
|
Task<bool> ChangePasswordAsync(int userId, string oldPassword, string newPassword);
|
|
Task<bool> ResetPasswordAsync(int userId, string newPassword);
|
|
Task<bool> AssignRoleAsync(int userId, int roleId);
|
|
Task<bool> UnassignRoleAsync(int userId, int roleId);
|
|
}
|
|
|
|
public interface IPermissionService
|
|
{
|
|
Task<IEnumerable<Permission>> GetAllPermissionsAsync();
|
|
Task<Permission> GetPermissionByIdAsync(int permissionId);
|
|
Task<IEnumerable<Permission>> GetPermissionsByCategoryAsync(string category);
|
|
Task<bool> UserHasPermissionAsync(int userId, string permissionName);
|
|
Task<IEnumerable<string>> GetUserPermissionsAsync(int userId);
|
|
Task<bool> AddPermissionToRoleAsync(int roleId, int permissionId);
|
|
Task<bool> RemovePermissionFromRoleAsync(int roleId, int permissionId);
|
|
Task<bool> CreatePermissionAsync(Permission permission);
|
|
Task<bool> UpdatePermissionAsync(Permission permission);
|
|
Task<bool> DeletePermissionAsync(int permissionId);
|
|
}
|
|
|
|
public interface ISessionService
|
|
{
|
|
Task<UserSession> CreateSessionAsync(int userId, string deviceInfo, string ipAddress);
|
|
Task<bool> ValidateSessionAsync(string sessionToken);
|
|
Task<UserSession> GetSessionByTokenAsync(string sessionToken);
|
|
Task<bool> UpdateSessionActivityAsync(string sessionToken);
|
|
Task<bool> TerminateSessionAsync(string sessionToken);
|
|
Task<bool> TerminateAllUserSessionsAsync(int userId);
|
|
Task<IEnumerable<UserSession>> GetUserSessionsAsync(int userId);
|
|
Task<bool> CleanupExpiredSessionsAsync();
|
|
}
|
|
|
|
public class JwtSettings
|
|
{
|
|
public string SecretKey { get; set; }
|
|
public string Issuer { get; set; }
|
|
public string Audience { get; set; }
|
|
public int AccessTokenExpirationMinutes { get; set; }
|
|
public int RefreshTokenExpirationDays { get; set; }
|
|
}
|
|
|
|
public class AuthService : IAuthService
|
|
{
|
|
private readonly IUserRepository _userRepository;
|
|
private readonly IRoleRepository _roleRepository;
|
|
private readonly IUserSessionRepository _userSessionRepository;
|
|
private readonly IPasswordResetRepository _passwordResetRepository;
|
|
private readonly IOptions<JwtSettings> _jwtSettings;
|
|
private readonly ILoggerService _logger;
|
|
|
|
public AuthService(
|
|
IUserRepository userRepository,
|
|
IRoleRepository roleRepository,
|
|
IUserSessionRepository userSessionRepository,
|
|
IPasswordResetRepository passwordResetRepository,
|
|
IOptions<JwtSettings> jwtSettings,
|
|
ILoggerService logger)
|
|
{
|
|
_userRepository = userRepository;
|
|
_roleRepository = roleRepository;
|
|
_userSessionRepository = userSessionRepository;
|
|
_passwordResetRepository = passwordResetRepository;
|
|
_jwtSettings = jwtSettings;
|
|
_logger = logger;
|
|
}
|
|
|
|
public async Task<AuthResult> LoginAsync(LoginRequest request)
|
|
{
|
|
try
|
|
{
|
|
var user = await _userRepository.AuthenticateAsync(request.Username, request.Password);
|
|
if (user == null)
|
|
{
|
|
await _logger.LogWarningAsync($"Failed login attempt for username: {request.Username}");
|
|
return new AuthResult
|
|
{
|
|
Success = false,
|
|
Message = "Invalid username or password"
|
|
};
|
|
}
|
|
|
|
var token = GenerateJwtToken(user);
|
|
var refreshToken = await GenerateRefreshTokenAsync(user.Id);
|
|
|
|
var userClaims = await GetUserClaimsAsync(user.Id);
|
|
var permissions = await _roleRepository.GetRolePermissionsAsync(user.RoleId);
|
|
|
|
await _logger.LogInformationAsync($"User {user.Username} logged in successfully");
|
|
|
|
return new AuthResult
|
|
{
|
|
Success = true,
|
|
Token = token,
|
|
User = user,
|
|
Permissions = permissions.Select(p => p.Name).ToList(),
|
|
ExpiresAt = DateTime.Now.AddMinutes(_jwtSettings.Value.AccessTokenExpirationMinutes)
|
|
};
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await _logger.LogErrorAsync($"Login failed: {ex.Message}");
|
|
return new AuthResult
|
|
{
|
|
Success = false,
|
|
Message = "An error occurred during login"
|
|
};
|
|
}
|
|
}
|
|
|
|
public async Task<bool> LogoutAsync(int userId)
|
|
{
|
|
try
|
|
{
|
|
var sessions = await _userSessionRepository.GetUserSessionsAsync(userId);
|
|
foreach (var session in sessions)
|
|
{
|
|
await _userSessionRepository.TerminateSessionAsync(session.SessionToken);
|
|
}
|
|
|
|
await _logger.LogInformationAsync($"User {userId} logged out");
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await _logger.LogErrorAsync($"Logout failed: {ex.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async Task<bool> ValidateTokenAsync(string token)
|
|
{
|
|
try
|
|
{
|
|
var tokenHandler = new JwtSecurityTokenHandler();
|
|
var key = Encoding.UTF8.GetBytes(_jwtSettings.Value.SecretKey);
|
|
|
|
tokenHandler.ValidateToken(token, new TokenValidationParameters
|
|
{
|
|
ValidateIssuerSigningKey = true,
|
|
IssuerSigningKey = new SymmetricSecurityKey(key),
|
|
ValidateIssuer = true,
|
|
ValidIssuer = _jwtSettings.Value.Issuer,
|
|
ValidateAudience = true,
|
|
ValidAudience = _jwtSettings.Value.Audience,
|
|
ValidateLifetime = true,
|
|
ClockSkew = TimeSpan.Zero
|
|
}, out SecurityToken validatedToken);
|
|
|
|
return true;
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async Task<UserClaims> GetUserClaimsAsync(int userId)
|
|
{
|
|
var user = await _userRepository.GetByIdAsync(userId);
|
|
if (user == null)
|
|
return null;
|
|
|
|
var role = await _roleRepository.GetByIdAsync(user.RoleId);
|
|
var permissions = await _roleRepository.GetRolePermissionsAsync(user.RoleId);
|
|
|
|
return new UserClaims
|
|
{
|
|
UserId = user.Id,
|
|
Username = user.Username,
|
|
RealName = user.RealName,
|
|
RoleId = user.RoleId,
|
|
RoleName = role?.RoleName ?? "",
|
|
Permissions = permissions.Select(p => p.Name).ToList(),
|
|
SessionTime = DateTime.Now
|
|
};
|
|
}
|
|
|
|
public async Task<string> GenerateRefreshTokenAsync(int userId)
|
|
{
|
|
var refreshToken = Guid.NewGuid().ToString();
|
|
var expiresAt = DateTime.Now.AddDays(_jwtSettings.Value.RefreshTokenExpirationDays);
|
|
|
|
var session = new UserSession
|
|
{
|
|
UserId = userId,
|
|
SessionToken = refreshToken,
|
|
DeviceInfo = "",
|
|
IPAddress = "",
|
|
LoginTime = DateTime.Now,
|
|
LastActivityTime = DateTime.Now,
|
|
IsActive = true,
|
|
CreatedAt = DateTime.Now
|
|
};
|
|
|
|
await _userSessionRepository.AddAsync(session);
|
|
await _userSessionRepository.SaveAsync();
|
|
|
|
return refreshToken;
|
|
}
|
|
|
|
public async Task<bool> ValidateRefreshTokenAsync(int userId, string refreshToken)
|
|
{
|
|
var session = await _userSessionRepository.GetSessionByTokenAsync(refreshToken);
|
|
return session != null && session.UserId == userId && session.IsActive;
|
|
}
|
|
|
|
public async Task<AuthResult> RefreshTokenAsync(string refreshToken)
|
|
{
|
|
try
|
|
{
|
|
var session = await _userSessionRepository.GetSessionByTokenAsync(refreshToken);
|
|
if (session == null || !session.IsActive)
|
|
{
|
|
return new AuthResult
|
|
{
|
|
Success = false,
|
|
Message = "Invalid refresh token"
|
|
};
|
|
}
|
|
|
|
var user = await _userRepository.GetByIdAsync(session.UserId);
|
|
if (user == null)
|
|
{
|
|
return new AuthResult
|
|
{
|
|
Success = false,
|
|
Message = "User not found"
|
|
};
|
|
}
|
|
|
|
var newToken = GenerateJwtToken(user);
|
|
var newRefreshToken = await GenerateRefreshTokenAsync(user.Id);
|
|
|
|
// Terminate old refresh token
|
|
await _userSessionRepository.TerminateSessionAsync(refreshToken);
|
|
|
|
var userClaims = await GetUserClaimsAsync(user.Id);
|
|
var permissions = await _roleRepository.GetRolePermissionsAsync(user.RoleId);
|
|
|
|
return new AuthResult
|
|
{
|
|
Success = true,
|
|
Token = newToken,
|
|
RefreshToken = newRefreshToken,
|
|
User = user,
|
|
Permissions = permissions.Select(p => p.Name).ToList(),
|
|
ExpiresAt = DateTime.Now.AddMinutes(_jwtSettings.Value.AccessTokenExpirationMinutes)
|
|
};
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await _logger.LogErrorAsync($"Token refresh failed: {ex.Message}");
|
|
return new AuthResult
|
|
{
|
|
Success = false,
|
|
Message = "Failed to refresh token"
|
|
};
|
|
}
|
|
}
|
|
|
|
private string GenerateJwtToken(User user)
|
|
{
|
|
var tokenHandler = new JwtSecurityTokenHandler();
|
|
var key = Encoding.UTF8.GetBytes(_jwtSettings.Value.SecretKey);
|
|
|
|
var claims = new[]
|
|
{
|
|
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
|
|
new Claim(ClaimTypes.Name, user.Username),
|
|
new Claim(ClaimTypes.GivenName, user.RealName),
|
|
new Claim(ClaimTypes.Email, user.Email),
|
|
new Claim(ClaimTypes.Role, user.RoleId.ToString())
|
|
};
|
|
|
|
var tokenDescriptor = new SecurityTokenDescriptor
|
|
{
|
|
Subject = new ClaimsIdentity(claims),
|
|
Expires = DateTime.Now.AddMinutes(_jwtSettings.Value.AccessTokenExpirationMinutes),
|
|
Issuer = _jwtSettings.Value.Issuer,
|
|
Audience = _jwtSettings.Value.Audience,
|
|
SigningCredentials = new SigningCredentials(
|
|
new SymmetricSecurityKey(key),
|
|
SecurityAlgorithms.HmacSha256Signature)
|
|
};
|
|
|
|
var token = tokenHandler.CreateToken(tokenDescriptor);
|
|
return tokenHandler.WriteToken(token);
|
|
}
|
|
}
|
|
|
|
public class UserService : IUserService
|
|
{
|
|
private readonly IUserRepository _userRepository;
|
|
private readonly IRoleRepository _roleRepository;
|
|
private readonly IEmployeeRepository _employeeRepository;
|
|
private readonly IPermissionService _permissionService;
|
|
private readonly ILoggerService _logger;
|
|
|
|
public UserService(
|
|
IUserRepository userRepository,
|
|
IRoleRepository roleRepository,
|
|
IEmployeeRepository employeeRepository,
|
|
IPermissionService permissionService,
|
|
ILoggerService logger)
|
|
{
|
|
_userRepository = userRepository;
|
|
_roleRepository = roleRepository;
|
|
_employeeRepository = employeeRepository;
|
|
_permissionService = permissionService;
|
|
_logger = logger;
|
|
}
|
|
|
|
public async Task<UserViewModel> CreateUserAsync(User user)
|
|
{
|
|
try
|
|
{
|
|
if (await _userRepository.UsernameExistsAsync(user.Username))
|
|
{
|
|
throw new Exception("Username already exists");
|
|
}
|
|
|
|
if (await _userRepository.EmailExistsAsync(user.Email))
|
|
{
|
|
throw new Exception("Email already exists");
|
|
}
|
|
|
|
user.PasswordHash = HashPassword(user.PasswordHash);
|
|
user.IsActive = true;
|
|
user.CreatedAt = DateTime.Now;
|
|
user.UpdatedAt = DateTime.Now;
|
|
|
|
await _userRepository.AddAsync(user);
|
|
await _userRepository.SaveAsync();
|
|
|
|
await _logger.LogInformationAsync($"User created: {user.Username}");
|
|
|
|
return await GetUserByIdAsync(user.Id);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await _logger.LogErrorAsync($"Failed to create user: {ex.Message}");
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public async Task<UserViewModel> UpdateUserAsync(int userId, User user)
|
|
{
|
|
try
|
|
{
|
|
var existingUser = await _userRepository.GetByIdAsync(userId);
|
|
if (existingUser == null)
|
|
throw new Exception("User not found");
|
|
|
|
// Don't update username if it hasn't changed
|
|
if (existingUser.Username != user.Username)
|
|
{
|
|
if (await _userRepository.UsernameExistsAsync(user.Username))
|
|
throw new Exception("Username already exists");
|
|
}
|
|
|
|
// Don't update email if it hasn't changed
|
|
if (existingUser.Email != user.Email)
|
|
{
|
|
if (await _userRepository.EmailExistsAsync(user.Email))
|
|
throw new Exception("Email already exists");
|
|
}
|
|
|
|
// Update user properties
|
|
existingUser.RealName = user.RealName;
|
|
existingUser.Email = user.Email;
|
|
existingUser.Phone = user.Phone;
|
|
existingUser.RoleId = user.RoleId;
|
|
existingUser.IsActive = user.IsActive;
|
|
existingUser.UpdatedAt = DateTime.Now;
|
|
|
|
if (!string.IsNullOrEmpty(user.PasswordHash))
|
|
{
|
|
existingUser.PasswordHash = HashPassword(user.PasswordHash);
|
|
}
|
|
|
|
_userRepository.Update(existingUser);
|
|
await _userRepository.SaveAsync();
|
|
|
|
await _logger.LogInformationAsync($"User updated: {existingUser.Username}");
|
|
|
|
return await GetUserByIdAsync(userId);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await _logger.LogErrorAsync($"Failed to update user: {ex.Message}");
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public async Task<bool> DeleteUserAsync(int userId)
|
|
{
|
|
try
|
|
{
|
|
var user = await _userRepository.GetByIdAsync(userId);
|
|
if (user == null)
|
|
return false;
|
|
|
|
// Check if user has active sessions
|
|
// (Assuming you have a session repository)
|
|
|
|
// Check if user is assigned to devices
|
|
var employee = await _employeeRepository.GetByEmployeeCodeAsync(user.Username);
|
|
if (employee != null && employee.AssignedDevices.Any())
|
|
{
|
|
throw new Exception("Cannot delete user that is assigned to devices");
|
|
}
|
|
|
|
_userRepository.Remove(user);
|
|
await _userRepository.SaveAsync();
|
|
|
|
await _logger.LogInformationAsync($"User deleted: {user.Username}");
|
|
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await _logger.LogErrorAsync($"Failed to delete user: {ex.Message}");
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public async Task<UserViewModel> GetUserByIdAsync(int userId)
|
|
{
|
|
var user = await _userRepository.GetByIdAsync(userId);
|
|
if (user == null)
|
|
return null;
|
|
|
|
var role = await _roleRepository.GetByIdAsync(user.RoleId);
|
|
var permissions = await _roleRepository.GetRolePermissionsAsync(user.RoleId);
|
|
|
|
return new UserViewModel
|
|
{
|
|
Id = user.Id,
|
|
Username = user.Username,
|
|
RealName = user.RealName,
|
|
Email = user.Email,
|
|
Phone = user.Phone,
|
|
RoleName = role?.RoleName ?? "",
|
|
IsActive = user.IsActive,
|
|
LastLoginTime = user.LastLoginTime,
|
|
CreatedAt = user.CreatedAt,
|
|
Permissions = permissions.Select(p => p.Name).ToList()
|
|
};
|
|
}
|
|
|
|
public async Task<IEnumerable<UserViewModel>> GetAllUsersAsync()
|
|
{
|
|
var users = await _userRepository.GetAllAsync();
|
|
var userViewModels = new List<UserViewModel>();
|
|
|
|
foreach (var user in users)
|
|
{
|
|
userViewModels.Add(await GetUserByIdAsync(user.Id));
|
|
}
|
|
|
|
return userViewModels;
|
|
}
|
|
|
|
public async Task<IEnumerable<UserViewModel>> GetUsersByRoleAsync(string roleName)
|
|
{
|
|
var role = await _roleRepository.GetByNameAsync(roleName);
|
|
if (role == null)
|
|
return new List<UserViewModel>();
|
|
|
|
var users = await _userRepository.GetByRoleIdAsync(role.Id);
|
|
var userViewModels = new List<UserViewModel>();
|
|
|
|
foreach (var user in users)
|
|
{
|
|
userViewModels.Add(await GetUserByIdAsync(user.Id));
|
|
}
|
|
|
|
return userViewModels;
|
|
}
|
|
|
|
public async Task<bool> ActivateUserAsync(int userId)
|
|
{
|
|
return await SetUserActiveStatusAsync(userId, true);
|
|
}
|
|
|
|
public async Task<bool> DeactivateUserAsync(int userId)
|
|
{
|
|
return await SetUserActiveStatusAsync(userId, false);
|
|
}
|
|
|
|
public async Task<bool> ChangePasswordAsync(int userId, string oldPassword, string newPassword)
|
|
{
|
|
try
|
|
{
|
|
return await _userRepository.ChangePasswordAsync(userId, oldPassword, newPassword);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await _logger.LogErrorAsync($"Failed to change password: {ex.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async Task<bool> ResetPasswordAsync(int userId, string newPassword)
|
|
{
|
|
try
|
|
{
|
|
return await _userRepository.ResetPasswordAsync(userId, newPassword);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await _logger.LogErrorAsync($"Failed to reset password: {ex.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async Task<bool> AssignRoleAsync(int userId, int roleId)
|
|
{
|
|
var user = await _userRepository.GetByIdAsync(userId);
|
|
if (user == null)
|
|
return false;
|
|
|
|
user.RoleId = roleId;
|
|
user.UpdatedAt = DateTime.Now;
|
|
|
|
_userRepository.Update(user);
|
|
await _userRepository.SaveAsync();
|
|
|
|
return true;
|
|
}
|
|
|
|
public async Task<bool> UnassignRoleAsync(int userId, int roleId)
|
|
{
|
|
var user = await _userRepository.GetByIdAsync(userId);
|
|
if (user == null || user.RoleId != roleId)
|
|
return false;
|
|
|
|
// Assign default role
|
|
var defaultRole = await _roleRepository.GetByNameAsync("User");
|
|
if (defaultRole != null)
|
|
{
|
|
user.RoleId = defaultRole.Id;
|
|
user.UpdatedAt = DateTime.Now;
|
|
|
|
_userRepository.Update(user);
|
|
await _userRepository.SaveAsync();
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private async Task<bool> SetUserActiveStatusAsync(int userId, bool isActive)
|
|
{
|
|
var user = await _userRepository.GetByIdAsync(userId);
|
|
if (user == null)
|
|
return false;
|
|
|
|
user.IsActive = isActive;
|
|
user.UpdatedAt = DateTime.Now;
|
|
|
|
_userRepository.Update(user);
|
|
await _userRepository.SaveAsync();
|
|
|
|
return true;
|
|
}
|
|
|
|
private string HashPassword(string password)
|
|
{
|
|
using (var sha256 = SHA256.Create())
|
|
{
|
|
var bytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(password));
|
|
return Convert.ToBase64String(bytes);
|
|
}
|
|
}
|
|
}
|
|
|
|
public class PermissionService : IPermissionService
|
|
{
|
|
private readonly IRoleRepository _roleRepository;
|
|
private readonly IPermissionRepository _permissionRepository;
|
|
private readonly ILoggerService _logger;
|
|
|
|
public PermissionService(
|
|
IRoleRepository roleRepository,
|
|
IPermissionRepository permissionRepository,
|
|
ILoggerService logger)
|
|
{
|
|
_roleRepository = roleRepository;
|
|
_permissionRepository = permissionRepository;
|
|
_logger = logger;
|
|
}
|
|
|
|
public async Task<IEnumerable<Permission>> GetAllPermissionsAsync()
|
|
{
|
|
return await _permissionRepository.GetAllAsync();
|
|
}
|
|
|
|
public async Task<Permission> GetPermissionByIdAsync(int permissionId)
|
|
{
|
|
return await _permissionRepository.GetByIdAsync(permissionId);
|
|
}
|
|
|
|
public async Task<IEnumerable<Permission>> GetPermissionsByCategoryAsync(string category)
|
|
{
|
|
return await _permissionRepository.FindAsync(p => p.Category == category);
|
|
}
|
|
|
|
public async Task<bool> UserHasPermissionAsync(int userId, string permissionName)
|
|
{
|
|
return await _roleRepository.UserHasPermissionAsync(userId, permissionName);
|
|
}
|
|
|
|
public async Task<IEnumerable<string>> GetUserPermissionsAsync(int userId)
|
|
{
|
|
var user = await _roleRepository.GetUserById(userId); // Assuming this method exists
|
|
if (user == null)
|
|
return new List<string>();
|
|
|
|
var role = await _roleRepository.GetByIdAsync(user.RoleId);
|
|
return role?.Permissions ?? new List<string>();
|
|
}
|
|
|
|
public async Task<bool> AddPermissionToRoleAsync(int roleId, int permissionId)
|
|
{
|
|
try
|
|
{
|
|
return await _roleRepository.AddPermissionToRoleAsync(roleId, permissionId);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await _logger.LogErrorAsync($"Failed to add permission to role: {ex.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async Task<bool> RemovePermissionFromRoleAsync(int roleId, int permissionId)
|
|
{
|
|
try
|
|
{
|
|
return await _roleRepository.RemovePermissionFromRoleAsync(roleId, permissionId);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await _logger.LogErrorAsync($"Failed to remove permission from role: {ex.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async Task<bool> CreatePermissionAsync(Permission permission)
|
|
{
|
|
try
|
|
{
|
|
return await _permissionRepository.AddPermissionAsync(permission);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await _logger.LogErrorAsync($"Failed to create permission: {ex.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async Task<bool> UpdatePermissionAsync(Permission permission)
|
|
{
|
|
try
|
|
{
|
|
await _permissionRepository.UpdatePermissionAsync(permission);
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await _logger.LogErrorAsync($"Failed to update permission: {ex.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async Task<bool> DeletePermissionAsync(int permissionId)
|
|
{
|
|
try
|
|
{
|
|
return await _permissionRepository.DeletePermissionAsync(permissionId);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await _logger.LogErrorAsync($"Failed to delete permission: {ex.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
public class SessionService : ISessionService
|
|
{
|
|
private readonly IUserSessionRepository _userSessionRepository;
|
|
private readonly ILoggerService _logger;
|
|
|
|
public SessionService(
|
|
IUserSessionRepository userSessionRepository,
|
|
ILoggerService logger)
|
|
{
|
|
_userSessionRepository = userSessionRepository;
|
|
_logger = logger;
|
|
}
|
|
|
|
public async Task<UserSession> CreateSessionAsync(int userId, string deviceInfo, string ipAddress)
|
|
{
|
|
var sessionToken = Guid.NewGuid().ToString();
|
|
|
|
var session = new UserSession
|
|
{
|
|
UserId = userId,
|
|
SessionToken = sessionToken,
|
|
DeviceInfo = deviceInfo,
|
|
IPAddress = ipAddress,
|
|
LoginTime = DateTime.Now,
|
|
LastActivityTime = DateTime.Now,
|
|
IsActive = true,
|
|
CreatedAt = DateTime.Now
|
|
};
|
|
|
|
await _userSessionRepository.AddAsync(session);
|
|
await _userSessionRepository.SaveAsync();
|
|
|
|
await _logger.LogInformationAsync($"Session created for user {userId}");
|
|
|
|
return session;
|
|
}
|
|
|
|
public async Task<bool> ValidateSessionAsync(string sessionToken)
|
|
{
|
|
try
|
|
{
|
|
var session = await _userSessionRepository.GetSessionByTokenAsync(sessionToken);
|
|
return session != null && session.IsActive;
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async Task<UserSession> GetSessionByTokenAsync(string sessionToken)
|
|
{
|
|
return await _userSessionRepository.GetSessionByTokenAsync(sessionToken);
|
|
}
|
|
|
|
public async Task<bool> UpdateSessionActivityAsync(string sessionToken)
|
|
{
|
|
try
|
|
{
|
|
var session = await _userSessionRepository.GetSessionByTokenAsync(sessionToken);
|
|
if (session != null)
|
|
{
|
|
session.LastActivityTime = DateTime.Now;
|
|
await _userSessionRepository.UpdateSessionAsync(session);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await _logger.LogErrorAsync($"Failed to update session: {ex.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async Task<bool> TerminateSessionAsync(string sessionToken)
|
|
{
|
|
try
|
|
{
|
|
var session = await _userSessionRepository.GetSessionByTokenAsync(sessionToken);
|
|
if (session != null)
|
|
{
|
|
session.IsActive = false;
|
|
session.LogoutTime = DateTime.Now;
|
|
await _userSessionRepository.UpdateSessionAsync(session);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await _logger.LogErrorAsync($"Failed to terminate session: {ex.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async Task<bool> TerminateAllUserSessionsAsync(int userId)
|
|
{
|
|
try
|
|
{
|
|
var sessions = await _userSessionRepository.GetUserSessionsAsync(userId);
|
|
foreach (var session in sessions)
|
|
{
|
|
await TerminateSessionAsync(session.SessionToken);
|
|
}
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await _logger.LogErrorAsync($"Failed to terminate all sessions: {ex.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async Task<IEnumerable<UserSession>> GetUserSessionsAsync(int userId)
|
|
{
|
|
return await _userSessionRepository.GetUserSessionsAsync(userId);
|
|
}
|
|
|
|
public async Task<bool> CleanupExpiredSessionsAsync()
|
|
{
|
|
try
|
|
{
|
|
var expiredSessions = await _userSessionRepository.GetExpiredSessionsAsync();
|
|
if (expiredSessions.Any())
|
|
{
|
|
await _userSessionRepository.RemoveRangeAsync(expiredSessions);
|
|
await _userSessionRepository.SaveAsync();
|
|
|
|
await _logger.LogInformationAsync($"Cleaned up {expiredSessions.Count()} expired sessions");
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await _logger.LogErrorAsync($"Failed to cleanup expired sessions: {ex.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
} |