From ce85af942c64fc3bad4e4502d683f730c882de96 Mon Sep 17 00:00:00 2001 From: crupest Date: Thu, 26 Nov 2020 23:43:11 +0800 Subject: refactor: ... --- BackEnd/Timeline/Controllers/UserController.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'BackEnd/Timeline/Controllers/UserController.cs') diff --git a/BackEnd/Timeline/Controllers/UserController.cs b/BackEnd/Timeline/Controllers/UserController.cs index 8edae139..626a116f 100644 --- a/BackEnd/Timeline/Controllers/UserController.cs +++ b/BackEnd/Timeline/Controllers/UserController.cs @@ -26,15 +26,17 @@ namespace Timeline.Controllers { private readonly ILogger _logger; private readonly IUserService _userService; + private readonly IUserCredentialService _userCredentialService; private readonly IUserPermissionService _userPermissionService; private readonly IUserDeleteService _userDeleteService; private readonly IMapper _mapper; /// - public UserController(ILogger logger, IUserService userService, IUserPermissionService userPermissionService, IUserDeleteService userDeleteService, IMapper mapper) + public UserController(ILogger logger, IUserService userService, IUserCredentialService userCredentialService, IUserPermissionService userPermissionService, IUserDeleteService userDeleteService, IMapper mapper) { _logger = logger; _userService = userService; + _userCredentialService = userCredentialService; _userPermissionService = userPermissionService; _userDeleteService = userDeleteService; _mapper = mapper; @@ -190,7 +192,7 @@ namespace Timeline.Controllers { try { - await _userService.ChangePassword(this.GetUserId(), request.OldPassword, request.NewPassword); + await _userCredentialService.ChangePassword(this.GetUserId(), request.OldPassword, request.NewPassword); return Ok(); } catch (BadPasswordException e) -- cgit v1.2.3 From 7883590a7a0c5c5c4e5cff6290e26c64e1258a25 Mon Sep 17 00:00:00 2001 From: crupest Date: Fri, 27 Nov 2020 00:07:09 +0800 Subject: refactor: ... --- .../HttpClientTimelineExtensions.cs | 8 +- .../IntegratedTests/HttpClientUserExtensions.cs | 4 +- .../IntegratedTests/IntegratedTestBase.cs | 4 +- .../Timeline.Tests/IntegratedTests/TimelineTest.cs | 150 ++++++++++----------- .../Timeline.Tests/IntegratedTests/TokenTest.cs | 24 ++-- BackEnd/Timeline.Tests/IntegratedTests/UserTest.cs | 66 ++++----- .../Timeline.Tests/Services/TimelineServiceTest.cs | 2 +- BackEnd/Timeline/Controllers/TimelineController.cs | 32 ++--- BackEnd/Timeline/Controllers/TokenController.cs | 12 +- BackEnd/Timeline/Controllers/UserController.cs | 12 +- BackEnd/Timeline/Models/Http/Timeline.cs | 45 +++---- BackEnd/Timeline/Models/Http/TimelineController.cs | 21 ++- BackEnd/Timeline/Models/Http/TokenController.cs | 20 +-- BackEnd/Timeline/Models/Http/User.cs | 105 +++++++++++++++ BackEnd/Timeline/Models/Http/UserController.cs | 18 +-- BackEnd/Timeline/Models/Http/UserInfo.cs | 105 --------------- BackEnd/Timeline/Models/Timeline.cs | 98 -------------- BackEnd/Timeline/Models/TimelineInfo.cs | 130 ++++++++++++++++++ BackEnd/Timeline/Models/User.cs | 21 --- BackEnd/Timeline/Models/UserInfo.cs | 48 +++++++ .../Timeline/Services/HighlightTimelineService.cs | 7 +- BackEnd/Timeline/Services/TimelinePostService.cs | 24 ++-- BackEnd/Timeline/Services/TimelineService.cs | 54 ++++---- BackEnd/Timeline/Services/UserCredentialService.cs | 2 - BackEnd/Timeline/Services/UserService.cs | 45 +++---- BackEnd/Timeline/Services/UserTokenManager.cs | 6 +- 26 files changed, 561 insertions(+), 502 deletions(-) create mode 100644 BackEnd/Timeline/Models/Http/User.cs delete mode 100644 BackEnd/Timeline/Models/Http/UserInfo.cs delete mode 100644 BackEnd/Timeline/Models/Timeline.cs create mode 100644 BackEnd/Timeline/Models/TimelineInfo.cs delete mode 100644 BackEnd/Timeline/Models/User.cs create mode 100644 BackEnd/Timeline/Models/UserInfo.cs (limited to 'BackEnd/Timeline/Controllers/UserController.cs') diff --git a/BackEnd/Timeline.Tests/IntegratedTests/HttpClientTimelineExtensions.cs b/BackEnd/Timeline.Tests/IntegratedTests/HttpClientTimelineExtensions.cs index 8e48ccbf..ac60ce7c 100644 --- a/BackEnd/Timeline.Tests/IntegratedTests/HttpClientTimelineExtensions.cs +++ b/BackEnd/Timeline.Tests/IntegratedTests/HttpClientTimelineExtensions.cs @@ -6,11 +6,11 @@ namespace Timeline.Tests.IntegratedTests { public static class HttpClientTimelineExtensions { - public static Task GetTimelineAsync(this HttpClient client, string timelineName) - => client.TestGetAsync($"timelines/{timelineName}"); + public static Task GetTimelineAsync(this HttpClient client, string timelineName) + => client.TestGetAsync($"timelines/{timelineName}"); - public static Task PatchTimelineAsync(this HttpClient client, string timelineName, TimelinePatchRequest body) - => client.TestPatchAsync($"timelines/{timelineName}", body); + public static Task PatchTimelineAsync(this HttpClient client, string timelineName, HttpTimelinePatchRequest body) + => client.TestPatchAsync($"timelines/{timelineName}", body); public static Task PutTimelineMemberAsync(this HttpClient client, string timelineName, string memberUsername) => client.TestPutAsync($"timelines/{timelineName}/members/{memberUsername}"); diff --git a/BackEnd/Timeline.Tests/IntegratedTests/HttpClientUserExtensions.cs b/BackEnd/Timeline.Tests/IntegratedTests/HttpClientUserExtensions.cs index 81787eef..7ca62e38 100644 --- a/BackEnd/Timeline.Tests/IntegratedTests/HttpClientUserExtensions.cs +++ b/BackEnd/Timeline.Tests/IntegratedTests/HttpClientUserExtensions.cs @@ -6,7 +6,7 @@ namespace Timeline.Tests.IntegratedTests { public static class HttpClientUserExtensions { - public static Task GetUserAsync(this HttpClient client, string username) - => client.TestGetAsync($"users/{username}"); + public static Task GetUserAsync(this HttpClient client, string username) + => client.TestGetAsync($"users/{username}"); } } diff --git a/BackEnd/Timeline.Tests/IntegratedTests/IntegratedTestBase.cs b/BackEnd/Timeline.Tests/IntegratedTests/IntegratedTestBase.cs index e426ac98..82aed24e 100644 --- a/BackEnd/Timeline.Tests/IntegratedTests/IntegratedTestBase.cs +++ b/BackEnd/Timeline.Tests/IntegratedTests/IntegratedTestBase.cs @@ -103,8 +103,8 @@ namespace Timeline.Tests.IntegratedTests public async Task CreateClientWithCredential(string username, string password, bool setApiBase = true) { var client = await CreateDefaultClient(setApiBase); - var res = await client.TestPostAsync("token/create", - new CreateTokenRequest { Username = username, Password = password }); + var res = await client.TestPostAsync("token/create", + new HttpCreateTokenRequest { Username = username, Password = password }); var token = res.Token; client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token); return client; diff --git a/BackEnd/Timeline.Tests/IntegratedTests/TimelineTest.cs b/BackEnd/Timeline.Tests/IntegratedTests/TimelineTest.cs index 9845e1b1..12dd2b8d 100644 --- a/BackEnd/Timeline.Tests/IntegratedTests/TimelineTest.cs +++ b/BackEnd/Timeline.Tests/IntegratedTests/TimelineTest.cs @@ -19,20 +19,20 @@ namespace Timeline.Tests.IntegratedTests { public static class TimelineHelper { - public static TimelinePostContentInfo TextPostContent(string text) + public static HttpTimelinePostContent TextPostContent(string text) { - return new TimelinePostContentInfo + return new HttpTimelinePostContent { Type = "text", Text = text }; } - public static TimelinePostCreateRequest TextPostCreateRequest(string text, DateTime? time = null) + public static HttpTimelinePostCreateRequest TextPostCreateRequest(string text, DateTime? time = null) { - return new TimelinePostCreateRequest + return new HttpTimelinePostCreateRequest { - Content = new TimelinePostCreateRequestContent + Content = new HttpTimelinePostCreateRequestContent { Type = "text", Text = text @@ -72,7 +72,7 @@ namespace Timeline.Tests.IntegratedTests { - var body = await client.TestGetAsync("timelines/@user1"); + var body = await client.TestGetAsync("timelines/@user1"); body.Owner.Should().BeEquivalentTo(await client.GetUserAsync("user1")); body.Visibility.Should().Be(TimelineVisibility.Register); body.Description.Should().Be(""); @@ -84,7 +84,7 @@ namespace Timeline.Tests.IntegratedTests } { - var body = await client.TestGetAsync("timelines/t1"); + var body = await client.TestGetAsync("timelines/t1"); body.Owner.Should().BeEquivalentTo(await client.GetUserAsync("user1")); body.Visibility.Should().Be(TimelineVisibility.Register); body.Description.Should().Be(""); @@ -101,7 +101,7 @@ namespace Timeline.Tests.IntegratedTests { using var client = await CreateDefaultClient(); - var result = new List + var result = new List { await client.GetTimelineAsync("@user1") }; @@ -112,7 +112,7 @@ namespace Timeline.Tests.IntegratedTests } - var body = await client.TestGetAsync>("timelines"); + var body = await client.TestGetAsync>("timelines"); body.Should().BeEquivalentTo(result); } @@ -127,14 +127,14 @@ namespace Timeline.Tests.IntegratedTests await client.TestGetAssertInvalidModelAsync("timelines?visibility=aaa"); } - var testResultRelate = new List(); - var testResultOwn = new List(); - var testResultJoin = new List(); - var testResultOwnPrivate = new List(); - var testResultRelatePublic = new List(); - var testResultRelateRegister = new List(); - var testResultJoinPrivate = new List(); - var testResultPublic = new List(); + var testResultRelate = new List(); + var testResultOwn = new List(); + var testResultJoin = new List(); + var testResultOwnPrivate = new List(); + var testResultRelatePublic = new List(); + var testResultRelateRegister = new List(); + var testResultJoinPrivate = new List(); + var testResultPublic = new List(); { using var client = await CreateClientAsUser(); @@ -185,8 +185,8 @@ namespace Timeline.Tests.IntegratedTests { using var client = await CreateClientAs(3); - await client.PatchTimelineAsync("@user3", new TimelinePatchRequest { Visibility = TimelineVisibility.Private }); - await client.PatchTimelineAsync("t3", new TimelinePatchRequest { Visibility = TimelineVisibility.Register }); + await client.PatchTimelineAsync("@user3", new HttpTimelinePatchRequest { Visibility = TimelineVisibility.Private }); + await client.PatchTimelineAsync("t3", new HttpTimelinePatchRequest { Visibility = TimelineVisibility.Register }); { var timeline = await client.GetTimelineAsync("@user3"); @@ -206,9 +206,9 @@ namespace Timeline.Tests.IntegratedTests { using var client = await CreateDefaultClient(); - async Task TestAgainst(string url, List against) + async Task TestAgainst(string url, List against) { - var body = await client.TestGetAsync>(url); + var body = await client.TestGetAsync>(url); body.Should().BeEquivalentTo(against); } @@ -236,7 +236,7 @@ namespace Timeline.Tests.IntegratedTests await client.TestPostAssertInvalidModelAsync("timelines", new TimelineCreateRequest { Name = "!!!" }); { - var body = await client.TestPostAsync("timelines", new TimelineCreateRequest { Name = "aaa" }); + var body = await client.TestPostAsync("timelines", new TimelineCreateRequest { Name = "aaa" }); body.Should().BeEquivalentTo(await client.GetTimelineAsync("aaa")); } @@ -342,7 +342,7 @@ namespace Timeline.Tests.IntegratedTests var timelineName = generator(1); - async Task AssertMembers(List members) + async Task AssertMembers(List members) { var body = await client.GetTimelineAsync(timelineName); body.Members.Should().NotBeNull().And.BeEquivalentTo(members); @@ -358,7 +358,7 @@ namespace Timeline.Tests.IntegratedTests await client.TestPutAssertErrorAsync($"timelines/{timelineName}/members/usernotexist", errorCode: ErrorCodes.TimelineController.MemberPut_NotExist); await AssertEmptyMembers(); await client.PutTimelineMemberAsync(timelineName, "user2"); - await AssertMembers(new List { await client.GetUserAsync("user2") }); + await AssertMembers(new List { await client.GetUserAsync("user2") }); await client.DeleteTimelineMemberAsync(timelineName, "user2", true); await AssertEmptyMembers(); await client.DeleteTimelineMemberAsync(timelineName, "aaa", false); @@ -462,7 +462,7 @@ namespace Timeline.Tests.IntegratedTests async Task CreatePost(int userNumber) { using var client = await CreateClientAs(userNumber); - var body = await client.TestPostAsync($"timelines/{generator(1)}/posts", TimelineHelper.TextPostCreateRequest("aaa")); + var body = await client.TestPostAsync($"timelines/{generator(1)}/posts", TimelineHelper.TextPostCreateRequest("aaa")); return body.Id; } @@ -515,28 +515,28 @@ namespace Timeline.Tests.IntegratedTests using var client = await CreateClientAsUser(); { - var body = await client.TestGetAsync>($"timelines/{generator(1)}/posts"); + var body = await client.TestGetAsync>($"timelines/{generator(1)}/posts"); body.Should().BeEmpty(); } const string mockContent = "aaa"; - TimelinePostInfo createRes; + HttpTimelinePost createRes; { - var body = await client.TestPostAsync($"timelines/{generator(1)}/posts", TimelineHelper.TextPostCreateRequest(mockContent)); + var body = await client.TestPostAsync($"timelines/{generator(1)}/posts", TimelineHelper.TextPostCreateRequest(mockContent)); body.Content.Should().BeEquivalentTo(TimelineHelper.TextPostContent(mockContent)); body.Author.Should().BeEquivalentTo(await client.GetUserAsync("user1")); body.Deleted.Should().BeFalse(); createRes = body; } { - var body = await client.TestGetAsync>($"timelines/{generator(1)}/posts"); + var body = await client.TestGetAsync>($"timelines/{generator(1)}/posts"); body.Should().BeEquivalentTo(createRes); } const string mockContent2 = "bbb"; var mockTime2 = DateTime.UtcNow.AddDays(-1); - TimelinePostInfo createRes2; + HttpTimelinePost createRes2; { - var body = await client.TestPostAsync($"timelines/{generator(1)}/posts", TimelineHelper.TextPostCreateRequest(mockContent2, mockTime2)); + var body = await client.TestPostAsync($"timelines/{generator(1)}/posts", TimelineHelper.TextPostCreateRequest(mockContent2, mockTime2)); body.Should().NotBeNull(); body.Content.Should().BeEquivalentTo(TimelineHelper.TextPostContent(mockContent2)); body.Author.Should().BeEquivalentTo(await client.GetUserAsync("user1")); @@ -545,7 +545,7 @@ namespace Timeline.Tests.IntegratedTests createRes2 = body; } { - var body = await client.TestGetAsync>($"timelines/{generator(1)}/posts"); + var body = await client.TestGetAsync>($"timelines/{generator(1)}/posts"); body.Should().BeEquivalentTo(createRes, createRes2); } { @@ -554,7 +554,7 @@ namespace Timeline.Tests.IntegratedTests await client.TestDeleteAsync($"timelines/{generator(1)}/posts/30000", false); } { - var body = await client.TestGetAsync>($"timelines/{generator(1)}/posts"); + var body = await client.TestGetAsync>($"timelines/{generator(1)}/posts"); body.Should().BeEquivalentTo(createRes2); } } @@ -567,7 +567,7 @@ namespace Timeline.Tests.IntegratedTests async Task CreatePost(DateTime time) { - var body = await client.TestPostAsync($"timelines/{generator(1)}/posts", TimelineHelper.TextPostCreateRequest("aaa", time)); + var body = await client.TestPostAsync($"timelines/{generator(1)}/posts", TimelineHelper.TextPostCreateRequest("aaa", time)); return body.Id; } @@ -577,7 +577,7 @@ namespace Timeline.Tests.IntegratedTests var id2 = await CreatePost(now); { - var body = await client.TestGetAsync>($"timelines/{generator(1)}/posts"); + var body = await client.TestGetAsync>($"timelines/{generator(1)}/posts"); body.Select(p => p.Id).Should().Equal(id1, id2, id0); } } @@ -588,15 +588,15 @@ namespace Timeline.Tests.IntegratedTests { using var client = await CreateClientAsUser(); var postUrl = $"timelines/{generator(1)}/posts"; - await client.TestPostAssertInvalidModelAsync(postUrl, new TimelinePostCreateRequest { Content = null! }); - await client.TestPostAssertInvalidModelAsync(postUrl, new TimelinePostCreateRequest { Content = new TimelinePostCreateRequestContent { Type = null! } }); - await client.TestPostAssertInvalidModelAsync(postUrl, new TimelinePostCreateRequest { Content = new TimelinePostCreateRequestContent { Type = "hahaha" } }); - await client.TestPostAssertInvalidModelAsync(postUrl, new TimelinePostCreateRequest { Content = new TimelinePostCreateRequestContent { Type = "text", Text = null } }); - await client.TestPostAssertInvalidModelAsync(postUrl, new TimelinePostCreateRequest { Content = new TimelinePostCreateRequestContent { Type = "image", Data = null } }); + await client.TestPostAssertInvalidModelAsync(postUrl, new HttpTimelinePostCreateRequest { Content = null! }); + await client.TestPostAssertInvalidModelAsync(postUrl, new HttpTimelinePostCreateRequest { Content = new HttpTimelinePostCreateRequestContent { Type = null! } }); + await client.TestPostAssertInvalidModelAsync(postUrl, new HttpTimelinePostCreateRequest { Content = new HttpTimelinePostCreateRequestContent { Type = "hahaha" } }); + await client.TestPostAssertInvalidModelAsync(postUrl, new HttpTimelinePostCreateRequest { Content = new HttpTimelinePostCreateRequestContent { Type = "text", Text = null } }); + await client.TestPostAssertInvalidModelAsync(postUrl, new HttpTimelinePostCreateRequest { Content = new HttpTimelinePostCreateRequestContent { Type = "image", Data = null } }); // image not base64 - await client.TestPostAssertInvalidModelAsync(postUrl, new TimelinePostCreateRequest { Content = new TimelinePostCreateRequestContent { Type = "image", Data = "!!!" } }); + await client.TestPostAssertInvalidModelAsync(postUrl, new HttpTimelinePostCreateRequest { Content = new HttpTimelinePostCreateRequestContent { Type = "image", Data = "!!!" } }); // image base64 not image - await client.TestPostAssertInvalidModelAsync(postUrl, new TimelinePostCreateRequest { Content = new TimelinePostCreateRequestContent { Type = "image", Data = Convert.ToBase64String(new byte[] { 0x01, 0x02, 0x03 }) } }); + await client.TestPostAssertInvalidModelAsync(postUrl, new HttpTimelinePostCreateRequest { Content = new HttpTimelinePostCreateRequestContent { Type = "image", Data = Convert.ToBase64String(new byte[] { 0x01, 0x02, 0x03 }) } }); } [Theory] @@ -608,7 +608,7 @@ namespace Timeline.Tests.IntegratedTests long postId; string postImageUrl; - void AssertPostContent(TimelinePostContentInfo content) + void AssertPostContent(HttpTimelinePostContent content) { content.Type.Should().Be(TimelinePostContentTypes.Image); content.Url.Should().EndWith($"timelines/{generator(1)}/posts/{postId}/data"); @@ -618,10 +618,10 @@ namespace Timeline.Tests.IntegratedTests using var client = await CreateClientAsUser(); { - var body = await client.TestPostAsync($"timelines/{generator(1)}/posts", - new TimelinePostCreateRequest + var body = await client.TestPostAsync($"timelines/{generator(1)}/posts", + new HttpTimelinePostCreateRequest { - Content = new TimelinePostCreateRequestContent + Content = new HttpTimelinePostCreateRequestContent { Type = TimelinePostContentTypes.Image, Data = Convert.ToBase64String(imageData) @@ -633,7 +633,7 @@ namespace Timeline.Tests.IntegratedTests } { - var body = await client.TestGetAsync>($"timelines/{generator(1)}/posts"); + var body = await client.TestGetAsync>($"timelines/{generator(1)}/posts"); body.Should().HaveCount(1); var post = body[0]; post.Id.Should().Be(postId); @@ -655,7 +655,7 @@ namespace Timeline.Tests.IntegratedTests await client.TestDeleteAsync($"timelines/{generator(1)}/posts/{postId}", false); { - var body = await client.TestGetAsync>($"timelines/{generator(1)}/posts"); + var body = await client.TestGetAsync>($"timelines/{generator(1)}/posts"); body.Should().BeEmpty(); } @@ -677,7 +677,7 @@ namespace Timeline.Tests.IntegratedTests long postId; { - var body = await client.TestPostAsync($"timelines/{generator(1)}/posts", TimelineHelper.TextPostCreateRequest("aaa")); + var body = await client.TestPostAsync($"timelines/{generator(1)}/posts", TimelineHelper.TextPostCreateRequest("aaa")); postId = body.Id; } @@ -726,12 +726,12 @@ namespace Timeline.Tests.IntegratedTests using var client = await CreateClientAsUser(); var postContentList = new List { "a", "b", "c", "d" }; - var posts = new List(); + var posts = new List(); foreach (var content in postContentList) { - var post = await client.TestPostAsync($"timelines/{generator(1)}/posts", - new TimelinePostCreateRequest { Content = new TimelinePostCreateRequestContent { Text = content, Type = TimelinePostContentTypes.Text } }); + var post = await client.TestPostAsync($"timelines/{generator(1)}/posts", + new HttpTimelinePostCreateRequest { Content = new HttpTimelinePostCreateRequestContent { Text = content, Type = TimelinePostContentTypes.Text } }); posts.Add(post); await Task.Delay(1000); } @@ -739,7 +739,7 @@ namespace Timeline.Tests.IntegratedTests await client.TestDeleteAsync($"timelines/{generator(1)}/posts/{posts[2].Id}", true); { - var body = await client.TestGetAsync>($"timelines/{generator(1)}/posts?modifiedSince={posts[1].LastUpdated.ToString("s", CultureInfo.InvariantCulture) }"); + var body = await client.TestGetAsync>($"timelines/{generator(1)}/posts?modifiedSince={posts[1].LastUpdated.ToString("s", CultureInfo.InvariantCulture) }"); body.Should().HaveCount(2) .And.Subject.Select(p => p.Content!.Text).Should().Equal("b", "d"); } @@ -752,12 +752,12 @@ namespace Timeline.Tests.IntegratedTests using var client = await CreateClientAsUser(); var postContentList = new List { "a", "b", "c", "d" }; - var posts = new List(); + var posts = new List(); foreach (var content in postContentList) { - var body = await client.TestPostAsync($"timelines/{generator(1)}/posts", - new TimelinePostCreateRequest { Content = new TimelinePostCreateRequestContent { Text = content, Type = TimelinePostContentTypes.Text } }); + var body = await client.TestPostAsync($"timelines/{generator(1)}/posts", + new HttpTimelinePostCreateRequest { Content = new HttpTimelinePostCreateRequestContent { Text = content, Type = TimelinePostContentTypes.Text } }); posts.Add(body); } @@ -767,7 +767,7 @@ namespace Timeline.Tests.IntegratedTests } { - posts = await client.TestGetAsync>($"timelines/{generator(1)}/posts?includeDeleted=true"); + posts = await client.TestGetAsync>($"timelines/{generator(1)}/posts?includeDeleted=true"); posts.Should().HaveCount(4); posts.Select(p => p.Deleted).Should().Equal(true, false, true, false); posts.Select(p => p.Content == null).Should().Equal(true, false, true, false); @@ -781,12 +781,12 @@ namespace Timeline.Tests.IntegratedTests using var client = await CreateClientAsUser(); var postContentList = new List { "a", "b", "c", "d" }; - var posts = new List(); + var posts = new List(); foreach (var (content, index) in postContentList.Select((v, i) => (v, i))) { - var post = await client.TestPostAsync($"timelines/{generator(1)}/posts", - new TimelinePostCreateRequest { Content = new TimelinePostCreateRequestContent { Text = content, Type = TimelinePostContentTypes.Text } }); + var post = await client.TestPostAsync($"timelines/{generator(1)}/posts", + new HttpTimelinePostCreateRequest { Content = new HttpTimelinePostCreateRequestContent { Text = content, Type = TimelinePostContentTypes.Text } }); posts.Add(post); await Task.Delay(1000); } @@ -795,7 +795,7 @@ namespace Timeline.Tests.IntegratedTests { - posts = await client.TestGetAsync>($"timelines/{generator(1)}/posts?modifiedSince={posts[1].LastUpdated.ToString("s", CultureInfo.InvariantCulture)}&includeDeleted=true"); + posts = await client.TestGetAsync>($"timelines/{generator(1)}/posts?modifiedSince={posts[1].LastUpdated.ToString("s", CultureInfo.InvariantCulture)}&includeDeleted=true"); posts.Should().HaveCount(3); posts.Select(p => p.Deleted).Should().Equal(false, true, false); posts.Select(p => p.Content == null).Should().Equal(false, true, false); @@ -809,7 +809,7 @@ namespace Timeline.Tests.IntegratedTests using var client = await CreateClientAsUser(); DateTime lastModifiedTime; - TimelineInfo timeline; + HttpTimeline timeline; string uniqueId; { @@ -830,7 +830,7 @@ namespace Timeline.Tests.IntegratedTests { - var body = await client.TestGetAsync($"timelines/{generator(1)}", + var body = await client.TestGetAsync($"timelines/{generator(1)}", headerSetup: (headers, _) => { headers.IfModifiedSince = lastModifiedTime.AddSeconds(-1); @@ -843,7 +843,7 @@ namespace Timeline.Tests.IntegratedTests } { - var body = await client.TestGetAsync($"timelines/{generator(1)}?ifModifiedSince={lastModifiedTime.AddSeconds(-1).ToString("s", CultureInfo.InvariantCulture) }"); + var body = await client.TestGetAsync($"timelines/{generator(1)}?ifModifiedSince={lastModifiedTime.AddSeconds(-1).ToString("s", CultureInfo.InvariantCulture) }"); body.Should().BeEquivalentTo(timeline); } @@ -853,7 +853,7 @@ namespace Timeline.Tests.IntegratedTests { var testUniqueId = (uniqueId[0] == 'a' ? "b" : "a") + uniqueId[1..]; - var body = await client.TestGetAsync($"timelines/{generator(1)}?ifModifiedSince={lastModifiedTime.AddSeconds(1).ToString("s", CultureInfo.InvariantCulture) }&checkUniqueId={testUniqueId}"); + var body = await client.TestGetAsync($"timelines/{generator(1)}?ifModifiedSince={lastModifiedTime.AddSeconds(1).ToString("s", CultureInfo.InvariantCulture) }&checkUniqueId={testUniqueId}"); body.Should().BeEquivalentTo(timeline); } } @@ -870,7 +870,7 @@ namespace Timeline.Tests.IntegratedTests } { - var body = await client.PatchTimelineAsync(generator(1), new TimelinePatchRequest { Title = "atitle" }); + var body = await client.PatchTimelineAsync(generator(1), new HttpTimelinePatchRequest { Title = "atitle" }); body.Title.Should().Be("atitle"); } @@ -885,26 +885,26 @@ namespace Timeline.Tests.IntegratedTests { { using var client = await CreateDefaultClient(); - await client.TestPostAssertUnauthorizedAsync("timelineop/changename", new TimelineChangeNameRequest { OldName = "t1", NewName = "tttttttt" }); + await client.TestPostAssertUnauthorizedAsync("timelineop/changename", new HttpTimelineChangeNameRequest { OldName = "t1", NewName = "tttttttt" }); } { using var client = await CreateClientAs(2); - await client.TestPostAssertForbiddenAsync("timelineop/changename", new TimelineChangeNameRequest { OldName = "t1", NewName = "tttttttt" }); + await client.TestPostAssertForbiddenAsync("timelineop/changename", new HttpTimelineChangeNameRequest { OldName = "t1", NewName = "tttttttt" }); } using (var client = await CreateClientAsUser()) { - await client.TestPostAssertInvalidModelAsync("timelineop/changename", new TimelineChangeNameRequest { OldName = "!!!", NewName = "tttttttt" }); - await client.TestPostAssertInvalidModelAsync("timelineop/changename", new TimelineChangeNameRequest { OldName = "ttt", NewName = "!!!!" }); - await client.TestPostAssertErrorAsync("timelineop/changename", new TimelineChangeNameRequest { OldName = "ttttt", NewName = "tttttttt" }, errorCode: ErrorCodes.TimelineController.NotExist); + await client.TestPostAssertInvalidModelAsync("timelineop/changename", new HttpTimelineChangeNameRequest { OldName = "!!!", NewName = "tttttttt" }); + await client.TestPostAssertInvalidModelAsync("timelineop/changename", new HttpTimelineChangeNameRequest { OldName = "ttt", NewName = "!!!!" }); + await client.TestPostAssertErrorAsync("timelineop/changename", new HttpTimelineChangeNameRequest { OldName = "ttttt", NewName = "tttttttt" }, errorCode: ErrorCodes.TimelineController.NotExist); - await client.TestPostAsync("timelineop/changename", new TimelineChangeNameRequest { OldName = "t1", NewName = "newt" }); + await client.TestPostAsync("timelineop/changename", new HttpTimelineChangeNameRequest { OldName = "t1", NewName = "newt" }); await client.TestGetAsync("timelines/t1", expectedStatusCode: HttpStatusCode.NotFound); { - var body = await client.TestGetAsync("timelines/newt"); + var body = await client.TestGetAsync("timelines/newt"); body.Name.Should().Be("newt"); } } @@ -920,9 +920,9 @@ namespace Timeline.Tests.IntegratedTests string etag; { - var body = await client.TestPostAsync($"timelines/{generator(1)}/posts", new TimelinePostCreateRequest + var body = await client.TestPostAsync($"timelines/{generator(1)}/posts", new HttpTimelinePostCreateRequest { - Content = new TimelinePostCreateRequestContent + Content = new HttpTimelinePostCreateRequestContent { Type = TimelinePostContentTypes.Image, Data = Convert.ToBase64String(ImageHelper.CreatePngWithSize(100, 50)) diff --git a/BackEnd/Timeline.Tests/IntegratedTests/TokenTest.cs b/BackEnd/Timeline.Tests/IntegratedTests/TokenTest.cs index a5208618..fdf1af99 100644 --- a/BackEnd/Timeline.Tests/IntegratedTests/TokenTest.cs +++ b/BackEnd/Timeline.Tests/IntegratedTests/TokenTest.cs @@ -14,9 +14,9 @@ namespace Timeline.Tests.IntegratedTests private const string CreateTokenUrl = "token/create"; private const string VerifyTokenUrl = "token/verify"; - private static async Task CreateUserTokenAsync(HttpClient client, string username, string password, int? expireOffset = null) + private static async Task CreateUserTokenAsync(HttpClient client, string username, string password, int? expireOffset = null) { - return await client.TestPostAsync(CreateTokenUrl, new CreateTokenRequest { Username = username, Password = password, Expire = expireOffset }); + return await client.TestPostAsync(CreateTokenUrl, new HttpCreateTokenRequest { Username = username, Password = password, Expire = expireOffset }); } public static IEnumerable CreateToken_InvalidModel_Data() @@ -32,7 +32,7 @@ namespace Timeline.Tests.IntegratedTests public async Task CreateToken_InvalidModel(string username, string password, int expire) { using var client = await CreateDefaultClient(); - await client.TestPostAssertInvalidModelAsync(CreateTokenUrl, new CreateTokenRequest + await client.TestPostAssertInvalidModelAsync(CreateTokenUrl, new HttpCreateTokenRequest { Username = username, Password = password, @@ -52,7 +52,7 @@ namespace Timeline.Tests.IntegratedTests { using var client = await CreateDefaultClient(); await client.TestPostAssertErrorAsync(CreateTokenUrl, - new CreateTokenRequest { Username = username, Password = password }, + new HttpCreateTokenRequest { Username = username, Password = password }, errorCode: ErrorCodes.TokenController.Create_BadCredential); } @@ -60,8 +60,8 @@ namespace Timeline.Tests.IntegratedTests public async Task CreateToken_Success() { using var client = await CreateDefaultClient(); - var body = await client.TestPostAsync(CreateTokenUrl, - new CreateTokenRequest { Username = "user1", Password = "user1pw" }); + var body = await client.TestPostAsync(CreateTokenUrl, + new HttpCreateTokenRequest { Username = "user1", Password = "user1pw" }); body.Token.Should().NotBeNullOrWhiteSpace(); body.User.Should().BeEquivalentTo(await client.GetUserAsync("user1")); } @@ -70,7 +70,7 @@ namespace Timeline.Tests.IntegratedTests public async Task VerifyToken_InvalidModel() { using var client = await CreateDefaultClient(); - await client.TestPostAssertInvalidModelAsync(VerifyTokenUrl, new VerifyTokenRequest { Token = null! }); + await client.TestPostAssertInvalidModelAsync(VerifyTokenUrl, new HttpVerifyTokenRequest { Token = null! }); } [Fact] @@ -78,7 +78,7 @@ namespace Timeline.Tests.IntegratedTests { using var client = await CreateDefaultClient(); await client.TestPostAssertErrorAsync(VerifyTokenUrl, - new VerifyTokenRequest { Token = "bad token hahaha" }, + new HttpVerifyTokenRequest { Token = "bad token hahaha" }, errorCode: ErrorCodes.TokenController.Verify_BadFormat); } @@ -97,7 +97,7 @@ namespace Timeline.Tests.IntegratedTests } await client.TestPostAssertErrorAsync(VerifyTokenUrl, - new VerifyTokenRequest { Token = token }, + new HttpVerifyTokenRequest { Token = token }, errorCode: ErrorCodes.TokenController.Verify_OldVersion); } @@ -114,7 +114,7 @@ namespace Timeline.Tests.IntegratedTests } await client.TestPostAssertErrorAsync(VerifyTokenUrl, - new VerifyTokenRequest { Token = token }, + new HttpVerifyTokenRequest { Token = token }, errorCode: ErrorCodes.TokenController.Verify_UserNotExist); } @@ -141,8 +141,8 @@ namespace Timeline.Tests.IntegratedTests { using var client = await CreateDefaultClient(); var createTokenResult = await CreateUserTokenAsync(client, "user1", "user1pw"); - var body = await client.TestPostAsync(VerifyTokenUrl, - new VerifyTokenRequest { Token = createTokenResult.Token }); + var body = await client.TestPostAsync(VerifyTokenUrl, + new HttpVerifyTokenRequest { Token = createTokenResult.Token }); body.User.Should().BeEquivalentTo(await client.GetUserAsync("user1")); } } diff --git a/BackEnd/Timeline.Tests/IntegratedTests/UserTest.cs b/BackEnd/Timeline.Tests/IntegratedTests/UserTest.cs index e0ebf635..56dbf92a 100644 --- a/BackEnd/Timeline.Tests/IntegratedTests/UserTest.cs +++ b/BackEnd/Timeline.Tests/IntegratedTests/UserTest.cs @@ -12,7 +12,7 @@ namespace Timeline.Tests.IntegratedTests public async Task UserListShouldHaveUniqueId() { using var client = await CreateDefaultClient(); - foreach (var user in await client.TestGetAsync>("users")) + foreach (var user in await client.TestGetAsync>("users")) { user.UniqueId.Should().NotBeNullOrWhiteSpace(); } @@ -22,14 +22,14 @@ namespace Timeline.Tests.IntegratedTests public async Task GetList() { using var client = await CreateDefaultClient(); - await client.TestGetAsync>("users"); + await client.TestGetAsync>("users"); } [Fact] public async Task Get() { using var client = await CreateDefaultClient(); - var user = await client.TestGetAsync($"users/admin"); + var user = await client.TestGetAsync($"users/admin"); user.Username.Should().Be("admin"); user.Nickname.Should().Be("administrator"); user.UniqueId.Should().NotBeNullOrEmpty(); @@ -55,8 +55,8 @@ namespace Timeline.Tests.IntegratedTests { using var client = await CreateClientAsUser(); { - var body = await client.TestPatchAsync("users/user1", - new UserPatchRequest { Nickname = "aaa" }); + var body = await client.TestPatchAsync("users/user1", + new HttpUserPatchRequest { Nickname = "aaa" }); body.Nickname.Should().Be("aaa"); } @@ -73,8 +73,8 @@ namespace Timeline.Tests.IntegratedTests using var userClient = await CreateClientAsUser(); { - var body = await client.TestPatchAsync("users/user1", - new UserPatchRequest + var body = await client.TestPatchAsync("users/user1", + new HttpUserPatchRequest { Username = "newuser", Password = "newpw", @@ -91,7 +91,7 @@ namespace Timeline.Tests.IntegratedTests { var token = userClient.DefaultRequestHeaders.Authorization!.Parameter!; // Token should expire. - await userClient.TestPostAssertErrorAsync("token/verify", new VerifyTokenRequest() { Token = token }); + await userClient.TestPostAssertErrorAsync("token/verify", new HttpVerifyTokenRequest() { Token = token }); } { @@ -104,26 +104,26 @@ namespace Timeline.Tests.IntegratedTests public async Task Patch_NotExist() { using var client = await CreateClientAsAdministrator(); - await client.TestPatchAssertNotFoundAsync("users/usernotexist", new UserPatchRequest { }, errorCode: ErrorCodes.UserCommon.NotExist); + await client.TestPatchAssertNotFoundAsync("users/usernotexist", new HttpUserPatchRequest { }, errorCode: ErrorCodes.UserCommon.NotExist); } [Fact] public async Task Patch_InvalidModel() { using var client = await CreateClientAsAdministrator(); - await client.TestPatchAssertInvalidModelAsync("users/aaa!a", new UserPatchRequest { }); + await client.TestPatchAssertInvalidModelAsync("users/aaa!a", new HttpUserPatchRequest { }); } public static IEnumerable Patch_InvalidModel_Body_Data() { - yield return new[] { new UserPatchRequest { Username = "aaa!a" } }; - yield return new[] { new UserPatchRequest { Password = "" } }; - yield return new[] { new UserPatchRequest { Nickname = new string('a', 50) } }; + yield return new[] { new HttpUserPatchRequest { Username = "aaa!a" } }; + yield return new[] { new HttpUserPatchRequest { Password = "" } }; + yield return new[] { new HttpUserPatchRequest { Nickname = new string('a', 50) } }; } [Theory] [MemberData(nameof(Patch_InvalidModel_Body_Data))] - public async Task Patch_InvalidModel_Body(UserPatchRequest body) + public async Task Patch_InvalidModel_Body(HttpUserPatchRequest body) { using var client = await CreateClientAsAdministrator(); await client.TestPatchAssertInvalidModelAsync("users/user1", body); @@ -133,35 +133,35 @@ namespace Timeline.Tests.IntegratedTests public async Task Patch_UsernameConflict() { using var client = await CreateClientAsAdministrator(); - await client.TestPatchAssertErrorAsync("users/user1", new UserPatchRequest { Username = "admin" }, errorCode: ErrorCodes.UserController.UsernameConflict); + await client.TestPatchAssertErrorAsync("users/user1", new HttpUserPatchRequest { Username = "admin" }, errorCode: ErrorCodes.UserController.UsernameConflict); } [Fact] public async Task Patch_NoAuth_Unauthorized() { using var client = await CreateDefaultClient(); - await client.TestPatchAssertUnauthorizedAsync("users/user1", new UserPatchRequest { Nickname = "aaa" }); + await client.TestPatchAssertUnauthorizedAsync("users/user1", new HttpUserPatchRequest { Nickname = "aaa" }); } [Fact] public async Task Patch_User_Forbid() { using var client = await CreateClientAsUser(); - await client.TestPatchAssertForbiddenAsync("users/admin", new UserPatchRequest { Nickname = "aaa" }); + await client.TestPatchAssertForbiddenAsync("users/admin", new HttpUserPatchRequest { Nickname = "aaa" }); } [Fact] public async Task Patch_Username_Forbid() { using var client = await CreateClientAsUser(); - await client.TestPatchAssertForbiddenAsync("users/user1", new UserPatchRequest { Username = "aaa" }); + await client.TestPatchAssertForbiddenAsync("users/user1", new HttpUserPatchRequest { Username = "aaa" }); } [Fact] public async Task Patch_Password_Forbid() { using var client = await CreateClientAsUser(); - await client.TestPatchAssertForbiddenAsync("users/user1", new UserPatchRequest { Password = "aaa" }); + await client.TestPatchAssertForbiddenAsync("users/user1", new HttpUserPatchRequest { Password = "aaa" }); } [Fact] @@ -214,7 +214,7 @@ namespace Timeline.Tests.IntegratedTests { using var client = await CreateClientAsAdministrator(); { - var body = await client.TestPostAsync(createUserUrl, new CreateUserRequest + var body = await client.TestPostAsync(createUserUrl, new HttpCreateUserRequest { Username = "aaa", Password = "bbb", @@ -233,15 +233,15 @@ namespace Timeline.Tests.IntegratedTests public static IEnumerable Op_CreateUser_InvalidModel_Data() { - yield return new[] { new CreateUserRequest { Username = "aaa" } }; - yield return new[] { new CreateUserRequest { Password = "bbb" } }; - yield return new[] { new CreateUserRequest { Username = "a!a", Password = "bbb" } }; - yield return new[] { new CreateUserRequest { Username = "aaa", Password = "" } }; + yield return new[] { new HttpCreateUserRequest { Username = "aaa" } }; + yield return new[] { new HttpCreateUserRequest { Password = "bbb" } }; + yield return new[] { new HttpCreateUserRequest { Username = "a!a", Password = "bbb" } }; + yield return new[] { new HttpCreateUserRequest { Username = "aaa", Password = "" } }; } [Theory] [MemberData(nameof(Op_CreateUser_InvalidModel_Data))] - public async Task Op_CreateUser_InvalidModel(CreateUserRequest body) + public async Task Op_CreateUser_InvalidModel(HttpCreateUserRequest body) { using var client = await CreateClientAsAdministrator(); await client.TestPostAssertInvalidModelAsync(createUserUrl, body); @@ -251,7 +251,7 @@ namespace Timeline.Tests.IntegratedTests public async Task Op_CreateUser_UsernameConflict() { using var client = await CreateClientAsAdministrator(); - await client.TestPostAssertErrorAsync(createUserUrl, new CreateUserRequest + await client.TestPostAssertErrorAsync(createUserUrl, new HttpCreateUserRequest { Username = "user1", Password = "bbb", @@ -262,7 +262,7 @@ namespace Timeline.Tests.IntegratedTests public async Task Op_CreateUser_NoAuth_Unauthorized() { using var client = await CreateDefaultClient(); - await client.TestPostAssertUnauthorizedAsync(createUserUrl, new CreateUserRequest + await client.TestPostAssertUnauthorizedAsync(createUserUrl, new HttpCreateUserRequest { Username = "aaa", Password = "bbb", @@ -273,7 +273,7 @@ namespace Timeline.Tests.IntegratedTests public async Task Op_CreateUser_User_Forbid() { using var client = await CreateClientAsUser(); - await client.TestPostAssertForbiddenAsync(createUserUrl, new CreateUserRequest + await client.TestPostAssertForbiddenAsync(createUserUrl, new HttpCreateUserRequest { Username = "aaa", Password = "bbb", @@ -286,8 +286,8 @@ namespace Timeline.Tests.IntegratedTests public async Task Op_ChangePassword() { using var client = await CreateClientAsUser(); - await client.TestPostAsync(changePasswordUrl, new ChangePasswordRequest { OldPassword = "user1pw", NewPassword = "newpw" }); - await client.TestPatchAssertUnauthorizedAsync("users/user1", new UserPatchRequest { }); + await client.TestPostAsync(changePasswordUrl, new HttpChangePasswordRequest { OldPassword = "user1pw", NewPassword = "newpw" }); + await client.TestPatchAssertUnauthorizedAsync("users/user1", new HttpUserPatchRequest { }); (await CreateClientWithCredential("user1", "newpw")).Dispose(); } @@ -303,21 +303,21 @@ namespace Timeline.Tests.IntegratedTests { using var client = await CreateClientAsUser(); await client.TestPostAssertInvalidModelAsync(changePasswordUrl, - new ChangePasswordRequest { OldPassword = oldPassword, NewPassword = newPassword }); + new HttpChangePasswordRequest { OldPassword = oldPassword, NewPassword = newPassword }); } [Fact] public async Task Op_ChangePassword_BadOldPassword() { using var client = await CreateClientAsUser(); - await client.TestPostAssertErrorAsync(changePasswordUrl, new ChangePasswordRequest { OldPassword = "???", NewPassword = "???" }, errorCode: ErrorCodes.UserController.ChangePassword_BadOldPassword); + await client.TestPostAssertErrorAsync(changePasswordUrl, new HttpChangePasswordRequest { OldPassword = "???", NewPassword = "???" }, errorCode: ErrorCodes.UserController.ChangePassword_BadOldPassword); } [Fact] public async Task Op_ChangePassword_NoAuth_Unauthorized() { using var client = await CreateDefaultClient(); - await client.TestPostAssertUnauthorizedAsync(changePasswordUrl, new ChangePasswordRequest { OldPassword = "???", NewPassword = "???" }); + await client.TestPostAssertUnauthorizedAsync(changePasswordUrl, new HttpChangePasswordRequest { OldPassword = "???", NewPassword = "???" }); } } } diff --git a/BackEnd/Timeline.Tests/Services/TimelineServiceTest.cs b/BackEnd/Timeline.Tests/Services/TimelineServiceTest.cs index fac0b6f3..98f03066 100644 --- a/BackEnd/Timeline.Tests/Services/TimelineServiceTest.cs +++ b/BackEnd/Timeline.Tests/Services/TimelineServiceTest.cs @@ -67,7 +67,7 @@ namespace Timeline.Tests.Services { var initTime = _clock.ForwardCurrentTime(); - void Check(Models.Timeline timeline) + void Check(TimelineInfo timeline) { timeline.NameLastModified.Should().Be(initTime); timeline.LastModified.Should().Be(_clock.GetCurrentTime()); diff --git a/BackEnd/Timeline/Controllers/TimelineController.cs b/BackEnd/Timeline/Controllers/TimelineController.cs index 0ffadc50..27b4b7a7 100644 --- a/BackEnd/Timeline/Controllers/TimelineController.cs +++ b/BackEnd/Timeline/Controllers/TimelineController.cs @@ -57,7 +57,7 @@ namespace Timeline.Controllers [HttpGet("timelines")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] - public async Task>> TimelineList([FromQuery][Username] string? relate, [FromQuery][RegularExpression("(own)|(join)")] string? relateType, [FromQuery] string? visibility) + public async Task>> TimelineList([FromQuery][Username] string? relate, [FromQuery][RegularExpression("(own)|(join)")] string? relateType, [FromQuery] string? visibility) { List? visibilityFilter = null; if (visibility != null) @@ -109,7 +109,7 @@ namespace Timeline.Controllers } var timelines = await _service.GetTimelines(relationship, visibilityFilter); - var result = _mapper.Map>(timelines); + var result = _mapper.Map>(timelines); return result; } @@ -125,7 +125,7 @@ namespace Timeline.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status304NotModified)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task> TimelineGet([FromRoute][GeneralTimelineName] string name, [FromQuery] string? checkUniqueId, [FromQuery(Name = "ifModifiedSince")] DateTime? queryIfModifiedSince, [FromHeader(Name = "If-Modified-Since")] DateTime? headerIfModifiedSince) + public async Task> TimelineGet([FromRoute][GeneralTimelineName] string name, [FromQuery] string? checkUniqueId, [FromQuery(Name = "ifModifiedSince")] DateTime? queryIfModifiedSince, [FromHeader(Name = "If-Modified-Since")] DateTime? headerIfModifiedSince) { DateTime? ifModifiedSince = null; if (queryIfModifiedSince.HasValue) @@ -166,7 +166,7 @@ namespace Timeline.Controllers else { var timeline = await _service.GetTimeline(name); - var result = _mapper.Map(timeline); + var result = _mapper.Map(timeline); return result; } } @@ -182,16 +182,16 @@ namespace Timeline.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task>> PostListGet([FromRoute][GeneralTimelineName] string name, [FromQuery] DateTime? modifiedSince, [FromQuery] bool? includeDeleted) + public async Task>> PostListGet([FromRoute][GeneralTimelineName] string name, [FromQuery] DateTime? modifiedSince, [FromQuery] bool? includeDeleted) { if (!UserHasAllTimelineManagementPermission && !await _service.HasReadPermission(name, this.GetOptionalUserId())) { return StatusCode(StatusCodes.Status403Forbidden, ErrorResponse.Common.Forbid()); } - List posts = await _postService.GetPosts(name, modifiedSince, includeDeleted ?? false); + List posts = await _postService.GetPosts(name, modifiedSince, includeDeleted ?? false); - var result = _mapper.Map>(posts); + var result = _mapper.Map>(posts); return result; } @@ -247,7 +247,7 @@ namespace Timeline.Controllers [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status403Forbidden)] - public async Task> PostPost([FromRoute][GeneralTimelineName] string name, [FromBody] TimelinePostCreateRequest body) + public async Task> PostPost([FromRoute][GeneralTimelineName] string name, [FromBody] HttpTimelinePostCreateRequest body) { var id = this.GetUserId(); if (!UserHasAllTimelineManagementPermission && !await _service.IsMemberOf(name, id)) @@ -257,7 +257,7 @@ namespace Timeline.Controllers var content = body.Content; - TimelinePost post; + TimelinePostInfo post; if (content.Type == TimelinePostContentTypes.Text) { @@ -299,7 +299,7 @@ namespace Timeline.Controllers return BadRequest(ErrorResponse.Common.CustomMessage_InvalidModel(Resources.Messages.TimelineController_ContentUnknownType)); } - var result = _mapper.Map(post); + var result = _mapper.Map(post); return result; } @@ -344,7 +344,7 @@ namespace Timeline.Controllers [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status403Forbidden)] - public async Task> TimelinePatch([FromRoute][GeneralTimelineName] string name, [FromBody] TimelinePatchRequest body) + public async Task> TimelinePatch([FromRoute][GeneralTimelineName] string name, [FromBody] HttpTimelinePatchRequest body) { if (!UserHasAllTimelineManagementPermission && !(await _service.HasManagePermission(name, this.GetUserId()))) { @@ -352,7 +352,7 @@ namespace Timeline.Controllers } await _service.ChangeProperty(name, _mapper.Map(body)); var timeline = await _service.GetTimeline(name); - var result = _mapper.Map(timeline); + var result = _mapper.Map(timeline); return result; } @@ -423,14 +423,14 @@ namespace Timeline.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] - public async Task> TimelineCreate([FromBody] TimelineCreateRequest body) + public async Task> TimelineCreate([FromBody] TimelineCreateRequest body) { var userId = this.GetUserId(); try { var timeline = await _service.CreateTimeline(body.Name, userId); - var result = _mapper.Map(timeline); + var result = _mapper.Map(timeline); return result; } catch (EntityAlreadyExistException e) when (e.EntityName == EntityNames.Timeline) @@ -474,7 +474,7 @@ namespace Timeline.Controllers [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status403Forbidden)] - public async Task> TimelineOpChangeName([FromBody] TimelineChangeNameRequest body) + public async Task> TimelineOpChangeName([FromBody] HttpTimelineChangeNameRequest body) { if (!UserHasAllTimelineManagementPermission && !(await _service.HasManagePermission(body.OldName, this.GetUserId()))) { @@ -484,7 +484,7 @@ namespace Timeline.Controllers try { var timeline = await _service.ChangeTimelineName(body.OldName, body.NewName); - return Ok(_mapper.Map(timeline)); + return Ok(_mapper.Map(timeline)); } catch (EntityAlreadyExistException) { diff --git a/BackEnd/Timeline/Controllers/TokenController.cs b/BackEnd/Timeline/Controllers/TokenController.cs index 41ec21e6..c801b8cc 100644 --- a/BackEnd/Timeline/Controllers/TokenController.cs +++ b/BackEnd/Timeline/Controllers/TokenController.cs @@ -47,7 +47,7 @@ namespace Timeline.Controllers [AllowAnonymous] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] - public async Task> Create([FromBody] CreateTokenRequest request) + public async Task> Create([FromBody] HttpCreateTokenRequest request) { void LogFailure(string reason, Exception? e = null) { @@ -71,10 +71,10 @@ namespace Timeline.Controllers ("Username", request.Username), ("Expire At", expireTime?.ToString(CultureInfo.CurrentCulture.DateTimeFormat) ?? "default") )); - return Ok(new CreateTokenResponse + return Ok(new HttpCreateTokenResponse { Token = result.Token, - User = _mapper.Map(result.User) + User = _mapper.Map(result.User) }); } catch (UserNotExistException e) @@ -97,7 +97,7 @@ namespace Timeline.Controllers [AllowAnonymous] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] - public async Task> Verify([FromBody] VerifyTokenRequest request) + public async Task> Verify([FromBody] HttpVerifyTokenRequest request) { void LogFailure(string reason, Exception? e = null, params (string, object?)[] otherProperties) { @@ -113,9 +113,9 @@ namespace Timeline.Controllers var result = await _userTokenManager.VerifyToken(request.Token); _logger.LogInformation(Log.Format(LogVerifySuccess, ("Username", result.Username), ("Token", request.Token))); - return Ok(new VerifyTokenResponse + return Ok(new HttpVerifyTokenResponse { - User = _mapper.Map(result) + User = _mapper.Map(result) }); } catch (UserTokenTimeExpireException e) diff --git a/BackEnd/Timeline/Controllers/UserController.cs b/BackEnd/Timeline/Controllers/UserController.cs index 626a116f..3727da36 100644 --- a/BackEnd/Timeline/Controllers/UserController.cs +++ b/BackEnd/Timeline/Controllers/UserController.cs @@ -42,7 +42,7 @@ namespace Timeline.Controllers _mapper = mapper; } - private UserInfo ConvertToUserInfo(User user) => _mapper.Map(user); + private HttpUser ConvertToUserInfo(UserInfo user) => _mapper.Map(user); private bool UserHasUserManagementPermission => this.UserHasPermission(UserPermission.UserManagement); @@ -52,7 +52,7 @@ namespace Timeline.Controllers /// All user list. [HttpGet("users")] [ProducesResponseType(StatusCodes.Status200OK)] - public async Task> List() + public async Task> List() { var users = await _userService.GetUsers(); var result = users.Select(u => ConvertToUserInfo(u)).ToArray(); @@ -67,7 +67,7 @@ namespace Timeline.Controllers [HttpGet("users/{username}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task> Get([FromRoute][Username] string username) + public async Task> Get([FromRoute][Username] string username) { try { @@ -94,7 +94,7 @@ namespace Timeline.Controllers [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task> Patch([FromBody] UserPatchRequest body, [FromRoute][Username] string username) + public async Task> Patch([FromBody] HttpUserPatchRequest body, [FromRoute][Username] string username) { if (UserHasUserManagementPermission) { @@ -168,7 +168,7 @@ namespace Timeline.Controllers [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status403Forbidden)] - public async Task> CreateUser([FromBody] CreateUserRequest body) + public async Task> CreateUser([FromBody] HttpCreateUserRequest body) { try { @@ -188,7 +188,7 @@ namespace Timeline.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] - public async Task ChangePassword([FromBody] ChangePasswordRequest request) + public async Task ChangePassword([FromBody] HttpChangePasswordRequest request) { try { diff --git a/BackEnd/Timeline/Models/Http/Timeline.cs b/BackEnd/Timeline/Models/Http/Timeline.cs index a81b33f5..8e3831e1 100644 --- a/BackEnd/Timeline/Models/Http/Timeline.cs +++ b/BackEnd/Timeline/Models/Http/Timeline.cs @@ -11,7 +11,7 @@ namespace Timeline.Models.Http /// /// Info of post content. /// - public class TimelinePostContentInfo + public class HttpTimelinePostContent { /// /// Type of the post content. @@ -34,7 +34,7 @@ namespace Timeline.Models.Http /// /// Info of a post. /// - public class TimelinePostInfo + public class HttpTimelinePost { /// /// Post id. @@ -43,7 +43,7 @@ namespace Timeline.Models.Http /// /// Content of the post. May be null if post is deleted. /// - public TimelinePostContentInfo? Content { get; set; } + public HttpTimelinePostContent? Content { get; set; } /// /// True if post is deleted. /// @@ -55,7 +55,7 @@ namespace Timeline.Models.Http /// /// The author. May be null if the user has been deleted. /// - public UserInfo? Author { get; set; } = default!; + public HttpUser? Author { get; set; } = default!; /// /// Last updated time. /// @@ -65,7 +65,7 @@ namespace Timeline.Models.Http /// /// Info of a timeline. /// - public class TimelineInfo + public class HttpTimeline { /// /// Unique id. @@ -90,7 +90,7 @@ namespace Timeline.Models.Http /// /// Owner of the timeline. /// - public UserInfo Owner { get; set; } = default!; + public HttpUser Owner { get; set; } = default!; /// /// Visibility of the timeline. /// @@ -99,7 +99,7 @@ namespace Timeline.Models.Http /// /// Members of timeline. /// - public List Members { get; set; } = default!; + public List Members { get; set; } = default!; #pragma warning restore CA2227 // Collection properties should be read only /// /// Create time of timeline. @@ -114,14 +114,14 @@ namespace Timeline.Models.Http /// /// Related links. /// - public TimelineInfoLinks _links { get; set; } = default!; + public HttpTimelineLinks _links { get; set; } = default!; #pragma warning restore CA1707 // Identifiers should not contain underscores } /// /// Related links for timeline. /// - public class TimelineInfoLinks + public class HttpTimelineLinks { /// /// Self. @@ -133,23 +133,23 @@ namespace Timeline.Models.Http public string Posts { get; set; } = default!; } - public class TimelineInfoLinksValueResolver : IValueResolver + public class HttpTimelineLinksValueResolver : IValueResolver { private readonly IActionContextAccessor _actionContextAccessor; private readonly IUrlHelperFactory _urlHelperFactory; - public TimelineInfoLinksValueResolver(IActionContextAccessor actionContextAccessor, IUrlHelperFactory urlHelperFactory) + public HttpTimelineLinksValueResolver(IActionContextAccessor actionContextAccessor, IUrlHelperFactory urlHelperFactory) { _actionContextAccessor = actionContextAccessor; _urlHelperFactory = urlHelperFactory; } - public TimelineInfoLinks Resolve(Timeline source, TimelineInfo destination, TimelineInfoLinks destMember, ResolutionContext context) + public HttpTimelineLinks Resolve(TimelineInfo source, HttpTimeline destination, HttpTimelineLinks destMember, ResolutionContext context) { var actionContext = _actionContextAccessor.AssertActionContextForUrlFill(); var urlHelper = _urlHelperFactory.GetUrlHelper(actionContext); - return new TimelineInfoLinks + return new HttpTimelineLinks { Self = urlHelper.ActionLink(nameof(TimelineController.TimelineGet), nameof(TimelineController)[0..^nameof(Controller).Length], new { source.Name }), Posts = urlHelper.ActionLink(nameof(TimelineController.PostListGet), nameof(TimelineController)[0..^nameof(Controller).Length], new { source.Name }) @@ -157,18 +157,18 @@ namespace Timeline.Models.Http } } - public class TimelinePostContentResolver : IValueResolver + public class HttpTimelinePostContentResolver : IValueResolver { private readonly IActionContextAccessor _actionContextAccessor; private readonly IUrlHelperFactory _urlHelperFactory; - public TimelinePostContentResolver(IActionContextAccessor actionContextAccessor, IUrlHelperFactory urlHelperFactory) + public HttpTimelinePostContentResolver(IActionContextAccessor actionContextAccessor, IUrlHelperFactory urlHelperFactory) { _actionContextAccessor = actionContextAccessor; _urlHelperFactory = urlHelperFactory; } - public TimelinePostContentInfo? Resolve(TimelinePost source, TimelinePostInfo destination, TimelinePostContentInfo? destMember, ResolutionContext context) + public HttpTimelinePostContent? Resolve(TimelinePostInfo source, HttpTimelinePost destination, HttpTimelinePostContent? destMember, ResolutionContext context) { var actionContext = _actionContextAccessor.AssertActionContextForUrlFill(); var urlHelper = _urlHelperFactory.GetUrlHelper(actionContext); @@ -182,7 +182,7 @@ namespace Timeline.Models.Http if (sourceContent is TextTimelinePostContent textContent) { - return new TimelinePostContentInfo + return new HttpTimelinePostContent { Type = TimelinePostContentTypes.Text, Text = textContent.Text @@ -190,7 +190,7 @@ namespace Timeline.Models.Http } else if (sourceContent is ImageTimelinePostContent imageContent) { - return new TimelinePostContentInfo + return new HttpTimelinePostContent { Type = TimelinePostContentTypes.Image, Url = urlHelper.ActionLink( @@ -207,13 +207,12 @@ namespace Timeline.Models.Http } } - public class TimelineInfoAutoMapperProfile : Profile + public class HttpTimelineAutoMapperProfile : Profile { - public TimelineInfoAutoMapperProfile() + public HttpTimelineAutoMapperProfile() { - CreateMap().ForMember(u => u._links, opt => opt.MapFrom()); - CreateMap().ForMember(p => p.Content, opt => opt.MapFrom()); - CreateMap(); + CreateMap().ForMember(u => u._links, opt => opt.MapFrom()); + CreateMap().ForMember(p => p.Content, opt => opt.MapFrom()); } } } diff --git a/BackEnd/Timeline/Models/Http/TimelineController.cs b/BackEnd/Timeline/Models/Http/TimelineController.cs index 7bd141ed..42a926fd 100644 --- a/BackEnd/Timeline/Models/Http/TimelineController.cs +++ b/BackEnd/Timeline/Models/Http/TimelineController.cs @@ -1,4 +1,5 @@ -using System; +using AutoMapper; +using System; using System.ComponentModel.DataAnnotations; using Timeline.Models.Validation; @@ -7,7 +8,7 @@ namespace Timeline.Models.Http /// /// Content of post create request. /// - public class TimelinePostCreateRequestContent + public class HttpTimelinePostCreateRequestContent { /// /// Type of post content. @@ -24,13 +25,13 @@ namespace Timeline.Models.Http public string? Data { get; set; } } - public class TimelinePostCreateRequest + public class HttpTimelinePostCreateRequest { /// /// Content of the new post. /// [Required] - public TimelinePostCreateRequestContent Content { get; set; } = default!; + public HttpTimelinePostCreateRequestContent Content { get; set; } = default!; /// /// Time of the post. If not set, current time will be used. @@ -54,7 +55,7 @@ namespace Timeline.Models.Http /// /// Patch timeline request model. /// - public class TimelinePatchRequest + public class HttpTimelinePatchRequest { /// /// New title. Null for not change. @@ -75,7 +76,7 @@ namespace Timeline.Models.Http /// /// Change timeline name request model. /// - public class TimelineChangeNameRequest + public class HttpTimelineChangeNameRequest { /// /// Old name of timeline. @@ -90,4 +91,12 @@ namespace Timeline.Models.Http [TimelineName] public string NewName { get; set; } = default!; } + + public class HttpTimelineControllerAutoMapperProfile : Profile + { + public HttpTimelineControllerAutoMapperProfile() + { + CreateMap(); + } + } } diff --git a/BackEnd/Timeline/Models/Http/TokenController.cs b/BackEnd/Timeline/Models/Http/TokenController.cs index a42c44e5..a5cbba14 100644 --- a/BackEnd/Timeline/Models/Http/TokenController.cs +++ b/BackEnd/Timeline/Models/Http/TokenController.cs @@ -4,9 +4,9 @@ using Timeline.Controllers; namespace Timeline.Models.Http { /// - /// Request model for . + /// Request model for . /// - public class CreateTokenRequest + public class HttpCreateTokenRequest { /// /// The username. @@ -24,9 +24,9 @@ namespace Timeline.Models.Http } /// - /// Response model for . + /// Response model for . /// - public class CreateTokenResponse + public class HttpCreateTokenResponse { /// /// The token created. @@ -35,13 +35,13 @@ namespace Timeline.Models.Http /// /// The user owning the token. /// - public UserInfo User { get; set; } = default!; + public HttpUser User { get; set; } = default!; } /// - /// Request model for . + /// Request model for . /// - public class VerifyTokenRequest + public class HttpVerifyTokenRequest { /// /// The token to verify. @@ -50,13 +50,13 @@ namespace Timeline.Models.Http } /// - /// Response model for . + /// Response model for . /// - public class VerifyTokenResponse + public class HttpVerifyTokenResponse { /// /// The user owning the token. /// - public UserInfo User { get; set; } = default!; + public HttpUser User { get; set; } = default!; } } diff --git a/BackEnd/Timeline/Models/Http/User.cs b/BackEnd/Timeline/Models/Http/User.cs new file mode 100644 index 00000000..bdb40b9f --- /dev/null +++ b/BackEnd/Timeline/Models/Http/User.cs @@ -0,0 +1,105 @@ +using AutoMapper; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Infrastructure; +using Microsoft.AspNetCore.Mvc.Routing; +using System.Collections.Generic; +using Timeline.Controllers; +using Timeline.Services; + +namespace Timeline.Models.Http +{ + /// + /// Info of a user. + /// + public class HttpUser + { + /// + /// Unique id. + /// + public string UniqueId { get; set; } = default!; + /// + /// Username. + /// + public string Username { get; set; } = default!; + /// + /// Nickname. + /// + public string Nickname { get; set; } = default!; +#pragma warning disable CA2227 // Collection properties should be read only + /// + /// The permissions of the user. + /// + public List Permissions { get; set; } = default!; +#pragma warning restore CA2227 // Collection properties should be read only +#pragma warning disable CA1707 // Identifiers should not contain underscores + /// + /// Related links. + /// + public HttpUserLinks _links { get; set; } = default!; +#pragma warning restore CA1707 // Identifiers should not contain underscores + } + + /// + /// Related links for user. + /// + public class HttpUserLinks + { + /// + /// Self. + /// + public string Self { get; set; } = default!; + /// + /// Avatar url. + /// + public string Avatar { get; set; } = default!; + /// + /// Personal timeline url. + /// + public string Timeline { get; set; } = default!; + } + + public class HttpUserPermissionsValueConverter : ITypeConverter> + { + public List Convert(UserPermissions source, List destination, ResolutionContext context) + { + return source.ToStringList(); + } + } + + public class HttpUserLinksValueResolver : IValueResolver + { + private readonly IActionContextAccessor _actionContextAccessor; + private readonly IUrlHelperFactory _urlHelperFactory; + + public HttpUserLinksValueResolver(IActionContextAccessor actionContextAccessor, IUrlHelperFactory urlHelperFactory) + { + _actionContextAccessor = actionContextAccessor; + _urlHelperFactory = urlHelperFactory; + } + + public HttpUserLinks Resolve(UserInfo source, HttpUser destination, HttpUserLinks destMember, ResolutionContext context) + { + var actionContext = _actionContextAccessor.AssertActionContextForUrlFill(); + var urlHelper = _urlHelperFactory.GetUrlHelper(actionContext); + + var result = new HttpUserLinks + { + Self = urlHelper.ActionLink(nameof(UserController.Get), nameof(UserController)[0..^nameof(Controller).Length], new { destination.Username }), + Avatar = urlHelper.ActionLink(nameof(UserAvatarController.Get), nameof(UserAvatarController)[0..^nameof(Controller).Length], new { destination.Username }), + Timeline = urlHelper.ActionLink(nameof(TimelineController.TimelineGet), nameof(TimelineController)[0..^nameof(Controller).Length], new { Name = "@" + destination.Username }) + }; + return result; + } + } + + public class HttpUserAutoMapperProfile : Profile + { + public HttpUserAutoMapperProfile() + { + CreateMap>() + .ConvertUsing(); + CreateMap() + .ForMember(u => u._links, opt => opt.MapFrom()); + } + } +} diff --git a/BackEnd/Timeline/Models/Http/UserController.cs b/BackEnd/Timeline/Models/Http/UserController.cs index 92a63874..1b4d09ec 100644 --- a/BackEnd/Timeline/Models/Http/UserController.cs +++ b/BackEnd/Timeline/Models/Http/UserController.cs @@ -7,9 +7,9 @@ using Timeline.Services; namespace Timeline.Models.Http { /// - /// Request model for . + /// Request model for . /// - public class UserPatchRequest + public class HttpUserPatchRequest { /// /// New username. Null if not change. Need to be administrator. @@ -31,9 +31,9 @@ namespace Timeline.Models.Http } /// - /// Request model for . + /// Request model for . /// - public class CreateUserRequest + public class HttpCreateUserRequest { /// /// Username of the new user. @@ -49,9 +49,9 @@ namespace Timeline.Models.Http } /// - /// Request model for . + /// Request model for . /// - public class ChangePasswordRequest + public class HttpChangePasswordRequest { /// /// Old password. @@ -66,11 +66,11 @@ namespace Timeline.Models.Http public string NewPassword { get; set; } = default!; } - public class UserControllerAutoMapperProfile : Profile + public class HttpUserControllerModelAutoMapperProfile : Profile { - public UserControllerAutoMapperProfile() + public HttpUserControllerModelAutoMapperProfile() { - CreateMap(); + CreateMap(); } } } diff --git a/BackEnd/Timeline/Models/Http/UserInfo.cs b/BackEnd/Timeline/Models/Http/UserInfo.cs deleted file mode 100644 index 0f865172..00000000 --- a/BackEnd/Timeline/Models/Http/UserInfo.cs +++ /dev/null @@ -1,105 +0,0 @@ -using AutoMapper; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Infrastructure; -using Microsoft.AspNetCore.Mvc.Routing; -using System.Collections.Generic; -using Timeline.Controllers; -using Timeline.Services; - -namespace Timeline.Models.Http -{ - /// - /// Info of a user. - /// - public class UserInfo - { - /// - /// Unique id. - /// - public string UniqueId { get; set; } = default!; - /// - /// Username. - /// - public string Username { get; set; } = default!; - /// - /// Nickname. - /// - public string Nickname { get; set; } = default!; -#pragma warning disable CA2227 // Collection properties should be read only - /// - /// The permissions of the user. - /// - public List Permissions { get; set; } = default!; -#pragma warning restore CA2227 // Collection properties should be read only -#pragma warning disable CA1707 // Identifiers should not contain underscores - /// - /// Related links. - /// - public UserInfoLinks _links { get; set; } = default!; -#pragma warning restore CA1707 // Identifiers should not contain underscores - } - - /// - /// Related links for user. - /// - public class UserInfoLinks - { - /// - /// Self. - /// - public string Self { get; set; } = default!; - /// - /// Avatar url. - /// - public string Avatar { get; set; } = default!; - /// - /// Personal timeline url. - /// - public string Timeline { get; set; } = default!; - } - - public class UserPermissionsValueConverter : ITypeConverter> - { - public List Convert(UserPermissions source, List destination, ResolutionContext context) - { - return source.ToStringList(); - } - } - - public class UserInfoLinksValueResolver : IValueResolver - { - private readonly IActionContextAccessor _actionContextAccessor; - private readonly IUrlHelperFactory _urlHelperFactory; - - public UserInfoLinksValueResolver(IActionContextAccessor actionContextAccessor, IUrlHelperFactory urlHelperFactory) - { - _actionContextAccessor = actionContextAccessor; - _urlHelperFactory = urlHelperFactory; - } - - public UserInfoLinks Resolve(User source, UserInfo destination, UserInfoLinks destMember, ResolutionContext context) - { - var actionContext = _actionContextAccessor.AssertActionContextForUrlFill(); - var urlHelper = _urlHelperFactory.GetUrlHelper(actionContext); - - var result = new UserInfoLinks - { - Self = urlHelper.ActionLink(nameof(UserController.Get), nameof(UserController)[0..^nameof(Controller).Length], new { destination.Username }), - Avatar = urlHelper.ActionLink(nameof(UserAvatarController.Get), nameof(UserAvatarController)[0..^nameof(Controller).Length], new { destination.Username }), - Timeline = urlHelper.ActionLink(nameof(TimelineController.TimelineGet), nameof(TimelineController)[0..^nameof(Controller).Length], new { Name = "@" + destination.Username }) - }; - return result; - } - } - - public class UserInfoAutoMapperProfile : Profile - { - public UserInfoAutoMapperProfile() - { - CreateMap>() - .ConvertUsing(); - CreateMap() - .ForMember(u => u._links, opt => opt.MapFrom()); - } - } -} diff --git a/BackEnd/Timeline/Models/Timeline.cs b/BackEnd/Timeline/Models/Timeline.cs deleted file mode 100644 index a5987577..00000000 --- a/BackEnd/Timeline/Models/Timeline.cs +++ /dev/null @@ -1,98 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace Timeline.Models -{ - public enum TimelineVisibility - { - /// - /// All people including those without accounts. - /// - Public, - /// - /// Only people signed in. - /// - Register, - /// - /// Only member. - /// - Private - } - - public static class TimelinePostContentTypes - { - public const string Text = "text"; - public const string Image = "image"; - } - - public interface ITimelinePostContent - { - public string Type { get; } - } - - public class TextTimelinePostContent : ITimelinePostContent - { - public TextTimelinePostContent(string text) { Text = text; } - - public string Type { get; } = TimelinePostContentTypes.Text; - public string Text { get; set; } - } - - public class ImageTimelinePostContent : ITimelinePostContent - { - public ImageTimelinePostContent(string dataTag) { DataTag = dataTag; } - - public string Type { get; } = TimelinePostContentTypes.Image; - - /// - /// The tag of the data. The tag of the entry in DataManager. Also the etag (not quoted). - /// - public string DataTag { get; set; } - } - - public class TimelinePost - { - public TimelinePost(long id, ITimelinePostContent? content, DateTime time, User? author, DateTime lastUpdated, string timelineName) - { - Id = id; - Content = content; - Time = time; - Author = author; - LastUpdated = lastUpdated; - TimelineName = timelineName; - } - - public long Id { get; set; } - public ITimelinePostContent? Content { get; set; } - public bool Deleted => Content == null; - public DateTime Time { get; set; } - public User? Author { get; set; } - public DateTime LastUpdated { get; set; } - public string TimelineName { get; set; } - } - -#pragma warning disable CA1724 // Type names should not match namespaces - public class Timeline -#pragma warning restore CA1724 // Type names should not match namespaces - { - public string UniqueID { get; set; } = default!; - public string Name { get; set; } = default!; - public DateTime NameLastModified { get; set; } = default!; - public string Title { get; set; } = default!; - public string Description { get; set; } = default!; - public User Owner { get; set; } = default!; - public TimelineVisibility Visibility { get; set; } -#pragma warning disable CA2227 // Collection properties should be read only - public List Members { get; set; } = default!; -#pragma warning restore CA2227 // Collection properties should be read only - public DateTime CreateTime { get; set; } = default!; - public DateTime LastModified { get; set; } = default!; - } - - public class TimelineChangePropertyRequest - { - public string? Title { get; set; } - public string? Description { get; set; } - public TimelineVisibility? Visibility { get; set; } - } -} diff --git a/BackEnd/Timeline/Models/TimelineInfo.cs b/BackEnd/Timeline/Models/TimelineInfo.cs new file mode 100644 index 00000000..440f6b81 --- /dev/null +++ b/BackEnd/Timeline/Models/TimelineInfo.cs @@ -0,0 +1,130 @@ +using System; +using System.Collections.Generic; + +namespace Timeline.Models +{ + public enum TimelineVisibility + { + /// + /// All people including those without accounts. + /// + Public, + /// + /// Only people signed in. + /// + Register, + /// + /// Only member. + /// + Private + } + + public static class TimelinePostContentTypes + { + public const string Text = "text"; + public const string Image = "image"; + } + + public interface ITimelinePostContent + { + public string Type { get; } + } + + public class TextTimelinePostContent : ITimelinePostContent + { + public TextTimelinePostContent(string text) { Text = text; } + + public string Type { get; } = TimelinePostContentTypes.Text; + public string Text { get; set; } + } + + public class ImageTimelinePostContent : ITimelinePostContent + { + public ImageTimelinePostContent(string dataTag) { DataTag = dataTag; } + + public string Type { get; } = TimelinePostContentTypes.Image; + + /// + /// The tag of the data. The tag of the entry in DataManager. Also the etag (not quoted). + /// + public string DataTag { get; set; } + } + + public record TimelinePostInfo + { + public TimelinePostInfo() + { + + } + + public TimelinePostInfo(long id, ITimelinePostContent? content, DateTime time, UserInfo? author, DateTime lastUpdated, string timelineName) + { + Id = id; + Content = content; + Time = time; + Author = author; + LastUpdated = lastUpdated; + TimelineName = timelineName; + } + + public long Id { get; set; } + public ITimelinePostContent? Content { get; set; } + public bool Deleted => Content == null; + public DateTime Time { get; set; } + public UserInfo? Author { get; set; } + public DateTime LastUpdated { get; set; } + public string TimelineName { get; set; } = default!; + } + + public record TimelineInfo + { + public TimelineInfo() + { + + } + + public TimelineInfo( + string uniqueId, + string name, + DateTime nameLastModified, + string title, + string description, + UserInfo owner, + TimelineVisibility visibility, + List members, + DateTime createTime, + DateTime lastModified) + { + UniqueId = uniqueId; + Name = name; + NameLastModified = nameLastModified; + Title = title; + Description = description; + Owner = owner; + Visibility = visibility; + Members = members; + CreateTime = createTime; + LastModified = lastModified; + } + + public string UniqueId { get; set; } = default!; + public string Name { get; set; } = default!; + public DateTime NameLastModified { get; set; } = default!; + public string Title { get; set; } = default!; + public string Description { get; set; } = default!; + public UserInfo Owner { get; set; } = default!; + public TimelineVisibility Visibility { get; set; } +#pragma warning disable CA2227 // Collection properties should be read only + public List Members { get; set; } = default!; +#pragma warning restore CA2227 // Collection properties should be read only + public DateTime CreateTime { get; set; } = default!; + public DateTime LastModified { get; set; } = default!; + } + + public class TimelineChangePropertyRequest + { + public string? Title { get; set; } + public string? Description { get; set; } + public TimelineVisibility? Visibility { get; set; } + } +} diff --git a/BackEnd/Timeline/Models/User.cs b/BackEnd/Timeline/Models/User.cs deleted file mode 100644 index ae2afe85..00000000 --- a/BackEnd/Timeline/Models/User.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using Timeline.Services; - -namespace Timeline.Models -{ - public record User - { - public long Id { get; set; } - public string UniqueId { get; set; } = default!; - - public string Username { get; set; } = default!; - public string Nickname { get; set; } = default!; - - public UserPermissions Permissions { get; set; } = default!; - - public DateTime UsernameChangeTime { get; set; } - public DateTime CreateTime { get; set; } - public DateTime LastModified { get; set; } - public long Version { get; set; } - } -} diff --git a/BackEnd/Timeline/Models/UserInfo.cs b/BackEnd/Timeline/Models/UserInfo.cs new file mode 100644 index 00000000..058cc590 --- /dev/null +++ b/BackEnd/Timeline/Models/UserInfo.cs @@ -0,0 +1,48 @@ +using System; +using Timeline.Services; + +namespace Timeline.Models +{ + public record UserInfo + { + public UserInfo() + { + + } + + public UserInfo( + long id, + string uniqueId, + string username, + string nickname, + UserPermissions permissions, + DateTime usernameChangeTime, + DateTime createTime, + DateTime lastModified, + long version) + { + Id = id; + UniqueId = uniqueId; + Username = username; + Nickname = nickname; + Permissions = permissions; + UsernameChangeTime = usernameChangeTime; + CreateTime = createTime; + LastModified = lastModified; + Version = version; + } + + public long Id { get; set; } + public string UniqueId { get; set; } = default!; + + public string Username { get; set; } = default!; + public string Nickname { get; set; } = default!; + + public UserPermissions Permissions { get; set; } = default!; + + public DateTime UsernameChangeTime { get; set; } + public DateTime CreateTime { get; set; } + public DateTime LastModified { get; set; } + public long Version { get; set; } + } +} diff --git a/BackEnd/Timeline/Services/HighlightTimelineService.cs b/BackEnd/Timeline/Services/HighlightTimelineService.cs index 88ad4a4b..619bc33e 100644 --- a/BackEnd/Timeline/Services/HighlightTimelineService.cs +++ b/BackEnd/Timeline/Services/HighlightTimelineService.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Timeline.Entities; +using Timeline.Models; using Timeline.Services.Exceptions; namespace Timeline.Services @@ -14,7 +15,7 @@ namespace Timeline.Services /// Get all highlight timelines. /// /// A list of all highlight timelines. - Task> GetHighlightTimelines(); + Task> GetHighlightTimelines(); /// /// Add a timeline to highlight list. @@ -73,11 +74,11 @@ namespace Timeline.Services await _database.SaveChangesAsync(); } - public async Task> GetHighlightTimelines() + public async Task> GetHighlightTimelines() { var entities = await _database.HighlightTimelines.Select(t => new { t.Id }).ToListAsync(); - var result = new List(); + var result = new List(); foreach (var entity in entities) { diff --git a/BackEnd/Timeline/Services/TimelinePostService.cs b/BackEnd/Timeline/Services/TimelinePostService.cs index a1176a68..35513a36 100644 --- a/BackEnd/Timeline/Services/TimelinePostService.cs +++ b/BackEnd/Timeline/Services/TimelinePostService.cs @@ -39,7 +39,7 @@ namespace Timeline.Services /// Thrown when timeline with name does not exist. /// If it is a personal timeline, then inner exception is . /// - Task> GetPosts(string timelineName, DateTime? modifiedSince = null, bool includeDeleted = false); + Task> GetPosts(string timelineName, DateTime? modifiedSince = null, bool includeDeleted = false); /// /// Get the etag of data of a post. @@ -90,7 +90,7 @@ namespace Timeline.Services /// If it is a personal timeline, then inner exception is . /// /// Thrown if user of does not exist. - Task CreateTextPost(string timelineName, long authorId, string text, DateTime? time); + Task CreateTextPost(string timelineName, long authorId, string text, DateTime? time); /// /// Create a new image post in timeline. @@ -108,7 +108,7 @@ namespace Timeline.Services /// /// Thrown if user of does not exist. /// Thrown if data is not a image. Validated by . - Task CreateImagePost(string timelineName, long authorId, byte[] imageData, DateTime? time); + Task CreateImagePost(string timelineName, long authorId, byte[] imageData, DateTime? time); /// /// Delete a post. @@ -179,9 +179,9 @@ namespace Timeline.Services _clock = clock; } - private async Task MapTimelinePostFromEntity(TimelinePostEntity entity, string timelineName) + private async Task MapTimelinePostFromEntity(TimelinePostEntity entity, string timelineName) { - User? author = entity.AuthorId.HasValue ? await _userService.GetUser(entity.AuthorId.Value) : null; + UserInfo? author = entity.AuthorId.HasValue ? await _userService.GetUser(entity.AuthorId.Value) : null; ITimelinePostContent? content = null; @@ -197,7 +197,7 @@ namespace Timeline.Services }; } - return new TimelinePost( + return new TimelinePostInfo( id: entity.LocalId, author: author, content: content, @@ -207,7 +207,7 @@ namespace Timeline.Services ); } - public async Task> GetPosts(string timelineName, DateTime? modifiedSince = null, bool includeDeleted = false) + public async Task> GetPosts(string timelineName, DateTime? modifiedSince = null, bool includeDeleted = false) { modifiedSince = modifiedSince?.MyToUtc(); @@ -231,7 +231,7 @@ namespace Timeline.Services var postEntities = await query.ToListAsync(); - var posts = new List(); + var posts = new List(); foreach (var entity in postEntities) { posts.Add(await MapTimelinePostFromEntity(entity, timelineName)); @@ -309,7 +309,7 @@ namespace Timeline.Services }; } - public async Task CreateTextPost(string timelineName, long authorId, string text, DateTime? time) + public async Task CreateTextPost(string timelineName, long authorId, string text, DateTime? time) { time = time?.MyToUtc(); @@ -342,7 +342,7 @@ namespace Timeline.Services await _database.SaveChangesAsync(); - return new TimelinePost( + return new TimelinePostInfo( id: postEntity.LocalId, content: new TextTimelinePostContent(text), time: finalTime, @@ -352,7 +352,7 @@ namespace Timeline.Services ); } - public async Task CreateImagePost(string timelineName, long authorId, byte[] data, DateTime? time) + public async Task CreateImagePost(string timelineName, long authorId, byte[] data, DateTime? time) { time = time?.MyToUtc(); @@ -391,7 +391,7 @@ namespace Timeline.Services _database.TimelinePosts.Add(postEntity); await _database.SaveChangesAsync(); - return new TimelinePost( + return new TimelinePostInfo( id: postEntity.LocalId, content: new ImageTimelinePostContent(tag), time: finalTime, diff --git a/BackEnd/Timeline/Services/TimelineService.cs b/BackEnd/Timeline/Services/TimelineService.cs index b8ec354a..b65b3cf4 100644 --- a/BackEnd/Timeline/Services/TimelineService.cs +++ b/BackEnd/Timeline/Services/TimelineService.cs @@ -90,7 +90,7 @@ namespace Timeline.Services /// Thrown when timeline with name does not exist. /// If it is a personal timeline, then inner exception is . /// - Task GetTimeline(string timelineName); + Task GetTimeline(string timelineName); /// /// Get timeline by id. @@ -98,7 +98,7 @@ namespace Timeline.Services /// Id of timeline. /// The timeline. /// Thrown when timeline with given id does not exist. - Task GetTimelineById(long id); + Task GetTimelineById(long id); /// /// Set the properties of a timeline. @@ -113,8 +113,6 @@ namespace Timeline.Services /// Task ChangeProperty(string timelineName, TimelineChangePropertyRequest newProperties); - - /// /// Change member of timeline. /// @@ -174,7 +172,6 @@ namespace Timeline.Services /// Task HasReadPermission(string timelineName, long? visitorId); - /// /// Verify whether a user is member of a timeline. /// @@ -202,7 +199,7 @@ namespace Timeline.Services /// /// If user with related user id does not exist, empty list will be returned. /// - Task> GetTimelines(TimelineUserRelationship? relate = null, List? visibility = null); + Task> GetTimelines(TimelineUserRelationship? relate = null, List? visibility = null); /// /// Create a timeline. @@ -214,7 +211,7 @@ namespace Timeline.Services /// Thrown when timeline name is invalid. /// Thrown when the timeline already exists. /// Thrown when the owner user does not exist. - Task CreateTimeline(string timelineName, long ownerId); + Task CreateTimeline(string timelineName, long ownerId); /// /// Delete a timeline. @@ -238,7 +235,7 @@ namespace Timeline.Services /// /// You can only change name of general timeline. /// - Task ChangeTimelineName(string oldTimelineName, string newTimelineName); + Task ChangeTimelineName(string oldTimelineName, string newTimelineName); } public class TimelineService : BasicTimelineService, ITimelineService @@ -270,11 +267,11 @@ namespace Timeline.Services } /// Remember to include Members when query. - private async Task MapTimelineFromEntity(TimelineEntity entity) + private async Task MapTimelineFromEntity(TimelineEntity entity) { var owner = await _userService.GetUser(entity.OwnerId); - var members = new List(); + var members = new List(); foreach (var memberEntity in entity.Members) { members.Add(await _userService.GetUser(memberEntity.UserId)); @@ -282,19 +279,18 @@ namespace Timeline.Services var name = entity.Name ?? ("@" + owner.Username); - return new Models.Timeline - { - UniqueID = entity.UniqueId, - Name = name, - NameLastModified = entity.NameLastModified, - Title = string.IsNullOrEmpty(entity.Title) ? name : entity.Title, - Description = entity.Description ?? "", - Owner = owner, - Visibility = entity.Visibility, - Members = members, - CreateTime = entity.CreateTime, - LastModified = entity.LastModified - }; + return new TimelineInfo( + entity.UniqueId, + name, + entity.NameLastModified, + string.IsNullOrEmpty(entity.Title) ? name : entity.Title, + entity.Description ?? "", + owner, + entity.Visibility, + members, + entity.CreateTime, + entity.LastModified + ); } public async Task GetTimelineLastModifiedTime(string timelineName) @@ -321,7 +317,7 @@ namespace Timeline.Services return timelineEntity.UniqueId; } - public async Task GetTimeline(string timelineName) + public async Task GetTimeline(string timelineName) { if (timelineName == null) throw new ArgumentNullException(nameof(timelineName)); @@ -333,7 +329,7 @@ namespace Timeline.Services return await MapTimelineFromEntity(timelineEntity); } - public async Task GetTimelineById(long id) + public async Task GetTimelineById(long id) { var timelineEntity = await _database.Timelines.Where(t => t.Id == id).Include(t => t.Members).SingleOrDefaultAsync(); @@ -522,7 +518,7 @@ namespace Timeline.Services return await _database.TimelineMembers.AnyAsync(m => m.TimelineId == timelineId && m.UserId == userId); } - public async Task> GetTimelines(TimelineUserRelationship? relate = null, List? visibility = null) + public async Task> GetTimelines(TimelineUserRelationship? relate = null, List? visibility = null) { List entities; @@ -556,7 +552,7 @@ namespace Timeline.Services } } - var result = new List(); + var result = new List(); foreach (var entity in entities) { @@ -566,7 +562,7 @@ namespace Timeline.Services return result; } - public async Task CreateTimeline(string name, long owner) + public async Task CreateTimeline(string name, long owner) { if (name == null) throw new ArgumentNullException(nameof(name)); @@ -604,7 +600,7 @@ namespace Timeline.Services await _database.SaveChangesAsync(); } - public async Task ChangeTimelineName(string oldTimelineName, string newTimelineName) + public async Task ChangeTimelineName(string oldTimelineName, string newTimelineName) { if (oldTimelineName == null) throw new ArgumentNullException(nameof(oldTimelineName)); diff --git a/BackEnd/Timeline/Services/UserCredentialService.cs b/BackEnd/Timeline/Services/UserCredentialService.cs index e5c3581b..8aeef9ef 100644 --- a/BackEnd/Timeline/Services/UserCredentialService.cs +++ b/BackEnd/Timeline/Services/UserCredentialService.cs @@ -1,12 +1,10 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using System; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Timeline.Entities; using Timeline.Helpers; -using Timeline.Models; using Timeline.Models.Validation; using Timeline.Services.Exceptions; diff --git a/BackEnd/Timeline/Services/UserService.cs b/BackEnd/Timeline/Services/UserService.cs index 9395cc52..96068e44 100644 --- a/BackEnd/Timeline/Services/UserService.cs +++ b/BackEnd/Timeline/Services/UserService.cs @@ -32,13 +32,13 @@ namespace Timeline.Services /// The id of the user. /// The user info. /// Thrown when the user with given id does not exist. - Task GetUser(long id); + Task GetUser(long id); /// /// List all users. /// /// The user info of users. - Task> GetUsers(); + Task> GetUsers(); /// /// Create a user with given info. @@ -49,7 +49,7 @@ namespace Timeline.Services /// Thrown when or is null. /// Thrown when or is of bad format. /// Thrown when a user with given username already exists. - Task CreateUser(string username, string password); + Task CreateUser(string username, string password); /// /// Modify a user. @@ -62,7 +62,7 @@ namespace Timeline.Services /// /// Version will increase if password is changed. /// - Task ModifyUser(long id, ModifyUserParams? param); + Task ModifyUser(long id, ModifyUserParams? param); } public class UserService : BasicUserService, IUserService @@ -116,26 +116,23 @@ namespace Timeline.Services throw new EntityAlreadyExistException(EntityNames.User, ExceptionUsernameConflict); } - private async Task CreateUserFromEntity(UserEntity entity) + private async Task CreateUserFromEntity(UserEntity entity) { var permission = await _userPermissionService.GetPermissionsOfUserAsync(entity.Id); - return new User - { - UniqueId = entity.UniqueId, - Username = entity.Username, - Permissions = permission, - Nickname = string.IsNullOrEmpty(entity.Nickname) ? entity.Username : entity.Nickname, - Id = entity.Id, - Version = entity.Version, - CreateTime = entity.CreateTime, - UsernameChangeTime = entity.UsernameChangeTime, - LastModified = entity.LastModified - }; + return new UserInfo( + entity.Id, + entity.UniqueId, + entity.Username, + string.IsNullOrEmpty(entity.Nickname) ? entity.Username : entity.Nickname, + permission, + entity.UsernameChangeTime, + entity.CreateTime, + entity.LastModified, + entity.Version + ); } - - - public async Task GetUser(long id) + public async Task GetUser(long id) { var user = await _databaseContext.Users.Where(u => u.Id == id).SingleOrDefaultAsync(); @@ -145,9 +142,9 @@ namespace Timeline.Services return await CreateUserFromEntity(user); } - public async Task> GetUsers() + public async Task> GetUsers() { - List result = new(); + List result = new(); foreach (var entity in await _databaseContext.Users.ToArrayAsync()) { result.Add(await CreateUserFromEntity(entity)); @@ -155,7 +152,7 @@ namespace Timeline.Services return result; } - public async Task CreateUser(string username, string password) + public async Task CreateUser(string username, string password) { if (username == null) throw new ArgumentNullException(nameof(username)); @@ -183,7 +180,7 @@ namespace Timeline.Services return await CreateUserFromEntity(newEntity); } - public async Task ModifyUser(long id, ModifyUserParams? param) + public async Task ModifyUser(long id, ModifyUserParams? param) { if (param != null) { diff --git a/BackEnd/Timeline/Services/UserTokenManager.cs b/BackEnd/Timeline/Services/UserTokenManager.cs index 831329e6..b887b987 100644 --- a/BackEnd/Timeline/Services/UserTokenManager.cs +++ b/BackEnd/Timeline/Services/UserTokenManager.cs @@ -10,7 +10,7 @@ namespace Timeline.Services public class UserTokenCreateResult { public string Token { get; set; } = default!; - public User User { get; set; } = default!; + public UserInfo User { get; set; } = default!; } public interface IUserTokenManager @@ -38,7 +38,7 @@ namespace Timeline.Services /// Thrown when the token is of bad version. /// Thrown when the token is of bad format. /// Thrown when the user specified by the token does not exist. Usually the user had been deleted after the token was issued. - public Task VerifyToken(string token); + public Task VerifyToken(string token); } public class UserTokenManager : IUserTokenManager @@ -75,7 +75,7 @@ namespace Timeline.Services } - public async Task VerifyToken(string token) + public async Task VerifyToken(string token) { if (token == null) throw new ArgumentNullException(nameof(token)); -- cgit v1.2.3