229 lines
6.6 KiB
C#
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
|
|
}
|