diff --git a/api/src/BaseClasses/BaseController.cs b/api/src/BaseClasses/BaseController.cs index dc09d65..83cb0c7 100644 --- a/api/src/BaseClasses/BaseController.cs +++ b/api/src/BaseClasses/BaseController.cs @@ -5,14 +5,14 @@ namespace WinStudentGoalTracker.BaseClasses; public class BaseController : ControllerBase { - protected (int userId, ActionResult? error) GetUserIdFromClaims() + protected (Guid userId, ActionResult? error) GetUserIdFromClaims() { var userIdClaim = User.FindFirst("user_id")?.Value ?? User.FindFirst(ClaimTypes.NameIdentifier)?.Value; - if (string.IsNullOrWhiteSpace(userIdClaim) || !int.TryParse(userIdClaim, out var userId)) + if (string.IsNullOrWhiteSpace(userIdClaim) || !Guid.TryParse(userIdClaim, out var userId)) { - return (0, Unauthorized("Missing or invalid user_id claim.")); + return (Guid.Empty, Unauthorized("Missing or invalid user_id claim.")); } return (userId, null); diff --git a/api/src/Controllers/AuthController.cs b/api/src/Controllers/AuthController.cs index a4e5488..e3980e1 100644 --- a/api/src/Controllers/AuthController.cs +++ b/api/src/Controllers/AuthController.cs @@ -87,6 +87,7 @@ public class AuthController : BaseController // Store refresh token in database (30 days expiration) var refreshTokenId = await _authRepo.CreateRefreshTokenAsync( + Guid.NewGuid(), user.IdUser, refreshTokenHash, refreshTokenSalt, @@ -151,7 +152,7 @@ public class AuthController : BaseController var tokenIdStr = refreshTokenDto.RefreshToken[..dotIndex]; var secretToken = refreshTokenDto.RefreshToken[(dotIndex + 1)..]; - if (!int.TryParse(tokenIdStr, out int tokenId)) + if (!Guid.TryParse(tokenIdStr, out Guid tokenId)) { return BadRequest(new ResponseResult { @@ -221,6 +222,7 @@ public class AuthController : BaseController var newRefreshTokenId = await _authRepo.ReplaceRefreshTokenAsync( matchedToken.IdRefreshToken, + Guid.NewGuid(), tokenUser.IdUser, newRefreshTokenHash, newRefreshTokenSalt, @@ -272,7 +274,7 @@ public class AuthController : BaseController if (error != null) return error; var dotIndex = logoutDto.RefreshToken.IndexOf('.'); - if (dotIndex < 1 || !int.TryParse(logoutDto.RefreshToken[..dotIndex], out int tokenId)) + if (dotIndex < 1 || !Guid.TryParse(logoutDto.RefreshToken[..dotIndex], out Guid tokenId)) { return BadRequest(new ResponseResult { diff --git a/api/src/Controllers/StudentController.cs b/api/src/Controllers/StudentController.cs index 57c78f8..1cac137 100644 --- a/api/src/Controllers/StudentController.cs +++ b/api/src/Controllers/StudentController.cs @@ -29,10 +29,10 @@ public class StudentController : BaseController }); } - [HttpGet("{idStudent:int}")] + [HttpGet("{idStudent:guid}")] [ProducesResponseType(typeof(ResponseResult), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ResponseResult), StatusCodes.Status404NotFound)] - public async Task>> GetById(int idStudent) + public async Task>> GetById(Guid idStudent) { var student = await _studentRepository.GetByIdAsync(idStudent); if (student is null) @@ -84,10 +84,10 @@ public class StudentController : BaseController }); } - [HttpPut("{idStudent:int}")] + [HttpPut("{idStudent:guid}")] [ProducesResponseType(typeof(ResponseResult), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ResponseResult), StatusCodes.Status404NotFound)] - public async Task>> Update(int idStudent, [FromBody] UpdateStudentDto request) + public async Task>> Update(Guid idStudent, [FromBody] UpdateStudentDto request) { var existing = await _studentRepository.GetByIdAsync(idStudent); if (existing is null) @@ -118,10 +118,10 @@ public class StudentController : BaseController }); } - [HttpDelete("{idStudent:int}")] + [HttpDelete("{idStudent:guid}")] [ProducesResponseType(typeof(ResponseResult), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ResponseResult), StatusCodes.Status404NotFound)] - public async Task>> Delete(int idStudent) + public async Task>> Delete(Guid idStudent) { var deleted = await _studentRepository.DeleteAsync(idStudent); if (!deleted) diff --git a/api/src/DataAccess/Models/DataTransferObjects/CreateStudentDto.cs b/api/src/DataAccess/Models/DataTransferObjects/CreateStudentDto.cs index a958b9b..b0e1c19 100644 --- a/api/src/DataAccess/Models/DataTransferObjects/CreateStudentDto.cs +++ b/api/src/DataAccess/Models/DataTransferObjects/CreateStudentDto.cs @@ -2,8 +2,8 @@ namespace WinStudentGoalTracker.DataAccess; public class CreateStudentDto { - public required int IdStudent { get; set; } - public int? IdProgram { get; set; } + public required Guid IdStudent { get; set; } + public Guid? IdProgram { get; set; } public string? Identifier { get; set; } public int? ProgramYear { get; set; } public DateTime? EnrollmentDate { get; set; } diff --git a/api/src/DataAccess/Models/DataTransferObjects/UpdateStudentDto.cs b/api/src/DataAccess/Models/DataTransferObjects/UpdateStudentDto.cs index 212fde7..fa721cc 100644 --- a/api/src/DataAccess/Models/DataTransferObjects/UpdateStudentDto.cs +++ b/api/src/DataAccess/Models/DataTransferObjects/UpdateStudentDto.cs @@ -2,7 +2,7 @@ namespace WinStudentGoalTracker.DataAccess; public class UpdateStudentDto { - public int? IdProgram { get; set; } + public Guid? IdProgram { get; set; } public string? Identifier { get; set; } public int? ProgramYear { get; set; } public DateTime? EnrollmentDate { get; set; } diff --git a/api/src/DataAccess/Models/DatabaseObjects/dbRefreshToken.cs b/api/src/DataAccess/Models/DatabaseObjects/dbRefreshToken.cs index ea9dd95..c54c65e 100644 --- a/api/src/DataAccess/Models/DatabaseObjects/dbRefreshToken.cs +++ b/api/src/DataAccess/Models/DatabaseObjects/dbRefreshToken.cs @@ -2,8 +2,8 @@ namespace WinStudentGoalTracker.DataAccess; public class dbRefreshToken { - public int IdRefreshToken { get; set; } - public int IdUser { get; set; } + public Guid IdRefreshToken { get; set; } + public Guid IdUser { get; set; } public required string TokenHash { get; set; } public required string TokenSalt { get; set; } public DateTime ExpiresAt { get; set; } @@ -11,7 +11,7 @@ public class dbRefreshToken public DateTime? RevokedAt { get; set; } public string? DeviceInfo { get; set; } public string? UserAgent { get; set; } - public int? ReplacedByTokenId { get; set; } + public Guid? ReplacedByTokenId { get; set; } public DateTime CreatedAt { get; set; } public DateTime UpdatedAt { get; set; } } diff --git a/api/src/DataAccess/Models/DatabaseObjects/dbStudent.cs b/api/src/DataAccess/Models/DatabaseObjects/dbStudent.cs index 8a5b50e..0f87a9b 100644 --- a/api/src/DataAccess/Models/DatabaseObjects/dbStudent.cs +++ b/api/src/DataAccess/Models/DatabaseObjects/dbStudent.cs @@ -2,8 +2,8 @@ namespace WinStudentGoalTracker.DataAccess; public class dbStudent { - public required int IdStudent { get; set; } - public int? IdProgram { get; set; } + public required Guid IdStudent { get; set; } + public Guid? IdProgram { get; set; } public string? Identifier { get; set; } public int? ProgramYear { get; set; } public DateTime? EnrollmentDate { get; set; } diff --git a/api/src/DataAccess/Models/DatabaseObjects/dbUser.cs b/api/src/DataAccess/Models/DatabaseObjects/dbUser.cs index f2a56f0..c37abb4 100644 --- a/api/src/DataAccess/Models/DatabaseObjects/dbUser.cs +++ b/api/src/DataAccess/Models/DatabaseObjects/dbUser.cs @@ -2,8 +2,8 @@ namespace WinStudentGoalTracker.DataAccess; public class dbUser { - public required int IdUser { get; set; } - public int? IdRole { get; set; } + public required Guid IdUser { get; set; } + public Guid? IdRole { get; set; } public string? Email { get; set; } public string? Name { get; set; } public string? PasswordHash { get; set; } diff --git a/api/src/DataAccess/Repositories/AuthRepository.cs b/api/src/DataAccess/Repositories/AuthRepository.cs index d4b5f85..cad3d48 100644 --- a/api/src/DataAccess/Repositories/AuthRepository.cs +++ b/api/src/DataAccess/Repositories/AuthRepository.cs @@ -8,8 +8,9 @@ public class AuthRepository { private IDbConnection Connection => new MySqlConnection(DatabaseManager.ConnectionString); - public async Task CreateRefreshTokenAsync( - int userId, + public async Task CreateRefreshTokenAsync( + Guid refreshTokenId, + Guid userId, string tokenHash, string tokenSalt, int expiresInSeconds, @@ -17,11 +18,12 @@ public class AuthRepository string? userAgent) { using var db = Connection; - return await db.QuerySingleOrDefaultAsync( + var result = await db.QuerySingleOrDefaultAsync( "sp_RefreshToken_Create", new { - p_id_user = userId, + p_id_refresh_token = refreshTokenId.ToString(), + p_id_user = userId.ToString(), p_token_hash = tokenHash, p_token_salt = tokenSalt, p_expires_in_seconds = expiresInSeconds, @@ -29,30 +31,32 @@ public class AuthRepository p_user_agent = userAgent }, commandType: CommandType.StoredProcedure); + return result != null ? Guid.Parse(result) : null; } - public async Task GetRefreshTokenByIdAsync(int refreshTokenId) + public async Task GetRefreshTokenByIdAsync(Guid refreshTokenId) { using var db = Connection; return await db.QuerySingleOrDefaultAsync( "sp_RefreshToken_GetById", - new { p_id_refresh_token = refreshTokenId }, + new { p_id_refresh_token = refreshTokenId.ToString() }, commandType: CommandType.StoredProcedure); } - public async Task RevokeRefreshTokenAsync(int refreshTokenId) + public async Task RevokeRefreshTokenAsync(Guid refreshTokenId) { using var db = Connection; var rowsAffected = await db.QuerySingleOrDefaultAsync( "sp_RefreshToken_Revoke", - new { p_id_refresh_token = refreshTokenId }, + new { p_id_refresh_token = refreshTokenId.ToString() }, commandType: CommandType.StoredProcedure); return rowsAffected > 0; } - public async Task ReplaceRefreshTokenAsync( - int oldTokenId, - int userId, + public async Task ReplaceRefreshTokenAsync( + Guid oldTokenId, + Guid newTokenId, + Guid userId, string tokenHash, string tokenSalt, int expiresInSeconds, @@ -60,12 +64,13 @@ public class AuthRepository string? userAgent) { using var db = Connection; - return await db.QuerySingleOrDefaultAsync( + var result = await db.QuerySingleOrDefaultAsync( "sp_RefreshToken_Replace", new { - p_old_token_id = oldTokenId, - p_id_user = userId, + p_old_token_id = oldTokenId.ToString(), + p_id_refresh_token = newTokenId.ToString(), + p_id_user = userId.ToString(), p_token_hash = tokenHash, p_token_salt = tokenSalt, p_expires_in_seconds = expiresInSeconds, @@ -73,5 +78,6 @@ public class AuthRepository p_user_agent = userAgent }, commandType: CommandType.StoredProcedure); + return result != null ? Guid.Parse(result) : null; } } diff --git a/api/src/DataAccess/Repositories/StudentRepository.cs b/api/src/DataAccess/Repositories/StudentRepository.cs index 9dbbebb..c646958 100644 --- a/api/src/DataAccess/Repositories/StudentRepository.cs +++ b/api/src/DataAccess/Repositories/StudentRepository.cs @@ -16,12 +16,12 @@ public class StudentRepository commandType: CommandType.StoredProcedure); } - public async Task GetByIdAsync(int idStudent) + public async Task GetByIdAsync(Guid idStudent) { using var db = Connection; return await db.QuerySingleOrDefaultAsync( "sp_Student_GetById", - new { p_id_student = idStudent }, + new { p_id_student = idStudent.ToString() }, commandType: CommandType.StoredProcedure); } @@ -32,8 +32,8 @@ public class StudentRepository "sp_Student_Insert", new { - p_id_student = dto.IdStudent, - p_id_program = dto.IdProgram, + p_id_student = dto.IdStudent.ToString(), + p_id_program = dto.IdProgram?.ToString(), p_identifier = dto.Identifier, p_program_year = dto.ProgramYear, p_enrollment_date = dto.EnrollmentDate, @@ -42,15 +42,15 @@ public class StudentRepository commandType: CommandType.StoredProcedure); } - public async Task UpdateAsync(int idStudent, UpdateStudentDto dto) + public async Task UpdateAsync(Guid idStudent, UpdateStudentDto dto) { using var db = Connection; var rowsAffected = await db.ExecuteScalarAsync( "sp_Student_Update", new { - p_id_student = idStudent, - p_id_program = dto.IdProgram, + p_id_student = idStudent.ToString(), + p_id_program = dto.IdProgram?.ToString(), p_identifier = dto.Identifier, p_program_year = dto.ProgramYear, p_enrollment_date = dto.EnrollmentDate, @@ -60,12 +60,12 @@ public class StudentRepository return rowsAffected > 0; } - public async Task DeleteAsync(int idStudent) + public async Task DeleteAsync(Guid idStudent) { using var db = Connection; var rowsAffected = await db.ExecuteScalarAsync( "sp_Student_Delete", - new { p_id_student = idStudent }, + new { p_id_student = idStudent.ToString() }, commandType: CommandType.StoredProcedure); return rowsAffected > 0; } diff --git a/api/src/DataAccess/Repositories/UserRepository.cs b/api/src/DataAccess/Repositories/UserRepository.cs index 97421ea..ff679a7 100644 --- a/api/src/DataAccess/Repositories/UserRepository.cs +++ b/api/src/DataAccess/Repositories/UserRepository.cs @@ -17,12 +17,12 @@ public class UserRepository commandType: CommandType.StoredProcedure); } - public async Task GetByIdAsync(int idUser) + public async Task GetByIdAsync(Guid idUser) { using var db = Connection; return await db.QuerySingleOrDefaultAsync( "sp_User_GetById", - new { p_id_user = idUser }, + new { p_id_user = idUser.ToString() }, commandType: CommandType.StoredProcedure); } } diff --git a/api/src/Models/ResponseTypes/LoginResponse.cs b/api/src/Models/ResponseTypes/LoginResponse.cs index dfdb325..da90350 100644 --- a/api/src/Models/ResponseTypes/LoginResponse.cs +++ b/api/src/Models/ResponseTypes/LoginResponse.cs @@ -2,7 +2,7 @@ namespace WinStudentGoalTracker.Models; public class LoginResponse { - public int UserId { get; set; } + public Guid UserId { get; set; } public required string Email { get; set; } public required string Jwt { get; set; } public required string RefreshToken { get; set; } diff --git a/api/src/Models/ResponseTypes/StudentResponse.cs b/api/src/Models/ResponseTypes/StudentResponse.cs index b0aed06..c538431 100644 --- a/api/src/Models/ResponseTypes/StudentResponse.cs +++ b/api/src/Models/ResponseTypes/StudentResponse.cs @@ -4,8 +4,8 @@ namespace WinStudentGoalTracker.Models; public class StudentResponse { - public int IdStudent { get; set; } - public int? IdProgram { get; set; } + public Guid IdStudent { get; set; } + public Guid? IdProgram { get; set; } public string? Identifier { get; set; } public int? ProgramYear { get; set; } public DateTime? EnrollmentDate { get; set; } diff --git a/api/src/Services/TokenService.cs b/api/src/Services/TokenService.cs index 2512ea1..9824a48 100644 --- a/api/src/Services/TokenService.cs +++ b/api/src/Services/TokenService.cs @@ -15,7 +15,7 @@ public class TokenService _config = config; } - public string GenerateToken(int userId, string email, string? roleName) + public string GenerateToken(Guid userId, string email, string? roleName) { var claims = new List {