using Microsoft.EntityFrameworkCore; using Microsoft.IdentityModel.Tokens; using QuotifyBE.Data; using QuotifyBE.Entities; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Security.Cryptography; using System.Text; namespace QuotifyBE.Controllers; public class GeneralUseHelpers(ApplicationDbContext db, IConfiguration appsettings) { 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); } public string HashWithSHA512(string s) { using (var sha512 = SHA512.Create()) { byte[] bytes = Encoding.ASCII.GetBytes(s); byte[] hash = sha512.ComputeHash(bytes); string hashstring = BitConverter.ToString(hash).Replace("-", "").ToLower(); return hashstring; } } public string GenerateJwtToken(User user) { var claims = new[] { new Claim(JwtRegisteredClaimNames.Sub, user.Id.ToString()), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()) }; var key = new SymmetricSecurityKey( Encoding.UTF8.GetBytes( // JwtSecret won't be null here - otherwise Program.cs wouldn't start _appsettings["JwtSecret"]! ) ); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var token = new JwtSecurityToken( issuer: _appsettings["DomainName"]!, audience: _appsettings["DomainName"]!, claims: claims, // https://stackoverflow.com/questions/21978658/invalidating-json-web-tokens#comment45057142_23089839 // small validity timeframe is important for invalidating tokens after a user changed their password expires: DateTime.Now.AddMinutes(5), signingCredentials: creds ); return new JwtSecurityTokenHandler().WriteToken(token); } }