source: iknow-api/Services/Implementations/AuthService.cs@ ea40556

Last change on this file since ea40556 was ea40556, checked in by Stefan-Saveski <stefansaveski19@…>, 8 days ago
  • ready for presentation
  • Property mode set to 100644
File size: 6.7 KB
RevLine 
[ea40556]1using System.IdentityModel.Tokens.Jwt;
[5b42c8d]2using System.Security.Claims;
3using System.Text;
4using BCrypt.Net;
[e49c3ed]5using iknow_api.Models;
[277bd72]6using iknow_api.DTOs;
7using iknow_api.Repositories;
[5b42c8d]8using Microsoft.IdentityModel.Tokens;
[22439d3]9using iknow_api.Data;
[5b42c8d]10
[277bd72]11namespace iknow_api.Services
[5b42c8d]12{
13 public class AuthService : IAuthService
14 {
15 private readonly IUserRepository _userRepository;
[c155364]16 private readonly IRefreshTokenRepository _refreshTokenRepository;
[3347c1b]17 private readonly IRefreshTokenService _refreshTokenService;
[5b42c8d]18 private readonly IConfiguration _configuration;
[22439d3]19 private readonly AppDbContext _context;
[5b42c8d]20
[22439d3]21 public AuthService(IUserRepository userRepository, IConfiguration configuration,
22 IRefreshTokenService refreshTokenService, IRefreshTokenRepository refreshTokenRepository,
23 AppDbContext context)
[5b42c8d]24 {
25 _userRepository = userRepository;
26 _configuration = configuration;
[3347c1b]27 _refreshTokenService = refreshTokenService;
[c155364]28 _refreshTokenRepository = refreshTokenRepository;
[22439d3]29 _context = context;
[5b42c8d]30 }
31
[c7d4a59]32 public async Task<bool> RegisterAsync(RegisterDto registerDto)
[5b42c8d]33 {
[c2f79d7]34 // Debug: Log all incoming DTO values
35 Console.WriteLine("=== RegisterDto Debug Info ===");
36 Console.WriteLine($"Name: {registerDto.Name}");
37 Console.WriteLine($"Email: {registerDto.Email}");
38 Console.WriteLine($"majorType: {registerDto.majorType}");
39 Console.WriteLine($"enrollmentYear: {registerDto.enrollmentYear}");
40 Console.WriteLine($"quotaType: {registerDto.quotaType}");
41 Console.WriteLine($"Role: {registerDto.Role}");
42 Console.WriteLine($"tip: {registerDto.tip}");
43 Console.WriteLine("==============================");
44
45 // Check if user already exists
[c7d4a59]46 if (await _userRepository.UserExistsAsync(registerDto.Email))
[c2f79d7]47 throw new InvalidOperationException("User with this email already exists");
[5b42c8d]48
[22439d3]49 // Use a transaction to ensure all entities are saved together
50 using var transaction = await _context.Database.BeginTransactionAsync();
51 try
[5b42c8d]52 {
[ea40556]53 // quota and enrollment_year are attributes of Users in the ER
54 // model, so they are set here rather than on a separate entity.
[22439d3]55 var user = new User
56 {
57 Name = registerDto.Name,
58 Surname = registerDto.Surname,
59 Index = registerDto.Index,
60 Email = registerDto.Email,
61 PasswordHash = BCrypt.Net.BCrypt.HashPassword(registerDto.Password),
[ea40556]62 Bday = DateTime.SpecifyKind(registerDto.Bday, DateTimeKind.Unspecified),
63 CreatedAt = DateTime.SpecifyKind(DateTime.UtcNow, DateTimeKind.Unspecified),
[22439d3]64 Role = (Models.UserRole)registerDto.Role,
[2d64b2e]65 EMBG = registerDto.EMBG,
[ea40556]66 Quota = (Models.Quota)registerDto.quotaType,
67 EnrollmentYear = registerDto.enrollmentYear
[22439d3]68 };
[5b42c8d]69
[22439d3]70 _context.User.Add(user);
71 await _context.SaveChangesAsync();
72
73 int userId = user.Id;
74
75 var contactInfo = new ContactInfo
76 {
77 UserId = userId,
[2d64b2e]78 City = registerDto.city,
79 Address = registerDto.address,
80 Municipality = registerDto.municipality,
81 PhoneNumber = registerDto.phoneNumber,
82 MicrosoftEmail = registerDto.microsoftEmail
[22439d3]83 };
84
85 var highSchool = new HighSchool
86 {
87 UserId = userId,
88 GPA = registerDto.gpa,
[2d64b2e]89 HighSchoolType = (Models.HighSchoolType)registerDto.tip
[22439d3]90 };
91
92 _context.ContactInfo.Add(contactInfo);
93 _context.HighSchool.Add(highSchool);
94
95 // Save all related entities in a single transaction
96 await _context.SaveChangesAsync();
97 await transaction.CommitAsync();
98
99 return true;
100 }
101 catch
[b38c39c]102 {
[22439d3]103 await transaction.RollbackAsync();
104 throw;
105 }
[5b42c8d]106 }
107
[3347c1b]108 public async Task<AuthResultDto?> LoginAsync(LoginDto loginDto)
[5b42c8d]109 {
[c7d4a59]110 var user = await _userRepository.GetUserByUsernameAsync(loginDto.Email);
111 if (user == null || !BCrypt.Net.BCrypt.Verify(loginDto.Password, user.PasswordHash))
[5b42c8d]112 return null;
113
[4b35197]114 var result = new AuthResultDto
[3347c1b]115 {
[4b35197]116 AccessToken = CreateToken(user),
117 Role = user.Role.ToString()
[3347c1b]118 };
119
120 if (loginDto.GenerateRefreshToken)
121 {
[22439d3]122 result.RefreshToken = await _refreshTokenService.GenerateRefreshToken(user.Id);
[3347c1b]123 }
124
125 return result;
[5b42c8d]126 }
127
128 public async Task<int> GetUsersCountAsync()
129 {
130 return await _userRepository.GetUsersCountAsync();
131 }
132
[c155364]133 public async Task<AuthResultDto> GenerateNewJWT(VerifyRefreshTokenDto token)
134 {
135 int userid = await _refreshTokenRepository.GetUserId(token.token) ?? 0;
[4b35197]136 User? user = await _userRepository.GetOnlyUserByIdAsync(userid);
[c155364]137
[4b35197]138 if (user == null)
139 throw new InvalidOperationException("User not found for provided refresh token.");
140
141 return new AuthResultDto
[c155364]142 {
[4b35197]143 AccessToken = CreateToken(user),
144 Role = user.Role.ToString()
[c155364]145 };
146 }
147
[5b42c8d]148 private string CreateToken(User user)
149 {
150 var claims = new[]
151 {
152 new Claim("id", user.Id.ToString()),
[e49c3ed]153 new Claim("email", user.Email ?? string.Empty),
[c7d4a59]154 new Claim("role", user.Role.ToString())
[5b42c8d]155 };
156
157 var keyString = _configuration["Jwt:Key"];
158 if (string.IsNullOrEmpty(keyString))
159 throw new Exception("JWT Key is missing in configuration!");
160
161 var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(keyString));
162 var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
163
[4b35197]164 var jwt = new JwtSecurityToken(
[c7d4a59]165 issuer: "iknow-api",
166 audience: "iknow-api",
[5b42c8d]167 claims: claims,
[c7d4a59]168 expires: DateTime.UtcNow.AddHours(1),
[5b42c8d]169 signingCredentials: creds
170 );
171
[4b35197]172 return new JwtSecurityTokenHandler().WriteToken(jwt);
[5b42c8d]173 }
174 }
175}
Note: See TracBrowser for help on using the repository browser.