Added register user

This commit is contained in:
quentin 2024-07-12 17:27:01 -05:00
parent d58eb8d973
commit 1dd4d3dca7
8 changed files with 135 additions and 21 deletions

View File

@ -1,5 +1,7 @@
using API.DTO.Base; using API.DTO.Base;
using API.DTO.Login; using API.DTO.Login;
using API.Errors;
using API.Services;
using API.Services.Interfaces; using API.Services.Interfaces;
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.Cookies;
@ -14,17 +16,19 @@ namespace API.Controllers
{ {
private readonly ILogger<AuthController> _logger; private readonly ILogger<AuthController> _logger;
private readonly IUserManager _userManager; private readonly IUserManager _userManager;
private readonly UserService _userService;
public AuthController(ILogger<AuthController> logger, IUserManager userManager) public AuthController(ILogger<AuthController> logger, IUserManager userManager, UserService userService)
{ {
_logger = logger; _logger = logger;
_userManager = userManager; _userManager = userManager;
_userService = userService;
} }
[HttpPost("login")] [HttpPost("login")]
public ActionResult<UserDTO> login(UserLoginDTO userLogin) public ActionResult<UserDTO> login(UserLoginDTO userLogin)
{ {
UserDTO? user = _userManager.AuthenticateUser(userLogin); UserDTO? user = _userManager.authenticateUser(userLogin);
if (user == null) if (user == null)
return new UnauthorizedResult(); return new UnauthorizedResult();
@ -42,5 +46,18 @@ namespace API.Controllers
return Ok(user); return Ok(user);
} }
[HttpPost("register")]
public ActionResult<UserDTO> register(UserRegisterDTO registerDTO)
{
UserDTO? user = _userManager.registerUser(registerDTO);
if (user == null)
{
return Conflict(Strings.UserExists);
}
return Ok(user);
}
} }
} }

View File

@ -0,0 +1,19 @@
using DAL.Values;
using System.ComponentModel.DataAnnotations;
namespace API.DTO.Login
{
public class UserRegisterDTO
{
[MaxLength(64)]
public string firstName { get; set; } = null!;
[MaxLength(64)]
public string lastName { get; set; } = null!;
public PhoneNumber phoneNumber { get; set; } = null!;
[MaxLength(1000)]
public string password { get; set; } = null!;
}
}

7
API/Errors/Strings.cs Normal file
View File

@ -0,0 +1,7 @@
namespace API.Errors
{
public static class Strings
{
public const string UserExists = "User with that phone number or first and last name already exists.\nIf you would like to change your phone number please login.";
}
}

View File

@ -40,7 +40,17 @@ namespace API
builder.Services.AddTransient<ImageService>(); builder.Services.AddTransient<ImageService>();
builder.Services.AddTransient<PermissionService>(); builder.Services.AddTransient<PermissionService>();
builder.Services.AddTransient<SavedEventService>(); builder.Services.AddTransient<SavedEventService>();
builder.Services.AddTransient<UserService>(); builder.Services.AddTransient<UserService>(options =>
{
ILogger<UserService> logger = options.GetRequiredService<ILogger<UserService>>();
SASGContext context = options.GetRequiredService<SASGContext>();
IYesAuthentication authentication = options.GetRequiredService<IYesAuthentication>();
PermissionService permissionService = options.GetRequiredService<PermissionService>();
ulong defaultUserPermission = UInt64.Parse(builder.Configuration["defaultUserPermission"] ?? throw new InvalidOperationException("defaultUserPermission is null"));
return new UserService(logger, context, authentication, permissionService, defaultUserPermission);
});
builder.Services.AddTransient<IYesAuthentication, YesAuthentication>(); builder.Services.AddTransient<IYesAuthentication, YesAuthentication>();
builder.Services.AddTransient<IColorAuthentication, ColorAuthentication>(); builder.Services.AddTransient<IColorAuthentication, ColorAuthentication>();

View File

@ -5,6 +5,8 @@ namespace API.Services.Interfaces
{ {
public interface IUserManager public interface IUserManager
{ {
UserDTO? AuthenticateUser(UserLoginDTO loginDTO); UserDTO? authenticateUser(UserLoginDTO loginDTO);
UserDTO? registerUser(UserRegisterDTO registerDTO);
} }
} }

View File

@ -15,19 +15,19 @@ namespace API.Services
where TDTO : IAdaptable<TModel> where TDTO : IAdaptable<TModel>
{ {
private readonly TAuthentication _auth; private readonly TAuthentication _auth;
private readonly SASGContext _context;
private readonly ILogger<TLoggerCategory> _logger; private readonly ILogger<TLoggerCategory> _logger;
public readonly SASGContext Context;
public ServiceBase(ILogger<TLoggerCategory> logger, SASGContext context, TAuthentication auth) public ServiceBase(ILogger<TLoggerCategory> logger, SASGContext context, TAuthentication auth)
{ {
_logger = logger; _logger = logger;
_context = context; Context = context;
_auth = auth; _auth = auth;
} }
public TModel? get(ulong id, User user) public TModel? get(ulong id, User user)
{ {
TModel? result = _context.Set<TModel>().Find(id); TModel? result = Context.Set<TModel>().Find(id);
if (result == null) if (result == null)
return null; return null;
@ -39,17 +39,17 @@ namespace API.Services
if (!_auth.canGetAll(user)) if (!_auth.canGetAll(user))
return null; return null;
return whereClause != null ? _context.Set<TModel>().Where(whereClause) : _context.Set<TModel>(); return whereClause != null ? Context.Set<TModel>().Where(whereClause) : Context.Set<TModel>();
} }
public TModel? getNoAuthentication(ulong id) public TModel? getNoAuthentication(ulong id)
{ {
return _context.Set<TModel>().Find(id); return Context.Set<TModel>().Find(id);
} }
public IEnumerable<TModel> getNoAuthentication(Expression<Func<TModel, bool>>? whereClause = null) public IEnumerable<TModel> getNoAuthentication(Expression<Func<TModel, bool>>? whereClause = null)
{ {
return whereClause != null ? _context.Set<TModel>().Where(whereClause) : _context.Set<TModel>(); return whereClause != null ? Context.Set<TModel>().Where(whereClause) : Context.Set<TModel>();
} }
public TModel? add(TDTO item, User user) public TModel? add(TDTO item, User user)
@ -61,8 +61,8 @@ namespace API.Services
model.updater = user.id; model.updater = user.id;
model.updated = DateTime.Now; model.updated = DateTime.Now;
_context.Add(model); Context.Add(model);
_context.SaveChanges(); Context.SaveChanges();
return model; return model;
} }
@ -72,7 +72,7 @@ namespace API.Services
if (!_auth.canUpdate(model, user)) if (!_auth.canUpdate(model, user))
return null; return null;
TModel? origModel = _context.Set<TModel>().Find(model.id); TModel? origModel = Context.Set<TModel>().Find(model.id);
if (origModel == null) if (origModel == null)
return null; return null;
@ -83,7 +83,7 @@ namespace API.Services
origModel.updated = DateTime.Now; origModel.updated = DateTime.Now;
origModel.updater = user.id; origModel.updater = user.id;
_context.SaveChanges(); Context.SaveChanges();
return origModel; return origModel;
} }
@ -93,7 +93,7 @@ namespace API.Services
if (!_auth.canDelete(model, user)) if (!_auth.canDelete(model, user))
return null; return null;
TModel? origModel = _context.Set<TModel>().Find(model.id); TModel? origModel = Context.Set<TModel>().Find(model.id);
if (origModel == null) if (origModel == null)
return null; return null;
@ -104,15 +104,15 @@ namespace API.Services
copyToAudit(origModel); copyToAudit(origModel);
_context.Remove(origModel); Context.Remove(origModel);
_context.SaveChanges(); Context.SaveChanges();
return origModel.adaptToAudit(); return origModel.adaptToAudit();
} }
private void copyToAudit(TModel model) private void copyToAudit(TModel model)
{ {
_context.Set<TAudit>().Add(model.adaptToAudit()); Context.Set<TAudit>().Add(model.adaptToAudit());
} }
} }
} }

View File

@ -21,7 +21,7 @@ namespace API.Services
_preferredHashingType = preferredHashingType; _preferredHashingType = preferredHashingType;
} }
public UserDTO? AuthenticateUser(UserLoginDTO loginDTO) public UserDTO? authenticateUser(UserLoginDTO loginDTO)
{ {
User? user = _userService.getNoAuthentication(x => x.phoneNumber.Equals(loginDTO.phoneNumber)).FirstOrDefault(); User? user = _userService.getNoAuthentication(x => x.phoneNumber.Equals(loginDTO.phoneNumber)).FirstOrDefault();
@ -53,5 +53,33 @@ namespace API.Services
return dto; return dto;
} }
public UserDTO? registerUser(UserRegisterDTO registerDTO)
{
if (_userService.getNoAuthentication(x =>
x.phoneNumber.Equals(registerDTO.phoneNumber) ||
x.firstName.Equals(registerDTO.firstName) && x.lastName.Equals(registerDTO.lastName))
.Any())
{
return null;
}
IHashingAlgorithm? hashingAlgorithm = _hashingFactory.getAlgorithm(_preferredHashingType);
if (hashingAlgorithm == null)
{
_logger.Log(LogLevel.Error, "Preferred hashing type '{hashingType}' that isn't recognized by factory '{factory}'.", _preferredHashingType, nameof(_hashingFactory));
return null;
}
byte[] salt;
string hashedPassword = hashingAlgorithm.hash(registerDTO.password, out salt);
User user = _userService.add(registerDTO, hashedPassword, salt);
UserDTO dto = new UserDTO();
dto.adaptFromModel(user);
return dto;
}
} }
} }

View File

@ -1,5 +1,6 @@
using API.Authentication.Interfaces; using API.Authentication.Interfaces;
using API.DTO.Base; using API.DTO.Base;
using API.DTO.Login;
using DAL.Contexts; using DAL.Contexts;
using DAL.Models; using DAL.Models;
using DAL.Models.Audits; using DAL.Models.Audits;
@ -8,9 +9,39 @@ namespace API.Services
{ {
public class UserService : ServiceBase<UserService, UserDTO, User, AuditUser, IYesAuthentication> public class UserService : ServiceBase<UserService, UserDTO, User, AuditUser, IYesAuthentication>
{ {
private readonly ulong _defaultUserPermission;
public UserService(ILogger<UserService> logger, SASGContext context, IYesAuthentication auth) : base(logger, context, auth) private readonly PermissionService _permissionService;
public UserService(ILogger<UserService> logger, SASGContext context, IYesAuthentication auth, PermissionService permissionService, ulong defaultUserPermission) : base(logger, context, auth)
{ {
_permissionService = permissionService;
_defaultUserPermission = defaultUserPermission;
}
public User add(UserRegisterDTO registerDTO, string hashedPassword, byte[] salt)
{
Permission? defaultPermission = _permissionService.getNoAuthentication(_defaultUserPermission);
if (defaultPermission == null)
throw new InvalidOperationException("defaultUserPermission doesn't exist.");
User model = new User
{
firstName = registerDTO.firstName,
lastName = registerDTO.lastName,
phoneNumber = registerDTO.phoneNumber,
password = hashedPassword,
salt = salt,
permissionId = defaultPermission.id,
updated = DateTime.Now
};
Context.Add(model);
Context.SaveChanges();
return model;
} }
} }
} }