diff --git a/WatchIt.Common/WatchIt.Common.Model/Roles/Role.cs b/WatchIt.Common/WatchIt.Common.Model/Roles/Role.cs new file mode 100644 index 0000000..6941a20 --- /dev/null +++ b/WatchIt.Common/WatchIt.Common.Model/Roles/Role.cs @@ -0,0 +1,13 @@ +using System.Text.Json.Serialization; + +namespace WatchIt.Common.Model.Roles; + +public class Role +{ + #region PROPERTIES + + [JsonPropertyName("name")] + public required string Name { get; set; } + + #endregion +} \ No newline at end of file diff --git a/WatchIt.Common/WatchIt.Common.Model/Roles/RoleQueryParameters.cs b/WatchIt.Common/WatchIt.Common.Model/Roles/RoleQueryParameters.cs new file mode 100644 index 0000000..b7e7c9d --- /dev/null +++ b/WatchIt.Common/WatchIt.Common.Model/Roles/RoleQueryParameters.cs @@ -0,0 +1,22 @@ +using Microsoft.AspNetCore.Mvc; +using WatchIt.Common.Query; + +namespace WatchIt.Common.Model.Roles; + +public class RoleQueryParameters : QueryParameters +{ + #region PROPERTIES + + [FromQuery(Name = "name")] + public string? Name { get; set; } + + #endregion + + + + #region PRIVATE METHODS + + protected override bool IsMeetingConditions(RoleResponse item) => TestStringWithRegex(item.Name, Name); + + #endregion +} \ No newline at end of file diff --git a/WatchIt.Common/WatchIt.Common.Model/Roles/RoleRequest.cs b/WatchIt.Common/WatchIt.Common.Model/Roles/RoleRequest.cs new file mode 100644 index 0000000..22388b1 --- /dev/null +++ b/WatchIt.Common/WatchIt.Common.Model/Roles/RoleRequest.cs @@ -0,0 +1,18 @@ +namespace WatchIt.Common.Model.Roles; + +public class RoleRequest : Role +{ + #region PUBLIC METHODS + + public Database.Model.Person.PersonActorRoleType CreateActorRoleType() => new Database.Model.Person.PersonActorRoleType() + { + Name = Name + }; + + public Database.Model.Person.PersonCreatorRoleType CreateCreatorRoleType() => new Database.Model.Person.PersonCreatorRoleType() + { + Name = Name + }; + + #endregion +} \ No newline at end of file diff --git a/WatchIt.Common/WatchIt.Common.Model/Roles/RoleResponse.cs b/WatchIt.Common/WatchIt.Common.Model/Roles/RoleResponse.cs new file mode 100644 index 0000000..1d4c24a --- /dev/null +++ b/WatchIt.Common/WatchIt.Common.Model/Roles/RoleResponse.cs @@ -0,0 +1,45 @@ +using System.Diagnostics.CodeAnalysis; +using System.Text.Json.Serialization; +using WatchIt.Common.Query; + +namespace WatchIt.Common.Model.Roles; + +public class RoleResponse : Role, IQueryOrderable +{ + #region PROPERTIES + + [JsonIgnore] + public static IDictionary> OrderableProperties { get; } = new Dictionary> + { + { "name", item => item.Name } + }; + + + [JsonPropertyName("id")] + public required short? Id { get; set; } + + #endregion + + + + #region CONSTRUCTORS + + [JsonConstructor] + public RoleResponse() { } + + [SetsRequiredMembers] + public RoleResponse(Database.Model.Person.PersonCreatorRoleType creatorRoleType) + { + Id = creatorRoleType.Id; + Name = creatorRoleType.Name; + } + + [SetsRequiredMembers] + public RoleResponse(Database.Model.Person.PersonActorRoleType actorRoleType) + { + Id = actorRoleType.Id; + Name = actorRoleType.Name; + } + + #endregion +} \ No newline at end of file diff --git a/WatchIt.WebAPI/WatchIt.WebAPI.Controllers/GendersController.cs b/WatchIt.WebAPI/WatchIt.WebAPI.Controllers/GendersController.cs index af3be9f..4f6e24d 100644 --- a/WatchIt.WebAPI/WatchIt.WebAPI.Controllers/GendersController.cs +++ b/WatchIt.WebAPI/WatchIt.WebAPI.Controllers/GendersController.cs @@ -55,7 +55,7 @@ public class GendersController : ControllerBase [HttpDelete("{id}")] [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] - [ProducesResponseType(typeof(GenderResponse), StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] [ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)] public async Task DeleteGender([FromRoute]short id) => await _gendersControllerService.DeleteGender(id); diff --git a/WatchIt.WebAPI/WatchIt.WebAPI.Controllers/RolesController.cs b/WatchIt.WebAPI/WatchIt.WebAPI.Controllers/RolesController.cs new file mode 100644 index 0000000..375ec59 --- /dev/null +++ b/WatchIt.WebAPI/WatchIt.WebAPI.Controllers/RolesController.cs @@ -0,0 +1,96 @@ +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using WatchIt.Common.Model.Roles; +using WatchIt.WebAPI.Services.Controllers.Roles; + +namespace WatchIt.WebAPI.Controllers; + +[ApiController] +[Route("persons")] +public class RolesController : ControllerBase +{ + #region SERVICES + + private readonly IRolesControllerService _rolesControllerService; + + #endregion + + + + #region CONSTRUCTORS + + public RolesController(IRolesControllerService rolesControllerService) + { + _rolesControllerService = rolesControllerService; + } + + #endregion + + + + #region METHODS + + #region Actor + + [HttpGet("actor")] + [AllowAnonymous] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + public async Task GetAllActorRoles(RoleQueryParameters query) => await _rolesControllerService.GetAllActorRoles(query); + + [HttpGet("actor/{id}")] + [AllowAnonymous] + [ProducesResponseType(typeof(RoleResponse), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public async Task GetActorRole([FromRoute]short id) => await _rolesControllerService.GetActorRole(id); + + [HttpPost("actor")] + [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] + [ProducesResponseType(typeof(RoleResponse), StatusCodes.Status201Created)] + [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)] + public async Task PostActorRoles([FromBody]RoleRequest body) => await _rolesControllerService.PostActorRole(body); + + [HttpDelete("actor/{id}")] + [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)] + public async Task DeleteActorRoles([FromRoute]short id) => await _rolesControllerService.DeleteActorRole(id); + + #endregion + + #region Creator + + [HttpGet("creator")] + [AllowAnonymous] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + public async Task GetAllCreatorRoles(RoleQueryParameters query) => await _rolesControllerService.GetAllCreatorRoles(query); + + [HttpGet("creator/{id}")] + [AllowAnonymous] + [ProducesResponseType(typeof(RoleResponse), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public async Task GetCreatorRole([FromRoute]short id) => await _rolesControllerService.GetCreatorRole(id); + + [HttpPost("creator")] + [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] + [ProducesResponseType(typeof(RoleResponse), StatusCodes.Status201Created)] + [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)] + public async Task PostCreatorRoles([FromBody]RoleRequest body) => await _rolesControllerService.PostCreatorRole(body); + + [HttpDelete("creator/{id}")] + [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)] + public async Task DeleteCreatorRoles([FromRoute]short id) => await _rolesControllerService.DeleteCreatorRole(id); + + #endregion + + #endregion +} \ No newline at end of file diff --git a/WatchIt.WebAPI/WatchIt.WebAPI.Controllers/WatchIt.WebAPI.Controllers.csproj b/WatchIt.WebAPI/WatchIt.WebAPI.Controllers/WatchIt.WebAPI.Controllers.csproj index c2bb202..c2ab0dd 100644 --- a/WatchIt.WebAPI/WatchIt.WebAPI.Controllers/WatchIt.WebAPI.Controllers.csproj +++ b/WatchIt.WebAPI/WatchIt.WebAPI.Controllers/WatchIt.WebAPI.Controllers.csproj @@ -20,6 +20,7 @@ + diff --git a/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Genders/GendersControllerService.cs b/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Genders/GendersControllerService.cs index 43011b9..6c7d7dc 100644 --- a/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Genders/GendersControllerService.cs +++ b/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Genders/GendersControllerService.cs @@ -33,6 +33,8 @@ public class GendersControllerService : IGendersControllerService #region PUBLIC METHODS + #region Main + public async Task GetAllGenders(GenderQueryParameters query) { IEnumerable rawData = await _database.Genders.ToListAsync(); @@ -90,4 +92,6 @@ public class GendersControllerService : IGendersControllerService } #endregion + + #endregion } \ No newline at end of file diff --git a/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Roles/IRolesControllerService.cs b/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Roles/IRolesControllerService.cs new file mode 100644 index 0000000..48982a2 --- /dev/null +++ b/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Roles/IRolesControllerService.cs @@ -0,0 +1,17 @@ +using WatchIt.Common.Model.Roles; +using WatchIt.WebAPI.Services.Controllers.Common; + +namespace WatchIt.WebAPI.Services.Controllers.Roles; + +public interface IRolesControllerService +{ + Task GetAllActorRoles(RoleQueryParameters query); + Task GetActorRole(short id); + Task PostActorRole(RoleRequest data); + Task DeleteActorRole(short id); + + Task GetAllCreatorRoles(RoleQueryParameters query); + Task GetCreatorRole(short id); + Task PostCreatorRole(RoleRequest data); + Task DeleteCreatorRole(short id); +} \ No newline at end of file diff --git a/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Roles/RolesControllerService.cs b/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Roles/RolesControllerService.cs new file mode 100644 index 0000000..6ea774c --- /dev/null +++ b/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Roles/RolesControllerService.cs @@ -0,0 +1,158 @@ +using Microsoft.EntityFrameworkCore; +using WatchIt.Common.Model.Roles; +using WatchIt.Database; +using WatchIt.Database.Model.Person; +using WatchIt.WebAPI.Services.Controllers.Common; +using WatchIt.WebAPI.Services.Utility.User; + +namespace WatchIt.WebAPI.Services.Controllers.Roles; + +public class RolesControllerService : IRolesControllerService +{ + #region SERVICES + + private readonly DatabaseContext _database; + private readonly IUserService _userService; + + #endregion + + + + #region CONSTRUCTORS + + public RolesControllerService(DatabaseContext database, IUserService userService) + { + _database = database; + _userService = userService; + } + + #endregion + + + + #region PUBLIC METHODS + + #region Actor + + public async Task GetAllActorRoles(RoleQueryParameters query) + { + IEnumerable rawData = await _database.PersonActorRoleTypes.ToListAsync(); + IEnumerable data = rawData.Select(x => new RoleResponse(x)); + data = query.PrepareData(data); + return RequestResult.Ok(data); + } + + public async Task GetActorRole(short id) + { + PersonActorRoleType? item = await _database.PersonActorRoleTypes.FirstOrDefaultAsync(x => x.Id == id); + if (item is null) + { + return RequestResult.NotFound(); + } + + RoleResponse data = new RoleResponse(item); + return RequestResult.Ok(data); + } + + public async Task PostActorRole(RoleRequest data) + { + UserValidator validator = _userService.GetValidator().MustBeAdmin(); + if (!validator.IsValid) + { + return RequestResult.Forbidden(); + } + + PersonActorRoleType item = data.CreateActorRoleType(); + await _database.PersonActorRoleTypes.AddAsync(item); + await _database.SaveChangesAsync(); + + return RequestResult.Created($"roles/actor/{item.Id}", new RoleResponse(item)); + } + + public async Task DeleteActorRole(short id) + { + UserValidator validator = _userService.GetValidator().MustBeAdmin(); + if (!validator.IsValid) + { + return RequestResult.Forbidden(); + } + + PersonActorRoleType? item = await _database.PersonActorRoleTypes.FirstOrDefaultAsync(x => x.Id == id); + if (item is null) + { + return RequestResult.NoContent(); + } + + _database.PersonActorRoleTypes.Attach(item); + _database.PersonActorRoleTypes.Remove(item); + await _database.SaveChangesAsync(); + + return RequestResult.NoContent(); + } + + #endregion + + + + #region Creator + + public async Task GetAllCreatorRoles(RoleQueryParameters query) + { + IEnumerable rawData = await _database.PersonCreatorRoleTypes.ToListAsync(); + IEnumerable data = rawData.Select(x => new RoleResponse(x)); + data = query.PrepareData(data); + return RequestResult.Ok(data); + } + + public async Task GetCreatorRole(short id) + { + PersonCreatorRoleType? item = await _database.PersonCreatorRoleTypes.FirstOrDefaultAsync(x => x.Id == id); + if (item is null) + { + return RequestResult.NotFound(); + } + + RoleResponse data = new RoleResponse(item); + return RequestResult.Ok(data); + } + + public async Task PostCreatorRole(RoleRequest data) + { + UserValidator validator = _userService.GetValidator().MustBeAdmin(); + if (!validator.IsValid) + { + return RequestResult.Forbidden(); + } + + PersonCreatorRoleType item = data.CreateCreatorRoleType(); + await _database.PersonCreatorRoleTypes.AddAsync(item); + await _database.SaveChangesAsync(); + + return RequestResult.Created($"roles/creator/{item.Id}", new RoleResponse(item)); + } + + public async Task DeleteCreatorRole(short id) + { + UserValidator validator = _userService.GetValidator().MustBeAdmin(); + if (!validator.IsValid) + { + return RequestResult.Forbidden(); + } + + PersonCreatorRoleType? item = await _database.PersonCreatorRoleTypes.FirstOrDefaultAsync(x => x.Id == id); + if (item is null) + { + return RequestResult.NoContent(); + } + + _database.PersonCreatorRoleTypes.Attach(item); + _database.PersonCreatorRoleTypes.Remove(item); + await _database.SaveChangesAsync(); + + return RequestResult.NoContent(); + } + + #endregion + + #endregion +} \ No newline at end of file diff --git a/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Roles/WatchIt.WebAPI.Services.Controllers.Roles.csproj b/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Roles/WatchIt.WebAPI.Services.Controllers.Roles.csproj new file mode 100644 index 0000000..9e4603e --- /dev/null +++ b/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Roles/WatchIt.WebAPI.Services.Controllers.Roles.csproj @@ -0,0 +1,16 @@ + + + + net8.0 + enable + enable + + + + + + + + + + diff --git a/WatchIt.WebAPI/WatchIt.WebAPI/Program.cs b/WatchIt.WebAPI/WatchIt.WebAPI/Program.cs index d8a531d..7d987e4 100644 --- a/WatchIt.WebAPI/WatchIt.WebAPI/Program.cs +++ b/WatchIt.WebAPI/WatchIt.WebAPI/Program.cs @@ -16,6 +16,7 @@ using WatchIt.WebAPI.Services.Controllers.Media; using WatchIt.WebAPI.Services.Controllers.Movies; using WatchIt.WebAPI.Services.Controllers.Persons; using WatchIt.WebAPI.Services.Controllers.Photos; +using WatchIt.WebAPI.Services.Controllers.Roles; using WatchIt.WebAPI.Services.Controllers.Series; using WatchIt.WebAPI.Services.Utility.Configuration; using WatchIt.WebAPI.Services.Utility.Tokens; @@ -162,6 +163,7 @@ public static class Program builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); + builder.Services.AddTransient(); return builder; } diff --git a/WatchIt.WebAPI/WatchIt.WebAPI/WatchIt.WebAPI.csproj b/WatchIt.WebAPI/WatchIt.WebAPI/WatchIt.WebAPI.csproj index 37917aa..56996dc 100644 --- a/WatchIt.WebAPI/WatchIt.WebAPI/WatchIt.WebAPI.csproj +++ b/WatchIt.WebAPI/WatchIt.WebAPI/WatchIt.WebAPI.csproj @@ -28,6 +28,7 @@ + diff --git a/WatchIt.sln b/WatchIt.sln index 5cd82c9..2a611d5 100644 --- a/WatchIt.sln +++ b/WatchIt.sln @@ -96,6 +96,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WatchIt.WebAPI.Services.Con EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WatchIt.Website.Services.WebAPI.Genders", "WatchIt.Website\WatchIt.Website.Services\WatchIt.Website.Services.WebAPI\WatchIt.Website.Services.WebAPI.Genders\WatchIt.Website.Services.WebAPI.Genders.csproj", "{B74144DE-EF62-430A-AB80-5D185DD03C05}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WatchIt.WebAPI.Services.Controllers.Roles", "WatchIt.WebAPI\WatchIt.WebAPI.Services\WatchIt.WebAPI.Services.Controllers\WatchIt.WebAPI.Services.Controllers.Roles\WatchIt.WebAPI.Services.Controllers.Roles.csproj", "{847D157A-E486-4FB6-9AA3-43931A60FB5F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -146,6 +148,7 @@ Global {83D42D72-FF67-4577-8280-2ABD5B20F985} = {46E3711F-18BD-4004-AF53-EA4D8643D92F} {13BE36AB-2120-4F1B-815A-6F5E3F589EE8} = {CEC468DB-CC49-47D3-9E3E-1CC9530C3CE7} {B74144DE-EF62-430A-AB80-5D185DD03C05} = {46E3711F-18BD-4004-AF53-EA4D8643D92F} + {847D157A-E486-4FB6-9AA3-43931A60FB5F} = {CEC468DB-CC49-47D3-9E3E-1CC9530C3CE7} EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {23383776-1F27-4B5D-8C7C-57BFF75FA473}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -292,5 +295,9 @@ Global {B74144DE-EF62-430A-AB80-5D185DD03C05}.Debug|Any CPU.Build.0 = Debug|Any CPU {B74144DE-EF62-430A-AB80-5D185DD03C05}.Release|Any CPU.ActiveCfg = Release|Any CPU {B74144DE-EF62-430A-AB80-5D185DD03C05}.Release|Any CPU.Build.0 = Release|Any CPU + {847D157A-E486-4FB6-9AA3-43931A60FB5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {847D157A-E486-4FB6-9AA3-43931A60FB5F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {847D157A-E486-4FB6-9AA3-43931A60FB5F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {847D157A-E486-4FB6-9AA3-43931A60FB5F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal