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

Last change on this file since 4b35197 was 4b35197, checked in by Stefan-Saveski <stefansaveski19@…>, 8 months ago

Added role to sign in.

  • Property mode set to 100644
File size: 7.1 KB
Line 
1using System.IdentityModel.Tokens.Jwt;
2using System.Security.Claims;
3using System.Text;
4using BCrypt.Net;
5using iknow_api.Models;
6using iknow_api.DTOs;
7using iknow_api.Repositories;
8using Microsoft.IdentityModel.Tokens;
9using iknow_api.Data;
10
11namespace iknow_api.Services
12{
13 public class AuthService : IAuthService
14 {
15 private readonly IUserRepository _userRepository;
16 private readonly IRefreshTokenRepository _refreshTokenRepository;
17 private readonly IRefreshTokenService _refreshTokenService;
18 private readonly IConfiguration _configuration;
19 private readonly AppDbContext _context;
20
21 public AuthService(IUserRepository userRepository, IConfiguration configuration,
22 IRefreshTokenService refreshTokenService, IRefreshTokenRepository refreshTokenRepository,
23 AppDbContext context)
24 {
25 _userRepository = userRepository;
26 _configuration = configuration;
27 _refreshTokenService = refreshTokenService;
28 _refreshTokenRepository = refreshTokenRepository;
29 _context = context;
30 }
31
32 public async Task<bool> RegisterAsync(RegisterDto registerDto)
33 {
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
46 if (await _userRepository.UserExistsAsync(registerDto.Email))
47 throw new InvalidOperationException("User with this email already exists");
48
49 // Use a transaction to ensure all entities are saved together
50 using var transaction = await _context.Database.BeginTransactionAsync();
51 try
52 {
53 var user = new User
54 {
55 Name = registerDto.Name,
56 MiddleName = registerDto.MiddleName,
57 Surname = registerDto.Surname,
58 Index = registerDto.Index,
59 Email = registerDto.Email,
60 PasswordHash = BCrypt.Net.BCrypt.HashPassword(registerDto.Password),
61 Bday = DateTime.SpecifyKind(registerDto.Bday, DateTimeKind.Utc),
62 CreatedAt = DateTime.UtcNow,
63 Role = (Models.UserRole)registerDto.Role,
64 EMBG = registerDto.EMBG,
65 Nationality = registerDto.nationality,
66 Citizenship = registerDto.citizenship,
67 Gender = registerDto.gender
68 };
69
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,
78 City = registerDto.city,
79 Address = registerDto.address,
80 Municipality = registerDto.municipality,
81 PhoneNumber = registerDto.phoneNumber,
82 MicrosoftEmail = registerDto.microsoftEmail
83 };
84
85 var enrollmentInfo = new EnrollmentInfo
86 {
87 UserId = userId,
88 EnrollmentYear = registerDto.enrollmentYear,
89 Quota = (Models.Quota)registerDto.quotaType,
90 MajorId = registerDto.majorType,
91 StudyStatus = registerDto.studyStatus,
92 StudyType = registerDto.studyType
93 };
94
95 var highSchool = new HighSchool
96 {
97 UserId = userId,
98 GPA = registerDto.gpa,
99 HighSchoolType = (Models.HighSchoolType)registerDto.tip
100 };
101
102 _context.ContactInfo.Add(contactInfo);
103 _context.EnrollmentInfo.Add(enrollmentInfo);
104 _context.HighSchool.Add(highSchool);
105
106 // Save all related entities in a single transaction
107 await _context.SaveChangesAsync();
108 await transaction.CommitAsync();
109
110 return true;
111 }
112 catch
113 {
114 await transaction.RollbackAsync();
115 throw;
116 }
117 }
118
119 public async Task<AuthResultDto?> LoginAsync(LoginDto loginDto)
120 {
121 var user = await _userRepository.GetUserByUsernameAsync(loginDto.Email);
122 if (user == null || !BCrypt.Net.BCrypt.Verify(loginDto.Password, user.PasswordHash))
123 return null;
124
125 var result = new AuthResultDto
126 {
127 AccessToken = CreateToken(user),
128 Role = user.Role.ToString()
129 };
130
131 if (loginDto.GenerateRefreshToken)
132 {
133 result.RefreshToken = await _refreshTokenService.GenerateRefreshToken(user.Id);
134 }
135
136 return result;
137 }
138
139 public async Task<int> GetUsersCountAsync()
140 {
141 return await _userRepository.GetUsersCountAsync();
142 }
143
144 public async Task<AuthResultDto> GenerateNewJWT(VerifyRefreshTokenDto token)
145 {
146 int userid = await _refreshTokenRepository.GetUserId(token.token) ?? 0;
147 User? user = await _userRepository.GetOnlyUserByIdAsync(userid);
148
149 if (user == null)
150 throw new InvalidOperationException("User not found for provided refresh token.");
151
152 return new AuthResultDto
153 {
154 AccessToken = CreateToken(user),
155 Role = user.Role.ToString()
156 };
157 }
158
159 private string CreateToken(User user)
160 {
161 var claims = new[]
162 {
163 new Claim("id", user.Id.ToString()),
164 new Claim("email", user.Email ?? string.Empty),
165 new Claim("role", user.Role.ToString())
166 };
167
168 var keyString = _configuration["Jwt:Key"];
169 if (string.IsNullOrEmpty(keyString))
170 throw new Exception("JWT Key is missing in configuration!");
171
172 var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(keyString));
173 var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
174
175 var jwt = new JwtSecurityToken(
176 issuer: "iknow-api",
177 audience: "iknow-api",
178 claims: claims,
179 expires: DateTime.UtcNow.AddHours(1),
180 signingCredentials: creds
181 );
182
183 return new JwtSecurityTokenHandler().WriteToken(jwt);
184 }
185 }
186}
Note: See TracBrowser for help on using the repository browser.