From cf25e4e1e67342283f06619df50e671914ddce55 Mon Sep 17 00:00:00 2001 From: Masu Baumgartner <68913099+Masu-Baumgartner@users.noreply.github.com> Date: Sun, 6 Oct 2024 01:19:23 +0200 Subject: [PATCH] Implemented admin users crud api --- .../Admin/Users/UsersController.cs | 73 +++++++++++++++++++ .../Moonlight.ApiServer.csproj | 2 +- Moonlight.ApiServer/Program.cs | 1 + Moonlight.Client/Moonlight.Client.csproj | 1 + .../Requests/Admin/Users/CreateUserRequest.cs | 19 +++++ .../Requests/Admin/Users/UpdateUserRequest.cs | 16 ++++ 6 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 Moonlight.ApiServer/Http/Controllers/Admin/Users/UsersController.cs create mode 100644 Moonlight.Shared/Http/Requests/Admin/Users/CreateUserRequest.cs create mode 100644 Moonlight.Shared/Http/Requests/Admin/Users/UpdateUserRequest.cs diff --git a/Moonlight.ApiServer/Http/Controllers/Admin/Users/UsersController.cs b/Moonlight.ApiServer/Http/Controllers/Admin/Users/UsersController.cs new file mode 100644 index 00000000..d0e5f949 --- /dev/null +++ b/Moonlight.ApiServer/Http/Controllers/Admin/Users/UsersController.cs @@ -0,0 +1,73 @@ +using Microsoft.AspNetCore.Mvc; +using MoonCore.Exceptions; +using MoonCore.Extended.Abstractions; +using MoonCore.Extended.Helpers; +using MoonCore.Models; +using Moonlight.ApiServer.Database.Entities; +using Moonlight.Shared.Http.Requests.Admin.Users; + +namespace Moonlight.ApiServer.Http.Controllers.Admin.Users; + +[ApiController] +[Route("api/admin/users")] +public class UsersController : Controller +{ + private readonly CrudHelper CrudHelper; + private readonly DatabaseRepository UserRepository; + + public UsersController(CrudHelper crudHelper, DatabaseRepository userRepository) + { + CrudHelper = crudHelper; + UserRepository = userRepository; + } + + [HttpGet] + public async Task> Get([FromQuery] int page, [FromQuery] int pageSize = 50) + => await CrudHelper.Get(page, pageSize); + + [HttpGet("{id}")] + public async Task GetSingle(int id) + => await CrudHelper.GetSingle(id); + + [HttpPost] + public async Task Create([FromBody] CreateUserRequest request) + { + // Reformat values + request.Username = request.Username.ToLower().Trim(); + request.Email = request.Email.ToLower().Trim(); + + // Check for users with the same values + if (UserRepository.Get().Any(x => x.Username == request.Username)) + throw new HttpApiException("A user with that username already exists", 400); + + if (UserRepository.Get().Any(x => x.Email == request.Email)) + throw new HttpApiException("A user with that email address already exists", 400); + + request.Password = HashHelper.Hash(request.Password); + + return await CrudHelper.Create(request); + } + + [HttpPatch("{id}")] + public async Task Update([FromRoute] int id, [FromBody] UpdateUserRequest request) + { + var user = await CrudHelper.GetSingle(id); + + // Reformat values + request.Username = request.Username.ToLower().Trim(); + request.Email = request.Email.ToLower().Trim(); + + // Check for users with the same values + if (UserRepository.Get().Any(x => x.Username == request.Username && x.Id != user.Id)) + throw new HttpApiException("A user with that username already exists", 400); + + if (UserRepository.Get().Any(x => x.Email == request.Email && x.Id != user.Id)) + throw new HttpApiException("A user with that email address already exists", 400); + + return await CrudHelper.Update(user, request); + } + + [HttpDelete("{id}")] + public async Task Delete([FromRoute] int id) + => await CrudHelper.Delete(id); +} \ No newline at end of file diff --git a/Moonlight.ApiServer/Moonlight.ApiServer.csproj b/Moonlight.ApiServer/Moonlight.ApiServer.csproj index cd92652b..6df60878 100644 --- a/Moonlight.ApiServer/Moonlight.ApiServer.csproj +++ b/Moonlight.ApiServer/Moonlight.ApiServer.csproj @@ -13,7 +13,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/Moonlight.ApiServer/Program.cs b/Moonlight.ApiServer/Program.cs index 3ca36c66..706b486b 100644 --- a/Moonlight.ApiServer/Program.cs +++ b/Moonlight.ApiServer/Program.cs @@ -86,6 +86,7 @@ var databaseHelper = new DatabaseHelper( builder.Services.AddSingleton(databaseHelper); builder.Services.AddScoped(typeof(DatabaseRepository<>)); +builder.Services.AddScoped(typeof(CrudHelper<>)); builder.Services.AddDbContext(); databaseHelper.AddDbContext(); diff --git a/Moonlight.Client/Moonlight.Client.csproj b/Moonlight.Client/Moonlight.Client.csproj index bc029be0..dd97f0d9 100644 --- a/Moonlight.Client/Moonlight.Client.csproj +++ b/Moonlight.Client/Moonlight.Client.csproj @@ -13,6 +13,7 @@ + diff --git a/Moonlight.Shared/Http/Requests/Admin/Users/CreateUserRequest.cs b/Moonlight.Shared/Http/Requests/Admin/Users/CreateUserRequest.cs new file mode 100644 index 00000000..fed2dafd --- /dev/null +++ b/Moonlight.Shared/Http/Requests/Admin/Users/CreateUserRequest.cs @@ -0,0 +1,19 @@ +using System.ComponentModel.DataAnnotations; + +namespace Moonlight.Shared.Http.Requests.Admin.Users; + +public class CreateUserRequest +{ + [Required(ErrorMessage = "You need to provide an email address")] + [EmailAddress(ErrorMessage = "You need to provide a valid email address")] + public string Email { get; set; } + + [Required(ErrorMessage = "You need to provide a username")] + [RegularExpression("^[a-z][a-z0-9]*$", ErrorMessage = "Usernames can only contain lowercase characters and numbers and should not start with a number")] + public string Username { get; set; } + + [Required(ErrorMessage = "You need to provide a password")] + [MinLength(8, ErrorMessage = "Your password needs to be at least 8 characters long")] + [MaxLength(256, ErrorMessage = "Your password should not exceed the length of 256 characters")] + public string Password { get; set; } +} \ No newline at end of file diff --git a/Moonlight.Shared/Http/Requests/Admin/Users/UpdateUserRequest.cs b/Moonlight.Shared/Http/Requests/Admin/Users/UpdateUserRequest.cs new file mode 100644 index 00000000..9dd2d4b1 --- /dev/null +++ b/Moonlight.Shared/Http/Requests/Admin/Users/UpdateUserRequest.cs @@ -0,0 +1,16 @@ +using System.ComponentModel.DataAnnotations; + +namespace Moonlight.Shared.Http.Requests.Admin.Users; + +public class UpdateUserRequest +{ + [Required(ErrorMessage = "You need to provide an email address")] + [EmailAddress(ErrorMessage = "You need to provide a valid email address")] + public string Email { get; set; } + + [Required(ErrorMessage = "You need to provide a username")] + [RegularExpression("^[a-z][a-z0-9]*$", ErrorMessage = "Usernames can only contain lowercase characters and numbers and should not start with a number")] + public string Username { get; set; } + + public string? Password { get; set; } +} \ No newline at end of file