aboutsummaryrefslogtreecommitdiff
path: root/BackEnd/Timeline/Controllers
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2022-04-12 18:07:17 +0800
committercrupest <crupest@outlook.com>2022-04-12 18:07:17 +0800
commitbdcbe0612ae3e4e173754c5e663e2668e9f380ec (patch)
treec8f2b703302b0fed91925962a1695c2394bf345a /BackEnd/Timeline/Controllers
parent3fc0cd57711b41e3a65e24e30ceaa3f95d7d4415 (diff)
downloadtimeline-bdcbe0612ae3e4e173754c5e663e2668e9f380ec.tar.gz
timeline-bdcbe0612ae3e4e173754c5e663e2668e9f380ec.tar.bz2
timeline-bdcbe0612ae3e4e173754c5e663e2668e9f380ec.zip
...
Diffstat (limited to 'BackEnd/Timeline/Controllers')
-rw-r--r--BackEnd/Timeline/Controllers/V2/TimelineBookmarkV2Controller.cs (renamed from BackEnd/Timeline/Controllers/TimelineBookmarkV2Controller.cs)4
-rw-r--r--BackEnd/Timeline/Controllers/V2/TimelinePostV2Controller.cs (renamed from BackEnd/Timeline/Controllers/TimelinePostV2Controller.cs)4
-rw-r--r--BackEnd/Timeline/Controllers/V2/TimelineV2Controller.cs (renamed from BackEnd/Timeline/Controllers/TimelineV2Controller.cs)4
-rw-r--r--BackEnd/Timeline/Controllers/V2/UserV2Controller.cs181
-rw-r--r--BackEnd/Timeline/Controllers/V2/V2ControllerBase.cs28
5 files changed, 215 insertions, 6 deletions
diff --git a/BackEnd/Timeline/Controllers/TimelineBookmarkV2Controller.cs b/BackEnd/Timeline/Controllers/V2/TimelineBookmarkV2Controller.cs
index 2b31f43e..a23a061b 100644
--- a/BackEnd/Timeline/Controllers/TimelineBookmarkV2Controller.cs
+++ b/BackEnd/Timeline/Controllers/V2/TimelineBookmarkV2Controller.cs
@@ -10,11 +10,11 @@ using Timeline.Services.Api;
using Timeline.Services.Timeline;
using Timeline.Services.User;
-namespace Timeline.Controllers
+namespace Timeline.Controllers.V2
{
[ApiController]
[Route("v2/users/{username}/bookmarks")]
- public class TimelineBookmarkV2Controller : MyControllerBase
+ public class TimelineBookmarkV2Controller : V2ControllerBase
{
private readonly IUserService _userService;
private readonly ITimelineService _timelineService;
diff --git a/BackEnd/Timeline/Controllers/TimelinePostV2Controller.cs b/BackEnd/Timeline/Controllers/V2/TimelinePostV2Controller.cs
index c80cda17..aa839abf 100644
--- a/BackEnd/Timeline/Controllers/TimelinePostV2Controller.cs
+++ b/BackEnd/Timeline/Controllers/V2/TimelinePostV2Controller.cs
@@ -14,11 +14,11 @@ using Timeline.Services.Timeline;
using Timeline.Services.User;
using Timeline.SignalRHub;
-namespace Timeline.Controllers
+namespace Timeline.Controllers.V2
{
[ApiController]
[Route("v2/timelines/{owner}/{timeline}/posts")]
- public class TimelinePostV2Controller : MyControllerBase
+ public class TimelinePostV2Controller : V2ControllerBase
{
private readonly ITimelineService _timelineService;
private readonly ITimelinePostService _postService;
diff --git a/BackEnd/Timeline/Controllers/TimelineV2Controller.cs b/BackEnd/Timeline/Controllers/V2/TimelineV2Controller.cs
index 9811cbed..393446f7 100644
--- a/BackEnd/Timeline/Controllers/TimelineV2Controller.cs
+++ b/BackEnd/Timeline/Controllers/V2/TimelineV2Controller.cs
@@ -10,11 +10,11 @@ using Timeline.Services.Mapper;
using Timeline.Services.Timeline;
using Timeline.Services.User;
-namespace Timeline.Controllers
+namespace Timeline.Controllers.V2
{
[ApiController]
[Route("v2/timelines")]
- public class TimelineV2Controller : MyControllerBase
+ public class TimelineV2Controller : V2ControllerBase
{
private ITimelineService _timelineService;
private IGenericMapper _mapper;
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
+{
+ /// <summary>
+ /// Operations about users.
+ /// </summary>
+ [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;
+ }
+
+ /// <summary>
+ /// Get all users.
+ /// </summary>
+ /// <returns>All user list.</returns>
+ [HttpGet]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ public async Task<ActionResult<Page<HttpUser>>> ListAsync([FromQuery][PositiveInteger] int? page, [FromQuery][PositiveInteger] int? pageSize)
+ {
+ var p = await _userService.GetUsersV2Async(page ?? 1, pageSize ?? 20);
+ var items = await _mapper.MapListAsync<HttpUser>(p.Items, Url, User);
+ return p.WithItems(items);
+ }
+
+ /// <summary>
+ /// Create a new user. You have to be administrator.
+ /// </summary>
+ /// <returns>The new user's info.</returns>
+ [HttpPost]
+ [PermissionAuthorize(UserPermission.UserManagement)]
+ [ProducesResponseType(StatusCodes.Status201Created)]
+ [ProducesResponseType(StatusCodes.Status401Unauthorized)]
+ [ProducesResponseType(StatusCodes.Status403Forbidden)]
+ [ProducesResponseType(StatusCodes.Status422UnprocessableEntity)]
+ public async Task<ActionResult<HttpUser>> 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<HttpUser>(user, Url, User));
+ }
+
+ /// <summary>
+ /// Get a user's info.
+ /// </summary>
+ /// <param name="username">Username of the user.</param>
+ /// <returns>User info.</returns>
+ [HttpGet("{username}")]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status404NotFound)]
+ [ProducesResponseType(StatusCodes.Status422UnprocessableEntity)]
+ public async Task<ActionResult<HttpUser>> GetAsync([FromRoute][Username] string username)
+ {
+ var id = await _userService.GetUserIdByUsernameAsync(username);
+ var user = await _userService.GetUserAsync(id);
+ return await _mapper.MapAsync<HttpUser>(user, Url, User);
+ }
+
+ /// <summary>
+ /// Change a user's property.
+ /// </summary>
+ /// <param name="body"></param>
+ /// <param name="username">Username of the user to change.</param>
+ /// <returns>The new user info.</returns>
+ [HttpPatch("{username}")]
+ [Authorize]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status401Unauthorized)]
+ [ProducesResponseType(StatusCodes.Status403Forbidden)]
+ [ProducesResponseType(StatusCodes.Status404NotFound)]
+ [ProducesResponseType(StatusCodes.Status422UnprocessableEntity)]
+ public async Task<ActionResult<HttpUser>> 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<ModifyUserParams>(body));
+ return await _mapper.MapAsync<HttpUser>(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<ModifyUserParams>(body));
+ return await _mapper.MapAsync<HttpUser>(user, Url, User);
+ }
+ }
+
+ /// <summary>
+ /// Delete a user and all his related data. You have to be administrator.
+ /// </summary>
+ /// <param name="username">Username of the user to delete.</param>
+ /// <returns>Info of deletion.</returns>
+ [HttpDelete("{username}")]
+ [PermissionAuthorize(UserPermission.UserManagement)]
+ [ProducesResponseType(StatusCodes.Status204NoContent)]
+ [ProducesResponseType(StatusCodes.Status401Unauthorized)]
+ [ProducesResponseType(StatusCodes.Status403Forbidden)]
+ [ProducesResponseType(StatusCodes.Status422UnprocessableEntity)]
+ public async Task<ActionResult<CommonDeleteResponse>> 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<ActionResult<CommonResponse>> 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<ActionResult<CommonResponse>> 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();
+ }
+ }
+ }
+}
diff --git a/BackEnd/Timeline/Controllers/V2/V2ControllerBase.cs b/BackEnd/Timeline/Controllers/V2/V2ControllerBase.cs
new file mode 100644
index 00000000..54b9c7c9
--- /dev/null
+++ b/BackEnd/Timeline/Controllers/V2/V2ControllerBase.cs
@@ -0,0 +1,28 @@
+using System;
+using Microsoft.AspNetCore.Mvc;
+using Timeline.Auth;
+using Timeline.Services.User;
+
+namespace Timeline.Controllers.V2
+{
+ public class V2ControllerBase : ControllerBase
+ {
+ #region auth
+ protected bool UserHasPermission(UserPermission permission)
+ {
+ return User.HasPermission(permission);
+ }
+
+ protected long? GetOptionalAuthUserId()
+ {
+ return User.GetOptionalUserId();
+ }
+
+ protected long GetAuthUserId()
+ {
+ return GetOptionalAuthUserId() ?? throw new InvalidOperationException(Resource.ExceptionNoUserId);
+ }
+ #endregion
+ }
+}
+