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

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

Upgraded database, added get subjects and get passed subjects.

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