aboutsummaryrefslogtreecommitdiff
path: root/BackEnd/Timeline
diff options
context:
space:
mode:
Diffstat (limited to 'BackEnd/Timeline')
-rw-r--r--BackEnd/Timeline/Auth/PrincipalExtensions.cs8
-rw-r--r--BackEnd/Timeline/Controllers/ActionResultControllerExtensions.cs29
-rw-r--r--BackEnd/Timeline/Controllers/BookmarkTimelineController.cs10
-rw-r--r--BackEnd/Timeline/Controllers/ControllerAuthExtensions.cs25
-rw-r--r--BackEnd/Timeline/Controllers/HighlightTimelineController.cs6
-rw-r--r--BackEnd/Timeline/Controllers/MyControllerBase.cs76
-rw-r--r--BackEnd/Timeline/Controllers/Resource.Designer.cs18
-rw-r--r--BackEnd/Timeline/Controllers/Resource.resx6
-rw-r--r--BackEnd/Timeline/Controllers/SearchController.cs2
-rw-r--r--BackEnd/Timeline/Controllers/TimelineController.cs59
-rw-r--r--BackEnd/Timeline/Controllers/TimelinePostController.cs30
-rw-r--r--BackEnd/Timeline/Controllers/TokenController.cs14
-rw-r--r--BackEnd/Timeline/Controllers/UserAvatarController.cs10
-rw-r--r--BackEnd/Timeline/Controllers/UserController.cs54
-rw-r--r--BackEnd/Timeline/Filters/CatchEntityNotExistExceptionFilter.cs10
-rw-r--r--BackEnd/Timeline/Filters/NotEntityDeleteAttribute.cs9
-rw-r--r--BackEnd/Timeline/Helpers/Cache/DataCacheHelper.cs4
-rw-r--r--BackEnd/Timeline/Services/Mapper/TimelineMapper.cs4
18 files changed, 231 insertions, 143 deletions
diff --git a/BackEnd/Timeline/Auth/PrincipalExtensions.cs b/BackEnd/Timeline/Auth/PrincipalExtensions.cs
index 6c974ed2..d338846a 100644
--- a/BackEnd/Timeline/Auth/PrincipalExtensions.cs
+++ b/BackEnd/Timeline/Auth/PrincipalExtensions.cs
@@ -6,7 +6,13 @@ namespace Timeline.Auth
{
public static class PrincipalExtensions
{
- public static long? GetUserId(this ClaimsPrincipal? principal)
+ public static string? GetOptionalName(this ClaimsPrincipal? principal)
+ {
+ if (principal is null) return null;
+ return principal.Identity?.Name;
+ }
+
+ public static long? GetOptionalUserId(this ClaimsPrincipal? principal)
{
if (principal is null) return null;
diff --git a/BackEnd/Timeline/Controllers/ActionResultControllerExtensions.cs b/BackEnd/Timeline/Controllers/ActionResultControllerExtensions.cs
deleted file mode 100644
index a7a5486c..00000000
--- a/BackEnd/Timeline/Controllers/ActionResultControllerExtensions.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using Microsoft.AspNetCore.Http;
-using Microsoft.AspNetCore.Mvc;
-using Timeline.Models.Http;
-
-namespace Timeline.Controllers
-{
- public static class ActionResultControllerExtensions
- {
- public static ObjectResult StatusCodeWithCommonResponse(this ControllerBase controller, int statusCode, int code, string message)
- {
- return controller.StatusCode(statusCode, new CommonResponse(code, message));
- }
-
- public static ObjectResult ForbidWithMessage(this ControllerBase controller, string? message = null)
- {
- return controller.StatusCode(StatusCodes.Status403Forbidden, new CommonResponse(ErrorCodes.Common.Forbid, message ?? Resource.MessageForbid));
- }
-
- public static ObjectResult Delete(this ControllerBase controller, bool delete = true)
- {
- return controller.StatusCode(StatusCodes.Status200OK, CommonDeleteResponse.Create(delete));
- }
-
- public static BadRequestObjectResult BadRequestWithCommonResponse(this ControllerBase controller, int code, string message)
- {
- return controller.BadRequest(new CommonResponse(code, message));
- }
- }
-}
diff --git a/BackEnd/Timeline/Controllers/BookmarkTimelineController.cs b/BackEnd/Timeline/Controllers/BookmarkTimelineController.cs
index 94cb0f3e..bfbf82f3 100644
--- a/BackEnd/Timeline/Controllers/BookmarkTimelineController.cs
+++ b/BackEnd/Timeline/Controllers/BookmarkTimelineController.cs
@@ -16,7 +16,7 @@ namespace Timeline.Controllers
/// </summary>
[ApiController]
[ProducesErrorResponseType(typeof(CommonResponse))]
- public class BookmarkTimelineController : Controller
+ public class BookmarkTimelineController : MyControllerBase
{
private readonly IBookmarkTimelineService _service;
private readonly ITimelineService _timelineService;
@@ -44,7 +44,7 @@ namespace Timeline.Controllers
[ProducesResponseType(401)]
public async Task<ActionResult<List<HttpTimeline>>> List()
{
- var ids = await _service.GetBookmarksAsync(this.GetUserId());
+ var ids = await _service.GetBookmarksAsync(GetUserId());
var timelines = await _timelineService.GetTimelineList(ids);
return await Map(timelines);
}
@@ -61,7 +61,7 @@ namespace Timeline.Controllers
public async Task<ActionResult<CommonPutResponse>> Put([GeneralTimelineName] string timeline)
{
var timelineId = await _timelineService.GetTimelineIdByNameAsync(timeline);
- var create = await _service.AddBookmarkAsync(this.GetUserId(), timelineId);
+ var create = await _service.AddBookmarkAsync(GetUserId(), timelineId);
return CommonPutResponse.Create(create);
}
@@ -77,7 +77,7 @@ namespace Timeline.Controllers
public async Task<ActionResult<CommonDeleteResponse>> Delete([GeneralTimelineName] string timeline)
{
var timelineId = await _timelineService.GetTimelineIdByNameAsync(timeline);
- var delete = await _service.RemoveBookmarkAsync(this.GetUserId(), timelineId);
+ var delete = await _service.RemoveBookmarkAsync(GetUserId(), timelineId);
return CommonDeleteResponse.Create(delete);
}
@@ -95,7 +95,7 @@ namespace Timeline.Controllers
try
{
var timelineId = await _timelineService.GetTimelineIdByNameAsync(request.Timeline);
- await _service.MoveBookmarkAsync(this.GetUserId(), timelineId, request.NewPosition!.Value);
+ await _service.MoveBookmarkAsync(GetUserId(), timelineId, request.NewPosition!.Value);
return Ok();
}
catch (InvalidBookmarkException)
diff --git a/BackEnd/Timeline/Controllers/ControllerAuthExtensions.cs b/BackEnd/Timeline/Controllers/ControllerAuthExtensions.cs
deleted file mode 100644
index cd2bdadf..00000000
--- a/BackEnd/Timeline/Controllers/ControllerAuthExtensions.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using Microsoft.AspNetCore.Mvc;
-using System;
-using Timeline.Auth;
-using Timeline.Services.User;
-
-namespace Timeline.Controllers
-{
- public static class ControllerAuthExtensions
- {
- public static bool UserHasPermission(this ControllerBase controller, UserPermission permission)
- {
- return controller.User.HasPermission(permission);
- }
-
- public static long GetUserId(this ControllerBase controller)
- {
- return controller.GetOptionalUserId() ?? throw new InvalidOperationException(Resource.ExceptionNoUserId);
- }
-
- public static long? GetOptionalUserId(this ControllerBase controller)
- {
- return controller.User.GetUserId();
- }
- }
-}
diff --git a/BackEnd/Timeline/Controllers/HighlightTimelineController.cs b/BackEnd/Timeline/Controllers/HighlightTimelineController.cs
index e73bc7a9..24201126 100644
--- a/BackEnd/Timeline/Controllers/HighlightTimelineController.cs
+++ b/BackEnd/Timeline/Controllers/HighlightTimelineController.cs
@@ -17,7 +17,7 @@ namespace Timeline.Controllers
/// </summary>
[ApiController]
[ProducesErrorResponseType(typeof(CommonResponse))]
- public class HighlightTimelineController : Controller
+ public class HighlightTimelineController : MyControllerBase
{
private readonly IHighlightTimelineService _service;
private readonly ITimelineService _timelineService;
@@ -61,7 +61,7 @@ namespace Timeline.Controllers
public async Task<ActionResult<CommonPutResponse>> Put([GeneralTimelineName] string timeline)
{
var timelineId = await _timelineService.GetTimelineIdByNameAsync(timeline);
- var create = await _service.AddHighlightTimelineAsync(timelineId, this.GetUserId());
+ var create = await _service.AddHighlightTimelineAsync(timelineId, GetUserId());
return CommonPutResponse.Create(create);
}
@@ -78,7 +78,7 @@ namespace Timeline.Controllers
public async Task<ActionResult<CommonDeleteResponse>> Delete([GeneralTimelineName] string timeline)
{
var timelineId = await _timelineService.GetTimelineIdByNameAsync(timeline);
- var delete = await _service.RemoveHighlightTimelineAsync(timelineId, this.GetUserId());
+ var delete = await _service.RemoveHighlightTimelineAsync(timelineId, GetUserId());
return CommonDeleteResponse.Create(delete);
}
diff --git a/BackEnd/Timeline/Controllers/MyControllerBase.cs b/BackEnd/Timeline/Controllers/MyControllerBase.cs
new file mode 100644
index 00000000..d4ee9d3e
--- /dev/null
+++ b/BackEnd/Timeline/Controllers/MyControllerBase.cs
@@ -0,0 +1,76 @@
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using System;
+using Timeline.Auth;
+using Timeline.Models.Http;
+using Timeline.Services.User;
+
+namespace Timeline.Controllers
+{
+ public class MyControllerBase : ControllerBase
+ {
+ #region auth
+ protected bool UserHasPermission(UserPermission permission)
+ {
+ return User.HasPermission(permission);
+ }
+
+ protected string? GetOptionalUsername()
+ {
+ return User.GetOptionalName();
+ }
+
+ protected string GetUsername()
+ {
+ return GetOptionalUsername() ?? throw new InvalidOperationException(Resource.ExceptionNoUsername);
+ }
+
+ protected long? GetOptionalUserId()
+ {
+ return User.GetOptionalUserId();
+ }
+
+ protected long GetUserId()
+ {
+ return GetOptionalUserId() ?? throw new InvalidOperationException(Resource.ExceptionNoUserId);
+ }
+ #endregion auth
+
+ #region action result
+ protected ObjectResult StatusCodeWithCommonResponse(int statusCode, int code, string message)
+ {
+ return StatusCode(statusCode, new CommonResponse(code, message));
+ }
+
+ protected ObjectResult OkWithCommonResponse(int statusCode = 0, string? message = null)
+ {
+ return Ok(new CommonResponse(statusCode, message ?? Resource.MessageOperationSucceeded));
+ }
+
+ protected ObjectResult OkWithCommonResponse(string? message)
+ {
+ return OkWithCommonResponse(message: message);
+ }
+
+ protected ObjectResult ForbidWithCommonResponse(string? message = null)
+ {
+ return StatusCode(StatusCodes.Status403Forbidden, new CommonResponse(ErrorCodes.Common.Forbid, message ?? Resource.MessageForbid));
+ }
+
+ protected ObjectResult ForbidWithCommonResponse(int code, string? message = null)
+ {
+ return StatusCode(StatusCodes.Status403Forbidden, new CommonResponse(code, message ?? Resource.MessageForbid));
+ }
+
+ protected ObjectResult DeleteWithCommonDeleteResponse(bool delete = true)
+ {
+ return StatusCode(StatusCodes.Status200OK, CommonDeleteResponse.Create(delete));
+ }
+
+ protected BadRequestObjectResult BadRequestWithCommonResponse(int code, string message)
+ {
+ return BadRequest(new CommonResponse(code, message));
+ }
+ #endregion action result
+ }
+}
diff --git a/BackEnd/Timeline/Controllers/Resource.Designer.cs b/BackEnd/Timeline/Controllers/Resource.Designer.cs
index f3d7264a..c062380b 100644
--- a/BackEnd/Timeline/Controllers/Resource.Designer.cs
+++ b/BackEnd/Timeline/Controllers/Resource.Designer.cs
@@ -70,6 +70,15 @@ namespace Timeline.Controllers {
}
/// <summary>
+ /// Looks up a localized string similar to Can&apos;t get username..
+ /// </summary>
+ internal static string ExceptionNoUsername {
+ get {
+ return ResourceManager.GetString("ExceptionNoUsername", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to You have no permission to access this..
/// </summary>
internal static string MessageForbid {
@@ -151,6 +160,15 @@ namespace Timeline.Controllers {
}
/// <summary>
+ /// Looks up a localized string similar to Operation succeeded..
+ /// </summary>
+ internal static string MessageOperationSucceeded {
+ get {
+ return ResourceManager.GetString("MessageOperationSucceeded", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to The user specified by query param &quot;relate&quot; does not exist..
/// </summary>
internal static string MessageTimelineListQueryRelateNotExist {
diff --git a/BackEnd/Timeline/Controllers/Resource.resx b/BackEnd/Timeline/Controllers/Resource.resx
index 90c6bdd6..afaa1ba1 100644
--- a/BackEnd/Timeline/Controllers/Resource.resx
+++ b/BackEnd/Timeline/Controllers/Resource.resx
@@ -120,6 +120,9 @@
<data name="ExceptionNoUserId" xml:space="preserve">
<value>Can't get user id.</value>
</data>
+ <data name="ExceptionNoUsername" xml:space="preserve">
+ <value>Can't get username.</value>
+ </data>
<data name="MessageForbid" xml:space="preserve">
<value>You have no permission to access this.</value>
</data>
@@ -147,6 +150,9 @@
<data name="MessageOldPasswordWrong" xml:space="preserve">
<value>The old password is wrong.</value>
</data>
+ <data name="MessageOperationSucceeded" xml:space="preserve">
+ <value>Operation succeeded.</value>
+ </data>
<data name="MessageTimelineListQueryRelateNotExist" xml:space="preserve">
<value>The user specified by query param "relate" does not exist.</value>
</data>
diff --git a/BackEnd/Timeline/Controllers/SearchController.cs b/BackEnd/Timeline/Controllers/SearchController.cs
index cd085e5b..358c3739 100644
--- a/BackEnd/Timeline/Controllers/SearchController.cs
+++ b/BackEnd/Timeline/Controllers/SearchController.cs
@@ -16,7 +16,7 @@ namespace Timeline.Controllers
[ApiController]
[ProducesErrorResponseType(typeof(CommonResponse))]
[Route("search")]
- public class SearchController : Controller
+ public class SearchController : MyControllerBase
{
private readonly ISearchService _service;
private readonly IGenericMapper _mapper;
diff --git a/BackEnd/Timeline/Controllers/TimelineController.cs b/BackEnd/Timeline/Controllers/TimelineController.cs
index 7347f135..f98ff3e0 100644
--- a/BackEnd/Timeline/Controllers/TimelineController.cs
+++ b/BackEnd/Timeline/Controllers/TimelineController.cs
@@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Timeline.Entities;
+using Timeline.Filters;
using Timeline.Models;
using Timeline.Models.Http;
using Timeline.Models.Validation;
@@ -21,7 +22,7 @@ namespace Timeline.Controllers
[ApiController]
[Route("timelines")]
[ProducesErrorResponseType(typeof(CommonResponse))]
- public class TimelineController : Controller
+ public class TimelineController : MyControllerBase
{
private readonly IUserService _userService;
private readonly ITimelineService _service;
@@ -34,7 +35,7 @@ namespace Timeline.Controllers
_mapper = mapper;
}
- private bool UserHasAllTimelineManagementPermission => this.UserHasPermission(UserPermission.AllTimelineManagement);
+ private bool UserHasAllTimelineManagementPermission => UserHasPermission(UserPermission.AllTimelineManagement);
private Task<HttpTimeline> Map(TimelineEntity timeline)
{
@@ -82,7 +83,7 @@ namespace Timeline.Controllers
}
else
{
- return this.BadRequestWithCommonResponse(ErrorCodes.Common.InvalidModel, string.Format(Resource.MessageTimelineListQueryVisibilityUnknown, visibility));
+ return BadRequestWithCommonResponse(ErrorCodes.Common.InvalidModel, string.Format(Resource.MessageTimelineListQueryVisibilityUnknown, visibility));
}
}
}
@@ -100,7 +101,7 @@ namespace Timeline.Controllers
}
catch (EntityNotExistException)
{
- return this.BadRequestWithCommonResponse(ErrorCodes.TimelineController.QueryRelateNotExist, Resource.MessageTimelineListQueryRelateNotExist);
+ return BadRequestWithCommonResponse(ErrorCodes.TimelineController.QueryRelateNotExist, Resource.MessageTimelineListQueryRelateNotExist);
}
}
@@ -141,9 +142,9 @@ namespace Timeline.Controllers
{
var timelineId = await _service.GetTimelineIdByNameAsync(timeline);
- if (!UserHasAllTimelineManagementPermission && !await _service.HasManagePermissionAsync(timelineId, this.GetUserId()))
+ if (!UserHasAllTimelineManagementPermission && !await _service.HasManagePermissionAsync(timelineId, GetUserId()))
{
- return this.ForbidWithMessage();
+ return ForbidWithCommonResponse();
}
await _service.ChangePropertyAsync(timelineId, _mapper.AutoMapperMap<TimelineChangePropertyParams>(body));
@@ -167,14 +168,14 @@ namespace Timeline.Controllers
{
var timelineId = await _service.GetTimelineIdByNameAsync(timeline);
- if (!UserHasAllTimelineManagementPermission && !(await _service.HasManagePermissionAsync(timelineId, this.GetUserId())))
+ if (!UserHasAllTimelineManagementPermission && !(await _service.HasManagePermissionAsync(timelineId, GetUserId())))
{
- return this.ForbidWithMessage();
+ return ForbidWithCommonResponse();
}
var userId = await _userService.GetUserIdByUsernameAsync(member);
- var create = await _service.AddMemberAsync(timelineId, userId);
- return Ok(CommonPutResponse.Create(create));
+ await _service.AddMemberAsync(timelineId, userId);
+ return OkWithCommonResponse();
}
/// <summary>
@@ -184,6 +185,7 @@ namespace Timeline.Controllers
/// <param name="member">The member's username.</param>
[HttpDelete("{timeline}/members/{member}")]
[Authorize]
+ [NotEntityDelete]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
@@ -192,15 +194,14 @@ namespace Timeline.Controllers
{
var timelineId = await _service.GetTimelineIdByNameAsync(timeline);
- if (!UserHasAllTimelineManagementPermission && !(await _service.HasManagePermissionAsync(timelineId, this.GetUserId())))
+ if (!UserHasAllTimelineManagementPermission && !(await _service.HasManagePermissionAsync(timelineId, GetUserId())))
{
- return this.ForbidWithMessage();
+ return ForbidWithCommonResponse();
}
-
var userId = await _userService.GetUserIdByUsernameAsync(member);
- var delete = await _service.RemoveMemberAsync(timelineId, userId);
- return Ok(CommonDeleteResponse.Create(delete));
+ await _service.RemoveMemberAsync(timelineId, userId);
+ return OkWithCommonResponse();
}
/// <summary>
@@ -215,7 +216,7 @@ namespace Timeline.Controllers
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public async Task<ActionResult<HttpTimeline>> TimelineCreate([FromBody] HttpTimelineCreateRequest body)
{
- var userId = this.GetUserId();
+ var userId = GetUserId();
var timeline = await _service.CreateTimelineAsync(body.Name, userId);
var result = await Map(timeline);
@@ -235,15 +236,29 @@ namespace Timeline.Controllers
[ProducesResponseType(StatusCodes.Status403Forbidden)]
public async Task<ActionResult> TimelineDelete([FromRoute][TimelineName] string timeline)
{
- var timelineId = await _service.GetTimelineIdByNameAsync(timeline);
+ try
+ {
+ var timelineId = await _service.GetTimelineIdByNameAsync(timeline);
+
+ if (!UserHasAllTimelineManagementPermission && !(await _service.HasManagePermissionAsync(timelineId, GetUserId())))
+ {
+ return ForbidWithCommonResponse();
+ }
- if (!UserHasAllTimelineManagementPermission && !(await _service.HasManagePermissionAsync(timelineId, this.GetUserId())))
+ await _service.DeleteTimelineAsync(timelineId);
+ return DeleteWithCommonDeleteResponse();
+ }
+ catch (EntityNotExistException)
{
- return this.ForbidWithMessage();
+ if (UserHasAllTimelineManagementPermission)
+ {
+ return DeleteWithCommonDeleteResponse(false);
+ }
+ else
+ {
+ return ForbidWithCommonResponse();
+ }
}
-
- await _service.DeleteTimelineAsync(timelineId);
- return this.Delete();
}
}
}
diff --git a/BackEnd/Timeline/Controllers/TimelinePostController.cs b/BackEnd/Timeline/Controllers/TimelinePostController.cs
index 09e7e624..c33d47aa 100644
--- a/BackEnd/Timeline/Controllers/TimelinePostController.cs
+++ b/BackEnd/Timeline/Controllers/TimelinePostController.cs
@@ -22,7 +22,7 @@ namespace Timeline.Controllers
[ApiController]
[Route("timelines/{timeline}/posts")]
[ProducesErrorResponseType(typeof(CommonResponse))]
- public class TimelinePostController : Controller
+ public class TimelinePostController : MyControllerBase
{
private readonly ITimelineService _timelineService;
private readonly ITimelinePostService _postService;
@@ -39,7 +39,7 @@ namespace Timeline.Controllers
_markdownProcessor = markdownProcessor;
}
- private bool UserHasAllTimelineManagementPermission => this.UserHasPermission(UserPermission.AllTimelineManagement);
+ private bool UserHasAllTimelineManagementPermission => UserHasPermission(UserPermission.AllTimelineManagement);
private Task<HttpTimelinePost> Map(TimelinePostEntity post)
{
@@ -66,9 +66,9 @@ namespace Timeline.Controllers
{
var timelineId = await _timelineService.GetTimelineIdByNameAsync(timeline);
- if (!UserHasAllTimelineManagementPermission && !await _timelineService.HasReadPermissionAsync(timelineId, this.GetOptionalUserId()))
+ if (!UserHasAllTimelineManagementPermission && !await _timelineService.HasReadPermissionAsync(timelineId, GetOptionalUserId()))
{
- return this.ForbidWithMessage();
+ return ForbidWithCommonResponse();
}
var posts = await _postService.GetPostsAsync(timelineId, modifiedSince, includeDeleted ?? false);
@@ -91,9 +91,9 @@ namespace Timeline.Controllers
{
var timelineId = await _timelineService.GetTimelineIdByNameAsync(timeline);
- if (!UserHasAllTimelineManagementPermission && !await _timelineService.HasReadPermissionAsync(timelineId, this.GetOptionalUserId()))
+ if (!UserHasAllTimelineManagementPermission && !await _timelineService.HasReadPermissionAsync(timelineId, GetOptionalUserId()))
{
- return this.ForbidWithMessage();
+ return ForbidWithCommonResponse();
}
var post = await _postService.GetPostAsync(timelineId, postId);
@@ -137,9 +137,9 @@ namespace Timeline.Controllers
{
var timelineId = await _timelineService.GetTimelineIdByNameAsync(timeline);
- if (!UserHasAllTimelineManagementPermission && !await _timelineService.HasReadPermissionAsync(timelineId, this.GetOptionalUserId()))
+ if (!UserHasAllTimelineManagementPermission && !await _timelineService.HasReadPermissionAsync(timelineId, GetOptionalUserId()))
{
- return this.ForbidWithMessage();
+ return ForbidWithCommonResponse();
}
return await DataCacheHelper.GenerateActionResult(this,
@@ -171,11 +171,11 @@ namespace Timeline.Controllers
public async Task<ActionResult<HttpTimelinePost>> Post([FromRoute][GeneralTimelineName] string timeline, [FromBody] HttpTimelinePostCreateRequest body)
{
var timelineId = await _timelineService.GetTimelineIdByNameAsync(timeline);
- var userId = this.GetUserId();
+ var userId = GetUserId();
if (!UserHasAllTimelineManagementPermission && !await _timelineService.IsMemberOfAsync(timelineId, userId))
{
- return this.ForbidWithMessage();
+ return ForbidWithCommonResponse();
}
var createRequest = new TimelinePostCreateRequest()
@@ -232,9 +232,9 @@ namespace Timeline.Controllers
{
var timelineId = await _timelineService.GetTimelineIdByNameAsync(timeline);
- if (!UserHasAllTimelineManagementPermission && !await _postService.HasPostModifyPermissionAsync(timelineId, post, this.GetUserId(), true))
+ if (!UserHasAllTimelineManagementPermission && !await _postService.HasPostModifyPermissionAsync(timelineId, post, GetUserId(), true))
{
- return this.ForbidWithMessage();
+ return ForbidWithCommonResponse();
}
var entity = await _postService.PatchPostAsync(timelineId, post, new TimelinePostPatchRequest { Time = body.Time, Color = body.Color });
@@ -259,14 +259,14 @@ namespace Timeline.Controllers
{
var timelineId = await _timelineService.GetTimelineIdByNameAsync(timeline);
- if (!UserHasAllTimelineManagementPermission && !await _postService.HasPostModifyPermissionAsync(timelineId, post, this.GetUserId(), true))
+ if (!UserHasAllTimelineManagementPermission && !await _postService.HasPostModifyPermissionAsync(timelineId, post, GetUserId(), true))
{
- return this.ForbidWithMessage();
+ return ForbidWithCommonResponse();
}
await _postService.DeletePostAsync(timelineId, post);
- return this.Delete();
+ return DeleteWithCommonDeleteResponse();
}
}
}
diff --git a/BackEnd/Timeline/Controllers/TokenController.cs b/BackEnd/Timeline/Controllers/TokenController.cs
index 080a4dc4..ae3e1b94 100644
--- a/BackEnd/Timeline/Controllers/TokenController.cs
+++ b/BackEnd/Timeline/Controllers/TokenController.cs
@@ -17,7 +17,7 @@ namespace Timeline.Controllers
[Route("token")]
[ApiController]
[ProducesErrorResponseType(typeof(CommonResponse))]
- public class TokenController : Controller
+ public class TokenController : MyControllerBase
{
private readonly IUserTokenManager _userTokenManager;
private readonly IGenericMapper _mapper;
@@ -57,11 +57,11 @@ namespace Timeline.Controllers
}
catch (EntityNotExistException)
{
- return this.BadRequestWithCommonResponse(ErrorCodes.TokenController.CreateBadCredential, Resource.MessageTokenCreateBadCredential);
+ return BadRequestWithCommonResponse(ErrorCodes.TokenController.CreateBadCredential, Resource.MessageTokenCreateBadCredential);
}
catch (BadPasswordException)
{
- return this.BadRequestWithCommonResponse(ErrorCodes.TokenController.CreateBadCredential, Resource.MessageTokenCreateBadCredential);
+ return BadRequestWithCommonResponse(ErrorCodes.TokenController.CreateBadCredential, Resource.MessageTokenCreateBadCredential);
}
}
@@ -85,19 +85,19 @@ namespace Timeline.Controllers
}
catch (UserTokenTimeExpiredException)
{
- return this.BadRequestWithCommonResponse(ErrorCodes.TokenController.VerifyTimeExpired, Resource.MessageTokenVerifyTimeExpired);
+ return BadRequestWithCommonResponse(ErrorCodes.TokenController.VerifyTimeExpired, Resource.MessageTokenVerifyTimeExpired);
}
catch (UserTokenVersionExpiredException)
{
- return this.BadRequestWithCommonResponse(ErrorCodes.TokenController.VerifyOldVersion, Resource.MessageTokenVerifyOldVersion);
+ return BadRequestWithCommonResponse(ErrorCodes.TokenController.VerifyOldVersion, Resource.MessageTokenVerifyOldVersion);
}
catch (UserTokenBadFormatException)
{
- return this.BadRequestWithCommonResponse(ErrorCodes.TokenController.VerifyBadFormat, Resource.MessageTokenVerifyBadFormat);
+ return BadRequestWithCommonResponse(ErrorCodes.TokenController.VerifyBadFormat, Resource.MessageTokenVerifyBadFormat);
}
catch (UserTokenUserNotExistException)
{
- return this.BadRequestWithCommonResponse(ErrorCodes.TokenController.VerifyUserNotExist, Resource.MessageTokenVerifyUserNotExist);
+ return BadRequestWithCommonResponse(ErrorCodes.TokenController.VerifyUserNotExist, Resource.MessageTokenVerifyUserNotExist);
}
}
}
diff --git a/BackEnd/Timeline/Controllers/UserAvatarController.cs b/BackEnd/Timeline/Controllers/UserAvatarController.cs
index 47d46a54..376e1f11 100644
--- a/BackEnd/Timeline/Controllers/UserAvatarController.cs
+++ b/BackEnd/Timeline/Controllers/UserAvatarController.cs
@@ -18,7 +18,7 @@ namespace Timeline.Controllers
/// </summary>
[ApiController]
[ProducesErrorResponseType(typeof(CommonResponse))]
- public class UserAvatarController : Controller
+ public class UserAvatarController : MyControllerBase
{
private readonly IUserService _userService;
private readonly IUserAvatarService _service;
@@ -62,9 +62,9 @@ namespace Timeline.Controllers
[ProducesResponseType(StatusCodes.Status403Forbidden)]
public async Task<IActionResult> Put([FromRoute][Username] string username, [FromBody] ByteData body)
{
- if (!this.UserHasPermission(UserPermission.UserManagement) && User.Identity!.Name != username)
+ if (!UserHasPermission(UserPermission.UserManagement) && User.Identity!.Name != username)
{
- return this.ForbidWithMessage(Resource.MessageForbidNotAdministratorOrOwner);
+ return ForbidWithCommonResponse(Resource.MessageForbidNotAdministratorOrOwner);
}
long id = await _userService.GetUserIdByUsernameAsync(username);
@@ -105,9 +105,9 @@ namespace Timeline.Controllers
[Authorize]
public async Task<IActionResult> Delete([FromRoute][Username] string username)
{
- if (!this.UserHasPermission(UserPermission.UserManagement) && User.Identity!.Name != username)
+ if (!UserHasPermission(UserPermission.UserManagement) && User.Identity!.Name != username)
{
- return this.ForbidWithMessage(Resource.MessageForbidNotAdministratorOrOwner);
+ return ForbidWithCommonResponse(Resource.MessageForbidNotAdministratorOrOwner);
}
long id = await _userService.GetUserIdByUsernameAsync(username);
diff --git a/BackEnd/Timeline/Controllers/UserController.cs b/BackEnd/Timeline/Controllers/UserController.cs
index 47d2ee41..740bd0ed 100644
--- a/BackEnd/Timeline/Controllers/UserController.cs
+++ b/BackEnd/Timeline/Controllers/UserController.cs
@@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;
using Timeline.Auth;
+using Timeline.Filters;
using Timeline.Models.Http;
using Timeline.Models.Validation;
using Timeline.Services.Mapper;
@@ -16,7 +17,7 @@ namespace Timeline.Controllers
/// </summary>
[ApiController]
[ProducesErrorResponseType(typeof(CommonResponse))]
- public class UserController : Controller
+ public class UserController : MyControllerBase
{
private readonly IUserService _userService;
private readonly IUserPermissionService _userPermissionService;
@@ -32,7 +33,7 @@ namespace Timeline.Controllers
_mapper = mapper;
}
- private bool UserHasUserManagementPermission => this.UserHasPermission(UserPermission.UserManagement);
+ private bool UserHasUserManagementPermission => UserHasPermission(UserPermission.UserManagement);
/// <summary>
/// Get all users.
@@ -51,14 +52,14 @@ namespace Timeline.Controllers
/// Create a new user. You have to be administrator.
/// </summary>
/// <returns>The new user's info.</returns>
- [HttpPost("users"), PermissionAuthorize(UserPermission.UserManagement)]
+ [HttpPost("users")]
+ [PermissionAuthorize(UserPermission.UserManagement)]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
public async Task<ActionResult<HttpUser>> Post([FromBody] HttpUserPostRequest body)
{
-
var user = await _userService.CreateUserAsync(
new CreateUserParams(body.Username, body.Password) { Nickname = body.Nickname });
return await _mapper.MapAsync<HttpUser>(user, Url, User);
@@ -85,7 +86,8 @@ namespace Timeline.Controllers
/// <param name="body"></param>
/// <param name="username">Username of the user to change.</param>
/// <returns>The new user info.</returns>
- [HttpPatch("users/{username}"), Authorize]
+ [HttpPatch("users/{username}")]
+ [Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
@@ -101,16 +103,16 @@ namespace Timeline.Controllers
}
else
{
- if (User.Identity!.Name != username)
- return this.ForbidWithMessage(Resource.MessageForbidNotAdministratorOrOwner);
+ if (GetUsername() != username)
+ return ForbidWithCommonResponse(Resource.MessageForbidNotAdministratorOrOwner);
- if (body.Username != null)
- return this.ForbidWithMessage(Resource.MessageForbidNotAdministrator);
+ if (body.Username is not null)
+ return ForbidWithCommonResponse(Resource.MessageForbidNotAdministrator);
- if (body.Password != null)
- return this.ForbidWithMessage(Resource.MessageForbidNotAdministrator);
+ if (body.Password is not null)
+ return ForbidWithCommonResponse(Resource.MessageForbidNotAdministrator);
- var user = await _userService.ModifyUserAsync(this.GetUserId(), _mapper.AutoMapperMap<ModifyUserParams>(body));
+ var user = await _userService.ModifyUserAsync(GetUserId(), _mapper.AutoMapperMap<ModifyUserParams>(body));
return await _mapper.MapAsync<HttpUser>(user, Url, User);
}
}
@@ -120,7 +122,8 @@ namespace Timeline.Controllers
/// </summary>
/// <param name="username">Username of the user to delete.</param>
/// <returns>Info of deletion.</returns>
- [HttpDelete("users/{username}"), PermissionAuthorize(UserPermission.UserManagement)]
+ [HttpDelete("users/{username}")]
+ [PermissionAuthorize(UserPermission.UserManagement)]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
@@ -130,11 +133,11 @@ namespace Timeline.Controllers
try
{
await _userDeleteService.DeleteUserAsync(username);
- return this.Delete();
+ return DeleteWithCommonDeleteResponse();
}
catch (InvalidOperationOnRootUserException)
{
- return this.BadRequestWithCommonResponse(ErrorCodes.UserController.InvalidOperationOnRootUser, Resource.MessageInvalidOperationOnRootUser);
+ return BadRequestWithCommonResponse(ErrorCodes.UserController.InvalidOperationOnRootUser, Resource.MessageInvalidOperationOnRootUser);
}
}
@@ -145,16 +148,16 @@ namespace Timeline.Controllers
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
- public async Task<ActionResult> ChangePassword([FromBody] HttpChangePasswordRequest request)
+ public async Task<ActionResult<CommonResponse>> ChangePassword([FromBody] HttpChangePasswordRequest request)
{
try
{
- await _userService.ChangePassword(this.GetUserId(), request.OldPassword, request.NewPassword);
- return Ok();
+ await _userService.ChangePassword(GetUserId(), request.OldPassword, request.NewPassword);
+ return OkWithCommonResponse();
}
catch (BadPasswordException)
{
- return this.BadRequestWithCommonResponse(ErrorCodes.UserController.ChangePasswordBadOldPassword, Resource.MessageOldPasswordWrong);
+ return BadRequestWithCommonResponse(ErrorCodes.UserController.ChangePasswordBadOldPassword, Resource.MessageOldPasswordWrong);
}
// User can't be non-existent or the token is bad.
}
@@ -165,36 +168,37 @@ namespace Timeline.Controllers
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
- public async Task<ActionResult> PutUserPermission([FromRoute][Username] string username, [FromRoute] UserPermission permission)
+ 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 Ok();
+ return OkWithCommonResponse();
}
catch (InvalidOperationOnRootUserException)
{
- return this.BadRequestWithCommonResponse(ErrorCodes.UserController.InvalidOperationOnRootUser, Resource.MessageInvalidOperationOnRootUser);
+ return BadRequestWithCommonResponse(ErrorCodes.UserController.InvalidOperationOnRootUser, Resource.MessageInvalidOperationOnRootUser);
}
}
[HttpDelete("users/{username}/permissions/{permission}"), PermissionAuthorize(UserPermission.UserManagement)]
+ [NotEntityDelete]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
- public async Task<ActionResult> DeleteUserPermission([FromRoute][Username] string username, [FromRoute] UserPermission permission)
+ 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 Ok();
+ return OkWithCommonResponse();
}
catch (InvalidOperationOnRootUserException)
{
- return this.BadRequestWithCommonResponse(ErrorCodes.UserController.InvalidOperationOnRootUser, Resource.MessageInvalidOperationOnRootUser);
+ return BadRequestWithCommonResponse(ErrorCodes.UserController.InvalidOperationOnRootUser, Resource.MessageInvalidOperationOnRootUser);
}
}
}
diff --git a/BackEnd/Timeline/Filters/CatchEntityNotExistExceptionFilter.cs b/BackEnd/Timeline/Filters/CatchEntityNotExistExceptionFilter.cs
index 225fab4f..d97ffe9f 100644
--- a/BackEnd/Timeline/Filters/CatchEntityNotExistExceptionFilter.cs
+++ b/BackEnd/Timeline/Filters/CatchEntityNotExistExceptionFilter.cs
@@ -1,6 +1,7 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
+using System.Linq;
using Timeline.Models.Http;
using Timeline.Services;
@@ -28,7 +29,14 @@ namespace Timeline.Filters
}
else if (HttpMethods.IsDelete(context.HttpContext.Request.Method))
{
- context.Result = new OkObjectResult(CommonDeleteResponse.NotExist());
+ if (context.ActionDescriptor.EndpointMetadata.OfType<NotEntityDeleteAttribute>().Any())
+ {
+ context.Result = new BadRequestObjectResult(MakeCommonResponse(e));
+ }
+ else
+ {
+ context.Result = new OkObjectResult(CommonDeleteResponse.NotExist());
+ }
}
else
{
diff --git a/BackEnd/Timeline/Filters/NotEntityDeleteAttribute.cs b/BackEnd/Timeline/Filters/NotEntityDeleteAttribute.cs
new file mode 100644
index 00000000..a6d5dac7
--- /dev/null
+++ b/BackEnd/Timeline/Filters/NotEntityDeleteAttribute.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Timeline.Filters
+{
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
+ public class NotEntityDeleteAttribute : Attribute
+ {
+ }
+}
diff --git a/BackEnd/Timeline/Helpers/Cache/DataCacheHelper.cs b/BackEnd/Timeline/Helpers/Cache/DataCacheHelper.cs
index 1d1ab64e..79cac23b 100644
--- a/BackEnd/Timeline/Helpers/Cache/DataCacheHelper.cs
+++ b/BackEnd/Timeline/Helpers/Cache/DataCacheHelper.cs
@@ -11,7 +11,7 @@ namespace Timeline.Helpers.Cache
{
public static class DataCacheHelper
{
- public static async Task<ActionResult> GenerateActionResult(Controller controller, ICacheableDataProvider provider, TimeSpan? maxAge = null)
+ public static async Task<ActionResult> GenerateActionResult(ControllerBase controller, ICacheableDataProvider provider, TimeSpan? maxAge = null)
{
const string CacheControlHeaderKey = "Cache-Control";
const string IfNonMatchHeaderKey = "If-None-Match";
@@ -74,7 +74,7 @@ namespace Timeline.Helpers.Cache
return controller.File(data.Data, data.ContentType, digest.LastModified, eTag);
}
- public static Task<ActionResult> GenerateActionResult(Controller controller, Func<Task<ICacheableDataDigest>> getDigestDelegate, Func<Task<ByteData>> getDataDelegate, TimeSpan? maxAge = null)
+ public static Task<ActionResult> GenerateActionResult(ControllerBase controller, Func<Task<ICacheableDataDigest>> getDigestDelegate, Func<Task<ByteData>> getDataDelegate, TimeSpan? maxAge = null)
{
return GenerateActionResult(controller, new DelegateCacheableDataProvider(getDigestDelegate, getDataDelegate), maxAge);
}
diff --git a/BackEnd/Timeline/Services/Mapper/TimelineMapper.cs b/BackEnd/Timeline/Services/Mapper/TimelineMapper.cs
index d3159423..87bebbb3 100644
--- a/BackEnd/Timeline/Services/Mapper/TimelineMapper.cs
+++ b/BackEnd/Timeline/Services/Mapper/TimelineMapper.cs
@@ -41,7 +41,7 @@ namespace Timeline.Services.Mapper
public async Task<HttpTimeline> MapAsync(TimelineEntity entity, IUrlHelper urlHelper, ClaimsPrincipal? user)
{
- var userId = user.GetUserId();
+ var userId = user.GetOptionalUserId();
await _database.Entry(entity).Reference(e => e.Owner).LoadAsync();
await _database.Entry(entity).Collection(e => e.Members).Query().Include(m => m.User).LoadAsync();
@@ -99,7 +99,7 @@ namespace Timeline.Services.Mapper
public async Task<HttpTimelinePost> MapAsync(TimelinePostEntity entity, IUrlHelper urlHelper, ClaimsPrincipal? user)
{
- var userId = user.GetUserId();
+ var userId = user.GetOptionalUserId();
await _database.Entry(entity).Reference(e => e.Timeline).LoadAsync();
await _database.Entry(entity).Collection(p => p.DataList).LoadAsync();