From d45f776470a7cece565a46655f286fcb06cb3a87 Mon Sep 17 00:00:00 2001 From: crupest Date: Sat, 13 Feb 2021 15:09:21 +0800 Subject: feat: Post info add editable field. --- BackEnd/Timeline/Models/Mapper/TimelineMapper.cs | 37 ++++++++++++++++++++---- 1 file changed, 32 insertions(+), 5 deletions(-) (limited to 'BackEnd/Timeline/Models/Mapper/TimelineMapper.cs') diff --git a/BackEnd/Timeline/Models/Mapper/TimelineMapper.cs b/BackEnd/Timeline/Models/Mapper/TimelineMapper.cs index 5c46fa81..191e2f70 100644 --- a/BackEnd/Timeline/Models/Mapper/TimelineMapper.cs +++ b/BackEnd/Timeline/Models/Mapper/TimelineMapper.cs @@ -16,13 +16,17 @@ namespace Timeline.Models.Mapper private readonly UserMapper _userMapper; private readonly IHighlightTimelineService _highlightTimelineService; private readonly IBookmarkTimelineService _bookmarkTimelineService; + private readonly ITimelineService _timelineService; + private readonly ITimelinePostService _timelinePostService; - public TimelineMapper(DatabaseContext database, UserMapper userMapper, IHighlightTimelineService highlightTimelineService, IBookmarkTimelineService bookmarkTimelineService) + public TimelineMapper(DatabaseContext database, UserMapper userMapper, IHighlightTimelineService highlightTimelineService, IBookmarkTimelineService bookmarkTimelineService, ITimelineService timelineService, ITimelinePostService timelinePostService) { _database = database; _userMapper = userMapper; _highlightTimelineService = highlightTimelineService; _bookmarkTimelineService = bookmarkTimelineService; + _timelineService = timelineService; + _timelinePostService = timelinePostService; } public async Task MapToHttp(TimelineEntity entity, IUrlHelper urlHelper, long? userId) @@ -64,7 +68,7 @@ namespace Timeline.Models.Mapper } - public async Task MapToHttp(TimelinePostEntity entity, string timelineName, IUrlHelper urlHelper) + public async Task MapToHttp(TimelinePostEntity entity, string timelineName, IUrlHelper urlHelper, long? userId, bool isAdministrator) { _ = timelineName; @@ -79,6 +83,22 @@ namespace Timeline.Models.Mapper author = await _userMapper.MapToHttp(entity.Author, urlHelper); } + bool editable; + + if (userId is null) + { + editable = false; + } + else if (isAdministrator) + { + editable = true; + } + else + { + editable = await _timelinePostService.HasPostModifyPermission(entity.TimelineId, entity.LocalId, userId.Value); + } + + return new HttpTimelinePost( id: entity.LocalId, dataList: dataDigestList, @@ -86,18 +106,25 @@ namespace Timeline.Models.Mapper author: author, color: entity.Color, deleted: entity.Deleted, - lastUpdated: entity.LastUpdated + lastUpdated: entity.LastUpdated, + timelineName: timelineName, + editable: editable ); } - public async Task> MapToHttp(List entities, string timelineName, IUrlHelper urlHelper) + public async Task> MapToHttp(List entities, string timelineName, IUrlHelper urlHelper, long? userId, bool isAdministrator) { var result = new List(); foreach (var entity in entities) { - result.Add(await MapToHttp(entity, timelineName, urlHelper)); + result.Add(await MapToHttp(entity, timelineName, urlHelper, userId, isAdministrator)); } return result; } + + internal Task MapToHttp(TimelinePostEntity post, string timeline, IUrlHelper url) + { + throw new System.NotImplementedException(); + } } } -- cgit v1.2.3 From 57b95cf3c53c0248355ffa46214224cdba4bf79b Mon Sep 17 00:00:00 2001 From: crupest Date: Sat, 13 Feb 2021 15:46:02 +0800 Subject: feat: Add timeline manageable. --- .../Timeline.Tests/IntegratedTests/TimelineTest.cs | 73 +++++++++++++--------- .../Controllers/BookmarkTimelineController.cs | 8 ++- .../Controllers/HighlightTimelineController.cs | 8 ++- BackEnd/Timeline/Controllers/SearchController.cs | 8 ++- BackEnd/Timeline/Controllers/TimelineController.cs | 19 ++++-- .../Timeline/Controllers/TimelinePostController.cs | 4 +- BackEnd/Timeline/Models/Http/HttpTimeline.cs | 4 +- BackEnd/Timeline/Models/Mapper/TimelineMapper.cs | 22 ++++++- 8 files changed, 105 insertions(+), 41 deletions(-) (limited to 'BackEnd/Timeline/Models/Mapper/TimelineMapper.cs') diff --git a/BackEnd/Timeline.Tests/IntegratedTests/TimelineTest.cs b/BackEnd/Timeline.Tests/IntegratedTests/TimelineTest.cs index ec9a6d83..be00b595 100644 --- a/BackEnd/Timeline.Tests/IntegratedTests/TimelineTest.cs +++ b/BackEnd/Timeline.Tests/IntegratedTests/TimelineTest.cs @@ -75,15 +75,6 @@ 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(); - { using var client = await CreateClientAsUser(); @@ -91,6 +82,34 @@ namespace Timeline.Tests.IntegratedTests await client.PutTimelineMemberAsync("t1", "user3"); await client.PatchTimelineAsync("@user1", new() { Visibility = TimelineVisibility.Public }); await client.PatchTimelineAsync("t1", new() { Visibility = TimelineVisibility.Register }); + } + + { + using var client = await CreateClientAs(2); + + await client.PutTimelineMemberAsync("@user2", "user3"); + await client.PutTimelineMemberAsync("t2", "user3"); + await client.PatchTimelineAsync("@user2", new() { Visibility = TimelineVisibility.Register }); + await client.PatchTimelineAsync("t2", new() { Visibility = TimelineVisibility.Private }); + } + + { + using var client = await CreateClientAs(3); + await client.PatchTimelineAsync("@user3", new HttpTimelinePatchRequest { Visibility = TimelineVisibility.Private }); + await client.PatchTimelineAsync("t3", new HttpTimelinePatchRequest { Visibility = TimelineVisibility.Register }); + } + + { + 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 CreateDefaultClient(); { var timeline = await client.GetTimelineAsync("@user1"); @@ -106,15 +125,6 @@ namespace Timeline.Tests.IntegratedTests testResultJoin.Add(timeline); testResultRelateRegister.Add(timeline); } - } - - { - using var client = await CreateClientAs(2); - - await client.PutTimelineMemberAsync("@user2", "user3"); - await client.PutTimelineMemberAsync("t2", "user3"); - await client.PatchTimelineAsync("@user2", new() { Visibility = TimelineVisibility.Register }); - await client.PatchTimelineAsync("t2", new() { Visibility = TimelineVisibility.Private }); { var timeline = await client.GetTimelineAsync("@user2"); @@ -129,12 +139,6 @@ namespace Timeline.Tests.IntegratedTests testResultJoin.Add(timeline); testResultJoinPrivate.Add(timeline); } - } - - { - using var client = await CreateClientAs(3); - await client.PatchTimelineAsync("@user3", new HttpTimelinePatchRequest { Visibility = TimelineVisibility.Private }); - await client.PatchTimelineAsync("t3", new HttpTimelinePatchRequest { Visibility = TimelineVisibility.Register }); { var timeline = await client.GetTimelineAsync("@user3"); @@ -149,10 +153,6 @@ namespace Timeline.Tests.IntegratedTests testResultOwn.Add(timeline); testResultRelateRegister.Add(timeline); } - } - - { - using var client = await CreateDefaultClient(); async Task TestAgainst(string url, List against) { @@ -413,5 +413,22 @@ namespace Timeline.Tests.IntegratedTests timeline.Color.Should().Be("#112233"); } } + + [Theory] + [MemberData(nameof(TimelineNameGeneratorTestData))] + public async Task Get_Manageable(TimelineNameGenerator generator) + { + { + using var client = await CreateClientAsUser(); + var timeline = await client.TestGetAsync($"timelines/{generator(1)}"); + timeline.Manageable.Should().Be(true); + } + + { + using var client = await CreateClientAs(2); + var timeline = await client.TestGetAsync($"timelines/{generator(1)}"); + timeline.Manageable.Should().Be(false); + } + } } } diff --git a/BackEnd/Timeline/Controllers/BookmarkTimelineController.cs b/BackEnd/Timeline/Controllers/BookmarkTimelineController.cs index 16793de6..e2a08dcb 100644 --- a/BackEnd/Timeline/Controllers/BookmarkTimelineController.cs +++ b/BackEnd/Timeline/Controllers/BookmarkTimelineController.cs @@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; using System.Threading.Tasks; +using Timeline.Entities; using Timeline.Models.Http; using Timeline.Models.Mapper; using Timeline.Models.Validation; @@ -28,6 +29,11 @@ namespace Timeline.Controllers _timelineMapper = timelineMapper; } + private Task> Map(List timelines) + { + return _timelineMapper.MapToHttp(timelines, Url, this.GetOptionalUserId(), this.UserHasPermission(UserPermission.AllTimelineManagement)); + } + /// /// Get bookmark list in order. /// @@ -40,7 +46,7 @@ namespace Timeline.Controllers { var ids = await _service.GetBookmarks(this.GetUserId()); var timelines = await _timelineService.GetTimelineList(ids); - return await _timelineMapper.MapToHttp(timelines, Url, this.GetOptionalUserId()); + return await Map(timelines); } /// diff --git a/BackEnd/Timeline/Controllers/HighlightTimelineController.cs b/BackEnd/Timeline/Controllers/HighlightTimelineController.cs index ea012f76..f582e74b 100644 --- a/BackEnd/Timeline/Controllers/HighlightTimelineController.cs +++ b/BackEnd/Timeline/Controllers/HighlightTimelineController.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using Timeline.Auth; +using Timeline.Entities; using Timeline.Models.Http; using Timeline.Models.Mapper; using Timeline.Models.Validation; @@ -28,6 +29,11 @@ namespace Timeline.Controllers _timelineMapper = timelineMapper; } + private Task> Map(List timelines) + { + return _timelineMapper.MapToHttp(timelines, Url, this.GetOptionalUserId(), this.UserHasPermission(UserPermission.AllTimelineManagement)); + } + /// /// Get all highlight timelines. /// @@ -38,7 +44,7 @@ namespace Timeline.Controllers { var ids = await _service.GetHighlightTimelines(); var timelines = await _timelineService.GetTimelineList(ids); - return await _timelineMapper.MapToHttp(timelines, Url, this.GetOptionalUserId()); + return await Map(timelines); } /// diff --git a/BackEnd/Timeline/Controllers/SearchController.cs b/BackEnd/Timeline/Controllers/SearchController.cs index dec876b6..b2266c18 100644 --- a/BackEnd/Timeline/Controllers/SearchController.cs +++ b/BackEnd/Timeline/Controllers/SearchController.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; +using Timeline.Entities; using Timeline.Models.Http; using Timeline.Models.Mapper; using Timeline.Services; @@ -28,6 +29,11 @@ namespace Timeline.Controllers _userMapper = userMapper; } + private Task> Map(List timelines) + { + return _timelineMapper.MapToHttp(timelines, Url, this.GetOptionalUserId(), this.UserHasPermission(UserPermission.AllTimelineManagement)); + } + /// /// Search timelines whose name or title contains query string case-insensitively. /// @@ -40,7 +46,7 @@ namespace Timeline.Controllers { var searchResult = await _service.SearchTimeline(query); var timelines = searchResult.Items.Select(i => i.Item).ToList(); - return await _timelineMapper.MapToHttp(timelines, Url, this.GetOptionalUserId()); + return await Map(timelines); } /// diff --git a/BackEnd/Timeline/Controllers/TimelineController.cs b/BackEnd/Timeline/Controllers/TimelineController.cs index 8479ca83..b20ab227 100644 --- a/BackEnd/Timeline/Controllers/TimelineController.cs +++ b/BackEnd/Timeline/Controllers/TimelineController.cs @@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Mvc; using System; using System.Collections.Generic; using System.Threading.Tasks; +using Timeline.Entities; using Timeline.Filters; using Timeline.Models; using Timeline.Models.Http; @@ -43,6 +44,16 @@ namespace Timeline.Controllers private bool UserHasAllTimelineManagementPermission => this.UserHasPermission(UserPermission.AllTimelineManagement); + private Task Map(TimelineEntity timeline) + { + return _timelineMapper.MapToHttp(timeline, Url, this.GetOptionalUserId(), UserHasAllTimelineManagementPermission); + } + + private Task> Map(List timelines) + { + return _timelineMapper.MapToHttp(timelines, Url, this.GetOptionalUserId(), UserHasAllTimelineManagementPermission); + } + /// /// List all timelines. /// @@ -102,7 +113,7 @@ namespace Timeline.Controllers } var timelines = await _service.GetTimelines(relationship, visibilityFilter); - var result = await _timelineMapper.MapToHttp(timelines, Url, this.GetOptionalUserId()); + var result = await Map(timelines); return result; } @@ -118,7 +129,7 @@ namespace Timeline.Controllers { var timelineId = await _service.GetTimelineIdByName(timeline); var t = await _service.GetTimeline(timelineId); - var result = await _timelineMapper.MapToHttp(t, Url, this.GetOptionalUserId()); + var result = await Map(t); return result; } @@ -147,7 +158,7 @@ namespace Timeline.Controllers { await _service.ChangeProperty(timelineId, _mapper.Map(body)); var t = await _service.GetTimeline(timelineId); - var result = await _timelineMapper.MapToHttp(t, Url, this.GetOptionalUserId()); + var result = await Map(t); return result; } catch (EntityAlreadyExistException) @@ -237,7 +248,7 @@ namespace Timeline.Controllers try { var timeline = await _service.CreateTimeline(body.Name, userId); - var result = await _timelineMapper.MapToHttp(timeline, Url, this.GetOptionalUserId()); + var result = await Map(timeline); return result; } catch (EntityAlreadyExistException e) when (e.EntityName == EntityNames.Timeline) diff --git a/BackEnd/Timeline/Controllers/TimelinePostController.cs b/BackEnd/Timeline/Controllers/TimelinePostController.cs index 7e3d6900..4026d551 100644 --- a/BackEnd/Timeline/Controllers/TimelinePostController.cs +++ b/BackEnd/Timeline/Controllers/TimelinePostController.cs @@ -49,9 +49,9 @@ namespace Timeline.Controllers return _timelineMapper.MapToHttp(post, timelineName, Url, this.GetOptionalUserId(), UserHasAllTimelineManagementPermission); } - private Task> Map(List post, string timelineName) + private Task> Map(List posts, string timelineName) { - return _timelineMapper.MapToHttp(post, timelineName, Url, this.GetOptionalUserId(), UserHasAllTimelineManagementPermission); + return _timelineMapper.MapToHttp(posts, timelineName, Url, this.GetOptionalUserId(), UserHasAllTimelineManagementPermission); } /// diff --git a/BackEnd/Timeline/Models/Http/HttpTimeline.cs b/BackEnd/Timeline/Models/Http/HttpTimeline.cs index 87ebf0bb..8a865f96 100644 --- a/BackEnd/Timeline/Models/Http/HttpTimeline.cs +++ b/BackEnd/Timeline/Models/Http/HttpTimeline.cs @@ -10,7 +10,7 @@ namespace Timeline.Models.Http { public HttpTimeline() { } - public HttpTimeline(string uniqueId, string title, string name, DateTime nameLastModifed, string description, HttpUser owner, TimelineVisibility visibility, List members, string? color, DateTime createTime, DateTime lastModified, bool isHighlight, bool isBookmark, HttpTimelineLinks links) + public HttpTimeline(string uniqueId, string title, string name, DateTime nameLastModifed, string description, HttpUser owner, TimelineVisibility visibility, List members, string? color, DateTime createTime, DateTime lastModified, bool isHighlight, bool isBookmark, bool manageable, HttpTimelineLinks links) { UniqueId = uniqueId; Title = title; @@ -25,6 +25,7 @@ namespace Timeline.Models.Http LastModified = lastModified; IsHighlight = isHighlight; IsBookmark = isBookmark; + Manageable = manageable; _links = links; } @@ -78,6 +79,7 @@ namespace Timeline.Models.Http public bool IsHighlight { get; set; } public bool IsBookmark { get; set; } + public bool Manageable { get; set; } #pragma warning disable CA1707 // Identifiers should not contain underscores /// diff --git a/BackEnd/Timeline/Models/Mapper/TimelineMapper.cs b/BackEnd/Timeline/Models/Mapper/TimelineMapper.cs index 191e2f70..8dfd7b8d 100644 --- a/BackEnd/Timeline/Models/Mapper/TimelineMapper.cs +++ b/BackEnd/Timeline/Models/Mapper/TimelineMapper.cs @@ -29,13 +29,28 @@ namespace Timeline.Models.Mapper _timelinePostService = timelinePostService; } - public async Task MapToHttp(TimelineEntity entity, IUrlHelper urlHelper, long? userId) + public async Task MapToHttp(TimelineEntity entity, IUrlHelper urlHelper, long? userId, bool isAdministrator) { await _database.Entry(entity).Reference(e => e.Owner).LoadAsync(); await _database.Entry(entity).Collection(e => e.Members).Query().Include(m => m.User).LoadAsync(); var timelineName = entity.Name is null ? "@" + entity.Owner.Username : entity.Name; + bool manageable; + + if (userId is null) + { + manageable = false; + } + else if (isAdministrator) + { + manageable = true; + } + else + { + manageable = await _timelineService.HasManagePermission(entity.Id, userId.Value); + } + return new HttpTimeline( uniqueId: entity.UniqueId, title: string.IsNullOrEmpty(entity.Title) ? timelineName : entity.Title, @@ -50,6 +65,7 @@ namespace Timeline.Models.Mapper lastModified: entity.LastModified, isHighlight: await _highlightTimelineService.IsHighlightTimeline(entity.Id), isBookmark: userId is not null && await _bookmarkTimelineService.IsBookmark(userId.Value, entity.Id, false, false), + manageable: manageable, links: new HttpTimelineLinks( self: urlHelper.ActionLink(nameof(TimelineController.TimelineGet), nameof(TimelineController)[0..^nameof(Controller).Length], new { timeline = timelineName }), posts: urlHelper.ActionLink(nameof(TimelinePostController.List), nameof(TimelinePostController)[0..^nameof(Controller).Length], new { timeline = timelineName }) @@ -57,12 +73,12 @@ namespace Timeline.Models.Mapper ); } - public async Task> MapToHttp(List entities, IUrlHelper urlHelper, long? userId) + public async Task> MapToHttp(List entities, IUrlHelper urlHelper, long? userId, bool isAdministrator) { var result = new List(); foreach (var entity in entities) { - result.Add(await MapToHttp(entity, urlHelper, userId)); + result.Add(await MapToHttp(entity, urlHelper, userId, isAdministrator)); } return result; } -- cgit v1.2.3 From 2d9ca08366d91c22877cee143f43a062d4efda2d Mon Sep 17 00:00:00 2001 From: crupest Date: Sat, 13 Feb 2021 15:57:29 +0800 Subject: feat: Timeline add postable. --- BackEnd/Timeline.Tests/IntegratedTests/TimelineTest.cs | 4 +++- BackEnd/Timeline/Models/Http/HttpTimeline.cs | 4 +++- BackEnd/Timeline/Models/Mapper/TimelineMapper.cs | 11 +++++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) (limited to 'BackEnd/Timeline/Models/Mapper/TimelineMapper.cs') diff --git a/BackEnd/Timeline.Tests/IntegratedTests/TimelineTest.cs b/BackEnd/Timeline.Tests/IntegratedTests/TimelineTest.cs index be00b595..e2ce8875 100644 --- a/BackEnd/Timeline.Tests/IntegratedTests/TimelineTest.cs +++ b/BackEnd/Timeline.Tests/IntegratedTests/TimelineTest.cs @@ -416,18 +416,20 @@ namespace Timeline.Tests.IntegratedTests [Theory] [MemberData(nameof(TimelineNameGeneratorTestData))] - public async Task Get_Manageable(TimelineNameGenerator generator) + public async Task Get_Manageable_Postable(TimelineNameGenerator generator) { { using var client = await CreateClientAsUser(); var timeline = await client.TestGetAsync($"timelines/{generator(1)}"); timeline.Manageable.Should().Be(true); + timeline.Postable.Should().Be(true); } { using var client = await CreateClientAs(2); var timeline = await client.TestGetAsync($"timelines/{generator(1)}"); timeline.Manageable.Should().Be(false); + timeline.Postable.Should().Be(false); } } } diff --git a/BackEnd/Timeline/Models/Http/HttpTimeline.cs b/BackEnd/Timeline/Models/Http/HttpTimeline.cs index 8a865f96..e3e46bd5 100644 --- a/BackEnd/Timeline/Models/Http/HttpTimeline.cs +++ b/BackEnd/Timeline/Models/Http/HttpTimeline.cs @@ -10,7 +10,7 @@ namespace Timeline.Models.Http { public HttpTimeline() { } - public HttpTimeline(string uniqueId, string title, string name, DateTime nameLastModifed, string description, HttpUser owner, TimelineVisibility visibility, List members, string? color, DateTime createTime, DateTime lastModified, bool isHighlight, bool isBookmark, bool manageable, HttpTimelineLinks links) + public HttpTimeline(string uniqueId, string title, string name, DateTime nameLastModifed, string description, HttpUser owner, TimelineVisibility visibility, List members, string? color, DateTime createTime, DateTime lastModified, bool isHighlight, bool isBookmark, bool manageable, bool postable, HttpTimelineLinks links) { UniqueId = uniqueId; Title = title; @@ -26,6 +26,7 @@ namespace Timeline.Models.Http IsHighlight = isHighlight; IsBookmark = isBookmark; Manageable = manageable; + Postable = postable; _links = links; } @@ -80,6 +81,7 @@ namespace Timeline.Models.Http public bool IsBookmark { get; set; } public bool Manageable { get; set; } + public bool Postable { get; set; } #pragma warning disable CA1707 // Identifiers should not contain underscores /// diff --git a/BackEnd/Timeline/Models/Mapper/TimelineMapper.cs b/BackEnd/Timeline/Models/Mapper/TimelineMapper.cs index 8dfd7b8d..e4304311 100644 --- a/BackEnd/Timeline/Models/Mapper/TimelineMapper.cs +++ b/BackEnd/Timeline/Models/Mapper/TimelineMapper.cs @@ -51,6 +51,16 @@ namespace Timeline.Models.Mapper manageable = await _timelineService.HasManagePermission(entity.Id, userId.Value); } + bool postable; + if (userId is null) + { + postable = false; + } + else + { + postable = await _timelineService.IsMemberOf(entity.Id, userId.Value); + } + return new HttpTimeline( uniqueId: entity.UniqueId, title: string.IsNullOrEmpty(entity.Title) ? timelineName : entity.Title, @@ -66,6 +76,7 @@ namespace Timeline.Models.Mapper isHighlight: await _highlightTimelineService.IsHighlightTimeline(entity.Id), isBookmark: userId is not null && await _bookmarkTimelineService.IsBookmark(userId.Value, entity.Id, false, false), manageable: manageable, + postable: postable, links: new HttpTimelineLinks( self: urlHelper.ActionLink(nameof(TimelineController.TimelineGet), nameof(TimelineController)[0..^nameof(Controller).Length], new { timeline = timelineName }), posts: urlHelper.ActionLink(nameof(TimelinePostController.List), nameof(TimelinePostController)[0..^nameof(Controller).Length], new { timeline = timelineName }) -- cgit v1.2.3