From e7ca87f25dae2f806469043ee556d4790d9ebcae Mon Sep 17 00:00:00 2001 From: crupest Date: Tue, 10 Mar 2020 03:04:23 +0800 Subject: ... --- Timeline/Services/TimelineService.cs | 494 ++++++++++++++++++++--------------- 1 file changed, 286 insertions(+), 208 deletions(-) (limited to 'Timeline/Services/TimelineService.cs') diff --git a/Timeline/Services/TimelineService.cs b/Timeline/Services/TimelineService.cs index a2b7b5ea..8c1e62d4 100644 --- a/Timeline/Services/TimelineService.cs +++ b/Timeline/Services/TimelineService.cs @@ -1,5 +1,4 @@ -using AutoMapper; -using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using SixLabors.ImageSharp; using System; @@ -7,12 +6,12 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Threading.Tasks; -using Timeline.Entities; -using Timeline.Models.Http; -using Timeline.Models.Validation; -using static Timeline.Resources.Services.TimelineService; +using TimelineApp.Entities; +using TimelineApp.Models; +using TimelineApp.Models.Validation; +using static TimelineApp.Resources.Services.TimelineService; -namespace Timeline.Services +namespace TimelineApp.Services { public enum TimelineUserRelationshipType { @@ -42,70 +41,63 @@ namespace Timeline.Services } /// - /// This define the common interface of both personal timeline - /// and normal timeline. + /// This define the common interface of both personal timeline and normal timeline. /// /// - /// The "name" parameter in method means name of timeline in - /// while username of the owner - /// of the personal timeline in . + /// The "name" parameter in each method has different meaning. + /// => name of the ordinary timeline + /// => username of the owner of the personal timeline + /// => username if begin with '@' otherwise timeline name + /// + /// is thrown when name is illegal. + /// For ordinary timeline, it means the name is not a valid timeline name. + /// For personal timeline, it means the name is not a valid username. + /// + /// is thrown when timeline does not exist. + /// For ordinary timeline, it means the timeline of the name does not exist. + /// For personal timeline, it means the user with the username does not exist and the inner exception should be a . /// public interface IBaseTimelineService { /// /// Get the timeline info. /// - /// Username or the timeline name. See remarks of . + /// See remarks of . /// The timeline info. /// Thrown when is null. - /// Thrown when is illegal. It is not a valid timeline name (for normal timeline service) or a valid username (for personal timeline service). - /// - /// Thrown when timeline does not exist. - /// For normal timeline, it means the name does not exist. - /// For personal timeline, it means the user of that username does not exist - /// and the inner exception should be a . - /// - Task GetTimeline(string name); + /// See remarks of . + /// See remarks of . + Task GetTimeline(string name); /// /// Set the properties of a timeline. /// - /// Username or the timeline name. See remarks of . + /// See remarks of . /// The new properties. Null member means not to change. - /// The timeline info. - /// Thrown when is null. - /// Thrown when is illegal. It is not a valid timeline name (for normal timeline service) or a valid username (for personal timeline service). - /// - /// Thrown when timeline does not exist. - /// For normal timeline, it means the name does not exist. - /// For personal timeline, it means the user of that username does not exist - /// and the inner exception should be a . - /// - Task ChangeProperty(string name, TimelinePatchRequest newProperties); + /// Thrown when or is null. + /// See remarks of . + /// See remarks of . + Task ChangeProperty(string name, TimelineChangePropertyRequest newProperties); /// /// Get all the posts in the timeline. /// - /// Username or the timeline name. See remarks of . + /// See remarks of . /// A list of all posts. /// Thrown when is null. - /// Thrown when is illegal. It is not a valid timeline name (for normal timeline service) or a valid username (for personal timeline service). - /// - /// Thrown when timeline does not exist. - /// For normal timeline, it means the name does not exist. - /// For personal timeline, it means the user of that username does not exist - /// and the inner exception should be a . - /// - Task> GetPosts(string name); + /// See remarks of . + /// See remarks of . + Task> GetPosts(string name); /// /// Get the data of a post. /// - /// Username or the timeline name. See remarks of . + /// See remarks of . /// The id of the post. /// The data and its type. /// Thrown when is null. - /// Thrown when is illegal. It is not a valid timeline name (for normal timeline service) or a valid username (for personal timeline service). + /// See remarks of . + /// See remarks of . /// Thrown when post of does not exist or has been deleted. /// Thrown when post has no data. See remarks. /// @@ -116,55 +108,40 @@ namespace Timeline.Services /// /// Create a new text post in timeline. /// - /// Username or the timeline name. See remarks of . - /// The author's id. + /// See remarks of . + /// The author's user id. /// The content text. /// The time of the post. If null, then use current time. /// The info of the created post. /// Thrown when or is null. - /// Thrown when is illegal. It is not a valid timeline name (for normal timeline service) or a valid username (for personal timeline service). - /// - /// Thrown when timeline does not exist. - /// For normal timeline, it means the name does not exist. - /// For personal timeline, it means the user of that username does not exist - /// and the inner exception should be a . - /// + /// See remarks of . + /// See remarks of . /// Thrown if user with does not exist. - Task CreateTextPost(string name, long authorId, string text, DateTime? time); + Task CreateTextPost(string name, long authorId, string text, DateTime? time); /// /// Create a new image post in timeline. /// - /// Username or the timeline name. See remarks of . - /// The author's id. + /// See remarks of . + /// 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. - /// Thrown when is illegal. It is not a valid timeline name (for normal timeline service) or a valid username (for personal timeline service). - /// - /// Thrown when timeline does not exist. - /// For normal timeline, it means the name does not exist. - /// For personal timeline, it means the user of that username does not exist - /// and the inner exception should be a . - /// + /// Thrown when or is null. + /// See remarks of . + /// See remarks of . /// Thrown if user with does not exist. /// Thrown if data is not a image. Validated by . - Task CreateImagePost(string name, long authorId, byte[] data, DateTime? time); + Task CreateImagePost(string name, long authorId, byte[] data, DateTime? time); /// - /// Delete a post + /// Delete a post. /// - /// Username or the timeline name. See remarks of . + /// See remarks of . /// The id of the post to delete. - /// Thrown when or is null. - /// Thrown when is illegal. It is not a valid timeline name (for normal timeline service) or a valid username (for personal timeline service). - /// - /// Thrown when timeline does not exist. - /// For normal timeline, it means the name does not exist. - /// For personal timeline, it means the user of that username does not exist - /// and the inner exception should be a . - /// + /// Thrown when is null. + /// See remarks of . + /// See remarks of . /// /// Thrown when the post with given id does not exist or is deleted already. /// @@ -177,18 +154,13 @@ namespace Timeline.Services /// /// Remove members to a timeline. /// - /// Username or the timeline name. See remarks of . + /// See remarks of . /// 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. - /// Thrown when is illegal. It is not a valid timeline name (for normal timeline service) or a valid username (for personal timeline service). + /// See remarks of . + /// See remarks of . /// Thrown when names in or is not a valid username. - /// - /// Thrown when timeline does not exist. - /// For normal timeline, it means the name does not exist. - /// For personal timeline, it means the user of that username does not exist - /// and the inner exception should be a . - /// /// /// Thrown when one of the user to change does not exist. /// @@ -204,17 +176,12 @@ namespace Timeline.Services /// /// Check whether a user can manage(change timeline info, member, ...) a timeline. /// - /// - /// + /// See remarks of . + /// The user id. /// True if the user can manage the timeline, otherwise false. /// Thrown when is null. - /// Thrown when is illegal. It is not a valid timeline name (for normal timeline service) or a valid username (for personal timeline service). - /// - /// Thrown when timeline does not exist. - /// For normal timeline, it means the name does not exist. - /// For personal timeline, it means the user of that username does not exist - /// and the inner exception should be a . - /// + /// See remarks of . + /// See remarks of . /// /// This method does not check whether visitor is administrator. /// Return false if user with user id does not exist. @@ -224,17 +191,12 @@ namespace Timeline.Services /// /// Verify whether a visitor has the permission to read a timeline. /// - /// Username or the timeline name. See remarks of . + /// See remarks of . /// 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. - /// Thrown when is illegal. It is not a valid timeline name (for normal timeline service) or a valid username (for personal timeline service). - /// - /// Thrown when timeline does not exist. - /// For normal timeline, it means the name does not exist. - /// For personal timeline, it means the user of that username does not exist - /// and the inner exception should be a . - /// + /// See remarks of . + /// See remarks of . /// /// This method does not check whether visitor is administrator. /// Return false if user with visitor id does not exist. @@ -244,17 +206,12 @@ namespace Timeline.Services /// /// Verify whether a user has the permission to modify a post. /// - /// Username or the timeline name. See remarks of . + /// See remarks of . /// The id of the user to check on. /// True if can modify, false if can't modify. /// Thrown when is null. - /// Thrown when is illegal. It is not a valid timeline name (for normal timeline service) or a valid username (for personal timeline service). - /// - /// Thrown when timeline does not exist. - /// For normal timeline, it means the name does not exist. - /// For personal timeline, it means the user of that username does not exist - /// and the inner exception should be a . - /// + /// See remarks of . + /// See remarks of . /// /// Thrown when the post with given id does not exist or is deleted already. /// @@ -268,17 +225,12 @@ namespace Timeline.Services /// /// Verify whether a user is member of a timeline. /// - /// Username or the timeline name. See remarks of . + /// See remarks of . /// The id of user to check on. /// True if it is a member, false if not. /// Thrown when is null. - /// Thrown when is illegal. It is not a valid timeline name (for normal timeline service) or a valid username (for personal timeline service). - /// - /// Thrown when timeline does not exist. - /// For normal timeline, it means the name does not exist. - /// For personal timeline, it means the user of that username does not exist - /// and the inner exception should be a . - /// + /// See remarks of . + /// See remarks of . /// /// Timeline owner is also considered as a member. /// Return false when user with user id does not exist. @@ -300,7 +252,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. @@ -312,7 +264,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 name, long owner); + Task CreateTimeline(string name, long owner); /// /// Delete a timeline. @@ -324,25 +276,29 @@ namespace Timeline.Services Task DeleteTimeline(string name); } + public interface IOrdinaryTimelineService : IBaseTimelineService + { + + } + public interface IPersonalTimelineService : IBaseTimelineService { } - public abstract class BaseTimelineService : IBaseTimelineService + public abstract class BaseTimelineManager : IBaseTimelineService { - protected BaseTimelineService(ILoggerFactory loggerFactory, DatabaseContext database, IImageValidator imageValidator, IDataManager dataManager, IUserService userService, IMapper mapper, IClock clock) + protected BaseTimelineManager(ILoggerFactory loggerFactory, DatabaseContext database, IImageValidator imageValidator, IDataManager dataManager, IUserService userService, IClock clock) { - _logger = loggerFactory.CreateLogger(); + _logger = loggerFactory.CreateLogger(); Clock = clock; Database = database; ImageValidator = imageValidator; DataManager = dataManager; UserService = userService; - Mapper = mapper; } - private ILogger _logger; + private ILogger _logger; protected IClock Clock { get; } @@ -354,20 +310,6 @@ namespace Timeline.Services protected IDataManager DataManager { get; } protected IUserService UserService { get; } - protected IMapper Mapper { get; } - - protected TimelineEntity CreateNewEntity(string? name, long owner) - { - return new TimelineEntity - { - CurrentPostLocalId = 0, - Name = name, - OwnerId = owner, - Visibility = TimelineVisibility.Register, - CreateTime = Clock.GetCurrentTime() - }; - } - /// /// Find the timeline id by the name. /// For details, see remarks. @@ -392,7 +334,7 @@ namespace Timeline.Services /// protected abstract Task FindTimelineId(string name); - public async Task GetTimeline(string name) + public async Task GetTimeline(string name) { if (name == null) throw new ArgumentNullException(nameof(name)); @@ -403,17 +345,17 @@ namespace Timeline.Services var timelineMemberEntities = await Database.TimelineMembers.Where(m => m.TimelineId == timelineId).Select(m => new { m.UserId }).ToListAsync(); - var owner = Mapper.Map(await UserService.GetUserById(timelineEntity.OwnerId)); + var owner = await UserService.GetUserById(timelineEntity.OwnerId); - var members = new List(); + var members = new List(); foreach (var memberEntity in timelineMemberEntities) { - members.Add(Mapper.Map(await UserService.GetUserById(memberEntity.UserId))); + members.Add(await UserService.GetUserById(memberEntity.UserId)); } - return new TimelineInfo + return new Timeline { - Name = timelineEntity.Name, + Name = timelineEntity.Name ?? ("@" + owner.Username), Description = timelineEntity.Description ?? "", Owner = owner, Visibility = timelineEntity.Visibility, @@ -421,7 +363,7 @@ namespace Timeline.Services }; } - public async Task> GetPosts(string name) + public async Task> GetPosts(string name) { if (name == null) throw new ArgumentNullException(nameof(name)); @@ -429,12 +371,12 @@ namespace Timeline.Services var timelineId = await FindTimelineId(name); var postEntities = await Database.TimelinePosts.OrderBy(p => p.Time).Where(p => p.TimelineId == timelineId && p.Content != null).ToListAsync(); - var posts = new List(); + var posts = new List(); foreach (var entity in postEntities) { if (entity.Content != null) // otherwise it is deleted { - var author = Mapper.Map(await UserService.GetUserById(entity.AuthorId)); + var author = await UserService.GetUserById(entity.AuthorId); var type = entity.ContentType; @@ -445,7 +387,7 @@ namespace Timeline.Services _ => throw new DatabaseCorruptedException(string.Format(CultureInfo.InvariantCulture, ExceptionDatabaseUnknownContentType, type)) }; - posts.Add(new TimelinePostInfo + posts.Add(new TimelinePost { Id = entity.LocalId, Content = content, @@ -502,7 +444,7 @@ namespace Timeline.Services }; } - public async Task CreateTextPost(string name, long authorId, string text, DateTime? time) + public async Task CreateTextPost(string name, long authorId, string text, DateTime? time) { if (name == null) throw new ArgumentNullException(nameof(name)); @@ -512,7 +454,7 @@ namespace Timeline.Services var timelineId = await FindTimelineId(name); var timelineEntity = await Database.Timelines.Where(t => t.Id == timelineId).SingleAsync(); - var author = Mapper.Map(await UserService.GetUserById(authorId)); + var author = await UserService.GetUserById(authorId); var currentTime = Clock.GetCurrentTime(); var finalTime = time ?? currentTime; @@ -532,7 +474,7 @@ namespace Timeline.Services Database.TimelinePosts.Add(postEntity); await Database.SaveChangesAsync(); - return new TimelinePostInfo + return new TimelinePost { Id = postEntity.LocalId, Content = new TextTimelinePostContent(text), @@ -542,7 +484,7 @@ namespace Timeline.Services }; } - public async Task CreateImagePost(string name, long authorId, byte[] data, DateTime? time) + public async Task CreateImagePost(string name, long authorId, byte[] data, DateTime? time) { if (name == null) throw new ArgumentNullException(nameof(name)); @@ -552,7 +494,7 @@ namespace Timeline.Services var timelineId = await FindTimelineId(name); var timelineEntity = await Database.Timelines.Where(t => t.Id == timelineId).SingleAsync(); - var author = Mapper.Map(await UserService.GetUserById(authorId)); + var author = await UserService.GetUserById(authorId); var imageFormat = await ImageValidator.Validate(data); @@ -579,7 +521,7 @@ namespace Timeline.Services Database.TimelinePosts.Add(postEntity); await Database.SaveChangesAsync(); - return new TimelinePostInfo + return new TimelinePost { Id = postEntity.LocalId, Content = new ImageTimelinePostContent(tag), @@ -619,7 +561,7 @@ namespace Timeline.Services } } - public async Task ChangeProperty(string name, TimelinePatchRequest newProperties) + public async Task ChangeProperty(string name, TimelineChangePropertyRequest newProperties) { if (name == null) throw new ArgumentNullException(nameof(name)); @@ -789,7 +731,7 @@ namespace Timeline.Services } } - public class TimelineService : BaseTimelineService, ITimelineService + public class OrdinaryTimelineService : BaseTimelineManager, IOrdinaryTimelineService { private readonly TimelineNameValidator _timelineNameValidator = new TimelineNameValidator(); @@ -801,8 +743,8 @@ namespace Timeline.Services } } - public TimelineService(ILoggerFactory loggerFactory, DatabaseContext database, IImageValidator imageValidator, IDataManager dataManager, IUserService userService, IMapper mapper, IClock clock) - : base(loggerFactory, database, imageValidator, dataManager, userService, mapper, clock) + public OrdinaryTimelineService(ILoggerFactory loggerFactory, DatabaseContext database, IImageValidator imageValidator, IDataManager dataManager, IUserService userService, IClock clock) + : base(loggerFactory, database, imageValidator, dataManager, userService, clock) { } @@ -825,8 +767,89 @@ namespace Timeline.Services return timelineEntity.Id; } } + } + + public class PersonalTimelineService : BaseTimelineManager, IPersonalTimelineService + { + public PersonalTimelineService(ILoggerFactory loggerFactory, DatabaseContext database, IImageValidator imageValidator, IDataManager dataManager, IUserService userService, IClock clock) + : base(loggerFactory, database, imageValidator, dataManager, userService, clock) + { + + } - public async Task> GetTimelines(TimelineUserRelationship? relate = null, List? visibility = null) + protected override async Task FindTimelineId(string name) + { + if (name == null) + throw new ArgumentNullException(nameof(name)); + + long userId; + try + { + userId = await UserService.GetUserIdByUsername(name); + } + catch (ArgumentException e) + { + throw new ArgumentException(ExceptionFindTimelineUsernameBadFormat, nameof(name), e); + } + catch (UserNotExistException e) + { + throw new TimelineNotExistException(name, e); + } + + var timelineEntity = await Database.Timelines.Where(t => t.OwnerId == userId && t.Name == null).Select(t => new { t.Id }).SingleOrDefaultAsync(); + + if (timelineEntity != null) + { + return timelineEntity.Id; + } + else + { + var newTimelineEntity = new TimelineEntity + { + CurrentPostLocalId = 0, + Name = null, + OwnerId = userId, + Visibility = TimelineVisibility.Register, + CreateTime = Clock.GetCurrentTime() + }; + Database.Timelines.Add(newTimelineEntity); + await Database.SaveChangesAsync(); + + return newTimelineEntity.Id; + } + } + } + + public class TimelineService : ITimelineService + { + private readonly TimelineNameValidator _timelineNameValidator = new TimelineNameValidator(); + + private readonly DatabaseContext _database; + + private readonly IUserService _userService; + private readonly IClock _clock; + + private readonly IOrdinaryTimelineService _ordinaryTimelineService; + private readonly IPersonalTimelineService _personalTimelineService; + + public TimelineService(DatabaseContext database, IUserService userService, IClock clock, IOrdinaryTimelineService ordinaryTimelineService, IPersonalTimelineService personalTimelineService) + { + _database = database; + _userService = userService; + _clock = clock; + _ordinaryTimelineService = ordinaryTimelineService; + _personalTimelineService = personalTimelineService; + } + + private void ValidateTimelineName(string name, string paramName) + { + if (!_timelineNameValidator.Validate(name, out var message)) + { + throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, ExceptionTimelineNameBadFormat, message), paramName); + } + } + + public async Task> GetTimelines(TimelineUserRelationship? relate = null, List? visibility = null) { List entities; @@ -843,7 +866,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.Members).ToListAsync(); } else { @@ -851,31 +874,32 @@ 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.Members).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).Select(m => m.Timeline)).ToListAsync()); } } - var result = new List(); + var result = new List(); foreach (var entity in entities) { - var timeline = new TimelineInfo + var owner = await _userService.GetUserById(entity.OwnerId); + var timeline = new Timeline { - Name = entity.Name, + Name = entity.Name ?? ("@" + owner.Username), Description = entity.Description ?? "", - Owner = Mapper.Map(await UserService.GetUserById(entity.OwnerId)), + Owner = owner, Visibility = entity.Visibility, - Members = new List() + Members = new List() }; foreach (var m in entity.Members) { - timeline.Members.Add(Mapper.Map(await UserService.GetUserById(m.UserId))); + timeline.Members.Add(await _userService.GetUserById(m.UserId)); } result.Add(timeline); @@ -884,31 +908,39 @@ 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)); ValidateTimelineName(name, nameof(name)); - var user = await UserService.GetUserById(owner); + var user = await _userService.GetUserById(owner); - var conflict = await Database.Timelines.AnyAsync(t => t.Name == name); + var conflict = await _database.Timelines.AnyAsync(t => t.Name == name); if (conflict) throw new ConflictException(ExceptionTimelineNameConflict); - var newEntity = CreateNewEntity(name, owner); - Database.Timelines.Add(newEntity); - await Database.SaveChangesAsync(); + var newEntity = new TimelineEntity + { + CurrentPostLocalId = 0, + Name = name, + OwnerId = owner, + Visibility = TimelineVisibility.Register, + CreateTime = _clock.GetCurrentTime() + }; + + _database.Timelines.Add(newEntity); + await _database.SaveChangesAsync(); - return new TimelineInfo + return new Timeline { Name = name, Description = "", - Owner = Mapper.Map(user), + Owner = user, Visibility = newEntity.Visibility, - Members = new List() + Members = new List() }; } @@ -919,57 +951,103 @@ namespace Timeline.Services ValidateTimelineName(name, nameof(name)); - var entity = await Database.Timelines.Where(t => t.Name == name).SingleOrDefaultAsync(); + var entity = await _database.Timelines.Where(t => t.Name == name).SingleOrDefaultAsync(); if (entity == null) throw new TimelineNotExistException(name); - Database.Timelines.Remove(entity); - await Database.SaveChangesAsync(); + _database.Timelines.Remove(entity); + await _database.SaveChangesAsync(); } - } - - public class PersonalTimelineService : BaseTimelineService, IPersonalTimelineService - { - public PersonalTimelineService(ILoggerFactory loggerFactory, DatabaseContext database, IImageValidator imageValidator, IDataManager dataManager, IUserService userService, IMapper mapper, IClock clock) - : base(loggerFactory, database, imageValidator, dataManager, userService, mapper, clock) - { - } - protected override async Task FindTimelineId(string name) + private IBaseTimelineService BranchName(string name, out string realName) { if (name == null) throw new ArgumentNullException(nameof(name)); - long userId; - try - { - userId = await UserService.GetUserIdByUsername(name); - } - catch (ArgumentException e) + if (name.StartsWith('@')) { - throw new ArgumentException(ExceptionFindTimelineUsernameBadFormat, nameof(name), e); + realName = name.Substring(1); + return _personalTimelineService; } - catch (UserNotExistException e) + else { - throw new TimelineNotExistException(name, e); + realName = name; + return _ordinaryTimelineService; } + } - var timelineEntity = await Database.Timelines.Where(t => t.OwnerId == userId && t.Name == null).Select(t => new { t.Id }).SingleOrDefaultAsync(); + public Task GetTimeline(string name) + { + var s = BranchName(name, out var realName); + return s.GetTimeline(realName); + } - if (timelineEntity != null) - { - return timelineEntity.Id; - } - else - { - var newTimelineEntity = CreateNewEntity(null, userId); - Database.Timelines.Add(newTimelineEntity); - await Database.SaveChangesAsync(); + public Task ChangeProperty(string name, TimelineChangePropertyRequest newProperties) + { + var s = BranchName(name, out var realName); + return s.ChangeProperty(realName, newProperties); + } - return newTimelineEntity.Id; - } + public Task> GetPosts(string name) + { + var s = BranchName(name, out var realName); + return s.GetPosts(realName); + } + + public Task GetPostData(string name, long postId) + { + var s = BranchName(name, out var realName); + return s.GetPostData(realName, postId); + } + + public Task CreateTextPost(string name, long authorId, string text, DateTime? time) + { + var s = BranchName(name, out var realName); + return s.CreateTextPost(realName, authorId, text, time); + } + + public Task CreateImagePost(string name, long authorId, byte[] data, DateTime? time) + { + var s = BranchName(name, out var realName); + return s.CreateImagePost(realName, authorId, data, time); + } + + public Task DeletePost(string name, long id) + { + var s = BranchName(name, out var realName); + return s.DeletePost(realName, id); + } + + public Task ChangeMember(string name, IList? add, IList? remove) + { + var s = BranchName(name, out var realName); + return s.ChangeMember(realName, add, remove); + } + + public Task HasManagePermission(string name, long userId) + { + var s = BranchName(name, out var realName); + return s.HasManagePermission(realName, userId); + } + + public Task HasReadPermission(string name, long? visitorId) + { + var s = BranchName(name, out var realName); + return s.HasReadPermission(realName, visitorId); + } + + public Task HasPostModifyPermission(string name, long id, long modifierId) + { + var s = BranchName(name, out var realName); + return s.HasPostModifyPermission(realName, id, modifierId); + } + + public Task IsMemberOf(string name, long userId) + { + var s = BranchName(name, out var realName); + return s.IsMemberOf(realName, userId); } } } -- cgit v1.2.3