diff options
5 files changed, 108 insertions, 8 deletions
diff --git a/BackEnd/Timeline.Tests/IntegratedTests2/HttpClientTestExtensions.cs b/BackEnd/Timeline.Tests/IntegratedTests2/HttpClientTestExtensions.cs index cd7daf3e..48496853 100644 --- a/BackEnd/Timeline.Tests/IntegratedTests2/HttpClientTestExtensions.cs +++ b/BackEnd/Timeline.Tests/IntegratedTests2/HttpClientTestExtensions.cs @@ -12,7 +12,7 @@ namespace Timeline.Tests.IntegratedTests2 public static class HttpClientTestExtensions
{
- public static async Task<HttpResponseMessage> TestSendAsync(this HttpClient client, HttpMethod method, string url, HttpContent? body = null, HttpStatusCode expectedStatusCode = HttpStatusCode.OK, RequestSetupAsync? requestSetup = null)
+ public static async Task<HttpResponseMessage> TestSendAsync(this HttpClient client, HttpMethod method, string url, HttpContent? body = null, HttpStatusCode? expectedStatusCode = null, RequestSetupAsync? requestSetup = null)
{
using var req = new HttpRequestMessage
{
@@ -23,7 +23,14 @@ namespace Timeline.Tests.IntegratedTests2 var task = requestSetup?.Invoke(req);
if (task is not null) await task;
var res = await client.SendAsync(req);
- res.StatusCode.Should().Be(expectedStatusCode);
+ if (expectedStatusCode is null) + { + ((int)res.StatusCode).Should().BeGreaterThanOrEqualTo(200).And.BeLessThan(300);
+ }
+ else + { + res.StatusCode.Should().Be(expectedStatusCode.Value);
+ }
return res;
}
@@ -34,13 +41,13 @@ namespace Timeline.Tests.IntegratedTests2 return body!;
}
- public static async Task TestJsonSendAsync(this HttpClient client, HttpMethod method, string url, object? jsonBody = null, HttpStatusCode expectedStatusCode = HttpStatusCode.OK, RequestSetupAsync? requestSetup = null)
+ public static async Task TestJsonSendAsync(this HttpClient client, HttpMethod method, string url, object? jsonBody = null, HttpStatusCode? expectedStatusCode = null, RequestSetupAsync? requestSetup = null)
{
using JsonContent? reqContent = jsonBody is null ? null : JsonContent.Create(jsonBody, options: CommonJsonSerializeOptions.Options);
await client.TestSendAsync(method, url, reqContent, expectedStatusCode, requestSetup);
}
- public static async Task<T> TestJsonSendAsync<T>(this HttpClient client, HttpMethod method, string url, object? jsonBody = null, HttpStatusCode expectedStatusCode = HttpStatusCode.OK, RequestSetupAsync? requestSetup = null)
+ public static async Task<T> TestJsonSendAsync<T>(this HttpClient client, HttpMethod method, string url, object? jsonBody = null, HttpStatusCode? expectedStatusCode = null, RequestSetupAsync? requestSetup = null)
{
using JsonContent? reqContent = jsonBody == null ? null : JsonContent.Create(jsonBody, options: CommonJsonSerializeOptions.Options);
var res = await client.TestSendAsync(method, url, reqContent, expectedStatusCode, requestSetup);
diff --git a/BackEnd/Timeline.Tests/IntegratedTests2/TimelineBookmarkTest.cs b/BackEnd/Timeline.Tests/IntegratedTests2/TimelineBookmarkTest.cs index bac132ba..f708381f 100644 --- a/BackEnd/Timeline.Tests/IntegratedTests2/TimelineBookmarkTest.cs +++ b/BackEnd/Timeline.Tests/IntegratedTests2/TimelineBookmarkTest.cs @@ -23,7 +23,6 @@ namespace Timeline.Tests.IntegratedTests2 { Name = "hello" }, expectedStatusCode: HttpStatusCode.Created); - } [Fact] diff --git a/BackEnd/Timeline.Tests/IntegratedTests2/TimelineBookmarkTest2.cs b/BackEnd/Timeline.Tests/IntegratedTests2/TimelineBookmarkTest2.cs new file mode 100644 index 00000000..6bc93836 --- /dev/null +++ b/BackEnd/Timeline.Tests/IntegratedTests2/TimelineBookmarkTest2.cs @@ -0,0 +1,51 @@ +using System; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using FluentAssertions; +using Timeline.Models; +using Timeline.Models.Http; +using Xunit; +using Xunit.Abstractions; + +namespace Timeline.Tests.IntegratedTests2 +{ + public class TimelineBookmarkTest2 : IntegratedTestBase + { + public TimelineBookmarkTest2(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/users/user/bookmarks", new HttpTimelineBookmarkCreateRequest + { + TimelineOwner = "user", + TimelineName = "hello" + }, expectedStatusCode: HttpStatusCode.Created); + } + + [Fact] + public async Task ChangeVisibilityShouldWork() + { + using var client = CreateClientAsUser(); + var a = await client.TestJsonSendAsync<HttpTimelineBookmarkVisibility>(HttpMethod.Get, "v2/users/user/bookmarks/visibility", expectedStatusCode: HttpStatusCode.OK); + a.Visibility.Should().Be(TimelineVisibility.Private); + + await client.TestJsonSendAsync(HttpMethod.Put, "v2/users/user/bookmarks/visibility", new HttpTimelineBookmarkVisibility { Visibility = TimelineVisibility.Register }, expectedStatusCode: HttpStatusCode.NoContent); + var b = await client.TestJsonSendAsync<HttpTimelineBookmarkVisibility>(HttpMethod.Get, "v2/users/user/bookmarks/visibility", expectedStatusCode: HttpStatusCode.OK); + b.Visibility.Should().Be(TimelineVisibility.Register); + + await client.TestJsonSendAsync(HttpMethod.Put, "v2/users/user/bookmarks/visibility", new HttpTimelineBookmarkVisibility { Visibility = TimelineVisibility.Public }, expectedStatusCode: HttpStatusCode.NoContent); + var c = await client.TestJsonSendAsync<HttpTimelineBookmarkVisibility>(HttpMethod.Get, "v2/users/user/bookmarks/visibility", expectedStatusCode: HttpStatusCode.OK); + c.Visibility.Should().Be(TimelineVisibility.Public); + } + } +} + diff --git a/BackEnd/Timeline/Controllers/TimelineBookmarkV2Controller.cs b/BackEnd/Timeline/Controllers/TimelineBookmarkV2Controller.cs index 3990a1e6..c9898b61 100644 --- a/BackEnd/Timeline/Controllers/TimelineBookmarkV2Controller.cs +++ b/BackEnd/Timeline/Controllers/TimelineBookmarkV2Controller.cs @@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Timeline.Models; using Timeline.Models.Http; +using Timeline.Models.Validation; using Timeline.Services; using Timeline.Services.Api; using Timeline.Services.Timeline; @@ -31,7 +32,7 @@ namespace Timeline.Controllers [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status422UnprocessableEntity)] [HttpGet] - public async Task<ActionResult<Page<TimelineBookmark>>> ListAsync([FromRoute] string username, [FromQuery] int? page, [FromQuery] int? pageSize) + public async Task<ActionResult<Page<TimelineBookmark>>> ListAsync([FromRoute][Username] string username, [FromQuery] int? page, [FromQuery] int? pageSize) { var userId = await _userService.GetUserIdByUsernameAsync(username); if (!UserHasPermission(UserPermission.UserBookmarkManagement) && !await _timelineBookmarkService.CanReadBookmarksAsync(userId, GetOptionalAuthUserId())) @@ -46,7 +47,7 @@ namespace Timeline.Controllers [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status422UnprocessableEntity)] [HttpGet("{index}")] - public async Task<ActionResult<TimelineBookmark>> GetAsync([FromRoute] string username, [FromRoute] int index) + public async Task<ActionResult<TimelineBookmark>> GetAsync([FromRoute][Username] string username, [FromRoute] int index) { var userId = await _userService.GetUserIdByUsernameAsync(username); if (!UserHasPermission(UserPermission.UserBookmarkManagement) && !await _timelineBookmarkService.CanReadBookmarksAsync(userId, GetOptionalAuthUserId())) @@ -62,7 +63,8 @@ namespace Timeline.Controllers [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status422UnprocessableEntity)] [Authorize] - public async Task<ActionResult<TimelineBookmark>> CreateAsync([FromRoute] string username, [FromBody] HttpTimelineBookmarkCreateRequest body) + [HttpPost] + public async Task<ActionResult<TimelineBookmark>> CreateAsync([FromRoute][Username] string username, [FromBody] HttpTimelineBookmarkCreateRequest body) { var userId = await _userService.GetUserIdByUsernameAsync(username); if (!UserHasPermission(UserPermission.UserBookmarkManagement) && GetAuthUserId() != userId) @@ -81,5 +83,34 @@ namespace Timeline.Controllers var bookmark = await _timelineBookmarkService.AddBookmarkAsync(userId, timelineId, body.Position); return CreatedAtAction("Get", new { username, index = bookmark.Position }, bookmark); } + + [HttpGet("visibility")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status422UnprocessableEntity)] + public async Task<ActionResult<HttpTimelineBookmarkVisibility>> GetVisibilityAsync([FromRoute][Username] string username) + { + var userId = await _userService.GetUserIdByUsernameAsync(username); + var visibility = await _timelineBookmarkService.GetBookmarkVisibilityAsync(userId); + return Ok(new HttpTimelineBookmarkVisibility { Visibility = visibility }); + } + + [HttpPut("visibility")] + [Authorize] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status422UnprocessableEntity)] + public async Task<ActionResult> PutVisibilityAsync([FromRoute][Username] string username, [FromBody] HttpTimelineBookmarkVisibility body) + { + var userId = await _userService.GetUserIdByUsernameAsync(username); + if (!UserHasPermission(UserPermission.UserBookmarkManagement) && GetAuthUserId() != userId) + { + return Forbid(); + } + await _timelineBookmarkService.SetBookmarkVisibilityAsync(userId, body.Visibility); + return NoContent(); + } } } diff --git a/BackEnd/Timeline/Models/Http/HttpTimelineBookmarkVisibility.cs b/BackEnd/Timeline/Models/Http/HttpTimelineBookmarkVisibility.cs new file mode 100644 index 00000000..d19c12f6 --- /dev/null +++ b/BackEnd/Timeline/Models/Http/HttpTimelineBookmarkVisibility.cs @@ -0,0 +1,12 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace Timeline.Models.Http +{ + public class HttpTimelineBookmarkVisibility + { + [Required] + public TimelineVisibility Visibility { get; set; } + } +} + |