aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BackEnd/Timeline.Tests/IntegratedTests2/TimelineBookmarkTest2.cs6
-rw-r--r--BackEnd/Timeline.Tests/IntegratedTests2/TimelineBookmarkTest3.cs119
-rw-r--r--BackEnd/Timeline.Tests/IntegratedTests2/TimelinePostTest.cs (renamed from BackEnd/Timeline.Tests/IntegratedTests2/TimelinePostTest1.cs)4
-rw-r--r--BackEnd/Timeline/Controllers/TimelineBookmarkV2Controller.cs60
-rw-r--r--BackEnd/Timeline/Models/Http/HttpTimelineBookmarkMoveRequest.cs21
-rw-r--r--BackEnd/Timeline/Models/Http/HttpTimelinebookmarkDeleteRequest.cs18
6 files changed, 223 insertions, 5 deletions
diff --git a/BackEnd/Timeline.Tests/IntegratedTests2/TimelineBookmarkTest2.cs b/BackEnd/Timeline.Tests/IntegratedTests2/TimelineBookmarkTest2.cs
index 95c1dd97..b701e4eb 100644
--- a/BackEnd/Timeline.Tests/IntegratedTests2/TimelineBookmarkTest2.cs
+++ b/BackEnd/Timeline.Tests/IntegratedTests2/TimelineBookmarkTest2.cs
@@ -65,7 +65,7 @@ namespace Timeline.Tests.IntegratedTests2
public async Task OtherUserCantSeePrivate()
{
await CreateUserAsync("user2", "user2pw");
- var client = CreateClientWithToken(await CreateTokenWithCredentialAsync("user2", "user2pw"));
+ using var client = CreateClientWithToken(await CreateTokenWithCredentialAsync("user2", "user2pw"));
await client.TestJsonSendAsync(HttpMethod.Get, "v2/users/user/bookmarks", expectedStatusCode: HttpStatusCode.Forbidden);
await client.TestJsonSendAsync(HttpMethod.Get, "v2/users/user/bookmarks/1", expectedStatusCode: HttpStatusCode.Forbidden);
}
@@ -92,7 +92,7 @@ namespace Timeline.Tests.IntegratedTests2
{
await ChangeVisibilityAsync(TimelineVisibility.Register);
await CreateUserAsync("user2", "user2pw");
- var client = CreateClientWithToken(await CreateTokenWithCredentialAsync("user2", "user2pw"));
+ using var client = CreateClientWithToken(await CreateTokenWithCredentialAsync("user2", "user2pw"));
await client.TestJsonSendAsync(HttpMethod.Get, "v2/users/user/bookmarks", expectedStatusCode: HttpStatusCode.OK);
await client.TestJsonSendAsync(HttpMethod.Get, "v2/users/user/bookmarks/1", expectedStatusCode: HttpStatusCode.OK);
}
@@ -120,7 +120,7 @@ namespace Timeline.Tests.IntegratedTests2
{
await ChangeVisibilityAsync(TimelineVisibility.Public);
await CreateUserAsync("user2", "user2pw");
- var client = CreateClientWithToken(await CreateTokenWithCredentialAsync("user2", "user2pw"));
+ using var client = CreateClientWithToken(await CreateTokenWithCredentialAsync("user2", "user2pw"));
await client.TestJsonSendAsync(HttpMethod.Get, "v2/users/user/bookmarks", expectedStatusCode: HttpStatusCode.OK);
await client.TestJsonSendAsync(HttpMethod.Get, "v2/users/user/bookmarks/1", expectedStatusCode: HttpStatusCode.OK);
}
diff --git a/BackEnd/Timeline.Tests/IntegratedTests2/TimelineBookmarkTest3.cs b/BackEnd/Timeline.Tests/IntegratedTests2/TimelineBookmarkTest3.cs
new file mode 100644
index 00000000..fbf7e2c8
--- /dev/null
+++ b/BackEnd/Timeline.Tests/IntegratedTests2/TimelineBookmarkTest3.cs
@@ -0,0 +1,119 @@
+using System;
+using System.Net;
+using System.Net.Http;
+using System.Threading.Tasks;
+using Timeline.Models.Http;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace Timeline.Tests.IntegratedTests2
+{
+ public class TimelineBookmarkTest3 : IntegratedTestBase
+ {
+ public TimelineBookmarkTest3(ITestOutputHelper testOutput) : base(testOutput)
+ {
+ }
+
+ protected override async Task OnInitializeAsync()
+ {
+ using var client = CreateClientAsUser();
+ await client.TestJsonSendAsync(HttpMethod.Post, "v2/timelines", new HttpTimelineCreateRequest
+ {
+ Name = "hello"
+ }, expectedStatusCode: HttpStatusCode.Created);
+
+ await client.TestJsonSendAsync(HttpMethod.Post, "v2/timelines", new HttpTimelineCreateRequest
+ {
+ Name = "hello2"
+ }, expectedStatusCode: HttpStatusCode.Created);
+
+ await client.TestJsonSendAsync(HttpMethod.Post, "v2/users/user/bookmarks", new HttpTimelineBookmarkCreateRequest
+ {
+ TimelineOwner = "user",
+ TimelineName = "hello"
+ }, expectedStatusCode: HttpStatusCode.Created);
+
+ await client.TestJsonSendAsync(HttpMethod.Post, "v2/users/user/bookmarks", new HttpTimelineBookmarkCreateRequest
+ {
+ TimelineOwner = "user",
+ TimelineName = "hello2"
+ }, expectedStatusCode: HttpStatusCode.Created);
+ }
+
+ [Fact]
+ public async Task DeleteTest()
+ {
+ using var client = CreateClientAsUser();
+ await client.TestJsonSendAsync(HttpMethod.Post, "v2/users/user/bookmarks/delete", new HttpTimelinebookmarkDeleteRequest
+ {
+ TimelineOwner = "user",
+ TimelineName = "hello"
+ }, expectedStatusCode: HttpStatusCode.NoContent);
+
+ await client.TestJsonSendAsync(HttpMethod.Post, "v2/users/user/bookmarks/delete", new HttpTimelinebookmarkDeleteRequest
+ {
+ TimelineOwner = "user",
+ TimelineName = "hello"
+ }, expectedStatusCode: HttpStatusCode.NoContent);
+ }
+
+ [Fact]
+ public async Task DeleteNotExist()
+ {
+ using var client = CreateClientAsUser();
+
+ await client.TestJsonSendAsync(HttpMethod.Post, "v2/users/user/bookmarks/delete", new HttpTimelinebookmarkDeleteRequest
+ {
+ TimelineOwner = "notexist",
+ TimelineName = "hello"
+ }, expectedStatusCode: HttpStatusCode.UnprocessableEntity);
+
+ await client.TestJsonSendAsync(HttpMethod.Post, "v2/users/user/bookmarks/delete", new HttpTimelinebookmarkDeleteRequest
+ {
+ TimelineOwner = "user",
+ TimelineName = "notexist"
+ }, expectedStatusCode: HttpStatusCode.UnprocessableEntity);
+ }
+
+ [Fact]
+ public async Task DeleteNotLogin()
+ {
+ using var client = CreateDefaultClient();
+ await client.TestJsonSendAsync(HttpMethod.Post, "v2/users/user/bookmarks/delete", new HttpTimelinebookmarkDeleteRequest
+ {
+ TimelineOwner = "user",
+ TimelineName = "hello"
+ }, expectedStatusCode: HttpStatusCode.Unauthorized);
+ }
+
+ [Fact]
+ public async Task DeleteForbid()
+ {
+ await CreateUserAsync("user2", "user2pw");
+ using var client = CreateClientWithToken(await CreateTokenWithCredentialAsync("user2", "user2pw"));
+ await client.TestJsonSendAsync(HttpMethod.Post, "v2/users/user/bookmarks/delete", new HttpTimelinebookmarkDeleteRequest
+ {
+ TimelineOwner = "user",
+ TimelineName = "hello"
+ }, expectedStatusCode: HttpStatusCode.Forbidden);
+ }
+
+ [Fact]
+ public async Task DeleteAdmin()
+ {
+ using var client = CreateClientAsAdmin();
+ await client.TestJsonSendAsync(HttpMethod.Post, "v2/users/user/bookmarks/delete", new HttpTimelinebookmarkDeleteRequest
+ {
+ TimelineOwner = "user",
+ TimelineName = "hello"
+ }, expectedStatusCode: HttpStatusCode.NoContent);
+
+ await client.TestJsonSendAsync(HttpMethod.Post, "v2/users/notexist/bookmarks/delete", new HttpTimelinebookmarkDeleteRequest
+ {
+ TimelineOwner = "user",
+ TimelineName = "hello"
+ }, expectedStatusCode: HttpStatusCode.NotFound);
+ }
+ }
+}
+
diff --git a/BackEnd/Timeline.Tests/IntegratedTests2/TimelinePostTest1.cs b/BackEnd/Timeline.Tests/IntegratedTests2/TimelinePostTest.cs
index d06da9d9..53a98eae 100644
--- a/BackEnd/Timeline.Tests/IntegratedTests2/TimelinePostTest1.cs
+++ b/BackEnd/Timeline.Tests/IntegratedTests2/TimelinePostTest.cs
@@ -12,9 +12,9 @@ using Xunit.Abstractions;
namespace Timeline.Tests.IntegratedTests2
{
- public class TimelinePostTest1 : IntegratedTestBase
+ public class TimelinePostTest : IntegratedTestBase
{
- public TimelinePostTest1(ITestOutputHelper testOutput) : base(testOutput)
+ public TimelinePostTest(ITestOutputHelper testOutput) : base(testOutput)
{
}
diff --git a/BackEnd/Timeline/Controllers/TimelineBookmarkV2Controller.cs b/BackEnd/Timeline/Controllers/TimelineBookmarkV2Controller.cs
index c9898b61..c2130b5a 100644
--- a/BackEnd/Timeline/Controllers/TimelineBookmarkV2Controller.cs
+++ b/BackEnd/Timeline/Controllers/TimelineBookmarkV2Controller.cs
@@ -84,6 +84,66 @@ namespace Timeline.Controllers
return CreatedAtAction("Get", new { username, index = bookmark.Position }, bookmark);
}
+ [Authorize]
+ [HttpPost("delete")]
+ [ProducesResponseType(StatusCodes.Status204NoContent)]
+ [ProducesResponseType(StatusCodes.Status401Unauthorized)]
+ [ProducesResponseType(StatusCodes.Status403Forbidden)]
+ [ProducesResponseType(StatusCodes.Status404NotFound)]
+ [ProducesResponseType(StatusCodes.Status422UnprocessableEntity)]
+ public async Task<ActionResult> DeleteAsync([FromRoute][Username] string username, [FromBody] HttpTimelinebookmarkDeleteRequest body)
+ {
+ var userId = await _userService.GetUserIdByUsernameAsync(username);
+ if (!UserHasPermission(UserPermission.UserBookmarkManagement) && GetAuthUserId() != userId)
+ {
+ return Forbid();
+ }
+
+ long timelineId;
+ try
+ {
+ timelineId = await _timelineService.GetTimelineIdAsync(body.TimelineOwner, body.TimelineName);
+ }
+ catch (EntityNotExistException)
+ {
+ return UnprocessableEntity();
+ }
+
+ await _timelineBookmarkService.DeleteBookmarkAsync(userId, timelineId);
+
+ return NoContent();
+ }
+
+ [Authorize]
+ [HttpPost("move")]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status401Unauthorized)]
+ [ProducesResponseType(StatusCodes.Status403Forbidden)]
+ [ProducesResponseType(StatusCodes.Status404NotFound)]
+ [ProducesResponseType(StatusCodes.Status422UnprocessableEntity)]
+ public async Task<ActionResult<TimelineBookmark>> MoveAsync([FromRoute][Username] string username, [FromBody] HttpTimelineBookmarkMoveRequest body)
+ {
+ var userId = await _userService.GetUserIdByUsernameAsync(username);
+ if (!UserHasPermission(UserPermission.UserBookmarkManagement) && GetAuthUserId() != userId)
+ {
+ return Forbid();
+ }
+
+ long timelineId;
+ try
+ {
+ timelineId = await _timelineService.GetTimelineIdAsync(body.TimelineOwner, body.TimelineName);
+ }
+ catch (EntityNotExistException)
+ {
+ return UnprocessableEntity();
+ }
+
+ var bookmark = await _timelineBookmarkService.MoveBookmarkAsync(userId, timelineId, body.Position!.Value);
+
+ return Ok(bookmark);
+ }
+
[HttpGet("visibility")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
diff --git a/BackEnd/Timeline/Models/Http/HttpTimelineBookmarkMoveRequest.cs b/BackEnd/Timeline/Models/Http/HttpTimelineBookmarkMoveRequest.cs
new file mode 100644
index 00000000..5be7fd00
--- /dev/null
+++ b/BackEnd/Timeline/Models/Http/HttpTimelineBookmarkMoveRequest.cs
@@ -0,0 +1,21 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+using Timeline.Models.Validation;
+
+namespace Timeline.Models.Http
+{
+ public class HttpTimelineBookmarkMoveRequest
+ {
+ [Required]
+ [Username]
+ public string TimelineOwner { get; set; } = default!;
+
+ [Required]
+ [TimelineName]
+ public string TimelineName { get; set; } = default!;
+
+ [Required]
+ public int? Position { get; set; }
+ }
+}
+
diff --git a/BackEnd/Timeline/Models/Http/HttpTimelinebookmarkDeleteRequest.cs b/BackEnd/Timeline/Models/Http/HttpTimelinebookmarkDeleteRequest.cs
new file mode 100644
index 00000000..ab45f976
--- /dev/null
+++ b/BackEnd/Timeline/Models/Http/HttpTimelinebookmarkDeleteRequest.cs
@@ -0,0 +1,18 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+using Timeline.Models.Validation;
+
+namespace Timeline.Models.Http
+{
+ public class HttpTimelinebookmarkDeleteRequest
+ {
+ [Required]
+ [Username]
+ public string TimelineOwner { get; set; } = default!;
+
+ [Required]
+ [TimelineName]
+ public string TimelineName { get; set; } = default!;
+ }
+}
+