diff options
author | crupest <crupest@outlook.com> | 2021-05-05 16:36:18 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2021-05-05 16:36:18 +0800 |
commit | 1bce70b36d4666797ae157167be4a84217a71374 (patch) | |
tree | 656007e5953136219c8e97f0b4763faaee0bc021 /BackEnd | |
parent | 7d54e0b8b7ca84488fdcba90c68169a85b4d45c6 (diff) | |
download | timeline-1bce70b36d4666797ae157167be4a84217a71374.tar.gz timeline-1bce70b36d4666797ae157167be4a84217a71374.tar.bz2 timeline-1bce70b36d4666797ae157167be4a84217a71374.zip |
refactor: ...
Diffstat (limited to 'BackEnd')
-rw-r--r-- | BackEnd/Timeline.Tests/IntegratedTests/UserAvatarTest.cs | 2 | ||||
-rw-r--r-- | BackEnd/Timeline/Controllers/Resource.Designer.cs | 36 | ||||
-rw-r--r-- | BackEnd/Timeline/Controllers/Resource.resx | 12 | ||||
-rw-r--r-- | BackEnd/Timeline/Controllers/TimelinePostController.cs | 1 | ||||
-rw-r--r-- | BackEnd/Timeline/Controllers/UserAvatarController.cs | 32 | ||||
-rw-r--r-- | BackEnd/Timeline/Filters/CatchImageExceptionFilter.cs | 28 | ||||
-rw-r--r-- | BackEnd/Timeline/Filters/ConsumesImagesAttribute.cs | 17 | ||||
-rw-r--r-- | BackEnd/Timeline/Filters/ProducesImagesAttribute.cs | 19 | ||||
-rw-r--r-- | BackEnd/Timeline/Filters/Resource.Designer.cs | 36 | ||||
-rw-r--r-- | BackEnd/Timeline/Filters/Resource.resx | 12 | ||||
-rw-r--r-- | BackEnd/Timeline/Services/Timeline/ITimelinePostService.cs | 2 | ||||
-rw-r--r-- | BackEnd/Timeline/Startup.cs | 1 |
12 files changed, 124 insertions, 74 deletions
diff --git a/BackEnd/Timeline.Tests/IntegratedTests/UserAvatarTest.cs b/BackEnd/Timeline.Tests/IntegratedTests/UserAvatarTest.cs index e8c42d58..a7aa63cd 100644 --- a/BackEnd/Timeline.Tests/IntegratedTests/UserAvatarTest.cs +++ b/BackEnd/Timeline.Tests/IntegratedTests/UserAvatarTest.cs @@ -138,7 +138,7 @@ namespace Timeline.Tests.IntegratedTests await client.TestPutByteArrayAsync("users/user1/avatar", mockAvatar.Data, mockAvatar.ContentType);
await client.TestDeleteAsync("users/user1/avatar");
await client.TestPutByteArrayAssertErrorAsync("users/usernotexist/avatar", new[] { (byte)0x00 }, "image/png", errorCode: ErrorCodes.NotExist.User);
- await client.TestDeleteAsync("users/usernotexist/avatar");
+ await client.TestDeleteAssertErrorAsync("users/usernotexist/avatar");
}
// bad username check
diff --git a/BackEnd/Timeline/Controllers/Resource.Designer.cs b/BackEnd/Timeline/Controllers/Resource.Designer.cs index c062380b..a647558a 100644 --- a/BackEnd/Timeline/Controllers/Resource.Designer.cs +++ b/BackEnd/Timeline/Controllers/Resource.Designer.cs @@ -106,42 +106,6 @@ namespace Timeline.Controllers { }
/// <summary>
- /// Looks up a localized string similar to Image is not a square..
- /// </summary>
- internal static string MessageImageBadSize {
- get {
- return ResourceManager.GetString("MessageImageBadSize", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to Image decode failed..
- /// </summary>
- internal static string MessageImageDecodeFailed {
- get {
- return ResourceManager.GetString("MessageImageDecodeFailed", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to Specified image format does not match the actual one ..
- /// </summary>
- internal static string MessageImageFormatUnmatch {
- get {
- return ResourceManager.GetString("MessageImageFormatUnmatch", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to Unknown error happened to image..
- /// </summary>
- internal static string MessageImageUnknownError {
- get {
- return ResourceManager.GetString("MessageImageUnknownError", resourceCulture);
- }
- }
-
- /// <summary>
/// Looks up a localized string similar to You can't do this because it is the root user..
/// </summary>
internal static string MessageInvalidOperationOnRootUser {
diff --git a/BackEnd/Timeline/Controllers/Resource.resx b/BackEnd/Timeline/Controllers/Resource.resx index afaa1ba1..47b7a329 100644 --- a/BackEnd/Timeline/Controllers/Resource.resx +++ b/BackEnd/Timeline/Controllers/Resource.resx @@ -132,18 +132,6 @@ <data name="MessageForbidNotAdministratorOrOwner" xml:space="preserve">
<value>You can't do this unless you are administrator or resource owner.</value>
</data>
- <data name="MessageImageBadSize" xml:space="preserve">
- <value>Image is not a square.</value>
- </data>
- <data name="MessageImageDecodeFailed" xml:space="preserve">
- <value>Image decode failed.</value>
- </data>
- <data name="MessageImageFormatUnmatch" xml:space="preserve">
- <value>Specified image format does not match the actual one .</value>
- </data>
- <data name="MessageImageUnknownError" xml:space="preserve">
- <value>Unknown error happened to image.</value>
- </data>
<data name="MessageInvalidOperationOnRootUser" xml:space="preserve">
<value>You can't do this because it is the root user.</value>
</data>
diff --git a/BackEnd/Timeline/Controllers/TimelinePostController.cs b/BackEnd/Timeline/Controllers/TimelinePostController.cs index c33d47aa..21d3821a 100644 --- a/BackEnd/Timeline/Controllers/TimelinePostController.cs +++ b/BackEnd/Timeline/Controllers/TimelinePostController.cs @@ -202,7 +202,6 @@ namespace Timeline.Controllers }
}
-
try
{
var post = await _postService.CreatePostAsync(timelineId, userId, createRequest);
diff --git a/BackEnd/Timeline/Controllers/UserAvatarController.cs b/BackEnd/Timeline/Controllers/UserAvatarController.cs index 376e1f11..5b8c5cdf 100644 --- a/BackEnd/Timeline/Controllers/UserAvatarController.cs +++ b/BackEnd/Timeline/Controllers/UserAvatarController.cs @@ -7,7 +7,6 @@ using Timeline.Helpers.Cache; using Timeline.Models;
using Timeline.Models.Http;
using Timeline.Models.Validation;
-using Timeline.Services.Imaging;
using Timeline.Services.User;
using Timeline.Services.User.Avatar;
@@ -36,7 +35,7 @@ namespace Timeline.Controllers /// <param name="ifNoneMatch">If-None-Match header.</param>
/// <returns>Avatar data.</returns>
[HttpGet("users/{username}/avatar")]
- [Produces("image/png", "image/jpeg", "image/gif", "image/webp", "application/json", "text/json")]
+ [ProducesImages]
[ProducesResponseType(typeof(byte[]), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(void), StatusCodes.Status304NotModified)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
@@ -54,7 +53,7 @@ namespace Timeline.Controllers /// <param name="body">The avatar data.</param>
[HttpPut("users/{username}/avatar")]
[Authorize]
- [Consumes("image/png", "image/jpeg", "image/gif", "image/webp")]
+ [ConsumesImages]
[MaxContentLength(1000 * 1000 * 10)]
[ProducesResponseType(typeof(void), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
@@ -62,31 +61,17 @@ namespace Timeline.Controllers [ProducesResponseType(StatusCodes.Status403Forbidden)]
public async Task<IActionResult> Put([FromRoute][Username] string username, [FromBody] ByteData body)
{
- if (!UserHasPermission(UserPermission.UserManagement) && User.Identity!.Name != username)
+ if (!UserHasPermission(UserPermission.UserManagement) && GetUsername() != username)
{
return ForbidWithCommonResponse(Resource.MessageForbidNotAdministratorOrOwner);
}
long id = await _userService.GetUserIdByUsernameAsync(username);
- try
- {
- var digest = await _service.SetAvatarAsync(id, body);
-
- Response.Headers.Append("ETag", $"\"{digest.ETag}\"");
+ var digest = await _service.SetAvatarAsync(id, body);
- return Ok();
- }
- catch (ImageException e)
- {
- return BadRequest(e.Error switch
- {
- ImageException.ErrorReason.CantDecode => new CommonResponse(ErrorCodes.Image.CantDecode, Resource.MessageImageDecodeFailed),
- ImageException.ErrorReason.UnmatchedFormat => new CommonResponse(ErrorCodes.Image.UnmatchedFormat, Resource.MessageImageFormatUnmatch),
- ImageException.ErrorReason.BadSize => new CommonResponse(ErrorCodes.Image.BadSize, Resource.MessageImageBadSize),
- _ => new CommonResponse(ErrorCodes.Image.Unknown, Resource.MessageImageUnknownError)
- });
- }
+ Response.Headers.Append("ETag", $"\"{digest.ETag}\"");
+ return Ok();
}
/// <summary>
@@ -98,11 +83,12 @@ namespace Timeline.Controllers /// <response code="401">You have not logged in.</response>
/// <response code="403">You are not administrator.</response>
[HttpDelete("users/{username}/avatar")]
+ [Authorize]
+ [NotEntityDelete]
[ProducesResponseType(typeof(void), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
- [Authorize]
public async Task<IActionResult> Delete([FromRoute][Username] string username)
{
if (!UserHasPermission(UserPermission.UserManagement) && User.Identity!.Name != username)
@@ -113,7 +99,7 @@ namespace Timeline.Controllers long id = await _userService.GetUserIdByUsernameAsync(username);
await _service.DeleteAvatarAsync(id);
- return Ok();
+ return OkWithCommonResponse();
}
}
}
diff --git a/BackEnd/Timeline/Filters/CatchImageExceptionFilter.cs b/BackEnd/Timeline/Filters/CatchImageExceptionFilter.cs new file mode 100644 index 00000000..16278d15 --- /dev/null +++ b/BackEnd/Timeline/Filters/CatchImageExceptionFilter.cs @@ -0,0 +1,28 @@ +using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Filters;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Timeline.Models.Http;
+using Timeline.Services.Imaging;
+
+namespace Timeline.Filters
+{
+ public class CatchImageExceptionFilter : IExceptionFilter
+ {
+ public void OnException(ExceptionContext context)
+ {
+ if (context.Exception is ImageException e)
+ {
+ context.Result = new BadRequestObjectResult(e.Error switch
+ {
+ ImageException.ErrorReason.CantDecode => new CommonResponse(ErrorCodes.Image.CantDecode, Resource.MessageImageDecodeFailed),
+ ImageException.ErrorReason.UnmatchedFormat => new CommonResponse(ErrorCodes.Image.UnmatchedFormat, Resource.MessageImageFormatUnmatch),
+ ImageException.ErrorReason.BadSize => new CommonResponse(ErrorCodes.Image.BadSize, Resource.MessageImageBadSize),
+ _ => new CommonResponse(ErrorCodes.Image.Unknown, Resource.MessageImageUnknownError)
+ });
+ }
+ }
+ }
+}
diff --git a/BackEnd/Timeline/Filters/ConsumesImagesAttribute.cs b/BackEnd/Timeline/Filters/ConsumesImagesAttribute.cs new file mode 100644 index 00000000..5a293dfe --- /dev/null +++ b/BackEnd/Timeline/Filters/ConsumesImagesAttribute.cs @@ -0,0 +1,17 @@ +using Microsoft.AspNetCore.Mvc;
+using Timeline.Models;
+
+namespace Timeline.Filters
+{
+ public class ConsumesImagesAttribute : ConsumesAttribute
+ {
+ public ConsumesImagesAttribute()
+ : base(MimeTypes.ImagePng,
+ MimeTypes.ImageJpeg,
+ MimeTypes.ImageGif,
+ MimeTypes.ImageWebp)
+ {
+
+ }
+ }
+}
diff --git a/BackEnd/Timeline/Filters/ProducesImagesAttribute.cs b/BackEnd/Timeline/Filters/ProducesImagesAttribute.cs new file mode 100644 index 00000000..b38b6543 --- /dev/null +++ b/BackEnd/Timeline/Filters/ProducesImagesAttribute.cs @@ -0,0 +1,19 @@ +using Microsoft.AspNetCore.Mvc;
+using Timeline.Models;
+
+namespace Timeline.Filters
+{
+ public class ProducesImagesAttribute : ProducesAttribute
+ {
+ public ProducesImagesAttribute()
+ : base(MimeTypes.ImagePng,
+ MimeTypes.ImageJpeg,
+ MimeTypes.ImageGif,
+ MimeTypes.ImageWebp,
+ MimeTypes.TextJson,
+ MimeTypes.ApplicationJson)
+ {
+
+ }
+ }
+}
diff --git a/BackEnd/Timeline/Filters/Resource.Designer.cs b/BackEnd/Timeline/Filters/Resource.Designer.cs index d5b533d4..25d0e222 100644 --- a/BackEnd/Timeline/Filters/Resource.Designer.cs +++ b/BackEnd/Timeline/Filters/Resource.Designer.cs @@ -86,5 +86,41 @@ namespace Timeline.Filters { return ResourceManager.GetString("MessageEntityNotExist", resourceCulture);
}
}
+
+ /// <summary>
+ /// Looks up a localized string similar to Image is not a square..
+ /// </summary>
+ internal static string MessageImageBadSize {
+ get {
+ return ResourceManager.GetString("MessageImageBadSize", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Image decode failed..
+ /// </summary>
+ internal static string MessageImageDecodeFailed {
+ get {
+ return ResourceManager.GetString("MessageImageDecodeFailed", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Specified image format does not match the actual one ..
+ /// </summary>
+ internal static string MessageImageFormatUnmatch {
+ get {
+ return ResourceManager.GetString("MessageImageFormatUnmatch", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Unknown error happened to image..
+ /// </summary>
+ internal static string MessageImageUnknownError {
+ get {
+ return ResourceManager.GetString("MessageImageUnknownError", resourceCulture);
+ }
+ }
}
}
diff --git a/BackEnd/Timeline/Filters/Resource.resx b/BackEnd/Timeline/Filters/Resource.resx index d55e996c..15b13f97 100644 --- a/BackEnd/Timeline/Filters/Resource.resx +++ b/BackEnd/Timeline/Filters/Resource.resx @@ -126,4 +126,16 @@ <data name="MessageEntityNotExist" xml:space="preserve">
<value>The entity you operate on does not exist. Entity type is {0}. Constraints are {1}.</value>
</data>
+ <data name="MessageImageBadSize" xml:space="preserve">
+ <value>Image is not a square.</value>
+ </data>
+ <data name="MessageImageDecodeFailed" xml:space="preserve">
+ <value>Image decode failed.</value>
+ </data>
+ <data name="MessageImageFormatUnmatch" xml:space="preserve">
+ <value>Specified image format does not match the actual one .</value>
+ </data>
+ <data name="MessageImageUnknownError" xml:space="preserve">
+ <value>Unknown error happened to image.</value>
+ </data>
</root>
\ No newline at end of file diff --git a/BackEnd/Timeline/Services/Timeline/ITimelinePostService.cs b/BackEnd/Timeline/Services/Timeline/ITimelinePostService.cs index d746cf63..92984938 100644 --- a/BackEnd/Timeline/Services/Timeline/ITimelinePostService.cs +++ b/BackEnd/Timeline/Services/Timeline/ITimelinePostService.cs @@ -66,7 +66,7 @@ namespace Timeline.Services.Timeline /// <exception cref="ArgumentException">Thrown when <paramref name="request"/> is of invalid format.</exception>
/// <exception cref="EntityNotExistException">Thrown when timeline does not exist.</exception>
/// <exception cref="EntityNotExistException">Thrown if user of <paramref name="authorId"/> does not exist.</exception>
- /// <exception cref="ImageException">Thrown if data is not a image. Validated by <see cref="ImageService"/>.</exception>
+ /// <exception cref="TimelinePostCreateDataException">Thrown if data is illegal.</exception>
Task<TimelinePostEntity> CreatePostAsync(long timelineId, long authorId, TimelinePostCreateRequest request);
/// <summary>
diff --git a/BackEnd/Timeline/Startup.cs b/BackEnd/Timeline/Startup.cs index 774895fe..1e0d4779 100644 --- a/BackEnd/Timeline/Startup.cs +++ b/BackEnd/Timeline/Startup.cs @@ -71,6 +71,7 @@ namespace Timeline setup.Filters.Add(new ProducesAttribute(MimeTypes.ApplicationJson, MimeTypes.TextJson));
setup.Filters.Add<CatchEntityNotExistExceptionFilter>();
setup.Filters.Add<CatchEntityAlreadyExistExceptionFilter>();
+ setup.Filters.Add<CatchImageExceptionFilter>();
setup.UseApiRoutePrefix("api");
})
.AddJsonOptions(options =>
|