From bdcbe0612ae3e4e173754c5e663e2668e9f380ec Mon Sep 17 00:00:00 2001 From: crupest Date: Tue, 12 Apr 2022 18:07:17 +0800 Subject: ... --- .../Timeline/Controllers/V2/UserV2Controller.cs | 181 +++++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 BackEnd/Timeline/Controllers/V2/UserV2Controller.cs (limited to 'BackEnd/Timeline/Controllers/V2/UserV2Controller.cs') diff --git a/BackEnd/Timeline/Controllers/V2/UserV2Controller.cs b/BackEnd/Timeline/Controllers/V2/UserV2Controller.cs new file mode 100644 index 00000000..e556bf8e --- /dev/null +++ b/BackEnd/Timeline/Controllers/V2/UserV2Controller.cs @@ -0,0 +1,181 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System.Threading.Tasks; +using Timeline.Auth; +using Timeline.Models; +using Timeline.Models.Http; +using Timeline.Models.Validation; +using Timeline.Services.Mapper; +using Timeline.Services.User; + +namespace Timeline.Controllers.V2 +{ + /// + /// Operations about users. + /// + [ApiController] + [Route("v2/users")] + public class UserV2Controller : V2ControllerBase + { + private readonly IUserService _userService; + private readonly IUserPermissionService _userPermissionService; + private readonly IUserDeleteService _userDeleteService; + private readonly IGenericMapper _mapper; + + public UserV2Controller(IUserService userService, IUserPermissionService userPermissionService, IUserDeleteService userDeleteService, IGenericMapper mapper) + { + _userService = userService; + _userPermissionService = userPermissionService; + _userDeleteService = userDeleteService; + _mapper = mapper; + } + + /// + /// Get all users. + /// + /// All user list. + [HttpGet] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task>> ListAsync([FromQuery][PositiveInteger] int? page, [FromQuery][PositiveInteger] int? pageSize) + { + var p = await _userService.GetUsersV2Async(page ?? 1, pageSize ?? 20); + var items = await _mapper.MapListAsync(p.Items, Url, User); + return p.WithItems(items); + } + + /// + /// Create a new user. You have to be administrator. + /// + /// The new user's info. + [HttpPost] + [PermissionAuthorize(UserPermission.UserManagement)] + [ProducesResponseType(StatusCodes.Status201Created)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] + [ProducesResponseType(StatusCodes.Status422UnprocessableEntity)] + public async Task> PostAsync([FromBody] HttpUserPostRequest body) + { + var user = await _userService.CreateUserAsync( + new CreateUserParams(body.Username, body.Password) { Nickname = body.Nickname }); + return CreatedAtAction("Get", new { username = body.Username }, await _mapper.MapAsync(user, Url, User)); + } + + /// + /// Get a user's info. + /// + /// Username of the user. + /// User info. + [HttpGet("{username}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status422UnprocessableEntity)] + public async Task> GetAsync([FromRoute][Username] string username) + { + var id = await _userService.GetUserIdByUsernameAsync(username); + var user = await _userService.GetUserAsync(id); + return await _mapper.MapAsync(user, Url, User); + } + + /// + /// Change a user's property. + /// + /// + /// Username of the user to change. + /// The new user info. + [HttpPatch("{username}")] + [Authorize] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status422UnprocessableEntity)] + public async Task> Patch([FromBody] HttpUserPatchRequest body, [FromRoute][Username] string username) + { + var userId = await _userService.GetUserIdByUsernameAsync(username); + if (UserHasPermission(UserPermission.UserManagement)) + { + var user = await _userService.ModifyUserAsync(userId, _mapper.AutoMapperMap(body)); + return await _mapper.MapAsync(user, Url, User); + } + else + { + if (userId != GetAuthUserId()) + return Forbid(); + + if (body.Username is not null) + return Forbid(); + + if (body.Password is not null) + return Forbid(); + + var user = await _userService.ModifyUserAsync(GetAuthUserId(), _mapper.AutoMapperMap(body)); + return await _mapper.MapAsync(user, Url, User); + } + } + + /// + /// Delete a user and all his related data. You have to be administrator. + /// + /// Username of the user to delete. + /// Info of deletion. + [HttpDelete("{username}")] + [PermissionAuthorize(UserPermission.UserManagement)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] + [ProducesResponseType(StatusCodes.Status422UnprocessableEntity)] + public async Task> Delete([FromRoute][Username] string username) + { + try + { + await _userDeleteService.DeleteUserAsync(username); + return NoContent(); + } + catch (InvalidOperationOnRootUserException) + { + return UnprocessableEntity(); + } + } + + [HttpPut("{username}/permissions/{permission}"), PermissionAuthorize(UserPermission.UserManagement)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status422UnprocessableEntity)] + public async Task> PutUserPermission([FromRoute][Username] string username, [FromRoute] UserPermission permission) + { + try + { + var id = await _userService.GetUserIdByUsernameAsync(username); + await _userPermissionService.AddPermissionToUserAsync(id, permission); + return NoContent(); + } + catch (InvalidOperationOnRootUserException) + { + return UnprocessableEntity(); + } + } + + [HttpDelete("{username}/permissions/{permission}"), PermissionAuthorize(UserPermission.UserManagement)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] + [ProducesResponseType(StatusCodes.Status422UnprocessableEntity)] + public async Task> DeleteUserPermission([FromRoute][Username] string username, [FromRoute] UserPermission permission) + { + try + { + var id = await _userService.GetUserIdByUsernameAsync(username); + await _userPermissionService.RemovePermissionFromUserAsync(id, permission); + return NoContent(); + } + catch (InvalidOperationOnRootUserException) + { + return UnprocessableEntity(); + } + } + } +} -- cgit v1.2.3