From df1ef1e21d8d889a2c9abd440039533c6a43818f Mon Sep 17 00:00:00 2001 From: crupest Date: Thu, 7 Jan 2021 16:23:20 +0800 Subject: 史诗级重构! MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BackEnd/Timeline/Services/BasicTimelineService.cs | 12 + .../Timeline/Services/BookmarkTimelineService.cs | 20 +- .../Exceptions/TimelinePostNotExistException.cs | 17 +- .../Timeline/Services/HighlightTimelineService.cs | 20 +- BackEnd/Timeline/Services/TimelinePostService.cs | 221 +++------- BackEnd/Timeline/Services/TimelineService.cs | 449 +++++++-------------- BackEnd/Timeline/Services/UserService.cs | 56 +-- BackEnd/Timeline/Services/UserTokenManager.cs | 7 +- 8 files changed, 276 insertions(+), 526 deletions(-) (limited to 'BackEnd/Timeline/Services') diff --git a/BackEnd/Timeline/Services/BasicTimelineService.cs b/BackEnd/Timeline/Services/BasicTimelineService.cs index 0d9f64a9..be500135 100644 --- a/BackEnd/Timeline/Services/BasicTimelineService.cs +++ b/BackEnd/Timeline/Services/BasicTimelineService.cs @@ -15,6 +15,13 @@ namespace Timeline.Services /// public interface IBasicTimelineService { + /// + /// Check whether a timeline with given id exists without getting full info. + /// + /// The timeline id. + /// True if exist. Otherwise false. + Task CheckExistence(long id); + /// /// Get the timeline id by name. /// @@ -67,6 +74,11 @@ namespace Timeline.Services }; } + public async Task CheckExistence(long id) + { + return await _database.Timelines.AnyAsync(t => t.Id == id); + } + public async Task GetTimelineIdByName(string timelineName) { if (timelineName == null) diff --git a/BackEnd/Timeline/Services/BookmarkTimelineService.cs b/BackEnd/Timeline/Services/BookmarkTimelineService.cs index 2ec3af62..380e1909 100644 --- a/BackEnd/Timeline/Services/BookmarkTimelineService.cs +++ b/BackEnd/Timeline/Services/BookmarkTimelineService.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Timeline.Entities; -using Timeline.Models; using Timeline.Services.Exceptions; namespace Timeline.Services @@ -30,9 +29,9 @@ namespace Timeline.Services /// Get bookmarks of a user. /// /// User id of bookmark owner. - /// Bookmarks in order. + /// Id of Bookmark timelines in order. /// Thrown when user does not exist. - Task> GetBookmarks(long userId); + Task> GetBookmarks(long userId); /// /// Add a bookmark to tail to a user. @@ -75,9 +74,9 @@ namespace Timeline.Services { private readonly DatabaseContext _database; private readonly IBasicUserService _userService; - private readonly ITimelineService _timelineService; + private readonly IBasicTimelineService _timelineService; - public BookmarkTimelineService(DatabaseContext database, IBasicUserService userService, ITimelineService timelineService) + public BookmarkTimelineService(DatabaseContext database, IBasicUserService userService, IBasicTimelineService timelineService) { _database = database; _userService = userService; @@ -109,21 +108,14 @@ namespace Timeline.Services await _database.SaveChangesAsync(); } - public async Task> GetBookmarks(long userId) + public async Task> GetBookmarks(long userId) { if (!await _userService.CheckUserExistence(userId)) throw new UserNotExistException(userId); var entities = await _database.BookmarkTimelines.Where(t => t.UserId == userId).OrderBy(t => t.Rank).Select(t => new { t.TimelineId }).ToListAsync(); - List result = new(); - - foreach (var entity in entities) - { - result.Add(await _timelineService.GetTimelineById(entity.TimelineId)); - } - - return result; + return entities.Select(e => e.TimelineId).ToList(); } public async Task MoveBookmark(long userId, string timelineName, long newPosition) diff --git a/BackEnd/Timeline/Services/Exceptions/TimelinePostNotExistException.cs b/BackEnd/Timeline/Services/Exceptions/TimelinePostNotExistException.cs index f95dd410..2a7b5b28 100644 --- a/BackEnd/Timeline/Services/Exceptions/TimelinePostNotExistException.cs +++ b/BackEnd/Timeline/Services/Exceptions/TimelinePostNotExistException.cs @@ -14,16 +14,21 @@ namespace Timeline.Services.Exceptions protected TimelinePostNotExistException( System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { } + public TimelinePostNotExistException(long? timelineId, long? postId, bool isDelete, string? message = null, Exception? inner = null) + : base(EntityNames.TimelinePost, null, MakeMessage(timelineId, postId, isDelete).AppendAdditionalMessage(message), inner) + { + TimelineId = timelineId; + PostId = postId; + IsDelete = isDelete; + } - public TimelinePostNotExistException(string? timelineName, long? id, bool isDelete, string? message = null, Exception? inner = null) : base(EntityNames.TimelinePost, null, MakeMessage(timelineName, id, isDelete).AppendAdditionalMessage(message), inner) { TimelineName = timelineName; Id = id; IsDelete = isDelete; } - - private static string MakeMessage(string? timelineName, long? id, bool isDelete) + private static string MakeMessage(long? timelineId, long? postId, bool isDelete) { - return string.Format(CultureInfo.InvariantCulture, isDelete ? Resources.Services.Exceptions.TimelinePostNotExistExceptionDeleted : Resources.Services.Exceptions.TimelinePostNotExistException, timelineName ?? "", id); + return string.Format(CultureInfo.InvariantCulture, isDelete ? Resources.Services.Exceptions.TimelinePostNotExistExceptionDeleted : Resources.Services.Exceptions.TimelinePostNotExistException, timelineId, postId); } - public string? TimelineName { get; set; } - public long? Id { get; set; } + public long? TimelineId { get; set; } + public long? PostId { get; set; } /// /// True if the post is deleted. False if the post does not exist at all. diff --git a/BackEnd/Timeline/Services/HighlightTimelineService.cs b/BackEnd/Timeline/Services/HighlightTimelineService.cs index b19efe21..d0a06fe7 100644 --- a/BackEnd/Timeline/Services/HighlightTimelineService.cs +++ b/BackEnd/Timeline/Services/HighlightTimelineService.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Timeline.Entities; -using Timeline.Models; using Timeline.Services.Exceptions; namespace Timeline.Services @@ -29,8 +28,8 @@ namespace Timeline.Services /// /// Get all highlight timelines in order. /// - /// A list of all highlight timelines. - Task> GetHighlightTimelines(); + /// Id list of all highlight timelines. + Task> GetHighlightTimelines(); /// /// Add a timeline to highlight list. @@ -75,10 +74,10 @@ namespace Timeline.Services { private readonly DatabaseContext _database; private readonly IBasicUserService _userService; - private readonly ITimelineService _timelineService; + private readonly IBasicTimelineService _timelineService; private readonly IClock _clock; - public HighlightTimelineService(DatabaseContext database, IBasicUserService userService, ITimelineService timelineService, IClock clock) + public HighlightTimelineService(DatabaseContext database, IBasicUserService userService, IBasicTimelineService timelineService, IClock clock) { _database = database; _userService = userService; @@ -106,18 +105,11 @@ namespace Timeline.Services await _database.SaveChangesAsync(); } - public async Task> GetHighlightTimelines() + public async Task> GetHighlightTimelines() { var entities = await _database.HighlightTimelines.OrderBy(t => t.Order).Select(t => new { t.TimelineId }).ToListAsync(); - var result = new List(); - - foreach (var entity in entities) - { - result.Add(await _timelineService.GetTimelineById(entity.TimelineId)); - } - - return result; + return entities.Select(e => e.TimelineId).ToList(); } public async Task RemoveHighlightTimeline(string timelineName, long? operatorId) diff --git a/BackEnd/Timeline/Services/TimelinePostService.cs b/BackEnd/Timeline/Services/TimelinePostService.cs index 35513a36..9f0fd550 100644 --- a/BackEnd/Timeline/Services/TimelinePostService.cs +++ b/BackEnd/Timeline/Services/TimelinePostService.cs @@ -29,103 +29,74 @@ namespace Timeline.Services /// /// Get all the posts in the timeline. /// - /// The name of the timeline. + /// The id of the timeline. /// The time that posts have been modified since. /// Whether include deleted posts. /// A list of all posts. - /// Thrown when is null. - /// Throw when is of bad format. - /// - /// 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); + /// Thrown when timeline does not exist. + Task> GetPosts(long timelineId, DateTime? modifiedSince = null, bool includeDeleted = false); /// /// Get the etag of data of a post. /// - /// The name of the timeline of the post. + /// The id of the timeline of the post. /// The id of the post. /// The etag of the data. - /// Thrown when is null. - /// Throw when is of bad format. - /// - /// Thrown when timeline with name does not exist. - /// If it is a personal timeline, then inner exception is . - /// + /// Thrown when timeline does not exist. /// Thrown when post of does not exist or has been deleted. /// Thrown when post has no data. - /// - Task GetPostDataETag(string timelineName, long postId); + Task GetPostDataETag(long timelineId, long postId); /// /// Get the data of a post. /// - /// The name of the timeline of the post. + /// The id of the timeline of the post. /// The id of the post. /// The etag of the data. - /// Thrown when is null. - /// Throw when is of bad format. - /// - /// Thrown when timeline with name does not exist. - /// If it is a personal timeline, then inner exception is . - /// + /// Thrown when timeline does not exist. /// Thrown when post of does not exist or has been deleted. /// Thrown when post has no data. - /// - Task GetPostData(string timelineName, long postId); + /// + Task GetPostData(long timelineId, long postId); /// /// Create a new text post in timeline. /// - /// The name of the timeline to create post against. + /// The id of the timeline to create post against. /// The author's user id. /// The content text. /// The time of the post. If null, then current time is used. /// The info of the created post. - /// Thrown when or is null. - /// Throw when is of bad format. - /// - /// Thrown when timeline with name does not exist. - /// If it is a personal timeline, then inner exception is . - /// + /// Thrown when is null. + /// Thrown when timeline does not exist. /// Thrown if user of does not exist. - Task CreateTextPost(string timelineName, long authorId, string text, DateTime? time); + Task CreateTextPost(long timelineId, long authorId, string text, DateTime? time); /// /// Create a new image post in timeline. /// - /// The name of the timeline to create post against. + /// The id of the timeline to create post against. /// The author's user id. /// The image data. /// The time of the post. If null, then use current time. /// The info of the created post. - /// Thrown when or is null. - /// Throw when is of bad format. - /// - /// Thrown when timeline with name does not exist. - /// If it is a personal timeline, then inner exception is . - /// + /// Thrown when is null. + /// Thrown when timeline does not exist. /// 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(long timelineId, long authorId, byte[] imageData, DateTime? time); /// /// Delete a post. /// - /// The name of the timeline to delete post against. + /// The id of the timeline to delete post against. /// The id of the post to delete. - /// Thrown when is null. - /// Throw when is of bad format. - /// - /// Thrown when timeline with name does not exist. - /// If it is a personal timeline, then inner exception is . - /// + /// Thrown when timeline does not exist. /// Thrown when the post with given id does not exist or is deleted already. /// - /// First use to check the permission. + /// First use to check the permission. /// - Task DeletePost(string timelineName, long postId); + Task DeletePost(long timelineId, long postId); /// /// Delete all posts of the given user. Used when delete a user. @@ -136,17 +107,12 @@ namespace Timeline.Services /// /// Verify whether a user has the permission to modify a post. /// - /// The name of the timeline. + /// The id of the timeline. /// The id of the post. /// The id of the user to check on. /// True if you want it to throw . Default false. /// True if can modify, false if can't modify. - /// Thrown when is null. - /// Throw when is of bad format. - /// - /// Thrown when timeline with name does not exist. - /// If it is a personal timeline, then inner exception is . - /// + /// Thrown when timeline does not exist. /// Thrown when the post with given id does not exist or is deleted already and is true. /// /// Unless is true, this method should return true if the post does not exist. @@ -155,7 +121,7 @@ namespace Timeline.Services /// It only checks whether he is the author of the post or the owner of the timeline. /// Return false when user with modifier id does not exist. /// - Task HasPostModifyPermission(string timelineName, long postId, long modifierId, bool throwOnPostNotExist = false); + Task HasPostModifyPermission(long timelineId, long postId, long modifierId, bool throwOnPostNotExist = false); } public class TimelinePostService : ITimelinePostService @@ -179,42 +145,18 @@ namespace Timeline.Services _clock = clock; } - private async Task MapTimelinePostFromEntity(TimelinePostEntity entity, string timelineName) + private async Task CheckTimelineExistence(long timelineId) { - UserInfo? author = entity.AuthorId.HasValue ? await _userService.GetUser(entity.AuthorId.Value) : null; - - ITimelinePostContent? content = null; - - if (entity.Content != null) - { - var type = entity.ContentType; - - content = type switch - { - TimelinePostContentTypes.Text => new TextTimelinePostContent(entity.Content), - TimelinePostContentTypes.Image => new ImageTimelinePostContent(entity.Content), - _ => throw new DatabaseCorruptedException(string.Format(CultureInfo.InvariantCulture, ExceptionDatabaseUnknownContentType, type)) - }; - } - - return new TimelinePostInfo( - id: entity.LocalId, - author: author, - content: content, - time: entity.Time, - lastUpdated: entity.LastUpdated, - timelineName: timelineName - ); + if (!await _basicTimelineService.CheckExistence(timelineId)) + throw new TimelineNotExistException(timelineId); } - public async Task> GetPosts(string timelineName, DateTime? modifiedSince = null, bool includeDeleted = false) + public async Task> GetPosts(long timelineId, DateTime? modifiedSince = null, bool includeDeleted = false) { - modifiedSince = modifiedSince?.MyToUtc(); + await CheckTimelineExistence(timelineId); - if (timelineName == null) - throw new ArgumentNullException(nameof(timelineName)); + modifiedSince = modifiedSince?.MyToUtc(); - var timelineId = await _basicTimelineService.GetTimelineIdByName(timelineName); IQueryable query = _database.TimelinePosts.Where(p => p.TimelineId == timelineId); if (!includeDeleted) @@ -229,30 +171,20 @@ namespace Timeline.Services query = query.OrderBy(p => p.Time); - var postEntities = await query.ToListAsync(); - - var posts = new List(); - foreach (var entity in postEntities) - { - posts.Add(await MapTimelinePostFromEntity(entity, timelineName)); - } - return posts; + return await query.Include(p => p.Author!.Permissions).ToListAsync(); } - public async Task GetPostDataETag(string timelineName, long postId) + public async Task GetPostDataETag(long timelineId, long postId) { - if (timelineName == null) - throw new ArgumentNullException(nameof(timelineName)); - - var timelineId = await _basicTimelineService.GetTimelineIdByName(timelineName); + await CheckTimelineExistence(timelineId); var postEntity = await _database.TimelinePosts.Where(p => p.TimelineId == timelineId && p.LocalId == postId).SingleOrDefaultAsync(); if (postEntity == null) - throw new TimelinePostNotExistException(timelineName, postId, false); + throw new TimelinePostNotExistException(timelineId, postId, false); if (postEntity.Content == null) - throw new TimelinePostNotExistException(timelineName, postId, true); + throw new TimelinePostNotExistException(timelineId, postId, true); if (postEntity.ContentType != TimelinePostContentTypes.Image) throw new TimelinePostNoDataException(ExceptionGetDataNonImagePost); @@ -262,19 +194,17 @@ namespace Timeline.Services return tag; } - public async Task GetPostData(string timelineName, long postId) + public async Task GetPostData(long timelineId, long postId) { - if (timelineName == null) - throw new ArgumentNullException(nameof(timelineName)); + await CheckTimelineExistence(timelineId); - var timelineId = await _basicTimelineService.GetTimelineIdByName(timelineName); var postEntity = await _database.TimelinePosts.Where(p => p.TimelineId == timelineId && p.LocalId == postId).SingleOrDefaultAsync(); if (postEntity == null) - throw new TimelinePostNotExistException(timelineName, postId, false); + throw new TimelinePostNotExistException(timelineId, postId, false); if (postEntity.Content == null) - throw new TimelinePostNotExistException(timelineName, postId, true); + throw new TimelinePostNotExistException(timelineId, postId, true); if (postEntity.ContentType != TimelinePostContentTypes.Image) throw new TimelinePostNoDataException(ExceptionGetDataNonImagePost); @@ -309,16 +239,15 @@ namespace Timeline.Services }; } - public async Task CreateTextPost(string timelineName, long authorId, string text, DateTime? time) + public async Task CreateTextPost(long timelineId, long authorId, string text, DateTime? time) { - time = time?.MyToUtc(); - - if (timelineName == null) - throw new ArgumentNullException(nameof(timelineName)); - if (text == null) + if (text is null) throw new ArgumentNullException(nameof(text)); - var timelineId = await _basicTimelineService.GetTimelineIdByName(timelineName); + await CheckTimelineExistence(timelineId); + + time = time?.MyToUtc(); + var timelineEntity = await _database.Timelines.Where(t => t.Id == timelineId).SingleAsync(); var author = await _userService.GetUser(authorId); @@ -341,27 +270,20 @@ namespace Timeline.Services _database.TimelinePosts.Add(postEntity); await _database.SaveChangesAsync(); + await _database.Entry(postEntity).Reference(p => p.Author).Query().Include(a => a.Permissions).LoadAsync(); - return new TimelinePostInfo( - id: postEntity.LocalId, - content: new TextTimelinePostContent(text), - time: finalTime, - author: author, - lastUpdated: currentTime, - timelineName: timelineName - ); + return postEntity; } - public async Task CreateImagePost(string timelineName, long authorId, byte[] data, DateTime? time) + public async Task CreateImagePost(long timelineId, long authorId, byte[] data, DateTime? time) { - time = time?.MyToUtc(); - - if (timelineName == null) - throw new ArgumentNullException(nameof(timelineName)); - if (data == null) + if (data is null) throw new ArgumentNullException(nameof(data)); - var timelineId = await _basicTimelineService.GetTimelineIdByName(timelineName); + await CheckTimelineExistence(timelineId); + + time = time?.MyToUtc(); + var timelineEntity = await _database.Timelines.Where(t => t.Id == timelineId).SingleAsync(); var author = await _userService.GetUser(authorId); @@ -391,30 +313,22 @@ namespace Timeline.Services _database.TimelinePosts.Add(postEntity); await _database.SaveChangesAsync(); - return new TimelinePostInfo( - id: postEntity.LocalId, - content: new ImageTimelinePostContent(tag), - time: finalTime, - author: author, - lastUpdated: currentTime, - timelineName: timelineName - ); + await _database.Entry(postEntity).Reference(p => p.Author).Query().Include(a => a.Permissions).LoadAsync(); + + return postEntity; } - public async Task DeletePost(string timelineName, long id) + public async Task DeletePost(long timelineId, long postId) { - if (timelineName == null) - throw new ArgumentNullException(nameof(timelineName)); - - var timelineId = await _basicTimelineService.GetTimelineIdByName(timelineName); + await CheckTimelineExistence(timelineId); - var post = await _database.TimelinePosts.Where(p => p.TimelineId == timelineId && p.LocalId == id).SingleOrDefaultAsync(); + var post = await _database.TimelinePosts.Where(p => p.TimelineId == timelineId && p.LocalId == postId).SingleOrDefaultAsync(); if (post == null) - throw new TimelinePostNotExistException(timelineName, id, false); + throw new TimelinePostNotExistException(timelineId, postId, false); if (post.Content == null) - throw new TimelinePostNotExistException(timelineName, id, true); + throw new TimelinePostNotExistException(timelineId, postId, true); string? dataTag = null; @@ -463,12 +377,9 @@ namespace Timeline.Services } } - public async Task HasPostModifyPermission(string timelineName, long postId, long modifierId, bool throwOnPostNotExist = false) + public async Task HasPostModifyPermission(long timelineId, long postId, long modifierId, bool throwOnPostNotExist = false) { - if (timelineName == null) - throw new ArgumentNullException(nameof(timelineName)); - - var timelineId = await _basicTimelineService.GetTimelineIdByName(timelineName); + await CheckTimelineExistence(timelineId); var timelineEntity = await _database.Timelines.Where(t => t.Id == timelineId).Select(t => new { t.OwnerId }).SingleAsync(); @@ -477,14 +388,14 @@ namespace Timeline.Services if (postEntity == null) { if (throwOnPostNotExist) - throw new TimelinePostNotExistException(timelineName, postId, false); + throw new TimelinePostNotExistException(timelineId, postId, false); else return true; } if (postEntity.Content == null && throwOnPostNotExist) { - throw new TimelinePostNotExistException(timelineName, postId, true); + throw new TimelinePostNotExistException(timelineId, postId, true); } return timelineEntity.OwnerId == modifierId || postEntity.AuthorId == modifierId; diff --git a/BackEnd/Timeline/Services/TimelineService.cs b/BackEnd/Timeline/Services/TimelineService.cs index b65b3cf4..e310951a 100644 --- a/BackEnd/Timeline/Services/TimelineService.cs +++ b/BackEnd/Timeline/Services/TimelineService.cs @@ -1,7 +1,6 @@ using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; -using System.Globalization; using System.Linq; using System.Threading.Tasks; using Timeline.Entities; @@ -19,7 +18,7 @@ namespace Timeline.Services if (name.StartsWith("@", StringComparison.OrdinalIgnoreCase)) { isPersonal = true; - return name.Substring(1); + return name[1..]; } else { @@ -48,6 +47,13 @@ namespace Timeline.Services public long UserId { get; set; } } + public class TimelineChangePropertyParams + { + public string? Title { get; set; } + public string? Description { get; set; } + public TimelineVisibility? Visibility { get; set; } + } + /// /// This define the interface of both personal timeline and ordinary timeline. /// @@ -56,139 +62,94 @@ namespace Timeline.Services /// /// Get the timeline last modified time (not include name change). /// - /// The name of the timeline. - /// The timeline info. - /// Thrown when is null. - /// Throw when is of bad format. - /// - /// Thrown when timeline with name does not exist. - /// If it is a personal timeline, then inner exception is . - /// - Task GetTimelineLastModifiedTime(string timelineName); + /// The id of the timeline. + /// The timeline modified time. + /// Thrown when timeline does not exist. + Task GetTimelineLastModifiedTime(long id); /// /// Get the timeline unique id. /// - /// The name of the timeline. - /// The timeline info. - /// Thrown when is null. - /// Throw when is of bad format. - /// - /// Thrown when timeline with name does not exist. - /// If it is a personal timeline, then inner exception is . - /// - Task GetTimelineUniqueId(string timelineName); + /// The id of the timeline. + /// The timeline unique id. + /// Thrown when timeline does not exist. + Task GetTimelineUniqueId(long id); /// /// Get the timeline info. /// - /// The name of the timeline. + /// Id of timeline. /// The timeline info. - /// Thrown when is null. - /// Throw when is of bad format. - /// - /// Thrown when timeline with name does not exist. - /// If it is a personal timeline, then inner exception is . - /// - Task GetTimeline(string timelineName); + /// Thrown when timeline does not exist. + Task GetTimeline(long id); /// - /// Get timeline by id. + /// Set the properties of a timeline. /// - /// Id of timeline. - /// The timeline. + /// The id of the timeline. + /// The new properties. Null member means not to change. + /// Thrown when is null. /// Thrown when timeline with given id does not exist. - Task GetTimelineById(long id); + Task ChangeProperty(long id, TimelineChangePropertyParams newProperties); /// - /// Set the properties of a timeline. + /// Add a member to timeline. /// - /// The name of the timeline. - /// The new properties. Null member means not to change. - /// Thrown when or is null. - /// Throw when is of bad format. - /// - /// Thrown when timeline with name does not exist. - /// If it is a personal timeline, then inner exception is . - /// - Task ChangeProperty(string timelineName, TimelineChangePropertyRequest newProperties); + /// Timeline id. + /// User id. + /// True if the memeber was added. False if it is already a member. + /// Thrown when timeline does not exist. + /// Thrown when the user does not exist. + Task AddMember(long timelineId, long userId); /// - /// Change member of timeline. + /// Remove a member from timeline. /// - /// The name of the timeline. - /// A list of usernames of members to add. May be null. - /// A list of usernames of members to remove. May be null. - /// Thrown when is null. - /// Throw when is of bad format. - /// - /// Thrown when timeline with name does not exist. - /// If it is a personal timeline, then inner exception is . - /// - /// Thrown when names in or is not a valid username. - /// Thrown when one of the user to change does not exist. - /// - /// Operating on a username that is of bad format or does not exist always throws. - /// Add a user that already is a member has no effects. - /// Remove a user that is not a member also has not effects. - /// Add and remove an identical user results in no effects. - /// More than one same usernames are regarded as one. - /// - Task ChangeMember(string timelineName, IList? membersToAdd, IList? membersToRemove); + /// Timeline id. + /// User id. + /// True if the memeber was removed. False if it was not a member before. + /// Thrown when timeline does not exist. + /// Thrown when the user does not exist. + Task RemoveMember(long timelineId, long userId); /// /// Check whether a user can manage(change timeline info, member, ...) a timeline. /// - /// The name of the timeline. + /// The id of the timeline. /// The id of the user to check on. /// True if the user can manage the timeline, otherwise false. - /// Thrown when is null. - /// Throw when is of bad format. - /// - /// Thrown when timeline with name does not exist. - /// If it is a personal timeline, then inner exception is . - /// + /// Thrown when timeline does not exist. /// /// This method does not check whether visitor is administrator. /// Return false if user with user id does not exist. /// - Task HasManagePermission(string timelineName, long userId); + Task HasManagePermission(long timelineId, long userId); /// /// Verify whether a visitor has the permission to read a timeline. /// - /// The name of the timeline. + /// The id of the timeline. /// The id of the user to check on. Null means visitor without account. /// True if can read, false if can't read. - /// Thrown when is null. - /// Throw when is of bad format. - /// - /// Thrown when timeline with name does not exist. - /// If it is a personal timeline, then inner exception is . - /// + /// Thrown when timeline does not exist. /// /// This method does not check whether visitor is administrator. /// Return false if user with visitor id does not exist. /// - Task HasReadPermission(string timelineName, long? visitorId); + Task HasReadPermission(long timelineId, long? visitorId); /// /// Verify whether a user is member of a timeline. /// - /// The name of the timeline. + /// The id of the timeline. /// The id of user to check on. /// True if it is a member, false if not. - /// Thrown when is null. - /// Throw when is of bad format. - /// - /// Thrown when timeline with name does not exist. - /// If it is a personal timeline, then inner exception is . - /// + /// Thrown when timeline does not exist. /// /// Timeline owner is also considered as a member. /// Return false when user with user id does not exist. /// - Task IsMemberOf(string timelineName, long userId); + Task IsMemberOf(long timelineId, long userId); /// /// Get all timelines including personal and ordinary timelines. @@ -199,7 +160,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. @@ -211,36 +172,33 @@ 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. /// - /// The name of the timeline to delete. - /// Thrown when is null. - /// Thrown when timeline name is invalid. + /// The id of the timeline to delete. /// Thrown when the timeline does not exist. - Task DeleteTimeline(string timelineName); + Task DeleteTimeline(long id); /// /// Change name of a timeline. /// - /// The old timeline name. + /// The timeline id. /// The new timeline name. - /// The new timeline info. - /// Thrown when or is null. - /// Thrown when or is of invalid format. + /// Thrown when is null. + /// Thrown when is of invalid format. /// Thrown when timeline does not exist. /// Thrown when a timeline with new name already exists. /// /// You can only change name of general timeline. /// - Task ChangeTimelineName(string oldTimelineName, string newTimelineName); + Task ChangeTimelineName(long id, string newTimelineName); } public class TimelineService : BasicTimelineService, ITimelineService { - public TimelineService(DatabaseContext database, IUserService userService, IClock clock) + public TimelineService(DatabaseContext database, IBasicUserService userService, IClock clock) : base(database, userService, clock) { _database = database; @@ -250,12 +208,10 @@ namespace Timeline.Services private readonly DatabaseContext _database; - private readonly IUserService _userService; + private readonly IBasicUserService _userService; private readonly IClock _clock; - private readonly UsernameValidator _usernameValidator = new UsernameValidator(); - private readonly TimelineNameValidator _timelineNameValidator = new TimelineNameValidator(); private void ValidateTimelineName(string name, string paramName) @@ -266,230 +222,138 @@ namespace Timeline.Services } } - /// Remember to include Members when query. - private async Task MapTimelineFromEntity(TimelineEntity entity) + public async Task GetTimelineLastModifiedTime(long id) { - var owner = await _userService.GetUser(entity.OwnerId); + var entity = await _database.Timelines.Where(t => t.Id == id).Select(t => new { t.LastModified }).SingleOrDefaultAsync(); - var members = new List(); - foreach (var memberEntity in entity.Members) - { - members.Add(await _userService.GetUser(memberEntity.UserId)); - } - - var name = entity.Name ?? ("@" + owner.Username); - - 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) - { - if (timelineName == null) - throw new ArgumentNullException(nameof(timelineName)); - - var timelineId = await GetTimelineIdByName(timelineName); - - var timelineEntity = await _database.Timelines.Where(t => t.Id == timelineId).Select(t => new { t.LastModified }).SingleAsync(); - - return timelineEntity.LastModified; - } - - public async Task GetTimelineUniqueId(string timelineName) - { - if (timelineName == null) - throw new ArgumentNullException(nameof(timelineName)); - - var timelineId = await GetTimelineIdByName(timelineName); - - var timelineEntity = await _database.Timelines.Where(t => t.Id == timelineId).Select(t => new { t.UniqueId }).SingleAsync(); + if (entity is null) + throw new TimelineNotExistException(id); - return timelineEntity.UniqueId; + return entity.LastModified; } - public async Task GetTimeline(string timelineName) + public async Task GetTimelineUniqueId(long id) { - if (timelineName == null) - throw new ArgumentNullException(nameof(timelineName)); - - var timelineId = await GetTimelineIdByName(timelineName); + var entity = await _database.Timelines.Where(t => t.Id == id).Select(t => new { t.UniqueId }).SingleOrDefaultAsync(); - var timelineEntity = await _database.Timelines.Where(t => t.Id == timelineId).Include(t => t.Members).SingleAsync(); + if (entity is null) + throw new TimelineNotExistException(id); - return await MapTimelineFromEntity(timelineEntity); + return entity.UniqueId; } - public async Task GetTimelineById(long id) + public async Task GetTimeline(long id) { - var timelineEntity = await _database.Timelines.Where(t => t.Id == id).Include(t => t.Members).SingleOrDefaultAsync(); + var entity = await _database.Timelines.Where(t => t.Id == id).Include(t => t.Owner).ThenInclude(o => o.Permissions).Include(t => t.Members).ThenInclude(m => m.User).ThenInclude(u => u.Permissions).SingleOrDefaultAsync(); - if (timelineEntity is null) + if (entity is null) throw new TimelineNotExistException(id); - return await MapTimelineFromEntity(timelineEntity); + return entity; } - public async Task ChangeProperty(string timelineName, TimelineChangePropertyRequest newProperties) + public async Task ChangeProperty(long id, TimelineChangePropertyParams newProperties) { - if (timelineName == null) - throw new ArgumentNullException(nameof(timelineName)); - if (newProperties == null) + if (newProperties is null) throw new ArgumentNullException(nameof(newProperties)); - var timelineId = await GetTimelineIdByName(timelineName); + var entity = await _database.Timelines.Where(t => t.Id == id).SingleOrDefaultAsync(); - var timelineEntity = await _database.Timelines.Where(t => t.Id == timelineId).SingleAsync(); + if (entity is null) + throw new TimelineNotExistException(id); var changed = false; if (newProperties.Title != null) { changed = true; - timelineEntity.Title = newProperties.Title; + entity.Title = newProperties.Title; } if (newProperties.Description != null) { changed = true; - timelineEntity.Description = newProperties.Description; + entity.Description = newProperties.Description; } if (newProperties.Visibility.HasValue) { changed = true; - timelineEntity.Visibility = newProperties.Visibility.Value; + entity.Visibility = newProperties.Visibility.Value; } if (changed) { var currentTime = _clock.GetCurrentTime(); - timelineEntity.LastModified = currentTime; + entity.LastModified = currentTime; } await _database.SaveChangesAsync(); } - public async Task ChangeMember(string timelineName, IList? add, IList? remove) + public async Task AddMember(long timelineId, long userId) { - if (timelineName == null) - throw new ArgumentNullException(nameof(timelineName)); + if (!await CheckExistence(timelineId)) + throw new TimelineNotExistException(timelineId); - List? RemoveDuplicateAndCheckFormat(IList? list, string paramName) - { - if (list != null) - { - List result = new List(); - var count = list.Count; - for (var index = 0; index < count; index++) - { - var username = list[index]; - if (result.Contains(username)) - { - continue; - } - var (validationResult, message) = _usernameValidator.Validate(username); - if (!validationResult) - throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, ExceptionChangeMemberUsernameBadFormat, index), nameof(paramName)); - result.Add(username); - } - return result; - } - else - { - return null; - } - } - var simplifiedAdd = RemoveDuplicateAndCheckFormat(add, nameof(add)); - var simplifiedRemove = RemoveDuplicateAndCheckFormat(remove, nameof(remove)); + if (!await _userService.CheckUserExistence(userId)) + throw new UserNotExistException(userId); - // remove those both in add and remove - if (simplifiedAdd != null && simplifiedRemove != null) - { - var usersToClean = simplifiedRemove.Where(u => simplifiedAdd.Contains(u)).ToList(); - foreach (var u in usersToClean) - { - simplifiedAdd.Remove(u); - simplifiedRemove.Remove(u); - } + if (await _database.TimelineMembers.AnyAsync(m => m.TimelineId == timelineId && m.UserId == userId)) + return false; - if (simplifiedAdd.Count == 0) - simplifiedAdd = null; - if (simplifiedRemove.Count == 0) - simplifiedRemove = null; - } + var entity = new TimelineMemberEntity { UserId = userId, TimelineId = timelineId }; + _database.TimelineMembers.Add(entity); - if (simplifiedAdd == null && simplifiedRemove == null) - return; + var timelineEntity = await _database.Timelines.Where(t => t.Id == timelineId).SingleAsync(); + timelineEntity.LastModified = _clock.GetCurrentTime(); - var timelineId = await GetTimelineIdByName(timelineName); + await _database.SaveChangesAsync(); + return true; + } - async Task?> CheckExistenceAndGetId(List? list) - { - if (list == null) - return null; + public async Task RemoveMember(long timelineId, long userId) + { + if (!await CheckExistence(timelineId)) + throw new TimelineNotExistException(timelineId); - List result = new List(); - foreach (var username in list) - { - result.Add(await _userService.GetUserIdByUsername(username)); - } - return result; - } - var userIdsAdd = await CheckExistenceAndGetId(simplifiedAdd); - var userIdsRemove = await CheckExistenceAndGetId(simplifiedRemove); + if (!await _userService.CheckUserExistence(userId)) + throw new UserNotExistException(userId); - if (userIdsAdd != null) - { - var membersToAdd = userIdsAdd.Select(id => new TimelineMemberEntity { UserId = id, TimelineId = timelineId }).ToList(); - _database.TimelineMembers.AddRange(membersToAdd); - } + var entity = await _database.TimelineMembers.SingleOrDefaultAsync(m => m.TimelineId == timelineId && m.UserId == userId); + if (entity is null) return false; - if (userIdsRemove != null) - { - var membersToRemove = await _database.TimelineMembers.Where(m => m.TimelineId == timelineId && userIdsRemove.Contains(m.UserId)).ToListAsync(); - _database.TimelineMembers.RemoveRange(membersToRemove); - } + _database.TimelineMembers.Remove(entity); var timelineEntity = await _database.Timelines.Where(t => t.Id == timelineId).SingleAsync(); timelineEntity.LastModified = _clock.GetCurrentTime(); await _database.SaveChangesAsync(); + return true; } - public async Task HasManagePermission(string timelineName, long userId) + public async Task HasManagePermission(long timelineId, long userId) { - if (timelineName == null) - throw new ArgumentNullException(nameof(timelineName)); + var entity = await _database.Timelines.Where(t => t.Id == timelineId).Select(t => new { t.OwnerId }).SingleOrDefaultAsync(); - var timelineId = await GetTimelineIdByName(timelineName); - var timelineEntity = await _database.Timelines.Where(t => t.Id == timelineId).Select(t => new { t.OwnerId }).SingleAsync(); + if (entity is null) + throw new TimelineNotExistException(timelineId); - return userId == timelineEntity.OwnerId; + return entity.OwnerId == userId; } - public async Task HasReadPermission(string timelineName, long? visitorId) + public async Task HasReadPermission(long timelineId, long? visitorId) { - if (timelineName == null) - throw new ArgumentNullException(nameof(timelineName)); + var entity = await _database.Timelines.Where(t => t.Id == timelineId).Select(t => new { t.Visibility }).SingleOrDefaultAsync(); - var timelineId = await GetTimelineIdByName(timelineName); - var timelineEntity = await _database.Timelines.Where(t => t.Id == timelineId).Select(t => new { t.Visibility }).SingleAsync(); + if (entity is null) + throw new TimelineNotExistException(timelineId); - if (timelineEntity.Visibility == TimelineVisibility.Public) + if (entity.Visibility == TimelineVisibility.Public) return true; - if (timelineEntity.Visibility == TimelineVisibility.Register && visitorId != null) + if (entity.Visibility == TimelineVisibility.Register && visitorId != null) return true; if (visitorId == null) @@ -499,26 +363,24 @@ namespace Timeline.Services else { var memberEntity = await _database.TimelineMembers.Where(m => m.UserId == visitorId && m.TimelineId == timelineId).SingleOrDefaultAsync(); - return memberEntity != null; + return memberEntity is not null; } } - public async Task IsMemberOf(string timelineName, long userId) + public async Task IsMemberOf(long timelineId, long userId) { - if (timelineName == null) - throw new ArgumentNullException(nameof(timelineName)); - - var timelineId = await GetTimelineIdByName(timelineName); + var entity = await _database.Timelines.Where(t => t.Id == timelineId).Select(t => new { t.OwnerId }).SingleOrDefaultAsync(); - var timelineEntity = await _database.Timelines.Where(t => t.Id == timelineId).Select(t => new { t.OwnerId }).SingleAsync(); + if (entity is null) + throw new TimelineNotExistException(timelineId); - if (userId == timelineEntity.OwnerId) + if (userId == entity.OwnerId) return true; 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; @@ -535,7 +397,7 @@ namespace Timeline.Services if (relate == null) { - entities = await ApplyTimelineVisibilityFilter(_database.Timelines).Include(t => t.Members).ToListAsync(); + entities = await ApplyTimelineVisibilityFilter(_database.Timelines).Include(t => t.Owner).ThenInclude(o => o.Permissions).Include(t => t.Members).ThenInclude(m => m.User).ThenInclude(u => u.Permissions).ToListAsync(); } else { @@ -543,80 +405,66 @@ namespace Timeline.Services if ((relate.Type & TimelineUserRelationshipType.Own) != 0) { - entities.AddRange(await ApplyTimelineVisibilityFilter(_database.Timelines.Where(t => t.OwnerId == relate.UserId)).Include(t => t.Members).ToListAsync()); + entities.AddRange(await ApplyTimelineVisibilityFilter(_database.Timelines.Where(t => t.OwnerId == relate.UserId)).Include(t => t.Owner).ThenInclude(o => o.Permissions).Include(t => t.Members).ThenInclude(m => m.User).ThenInclude(u => u.Permissions).ToListAsync()); } if ((relate.Type & TimelineUserRelationshipType.Join) != 0) { - entities.AddRange(await ApplyTimelineVisibilityFilter(_database.TimelineMembers.Where(m => m.UserId == relate.UserId).Include(m => m.Timeline).ThenInclude(t => t.Members).Select(m => m.Timeline)).ToListAsync()); + entities.AddRange(await ApplyTimelineVisibilityFilter(_database.TimelineMembers.Where(m => m.UserId == relate.UserId).Include(m => m.Timeline).ThenInclude(t => t.Members).ThenInclude(m => m.User).ThenInclude(u => u.Permissions).Include(t => t.Timeline.Owner.Permissions).Select(m => m.Timeline)).ToListAsync()); } } - var result = new List(); - foreach (var entity in entities) - { - result.Add(await MapTimelineFromEntity(entity)); - } - - return result; + return entities; } - public async Task CreateTimeline(string name, long owner) + public async Task CreateTimeline(string name, long owner) { if (name == null) throw new ArgumentNullException(nameof(name)); ValidateTimelineName(name, nameof(name)); - var user = await _userService.GetUser(owner); - var conflict = await _database.Timelines.AnyAsync(t => t.Name == name); if (conflict) throw new EntityAlreadyExistException(EntityNames.Timeline, null, ExceptionTimelineNameConflict); - var newEntity = CreateNewTimelineEntity(name, user.Id); + var entity = CreateNewTimelineEntity(name, owner); - _database.Timelines.Add(newEntity); + _database.Timelines.Add(entity); await _database.SaveChangesAsync(); - return await MapTimelineFromEntity(newEntity); + await _database.Entry(entity).Reference(e => e.Owner).Query().Include(o => o.Permissions).LoadAsync(); + await _database.Entry(entity).Collection(e => e.Members).Query().Include(m => m.User).ThenInclude(u => u.Permissions).LoadAsync(); + + return entity; } - public async Task DeleteTimeline(string name) + public async Task DeleteTimeline(long id) { - if (name == null) - throw new ArgumentNullException(nameof(name)); - - ValidateTimelineName(name, nameof(name)); + var entity = await _database.Timelines.Where(t => t.Id == id).SingleOrDefaultAsync(); - var entity = await _database.Timelines.Where(t => t.Name == name).SingleOrDefaultAsync(); - - if (entity == null) - throw new TimelineNotExistException(name); + if (entity is null) + throw new TimelineNotExistException(id); _database.Timelines.Remove(entity); await _database.SaveChangesAsync(); } - public async Task ChangeTimelineName(string oldTimelineName, string newTimelineName) + public async Task ChangeTimelineName(long id, string newTimelineName) { - if (oldTimelineName == null) - throw new ArgumentNullException(nameof(oldTimelineName)); if (newTimelineName == null) throw new ArgumentNullException(nameof(newTimelineName)); - ValidateTimelineName(oldTimelineName, nameof(oldTimelineName)); ValidateTimelineName(newTimelineName, nameof(newTimelineName)); - var entity = await _database.Timelines.Include(t => t.Members).Where(t => t.Name == oldTimelineName).SingleOrDefaultAsync(); + var entity = await _database.Timelines.Where(t => t.Id == id).SingleOrDefaultAsync(); - if (entity == null) - throw new TimelineNotExistException(oldTimelineName); + if (entity is null) + throw new TimelineNotExistException(id); - if (oldTimelineName == newTimelineName) - return await MapTimelineFromEntity(entity); + if (entity.Name == newTimelineName) return; var conflict = await _database.Timelines.AnyAsync(t => t.Name == newTimelineName); @@ -630,8 +478,19 @@ namespace Timeline.Services entity.LastModified = now; await _database.SaveChangesAsync(); + } + } - return await MapTimelineFromEntity(entity); + public static class TimelineServiceExtensions + { + public static async Task> GetTimelineList(this ITimelineService service, IEnumerable ids) + { + var timelines = new List(); + foreach (var id in ids) + { + timelines.Add(await service.GetTimeline(id)); + } + return timelines; } } } diff --git a/BackEnd/Timeline/Services/UserService.cs b/BackEnd/Timeline/Services/UserService.cs index c99e86b0..d341759c 100644 --- a/BackEnd/Timeline/Services/UserService.cs +++ b/BackEnd/Timeline/Services/UserService.cs @@ -7,7 +7,6 @@ using System.Linq; using System.Threading.Tasks; using Timeline.Entities; using Timeline.Helpers; -using Timeline.Models; using Timeline.Models.Validation; using Timeline.Services.Exceptions; using static Timeline.Resources.Services.UserService; @@ -32,13 +31,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 +48,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 +61,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 @@ -73,17 +72,15 @@ namespace Timeline.Services private readonly DatabaseContext _databaseContext; private readonly IPasswordService _passwordService; - private readonly IUserPermissionService _userPermissionService; private readonly UsernameValidator _usernameValidator = new UsernameValidator(); private readonly NicknameValidator _nicknameValidator = new NicknameValidator(); - public UserService(ILogger logger, DatabaseContext databaseContext, IPasswordService passwordService, IUserPermissionService userPermissionService, IClock clock) : base(databaseContext) + public UserService(ILogger logger, DatabaseContext databaseContext, IPasswordService passwordService, IClock clock) : base(databaseContext) { _logger = logger; _databaseContext = databaseContext; _passwordService = passwordService; - _userPermissionService = userPermissionService; _clock = clock; } @@ -116,43 +113,22 @@ namespace Timeline.Services throw new EntityAlreadyExistException(EntityNames.User, ExceptionUsernameConflict); } - private async Task CreateUserFromEntity(UserEntity entity) + public async Task GetUser(long id) { - var permission = await _userPermissionService.GetPermissionsOfUserAsync(entity.Id); - 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) - { - var user = await _databaseContext.Users.Where(u => u.Id == id).SingleOrDefaultAsync(); + var user = await _databaseContext.Users.Where(u => u.Id == id).Include(u => u.Permissions).SingleOrDefaultAsync(); if (user == null) throw new UserNotExistException(id); - return await CreateUserFromEntity(user); + return user; } - public async Task> GetUsers() + public async Task> GetUsers() { - List result = new(); - foreach (var entity in await _databaseContext.Users.ToArrayAsync()) - { - result.Add(await CreateUserFromEntity(entity)); - } - return result; + return await _databaseContext.Users.Include(u => u.Permissions).ToListAsync(); } - public async Task CreateUser(string username, string password) + public async Task CreateUser(string username, string password) { if (username == null) throw new ArgumentNullException(nameof(username)); @@ -177,10 +153,12 @@ namespace Timeline.Services _logger.LogInformation(Log.Format(LogDatabaseCreate, ("Id", newEntity.Id), ("Username", username))); - return await CreateUserFromEntity(newEntity); + await _databaseContext.Entry(newEntity).Collection(e => e.Permissions).LoadAsync(); + + return newEntity; } - public async Task ModifyUser(long id, ModifyUserParams? param) + public async Task ModifyUser(long id, ModifyUserParams? param) { if (param != null) { @@ -194,7 +172,7 @@ namespace Timeline.Services CheckNicknameFormat(param.Nickname, nameof(param)); } - var entity = await _databaseContext.Users.Where(u => u.Id == id).SingleOrDefaultAsync(); + var entity = await _databaseContext.Users.Where(u => u.Id == id).Include(u => u.Permissions).SingleOrDefaultAsync(); if (entity == null) throw new UserNotExistException(id); @@ -238,7 +216,7 @@ namespace Timeline.Services _logger.LogInformation(LogDatabaseUpdate, ("Id", id)); } - return await CreateUserFromEntity(entity); + return entity; } } } diff --git a/BackEnd/Timeline/Services/UserTokenManager.cs b/BackEnd/Timeline/Services/UserTokenManager.cs index b887b987..4e24c922 100644 --- a/BackEnd/Timeline/Services/UserTokenManager.cs +++ b/BackEnd/Timeline/Services/UserTokenManager.cs @@ -1,6 +1,7 @@ using Microsoft.Extensions.Logging; using System; using System.Threading.Tasks; +using Timeline.Entities; using Timeline.Helpers; using Timeline.Models; using Timeline.Services.Exceptions; @@ -10,7 +11,7 @@ namespace Timeline.Services public class UserTokenCreateResult { public string Token { get; set; } = default!; - public UserInfo User { get; set; } = default!; + public UserEntity User { get; set; } = default!; } public interface IUserTokenManager @@ -38,7 +39,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 +76,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