Files
schedtxt_api/Controllers/UsersController.cs
T
kdeng00 b9d6318d0e Added authorization
Endpoint to create contacts with the queueing system is now functional
2023-10-01 12:10:13 -04:00

229 lines
6.6 KiB
C#

using System.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using TextSender_API.Models;
using TextSender_API.Repositories;
namespace TextSender_API.Controllers;
[ApiController]
[Route("api/v1/user")]
public class UsersController : ControllerBase
{
#region Fields
private readonly ILogger<UsersController> _logger;
private IConfiguration _config;
#endregion
#region Constructors
public UsersController(ILogger<UsersController> logger, IConfiguration config)
{
this._logger = logger;
this._config = config;
}
#endregion
#region Methods
private string AllScopes()
{
var allScopes = new List<String>()
{
"create:contact"
};
var scopes = string.Empty;
for (var i = 0; i < allScopes.Count; i++)
{
if (i == allScopes.Count - 1)
{
scopes += allScopes[i];
}
else
{
scopes += allScopes[i] + " ";
}
}
return scopes;
}
private List<Claim> Payload()
{
var expLimit = 30;
var currentDate = DateTime.Now;
var expiredDate = currentDate.AddMinutes(expLimit);
var issued = Math.Floor((currentDate - DateTime.UnixEpoch).TotalSeconds);
var expires = Math.Floor((expiredDate - DateTime.UnixEpoch).TotalSeconds);
var issuer = this._config["JWT:Issuer"];
var audience = this._config["JWT:Audience"];
var subject = this._config["JWT:Subject"];
var claim = new List<System.Security.Claims.Claim>()
{
new System.Security.Claims.Claim("scope", AllScopes(), "string"),
new System.Security.Claims.Claim(JwtRegisteredClaimNames.Exp, expiredDate.ToString(), "string"),
new System.Security.Claims.Claim(JwtRegisteredClaimNames.Aud, audience!),
new System.Security.Claims.Claim(JwtRegisteredClaimNames.Iss, issuer!),
new Claim(JwtRegisteredClaimNames.Sub, subject!)
};
return claim;
}
[HttpPost("login")]
public IActionResult Login([FromBody] User userRequest)
{
var response = new LoginResponse();
try
{
var connString = this._config.GetConnectionString("MongoDBURI");
var userRepo = new UsersRepository(connString!);
var saltRepo = new SaltRepository(connString!);
var pwdVerify = new PasswordVerification(userRepo, saltRepo);
var result = userRepo.Exists(userRequest);
if (result.Item1 && pwdVerify.VerifyPassword(result.Item2, userRequest.Password!))
{
var user = result.Item2;
var token = new Token();
token.Issued = DateTime.Now;
token.UserId = user.Id;
token.TokenType = "JWT";
var payload = Payload();
payload.Add(new System.Security.Claims.Claim("user_id", user.Id!, ClaimValueTypes.String));
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(this._config["JWT:Secret"]!));
var signIn = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var tok = new JwtSecurityToken(
this._config["JWT:Issuer"],
this._config["JWT:Audience"],
payload,
expires: DateTime.UtcNow.AddMinutes(30),
signingCredentials: signIn);
token.AccessToken = new JwtSecurityTokenHandler().WriteToken(tok);
var expClaim = payload.FirstOrDefault(cl =>
{
return cl.Type.Equals("exp");
});
if (expClaim != null)
{
var expiredDate = DateTime.Parse(expClaim!.Value);
var exp = Math.Floor((expiredDate - DateTime.UnixEpoch).TotalSeconds);
}
response.Data.Add(token);
Ok(response);
}
else
{
return NotFound(response);
}
}
catch (Exception ex)
{
this._logger.LogError($"An error occurred: {ex.Message}");
}
return Ok(response);
}
[HttpPost("register"), DisableRequestSizeLimit]
public IActionResult Upload([FromBody] User userRequest)
{
var response = new RegisterUserResponse();
try
{
var connString = this._config.GetConnectionString("MongoDBURI");
var userRepo = new UsersRepository(connString!);
var saltRepo = new SaltRepository(connString!);
var allUsers = userRepo.RetrieveAllUsers();
var result = allUsers.Exists(ea => ea.Username!.Equals(userRequest.Username));
if (!result)
{
var pwdVerify = new PasswordVerification(userRepo, saltRepo);
var salt = pwdVerify.CreateSalt(userRequest);
var hashedPassword = pwdVerify.HashPassword(userRequest, salt);
this._logger.LogInformation("Creating user");
userRequest.Password = hashedPassword;
userRequest.DateCreated = DateTime.Now;
userRepo.CreateUser(userRequest);
response.Data.Add(userRequest);
salt.UserId = userRequest.Id;
saltRepo.Create(salt);
}
else
{
this._logger.LogInformation("User already exists");
}
}
catch (Exception ex)
{
this._logger.LogError($"An error occurred: {ex.Message}");
}
return Ok(response);
}
#endregion
#region Responses
public class LoginResponse
{
#region Properties
[JsonProperty("data")]
public List<Token> Data { get; set; }
#endregion
#region Constructors
public LoginResponse()
{
this.Data = new List<Token>();
}
#endregion
#region Methods
#endregion
}
public class RegisterUserResponse
{
#region Properties
[JsonProperty("data")]
public List<User> Data { get; set; }
#endregion
#region Constructors
public RegisterUserResponse()
{
this.Data = new List<User>();
}
#endregion
#region Methods
#endregion
}
#endregion
}