diff options
-rw-r--r-- | Timeline.Tests/IntegratedTests/TimelineTest.cs | 61 | ||||
-rw-r--r-- | Timeline.Tests/Services/TimelineServiceTest.cs | 8 | ||||
-rw-r--r-- | Timeline/Controllers/TimelineController.cs | 26 | ||||
-rw-r--r-- | Timeline/Filters/Timeline.cs | 13 | ||||
-rw-r--r-- | Timeline/Models/Http/TimelineController.cs | 19 | ||||
-rw-r--r-- | Timeline/Services/TimelineService.cs | 3 |
6 files changed, 120 insertions, 10 deletions
diff --git a/Timeline.Tests/IntegratedTests/TimelineTest.cs b/Timeline.Tests/IntegratedTests/TimelineTest.cs index 302b2195..ac4f41a2 100644 --- a/Timeline.Tests/IntegratedTests/TimelineTest.cs +++ b/Timeline.Tests/IntegratedTests/TimelineTest.cs @@ -488,7 +488,7 @@ namespace Timeline.Tests.IntegratedTests {
var res = await client.DeleteAsync("timelines/t1");
- res.Should().HaveStatusCode(HttpStatusCode.NotFound);
+ res.Should().HaveStatusCode(400);
}
}
}
@@ -545,15 +545,15 @@ namespace Timeline.Tests.IntegratedTests }
{
var res = await client.PatchAsJsonAsync(generator("notexist", null), new TimelinePatchRequest { });
- res.Should().HaveStatusCode(404).And.HaveCommonBody(errorCode);
+ res.Should().HaveStatusCode(400).And.HaveCommonBody(errorCode);
}
{
var res = await client.PutAsync(generator("notexist", "members/user1"), null);
- res.Should().HaveStatusCode(404).And.HaveCommonBody(errorCode);
+ res.Should().HaveStatusCode(400).And.HaveCommonBody(errorCode);
}
{
var res = await client.DeleteAsync(generator("notexist", "members/user1"));
- res.Should().HaveStatusCode(404).And.HaveCommonBody(errorCode);
+ res.Should().HaveStatusCode(400).And.HaveCommonBody(errorCode);
}
{
var res = await client.GetAsync(generator("notexist", "posts"));
@@ -561,11 +561,11 @@ namespace Timeline.Tests.IntegratedTests }
{
var res = await client.PostAsJsonAsync(generator("notexist", "posts"), TimelineHelper.TextPostCreateRequest("aaa"));
- res.Should().HaveStatusCode(404).And.HaveCommonBody(errorCode);
+ res.Should().HaveStatusCode(400).And.HaveCommonBody(errorCode);
}
{
var res = await client.DeleteAsync(generator("notexist", "posts/123"));
- res.Should().HaveStatusCode(404).And.HaveCommonBody(errorCode);
+ res.Should().HaveStatusCode(400).And.HaveCommonBody(errorCode);
}
{
var res = await client.GetAsync(generator("notexist", "posts/123/data"));
@@ -1436,5 +1436,54 @@ namespace Timeline.Tests.IntegratedTests .Which.Title.Should().Be("atitle");
}
}
+
+ [Fact]
+ public async Task ChangeName()
+ {
+ {
+ using var client = await CreateDefaultClient();
+ var res = await client.PostAsJsonAsync("timelineop/changename", new TimelineChangeNameRequest { OldName = "t1", NewName = "tttttttt" });
+ res.Should().HaveStatusCode(401);
+ }
+
+ {
+ using var client = await CreateClientAs(2);
+ var res = await client.PostAsJsonAsync("timelineop/changename", new TimelineChangeNameRequest { OldName = "t1", NewName = "tttttttt" });
+ res.Should().HaveStatusCode(403);
+ }
+
+ using (var client = await CreateClientAsUser())
+ {
+ {
+ var res = await client.PostAsJsonAsync("timelineop/changename", new TimelineChangeNameRequest { OldName = "!!!", NewName = "tttttttt" });
+ res.Should().BeInvalidModel();
+ }
+
+ {
+ var res = await client.PostAsJsonAsync("timelineop/changename", new TimelineChangeNameRequest { OldName = "ttt", NewName = "!!!!" });
+ res.Should().BeInvalidModel();
+ }
+
+ {
+ var res = await client.PostAsJsonAsync("timelineop/changename", new TimelineChangeNameRequest { OldName = "ttttt", NewName = "tttttttt" });
+ res.Should().HaveStatusCode(400).And.HaveCommonBody().Which.Code.Should().Be(ErrorCodes.TimelineController.NotExist);
+ }
+
+ {
+ var res = await client.PostAsJsonAsync("timelineop/changename", new TimelineChangeNameRequest { OldName = "t1", NewName = "newt" });
+ res.Should().HaveStatusCode(200).And.HaveJsonBody<TimelineInfo>().Which.Name.Should().Be("newt");
+ }
+
+ {
+ var res = await client.GetAsync("timelines/t1");
+ res.Should().HaveStatusCode(404);
+ }
+
+ {
+ var res = await client.GetAsync("timelines/newt");
+ res.Should().HaveStatusCode(200).And.HaveJsonBody<TimelineInfo>().Which.Name.Should().Be("newt");
+ }
+ }
+ }
}
}
diff --git a/Timeline.Tests/Services/TimelineServiceTest.cs b/Timeline.Tests/Services/TimelineServiceTest.cs index 3883cda9..5a774b78 100644 --- a/Timeline.Tests/Services/TimelineServiceTest.cs +++ b/Timeline.Tests/Services/TimelineServiceTest.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Timeline.Entities;
using Timeline.Models;
using Timeline.Services;
+using Timeline.Services.Exceptions;
using Timeline.Tests.Helpers;
using Xunit;
@@ -304,7 +305,14 @@ namespace Timeline.Tests.Services {
_clock.ForwardCurrentTime();
+ await _timelineService.Awaiting(s => s.ChangeTimelineName("!!!", "newtl")).Should().ThrowAsync<ArgumentException>();
+ await _timelineService.Awaiting(s => s.ChangeTimelineName("tl", "!!!")).Should().ThrowAsync<ArgumentException>();
+ await _timelineService.Awaiting(s => s.ChangeTimelineName("tl", "newtl")).Should().ThrowAsync<TimelineNotExistException>();
+
await _timelineService.CreateTimeline("tl", await _userService.GetUserIdByUsername("user"));
+ await _timelineService.CreateTimeline("tl2", await _userService.GetUserIdByUsername("user"));
+
+ await _timelineService.Awaiting(s => s.ChangeTimelineName("tl", "tl2")).Should().ThrowAsync<EntityAlreadyExistException>();
var time = _clock.ForwardCurrentTime();
diff --git a/Timeline/Controllers/TimelineController.cs b/Timeline/Controllers/TimelineController.cs index 90b50bbb..9a3147ea 100644 --- a/Timeline/Controllers/TimelineController.cs +++ b/Timeline/Controllers/TimelineController.cs @@ -308,6 +308,7 @@ namespace Timeline.Controllers [HttpDelete("timelines/{name}/posts/{id}")]
[Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
public async Task<ActionResult<CommonDeleteResponse>> PostDelete([FromRoute][GeneralTimelineName] string name, [FromRoute] long id)
@@ -336,6 +337,7 @@ namespace Timeline.Controllers [HttpPatch("timelines/{name}")]
[Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
public async Task<ActionResult<TimelineInfo>> TimelinePatch([FromRoute][GeneralTimelineName] string name, [FromBody] TimelinePatchRequest body)
@@ -461,5 +463,29 @@ namespace Timeline.Controllers return CommonDeleteResponse.NotExist();
}
}
+
+ [HttpPost("timelineop/changename")]
+ [Authorize]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status400BadRequest)]
+ [ProducesResponseType(StatusCodes.Status401Unauthorized)]
+ [ProducesResponseType(StatusCodes.Status403Forbidden)]
+ public async Task<ActionResult<TimelineInfo>> TimelineOpChangeName([FromBody] TimelineChangeNameRequest body)
+ {
+ if (!this.IsAdministrator() && !(await _service.HasManagePermission(body.OldName, this.GetUserId())))
+ {
+ return StatusCode(StatusCodes.Status403Forbidden, ErrorResponse.Common.Forbid());
+ }
+
+ try
+ {
+ var timeline = await _service.ChangeTimelineName(body.OldName, body.NewName);
+ return Ok(_mapper.Map<TimelineInfo>(timeline));
+ }
+ catch (EntityAlreadyExistException)
+ {
+ return BadRequest(ErrorResponse.TimelineController.NameConflict());
+ }
+ }
}
}
diff --git a/Timeline/Filters/Timeline.cs b/Timeline/Filters/Timeline.cs index 90b87223..6a730ee7 100644 --- a/Timeline/Filters/Timeline.cs +++ b/Timeline/Filters/Timeline.cs @@ -1,4 +1,5 @@ -using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Timeline.Models.Http;
using Timeline.Services.Exceptions;
@@ -13,11 +14,17 @@ namespace Timeline.Filters {
if (e.InnerException is UserNotExistException)
{
- context.Result = new NotFoundObjectResult(ErrorResponse.UserCommon.NotExist());
+ if (HttpMethods.IsGet(context.HttpContext.Request.Method))
+ context.Result = new NotFoundObjectResult(ErrorResponse.UserCommon.NotExist());
+ else
+ context.Result = new BadRequestObjectResult(ErrorResponse.UserCommon.NotExist());
}
else
{
- context.Result = new NotFoundObjectResult(ErrorResponse.TimelineController.NotExist());
+ if (HttpMethods.IsGet(context.HttpContext.Request.Method))
+ context.Result = new NotFoundObjectResult(ErrorResponse.TimelineController.NotExist());
+ else
+ context.Result = new BadRequestObjectResult(ErrorResponse.TimelineController.NotExist());
}
}
}
diff --git a/Timeline/Models/Http/TimelineController.cs b/Timeline/Models/Http/TimelineController.cs index 95bae3e6..7bd141ed 100644 --- a/Timeline/Models/Http/TimelineController.cs +++ b/Timeline/Models/Http/TimelineController.cs @@ -71,4 +71,23 @@ namespace Timeline.Models.Http /// </summary>
public TimelineVisibility? Visibility { get; set; }
}
+
+ /// <summary>
+ /// Change timeline name request model.
+ /// </summary>
+ public class TimelineChangeNameRequest
+ {
+ /// <summary>
+ /// Old name of timeline.
+ /// </summary>
+ [Required]
+ [TimelineName]
+ public string OldName { get; set; } = default!;
+ /// <summary>
+ /// New name of timeline.
+ /// </summary>
+ [Required]
+ [TimelineName]
+ public string NewName { get; set; } = default!;
+ }
}
diff --git a/Timeline/Services/TimelineService.cs b/Timeline/Services/TimelineService.cs index 0a3a2076..4bcae596 100644 --- a/Timeline/Services/TimelineService.cs +++ b/Timeline/Services/TimelineService.cs @@ -411,6 +411,7 @@ namespace Timeline.Services }
}
+ /// Remember to include Members when query.
private async Task<Models.Timeline> MapTimelineFromEntity(TimelineEntity entity)
{
var owner = await _userService.GetUserById(entity.OwnerId);
@@ -1138,7 +1139,7 @@ namespace Timeline.Services ValidateTimelineName(oldTimelineName, nameof(oldTimelineName));
ValidateTimelineName(newTimelineName, nameof(newTimelineName));
- var entity = await _database.Timelines.Where(t => t.Name == oldTimelineName).SingleOrDefaultAsync();
+ var entity = await _database.Timelines.Include(t => t.Members).Where(t => t.Name == oldTimelineName).SingleOrDefaultAsync();
if (entity == null)
throw new TimelineNotExistException(oldTimelineName);
|