aboutsummaryrefslogtreecommitdiff
path: root/Timeline/Controllers
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2020-03-12 19:56:20 +0800
committerGitHub <noreply@github.com>2020-03-12 19:56:20 +0800
commit904f98bda60b3bd92331aacde3771dedde62d2b5 (patch)
tree70681348ddfc3bc8c3d9a92ae010a02020830573 /Timeline/Controllers
parenta37874830399c193392cc78367efcecbe8275ceb (diff)
parentf8ff7e20eb5d5673575d36b8964a013765b77bf8 (diff)
downloadtimeline-904f98bda60b3bd92331aacde3771dedde62d2b5.tar.gz
timeline-904f98bda60b3bd92331aacde3771dedde62d2b5.tar.bz2
timeline-904f98bda60b3bd92331aacde3771dedde62d2b5.zip
Merge pull request #69 from crupest/image
Post image feature.
Diffstat (limited to 'Timeline/Controllers')
-rw-r--r--Timeline/Controllers/PersonalTimelineController.cs131
-rw-r--r--Timeline/Controllers/TimelineController.cs146
-rw-r--r--Timeline/Controllers/UserAvatarController.cs8
-rw-r--r--Timeline/Controllers/UserController.cs1
4 files changed, 118 insertions, 168 deletions
diff --git a/Timeline/Controllers/PersonalTimelineController.cs b/Timeline/Controllers/PersonalTimelineController.cs
deleted file mode 100644
index cef04a97..00000000
--- a/Timeline/Controllers/PersonalTimelineController.cs
+++ /dev/null
@@ -1,131 +0,0 @@
-using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.Http;
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.Logging;
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using Timeline.Filters;
-using Timeline.Models.Http;
-using Timeline.Models.Validation;
-using Timeline.Services;
-
-namespace Timeline.Controllers
-{
- [ApiController]
- [CatchTimelineNotExistException]
- public class PersonalTimelineController : Controller
- {
- private readonly ILogger<PersonalTimelineController> _logger;
-
- private readonly IPersonalTimelineService _service;
-
- public PersonalTimelineController(ILogger<PersonalTimelineController> logger, IPersonalTimelineService service)
- {
- _logger = logger;
- _service = service;
- }
-
- [HttpGet("users/{username}/timeline")]
- public async Task<ActionResult<TimelineInfo>> TimelineGet([FromRoute][Username] string username)
- {
- return (await _service.GetTimeline(username)).FillLinks(Url);
- }
-
- [HttpGet("users/{username}/timeline/posts")]
- public async Task<ActionResult<IList<TimelinePostInfo>>> PostListGet([FromRoute][Username] string username)
- {
- if (!this.IsAdministrator() && !await _service.HasReadPermission(username, this.GetOptionalUserId()))
- {
- return StatusCode(StatusCodes.Status403Forbidden, ErrorResponse.Common.Forbid());
- }
-
- return await _service.GetPosts(username);
- }
-
- [HttpPost("users/{username}/timeline/posts")]
- [Authorize]
- public async Task<ActionResult<TimelinePostInfo>> PostPost([FromRoute][Username] string username, [FromBody] TimelinePostCreateRequest body)
- {
- var id = this.GetUserId();
- if (!this.IsAdministrator() && !await _service.IsMemberOf(username, id))
- {
- return StatusCode(StatusCodes.Status403Forbidden, ErrorResponse.Common.Forbid());
- }
-
- var res = await _service.CreatePost(username, id, body.Content, body.Time);
- return res;
- }
-
- [HttpDelete("users/{username}/timeline/posts/{id}")]
- [Authorize]
- public async Task<ActionResult> PostDelete([FromRoute][Username] string username, [FromRoute] long id)
- {
- try
- {
- if (!this.IsAdministrator() && !await _service.HasPostModifyPermission(username, id, this.GetUserId()))
- {
- return StatusCode(StatusCodes.Status403Forbidden, ErrorResponse.Common.Forbid());
- }
- await _service.DeletePost(username, id);
- return Ok(CommonDeleteResponse.Delete());
- }
- catch (TimelinePostNotExistException)
- {
- return Ok(CommonDeleteResponse.NotExist());
- }
- }
-
- [HttpPatch("users/{username}/timeline")]
- [Authorize]
- public async Task<ActionResult<TimelineInfo>> TimelinePatch([FromRoute][Username] string username, [FromBody] TimelinePatchRequest body)
- {
- if (!this.IsAdministrator() && !(await _service.HasManagePermission(username, this.GetUserId())))
- {
- return StatusCode(StatusCodes.Status403Forbidden, ErrorResponse.Common.Forbid());
- }
- await _service.ChangeProperty(username, body);
- var timeline = (await _service.GetTimeline(username)).FillLinks(Url);
- return Ok(timeline);
- }
-
- [HttpPut("users/{username}/timeline/members/{member}")]
- [Authorize]
- public async Task<ActionResult> TimelineMemberPut([FromRoute][Username] string username, [FromRoute][Username] string member)
- {
- if (!this.IsAdministrator() && !(await _service.HasManagePermission(username, this.GetUserId())))
- {
- return StatusCode(StatusCodes.Status403Forbidden, ErrorResponse.Common.Forbid());
- }
-
- try
- {
- await _service.ChangeMember(username, new List<string> { member }, null);
- return Ok();
- }
- catch (UserNotExistException)
- {
- return BadRequest(ErrorResponse.TimelineCommon.MemberPut_NotExist());
- }
- }
-
- [HttpDelete("users/{username}/timeline/members/{member}")]
- [Authorize]
- public async Task<ActionResult> TimelineMemberDelete([FromRoute][Username] string username, [FromRoute][Username] string member)
- {
- if (!this.IsAdministrator() && !(await _service.HasManagePermission(username, this.GetUserId())))
- {
- return StatusCode(StatusCodes.Status403Forbidden, ErrorResponse.Common.Forbid());
- }
-
- try
- {
- await _service.ChangeMember(username, null, new List<string> { member });
- return Ok(CommonDeleteResponse.Delete());
- }
- catch (UserNotExistException)
- {
- return Ok(CommonDeleteResponse.NotExist());
- }
- }
- }
-}
diff --git a/Timeline/Controllers/TimelineController.cs b/Timeline/Controllers/TimelineController.cs
index 85ccb5c1..58390c29 100644
--- a/Timeline/Controllers/TimelineController.cs
+++ b/Timeline/Controllers/TimelineController.cs
@@ -1,12 +1,15 @@
-using Microsoft.AspNetCore.Authorization;
+using AutoMapper;
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
+using Microsoft.Net.Http.Headers;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;
using Timeline.Filters;
+using Timeline.Models;
using Timeline.Models.Http;
using Timeline.Models.Validation;
using Timeline.Services;
@@ -22,11 +25,14 @@ namespace Timeline.Controllers
private readonly IUserService _userService;
private readonly ITimelineService _service;
- public TimelineController(ILogger<TimelineController> logger, IUserService userService, ITimelineService service)
+ private readonly IMapper _mapper;
+
+ public TimelineController(ILogger<TimelineController> logger, IUserService userService, ITimelineService service, IMapper mapper)
{
_logger = logger;
_userService = userService;
_service = service;
+ _mapper = mapper;
}
[HttpGet("timelines")]
@@ -81,32 +87,60 @@ namespace Timeline.Controllers
}
}
- var result = await _service.GetTimelines(relationship, visibilityFilter);
- result.ForEach(t => t.FillLinks(Url));
- return Ok(result);
+ var timelines = await _service.GetTimelines(relationship, visibilityFilter);
+ var result = _mapper.Map<List<TimelineInfo>>(timelines);
+ return result;
}
[HttpGet("timelines/{name}")]
- public async Task<ActionResult<TimelineInfo>> TimelineGet([FromRoute][TimelineName] string name)
+ public async Task<ActionResult<TimelineInfo>> TimelineGet([FromRoute][GeneralTimelineName] string name)
{
- var result = (await _service.GetTimeline(name)).FillLinks(Url);
- return Ok(result);
+ var timeline = await _service.GetTimeline(name);
+ var result = _mapper.Map<TimelineInfo>(timeline);
+ return result;
}
[HttpGet("timelines/{name}/posts")]
- public async Task<ActionResult<IList<TimelinePostInfo>>> PostListGet([FromRoute][TimelineName] string name)
+ public async Task<ActionResult<List<TimelinePostInfo>>> PostListGet([FromRoute][GeneralTimelineName] string name)
{
if (!this.IsAdministrator() && !await _service.HasReadPermission(name, this.GetOptionalUserId()))
{
return StatusCode(StatusCodes.Status403Forbidden, ErrorResponse.Common.Forbid());
}
- return await _service.GetPosts(name);
+ var posts = await _service.GetPosts(name);
+ var result = _mapper.Map<List<TimelinePostInfo>>(posts);
+
+ return result;
+ }
+
+ // TODO: Make cache available.
+ [HttpGet("timelines/{name}/posts/{id}/data")]
+ public async Task<ActionResult<List<TimelinePostInfo>>> PostDataGet([FromRoute][GeneralTimelineName] string name, [FromRoute] long id)
+ {
+ if (!this.IsAdministrator() && !await _service.HasReadPermission(name, this.GetOptionalUserId()))
+ {
+ return StatusCode(StatusCodes.Status403Forbidden, ErrorResponse.Common.Forbid());
+ }
+
+ try
+ {
+ var data = await _service.GetPostData(name, id);
+ return File(data.Data, data.Type, data.LastModified, new EntityTagHeaderValue($"\"{data.ETag}\""));
+ }
+ catch (TimelinePostNotExistException)
+ {
+ return NotFound(ErrorResponse.TimelineController.PostNotExist());
+ }
+ catch (InvalidOperationException)
+ {
+ return BadRequest(ErrorResponse.TimelineController.PostNoData());
+ }
}
[HttpPost("timelines/{name}/posts")]
[Authorize]
- public async Task<ActionResult<TimelinePostInfo>> PostPost([FromRoute][TimelineName] string name, [FromBody] TimelinePostCreateRequest body)
+ public async Task<ActionResult<TimelinePostInfo>> PostPost([FromRoute][GeneralTimelineName] string name, [FromBody] TimelinePostCreateRequest body)
{
var id = this.GetUserId();
if (!this.IsAdministrator() && !await _service.IsMemberOf(name, id))
@@ -114,45 +148,90 @@ namespace Timeline.Controllers
return StatusCode(StatusCodes.Status403Forbidden, ErrorResponse.Common.Forbid());
}
- var res = await _service.CreatePost(name, id, body.Content, body.Time);
- return res;
+ var content = body.Content;
+
+ TimelinePost post;
+
+ if (content.Type == TimelinePostContentTypes.Text)
+ {
+ var text = content.Text;
+ if (text == null)
+ {
+ return BadRequest(ErrorResponse.Common.CustomMessage_InvalidModel(Resources.Messages.TimelineController_TextContentTextRequired));
+ }
+ post = await _service.CreateTextPost(name, id, text, body.Time);
+ }
+ else if (content.Type == TimelinePostContentTypes.Image)
+ {
+ var base64Data = content.Data;
+ if (base64Data == null)
+ {
+ return BadRequest(ErrorResponse.Common.CustomMessage_InvalidModel(Resources.Messages.TimelineController_ImageContentDataRequired));
+ }
+ byte[] data;
+ try
+ {
+ data = Convert.FromBase64String(base64Data);
+ }
+ catch (FormatException)
+ {
+ return BadRequest(ErrorResponse.Common.CustomMessage_InvalidModel(Resources.Messages.TimelineController_ImageContentDataNotBase64));
+ }
+
+ try
+ {
+ post = await _service.CreateImagePost(name, id, data, body.Time);
+ }
+ catch (ImageException)
+ {
+ return BadRequest(ErrorResponse.Common.CustomMessage_InvalidModel(Resources.Messages.TimelineController_ImageContentDataNotImage));
+ }
+ }
+ else
+ {
+ return BadRequest(ErrorResponse.Common.CustomMessage_InvalidModel(Resources.Messages.TimelineController_ContentUnknownType));
+ }
+
+ var result = _mapper.Map<TimelinePostInfo>(post);
+ return result;
}
[HttpDelete("timelines/{name}/posts/{id}")]
[Authorize]
- public async Task<ActionResult> PostDelete([FromRoute][TimelineName] string name, [FromRoute] long id)
+ public async Task<ActionResult<CommonDeleteResponse>> PostDelete([FromRoute][GeneralTimelineName] string name, [FromRoute] long id)
{
+ if (!this.IsAdministrator() && !await _service.HasPostModifyPermission(name, id, this.GetUserId()))
+ {
+ return StatusCode(StatusCodes.Status403Forbidden, ErrorResponse.Common.Forbid());
+ }
try
{
- if (!this.IsAdministrator() && !await _service.HasPostModifyPermission(name, id, this.GetUserId()))
- {
- return StatusCode(StatusCodes.Status403Forbidden, ErrorResponse.Common.Forbid());
- }
await _service.DeletePost(name, id);
- return Ok(CommonDeleteResponse.Delete());
+ return CommonDeleteResponse.Delete();
}
catch (TimelinePostNotExistException)
{
- return Ok(CommonDeleteResponse.NotExist());
+ return CommonDeleteResponse.NotExist();
}
}
[HttpPatch("timelines/{name}")]
[Authorize]
- public async Task<ActionResult<TimelineInfo>> TimelinePatch([FromRoute][TimelineName] string name, [FromBody] TimelinePatchRequest body)
+ public async Task<ActionResult<TimelineInfo>> TimelinePatch([FromRoute][GeneralTimelineName] string name, [FromBody] TimelinePatchRequest body)
{
if (!this.IsAdministrator() && !(await _service.HasManagePermission(name, this.GetUserId())))
{
return StatusCode(StatusCodes.Status403Forbidden, ErrorResponse.Common.Forbid());
}
- await _service.ChangeProperty(name, body);
- var timeline = (await _service.GetTimeline(name)).FillLinks(Url);
- return Ok(timeline);
+ await _service.ChangeProperty(name, _mapper.Map<TimelineChangePropertyRequest>(body));
+ var timeline = await _service.GetTimeline(name);
+ var result = _mapper.Map<TimelineInfo>(timeline);
+ return result;
}
[HttpPut("timelines/{name}/members/{member}")]
[Authorize]
- public async Task<ActionResult> TimelineMemberPut([FromRoute][TimelineName] string name, [FromRoute][Username] string member)
+ public async Task<ActionResult> TimelineMemberPut([FromRoute][GeneralTimelineName] string name, [FromRoute][Username] string member)
{
if (!this.IsAdministrator() && !(await _service.HasManagePermission(name, this.GetUserId())))
{
@@ -166,13 +245,13 @@ namespace Timeline.Controllers
}
catch (UserNotExistException)
{
- return BadRequest(ErrorResponse.TimelineCommon.MemberPut_NotExist());
+ return BadRequest(ErrorResponse.TimelineController.MemberPut_NotExist());
}
}
[HttpDelete("timelines/{name}/members/{member}")]
[Authorize]
- public async Task<ActionResult> TimelineMemberDelete([FromRoute][TimelineName] string name, [FromRoute][Username] string member)
+ public async Task<ActionResult> TimelineMemberDelete([FromRoute][GeneralTimelineName] string name, [FromRoute][Username] string member)
{
if (!this.IsAdministrator() && !(await _service.HasManagePermission(name, this.GetUserId())))
{
@@ -198,18 +277,19 @@ namespace Timeline.Controllers
try
{
- var timelineInfo = (await _service.CreateTimeline(body.Name, userId)).FillLinks(Url);
- return Ok(timelineInfo);
+ var timeline = await _service.CreateTimeline(body.Name, userId);
+ var result = _mapper.Map<TimelineInfo>(timeline);
+ return result;
}
catch (ConflictException)
{
- return BadRequest(ErrorResponse.TimelineCommon.NameConflict());
+ return BadRequest(ErrorResponse.TimelineController.NameConflict());
}
}
[HttpDelete("timelines/{name}")]
[Authorize]
- public async Task<ActionResult<TimelineInfo>> TimelineDelete([FromRoute][TimelineName] string name)
+ public async Task<ActionResult<CommonDeleteResponse>> TimelineDelete([FromRoute][TimelineName] string name)
{
if (!this.IsAdministrator() && !(await _service.HasManagePermission(name, this.GetUserId())))
{
@@ -219,11 +299,11 @@ namespace Timeline.Controllers
try
{
await _service.DeleteTimeline(name);
- return Ok(CommonDeleteResponse.Delete());
+ return CommonDeleteResponse.Delete();
}
catch (TimelineNotExistException)
{
- return Ok(CommonDeleteResponse.NotExist());
+ return CommonDeleteResponse.NotExist();
}
}
}
diff --git a/Timeline/Controllers/UserAvatarController.cs b/Timeline/Controllers/UserAvatarController.cs
index 2dd279a8..f4f3db3e 100644
--- a/Timeline/Controllers/UserAvatarController.cs
+++ b/Timeline/Controllers/UserAvatarController.cs
@@ -126,14 +126,14 @@ namespace Timeline.Controllers
("Username", username), ("Mime Type", Request.ContentType)));
return Ok();
}
- catch (AvatarFormatException e)
+ catch (ImageException e)
{
_logger.LogInformation(e, Log.Format(LogPutUserBadFormat, ("Username", username)));
return BadRequest(e.Error switch
{
- AvatarFormatException.ErrorReason.CantDecode => ErrorResponse.UserAvatar.BadFormat_CantDecode(),
- AvatarFormatException.ErrorReason.UnmatchedFormat => ErrorResponse.UserAvatar.BadFormat_UnmatchedFormat(),
- AvatarFormatException.ErrorReason.BadSize => ErrorResponse.UserAvatar.BadFormat_BadSize(),
+ ImageException.ErrorReason.CantDecode => ErrorResponse.UserAvatar.BadFormat_CantDecode(),
+ ImageException.ErrorReason.UnmatchedFormat => ErrorResponse.UserAvatar.BadFormat_UnmatchedFormat(),
+ ImageException.ErrorReason.NotSquare => ErrorResponse.UserAvatar.BadFormat_BadSize(),
_ =>
throw new Exception(ExceptionUnknownAvatarFormatError)
});
diff --git a/Timeline/Controllers/UserController.cs b/Timeline/Controllers/UserController.cs
index a3e8d816..0bc8bcda 100644
--- a/Timeline/Controllers/UserController.cs
+++ b/Timeline/Controllers/UserController.cs
@@ -7,6 +7,7 @@ using System.Linq;
using System.Threading.Tasks;
using Timeline.Auth;
using Timeline.Helpers;
+using Timeline.Models;
using Timeline.Models.Http;
using Timeline.Models.Validation;
using Timeline.Services;