using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Text; using BCrypt.Net; using iknow_api.Services; using iknow_api.Models; using iknow_api.DTOs; using iknow_api.Repositories; using Microsoft.IdentityModel.Tokens; namespace iknow_api.Services { public class AuthService : IAuthService { private readonly IUserRepository _userRepository; private readonly IRefreshTokenRepository _refreshTokenRepository; private readonly IRefreshTokenService _refreshTokenService; private readonly IConfiguration _configuration; public AuthService(IUserRepository userRepository, IConfiguration configuration , IRefreshTokenService refreshTokenService, IRefreshTokenRepository refreshTokenRepository) { _userRepository = userRepository; _configuration = configuration; _refreshTokenService = refreshTokenService; _refreshTokenRepository = refreshTokenRepository; } public async Task RegisterAsync(RegisterDto registerDto) { if (await _userRepository.UserExistsAsync(registerDto.Email)) return false; var user = new User { Name = registerDto.Name, Surname = registerDto.Surname, Index = registerDto.Index, Email = registerDto.Email, PasswordHash = BCrypt.Net.BCrypt.HashPassword(registerDto.Password), Bday = DateTime.SpecifyKind(registerDto.Bday, DateTimeKind.Utc), CreatedAt = DateTime.UtcNow, Role = (Models.UserRole)registerDto.Role, EMBG = registerDto.EMBG }; await _userRepository.AddUserAsync(user); int userId = user.Id; var contactInfo = new ContactInfo { UserId = userId, city = registerDto.city, address = registerDto.address, municipality = registerDto.municipality, phoneNumber = registerDto.phoneNumber, microsoftEmail = registerDto.microsoftEmail }; await _userRepository.AddContactAsync(contactInfo); var enrollmentInfo = new EnrollmentInfo { UserId = userId, enrollmentYear = registerDto.enrollmentYear, quota = (Models.Quota)registerDto.quotaType, MajorId = registerDto.majorType }; await _userRepository.AddEnrollmentAsync(enrollmentInfo); await _userRepository.AddHighSchoolAsync(new HighSchool { UserId = userId, GPA = registerDto.gpa, tip = (Models.type)registerDto.tip }); return true; } public async Task LoginAsync(LoginDto loginDto) { var user = await _userRepository.GetUserByUsernameAsync(loginDto.Email); if (user == null || !BCrypt.Net.BCrypt.Verify(loginDto.Password, user.PasswordHash)) return null; var result = new AuthResultDto { AccessToken = CreateToken(user) }; if (loginDto.GenerateRefreshToken) { int userid = _userRepository.GetUserByUsernameAsync(loginDto.Email).Id; result.RefreshToken = await _refreshTokenService.GenerateRefreshToken(userid); } return result; } public async Task GetUsersCountAsync() { return await _userRepository.GetUsersCountAsync(); } public async Task GenerateNewJWT(VerifyRefreshTokenDto token) { int userid = await _refreshTokenRepository.GetUserId(token.token) ?? 0; User ?user = await _userRepository.GetOnlyUserByIdAsync(userid); var result = new AuthResultDto { AccessToken = CreateToken(user) }; return result; } private string CreateToken(User user) { var claims = new[] { new Claim("id", user.Id.ToString()), new Claim("email", user.Email ?? string.Empty), new Claim("role", user.Role.ToString()) }; var keyString = _configuration["Jwt:Key"]; if (string.IsNullOrEmpty(keyString)) throw new Exception("JWT Key is missing in configuration!"); var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(keyString)); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var token = new JwtSecurityToken( issuer: "iknow-api", audience: "iknow-api", claims: claims, expires: DateTime.UtcNow.AddHours(1), signingCredentials: creds ); return new JwtSecurityTokenHandler().WriteToken(token); } } }