diff --git a/Controllers/AuthController.cs b/Controllers/AuthController.cs index 87b3a21..2a216b9 100644 --- a/Controllers/AuthController.cs +++ b/Controllers/AuthController.cs @@ -98,4 +98,31 @@ public class AuthController : ControllerBase return Ok(new string[] { "value1", "value2" }); } + // GET /api/v1/auth/user_role + /// + /// [AUTHED] Get user role as a string + /// + /// + /// Authed endpoint used to check human-readable user role. + /// Authed endpoints expect Authorization header, e.g.: + /// Authorization: bearer {jwt} + /// Json containing single field "role" + /// Returned on request with valid credentials + /// Returned on request with JWT whose user could not be found (sanity check) + [HttpGet("user_role")] + [Authorize] + [EnableCors] + [ProducesResponseType(200)] + [ProducesResponseType(typeof(ErrorDTO), 400)] + public IActionResult GetUserRole() + { + // Get user from token + User? u = guhf.GetUserFromToken(Request.Headers.Authorization!); + if (u == null) + return BadRequest(new ErrorDTO { Status = "error", Error_msg = "User not found" }); + + // Return the role as a string + return Ok(new { Role = guhf.UserRoleAsStr(u) }); + } + } diff --git a/Controllers/GeneralUseHelperFunctions.cs b/Controllers/GeneralUseHelperFunctions.cs index 70411b5..8fff54c 100644 --- a/Controllers/GeneralUseHelperFunctions.cs +++ b/Controllers/GeneralUseHelperFunctions.cs @@ -14,6 +14,78 @@ public class GeneralUseHelpers(ApplicationDbContext db, IConfiguration appsettin private readonly ApplicationDbContext _db = db; private readonly IConfiguration _appsettings = appsettings; + // Allows to check whether the user is of role present in roles. + // Example: + // For user with role 0, + // - IsUser(["Manager"], req) yields false + // - IsUser(["Admin"], req) yields true + // - IsUser(["Admin", "Manager"], req) yields true because the user is an admin + public bool IsUser(string[] roles, HttpRequest req) + { + + // Get the user to read its roles + User? user = GetUserFromToken(req.Headers.Authorization!); + if (user == null) { + return false; + } + foreach (var role in roles) + { + if (string.IsNullOrEmpty(role)) + { + continue; + } + switch (role) + { + case "Admin": + if (user.Role == 0) + return true; + break; + case "Manager": + if (user.Role == 1) + return true; + break; + case "Pracownik": + if (user.Role == 2) + return true; + break; + default: + continue; + } + } + + return false; + } + + public string UserRoleAsStr(User user) + { + switch (user.Role) + { + case 0: + return "Admin"; + case 1: + return "Manager"; + case 2: + return "Pracownik"; + default: + return "Unknown role"; + } + } + + public User? GetUserFromToken(string token) + { + if (token.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase)) + { + token = token.Substring("Bearer ".Length).Trim(); + } + var handler = new JwtSecurityTokenHandler(); + var jwtSecurityToken = handler.ReadJwtToken(token); + if (int.TryParse(jwtSecurityToken.Subject, out int userId)) + { + return _db.Users.FirstOrDefault(u => u.Id == userId); + } + return null; + } + async public Task GetUserFromEmail(string email) { return await _db.Users.FirstOrDefaultAsync(e => e.Email == email); @@ -37,7 +109,6 @@ public class GeneralUseHelpers(ApplicationDbContext db, IConfiguration appsettin var claims = new[] { new Claim(JwtRegisteredClaimNames.Sub, user.Id.ToString()), - // new Claim(ClaimTypes.Role, ) new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()) }; diff --git a/Controllers/QuoteController.cs b/Controllers/QuoteController.cs index 491f6e5..acb242c 100644 --- a/Controllers/QuoteController.cs +++ b/Controllers/QuoteController.cs @@ -109,13 +109,12 @@ public class QuotesController : ControllerBase [HttpPost("new")] [Authorize] [EnableCors] - [ProducesResponseType(201)] // ? FIXME + [ProducesResponseType(201)] [ProducesResponseType(typeof(ErrorDTO), 400)] [ProducesResponseType(typeof(ErrorDTO), 403)] public async Task CreateQuote([FromBody] CreateQuoteDTO request) { // Get user ID from claims - // FIXME var userIdClaim = User.FindFirst(ClaimTypes.NameIdentifier)?.Value; if (userIdClaim == null || !int.TryParse(userIdClaim, out int userId)) // https://stackoverflow.com/a/47708867 diff --git a/Program.cs b/Program.cs index 6258a0c..6caf51b 100644 --- a/Program.cs +++ b/Program.cs @@ -59,6 +59,7 @@ builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) // Add services to the container. builder.Services.AddAuthorization(); builder.Services.AddSingleton(builder.Configuration); +builder.Services.AddHttpContextAccessor(); builder.Services.AddScoped(); builder.Services.AddControllers();