From d922b3241245c9bc1ca6cff8ac69dd7659a958f1 Mon Sep 17 00:00:00 2001 From: crupest Date: Wed, 28 Apr 2021 19:20:40 +0800 Subject: refator: ... --- BackEnd/Timeline/Services/Mapper/GenericMapper.cs | 37 +++++++ BackEnd/Timeline/Services/Mapper/IGenericMapper.cs | 12 ++ BackEnd/Timeline/Services/Mapper/IMapper.cs | 11 ++ .../Timeline/Services/Mapper/MapperExtensions.cs | 47 ++++++++ .../Mapper/MapperServiceCollectionExtensions.cs | 9 +- .../Timeline/Services/Mapper/Resource.Designer.cs | 72 ++++++++++++ BackEnd/Timeline/Services/Mapper/Resource.resx | 123 +++++++++++++++++++++ BackEnd/Timeline/Services/Mapper/TimelineMapper.cs | 71 +++++------- BackEnd/Timeline/Services/Mapper/UserMapper.cs | 16 +-- .../TimelineServicesServiceCollectionExtensions.cs | 4 - 10 files changed, 341 insertions(+), 61 deletions(-) create mode 100644 BackEnd/Timeline/Services/Mapper/GenericMapper.cs create mode 100644 BackEnd/Timeline/Services/Mapper/IGenericMapper.cs create mode 100644 BackEnd/Timeline/Services/Mapper/IMapper.cs create mode 100644 BackEnd/Timeline/Services/Mapper/MapperExtensions.cs create mode 100644 BackEnd/Timeline/Services/Mapper/Resource.Designer.cs create mode 100644 BackEnd/Timeline/Services/Mapper/Resource.resx (limited to 'BackEnd/Timeline/Services') diff --git a/BackEnd/Timeline/Services/Mapper/GenericMapper.cs b/BackEnd/Timeline/Services/Mapper/GenericMapper.cs new file mode 100644 index 00000000..4dd44828 --- /dev/null +++ b/BackEnd/Timeline/Services/Mapper/GenericMapper.cs @@ -0,0 +1,37 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Security.Claims; +using System.Threading.Tasks; + +namespace Timeline.Services.Mapper +{ + class GenericMapper : IGenericMapper + { + private readonly IServiceProvider _serviceProvider; + private readonly AutoMapper.IMapper _autoMapper; + + public GenericMapper(IServiceProvider serviceProvider, AutoMapper.IMapper autoMapper) + { + _serviceProvider = serviceProvider; + _autoMapper = autoMapper; + } + + public TDestination AutoMapperMap(object source) + { + return _autoMapper.Map(source); + } + + public async Task MapAsync(TSource source, IUrlHelper urlHelper, ClaimsPrincipal? user) + { + var mapper = _serviceProvider.GetService>(); + + if (mapper is not null) + { + return await mapper.MapAsync(source, urlHelper, user); + } + + return _autoMapper.Map(source); + } + } +} diff --git a/BackEnd/Timeline/Services/Mapper/IGenericMapper.cs b/BackEnd/Timeline/Services/Mapper/IGenericMapper.cs new file mode 100644 index 00000000..2583f036 --- /dev/null +++ b/BackEnd/Timeline/Services/Mapper/IGenericMapper.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Mvc; +using System.Security.Claims; +using System.Threading.Tasks; + +namespace Timeline.Services.Mapper +{ + public interface IGenericMapper + { + TDestination AutoMapperMap(object source); + Task MapAsync(TSource source, IUrlHelper urlHelper, ClaimsPrincipal? user); + } +} diff --git a/BackEnd/Timeline/Services/Mapper/IMapper.cs b/BackEnd/Timeline/Services/Mapper/IMapper.cs new file mode 100644 index 00000000..ef1b619f --- /dev/null +++ b/BackEnd/Timeline/Services/Mapper/IMapper.cs @@ -0,0 +1,11 @@ +using Microsoft.AspNetCore.Mvc; +using System.Security.Claims; +using System.Threading.Tasks; + +namespace Timeline.Services.Mapper +{ + public interface IMapper + { + Task MapAsync(TSource source, IUrlHelper urlHelper, ClaimsPrincipal? user); + } +} diff --git a/BackEnd/Timeline/Services/Mapper/MapperExtensions.cs b/BackEnd/Timeline/Services/Mapper/MapperExtensions.cs new file mode 100644 index 00000000..03dd1189 --- /dev/null +++ b/BackEnd/Timeline/Services/Mapper/MapperExtensions.cs @@ -0,0 +1,47 @@ +using Microsoft.AspNetCore.Mvc; +using System.Collections.Generic; +using System.Security.Claims; +using System.Threading.Tasks; + +namespace Timeline.Services.Mapper +{ + public static class MapperExtensions + { + public static async Task> MapListAsync(this IMapper mapper, IEnumerable source, IUrlHelper urlHelper, ClaimsPrincipal? user) + { + var result = new List(); + foreach (var s in source) + { + result.Add(await mapper.MapAsync(s, urlHelper, user)); + } + return result; + } + + public static Task MapAsync(this IGenericMapper mapper, object source, IUrlHelper urlHelper, ClaimsPrincipal? user) + { + var method = typeof(IGenericMapper).GetMethod(nameof(IGenericMapper.MapAsync)); + var m = method!.MakeGenericMethod(source.GetType(), typeof(TDestination))!; + return (Task)m.Invoke(mapper, new object?[] { source, urlHelper, user })!; + } + + public static async Task> MapListAsync(this IGenericMapper mapper, IEnumerable source, IUrlHelper urlHelper, ClaimsPrincipal? user) + { + var result = new List(); + foreach (var s in source) + { + result.Add(await mapper.MapAsync(s, urlHelper, user)); + } + return result; + } + + public static async Task> MapListAsync(this IGenericMapper mapper, IEnumerable source, IUrlHelper urlHelper, ClaimsPrincipal? user) + { + var result = new List(); + foreach (var s in source) + { + result.Add(await mapper.MapAsync(s, urlHelper, user)); + } + return result; + } + } +} diff --git a/BackEnd/Timeline/Services/Mapper/MapperServiceCollectionExtensions.cs b/BackEnd/Timeline/Services/Mapper/MapperServiceCollectionExtensions.cs index 262b2f20..0c2d0cfd 100644 --- a/BackEnd/Timeline/Services/Mapper/MapperServiceCollectionExtensions.cs +++ b/BackEnd/Timeline/Services/Mapper/MapperServiceCollectionExtensions.cs @@ -1,4 +1,6 @@ using Microsoft.Extensions.DependencyInjection; +using Timeline.Entities; +using Timeline.Models.Http; namespace Timeline.Services.Mapper { @@ -6,8 +8,11 @@ namespace Timeline.Services.Mapper { public static void AddMappers(this IServiceCollection services) { - services.AddScoped(); - services.AddScoped(); + services.AddAutoMapper(typeof(Startup).Assembly); + services.AddScoped, UserMapper>(); + services.AddScoped, TimelineMapper>(); + services.AddScoped, TimelineMapper>(); + services.AddScoped(); } } } diff --git a/BackEnd/Timeline/Services/Mapper/Resource.Designer.cs b/BackEnd/Timeline/Services/Mapper/Resource.Designer.cs new file mode 100644 index 00000000..71aab793 --- /dev/null +++ b/BackEnd/Timeline/Services/Mapper/Resource.Designer.cs @@ -0,0 +1,72 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Timeline.Services.Mapper { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resource { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resource() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Timeline.Services.Mapper.Resource", typeof(Resource).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to This map is unsupported by this map provider.. + /// + internal static string ExceptionUnsupportedMap { + get { + return ResourceManager.GetString("ExceptionUnsupportedMap", resourceCulture); + } + } + } +} diff --git a/BackEnd/Timeline/Services/Mapper/Resource.resx b/BackEnd/Timeline/Services/Mapper/Resource.resx new file mode 100644 index 00000000..f075c1bb --- /dev/null +++ b/BackEnd/Timeline/Services/Mapper/Resource.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + This map is unsupported by this map provider. + + \ No newline at end of file diff --git a/BackEnd/Timeline/Services/Mapper/TimelineMapper.cs b/BackEnd/Timeline/Services/Mapper/TimelineMapper.cs index c8279b42..5ee90a8f 100644 --- a/BackEnd/Timeline/Services/Mapper/TimelineMapper.cs +++ b/BackEnd/Timeline/Services/Mapper/TimelineMapper.cs @@ -2,25 +2,29 @@ using Microsoft.EntityFrameworkCore; using System.Collections.Generic; using System.Linq; +using System.Security.Claims; using System.Threading.Tasks; +using Timeline.Auth; using Timeline.Controllers; using Timeline.Entities; using Timeline.Models.Http; using Timeline.Services.Api; using Timeline.Services.Timeline; +using Timeline.Services.User; namespace Timeline.Services.Mapper { - public class TimelineMapper + public class TimelineMapper : IMapper, + IMapper { private readonly DatabaseContext _database; - private readonly UserMapper _userMapper; + private readonly IMapper _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, ITimelineService timelineService, ITimelinePostService timelinePostService) + public TimelineMapper(DatabaseContext database, IMapper userMapper, IHighlightTimelineService highlightTimelineService, IBookmarkTimelineService bookmarkTimelineService, ITimelineService timelineService, ITimelinePostService timelinePostService) { _database = database; _userMapper = userMapper; @@ -30,20 +34,27 @@ namespace Timeline.Services.Mapper _timelinePostService = timelinePostService; } - public async Task MapToHttp(TimelineEntity entity, IUrlHelper urlHelper, long? userId, bool isAdministrator) + private string CalculateTimelineName(TimelineEntity entity) { + return entity.Name is null ? "@" + entity.Owner.Username : entity.Name; + } + + public async Task MapAsync(TimelineEntity entity, IUrlHelper urlHelper, ClaimsPrincipal? user) + { + var userId = user.GetUserId(); + 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; + var timelineName = CalculateTimelineName(entity); bool manageable; - if (userId is null) + if (user is null || userId is null) { manageable = false; } - else if (isAdministrator) + else if (user.HasPermission(UserPermission.AllTimelineManagement)) { manageable = true; } @@ -53,7 +64,7 @@ namespace Timeline.Services.Mapper } bool postable; - if (userId is null) + if (user is null || userId is null) { postable = false; } @@ -68,9 +79,9 @@ namespace Timeline.Services.Mapper name: timelineName, nameLastModifed: entity.NameLastModified, description: entity.Description ?? "", - owner: await _userMapper.MapToHttp(entity.Owner, urlHelper), + owner: await _userMapper.MapAsync(entity.Owner, urlHelper, user), visibility: entity.Visibility, - members: await _userMapper.MapToHttp(entity.Members.Select(m => m.User).ToList(), urlHelper), + members: await _userMapper.MapListAsync(entity.Members.Select(m => m.User).ToList(), urlHelper, user), color: entity.Color, createTime: entity.CreateTime, lastModified: entity.LastModified, @@ -85,39 +96,31 @@ namespace Timeline.Services.Mapper ); } - 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, isAdministrator)); - } - return result; - } - - public async Task MapToHttp(TimelinePostEntity entity, string timelineName, IUrlHelper urlHelper, long? userId, bool isAdministrator) + public async Task MapAsync(TimelinePostEntity entity, IUrlHelper urlHelper, ClaimsPrincipal? user) { - _ = timelineName; + var userId = user.GetUserId(); + await _database.Entry(entity).Reference(e => e.Timeline).LoadAsync(); await _database.Entry(entity).Collection(p => p.DataList).LoadAsync(); await _database.Entry(entity).Reference(e => e.Author).LoadAsync(); + await _database.Entry(entity.Timeline).Reference(e => e.Owner).LoadAsync(); List dataDigestList = entity.DataList.OrderBy(d => d.Index).Select(d => new HttpTimelinePostDataDigest(d.Kind, $"\"{d.DataTag}\"", d.LastUpdated)).ToList(); HttpUser? author = null; if (entity.Author is not null) { - author = await _userMapper.MapToHttp(entity.Author, urlHelper); + author = await _userMapper.MapAsync(entity.Author, urlHelper, user); } bool editable; - if (userId is null) + if (user is null || userId is null) { editable = false; } - else if (isAdministrator) + else if (user.HasPermission(UserPermission.AllTimelineManagement)) { editable = true; } @@ -126,7 +129,6 @@ namespace Timeline.Services.Mapper editable = await _timelinePostService.HasPostModifyPermissionAsync(entity.TimelineId, entity.LocalId, userId.Value); } - return new HttpTimelinePost( id: entity.LocalId, dataList: dataDigestList, @@ -135,24 +137,9 @@ namespace Timeline.Services.Mapper color: entity.Color, deleted: entity.Deleted, lastUpdated: entity.LastUpdated, - timelineName: timelineName, + timelineName: CalculateTimelineName(entity.Timeline), editable: editable ); } - - 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, userId, isAdministrator)); - } - return result; - } - - internal Task MapToHttp(TimelinePostEntity post, string timeline, IUrlHelper url) - { - throw new System.NotImplementedException(); - } } } diff --git a/BackEnd/Timeline/Services/Mapper/UserMapper.cs b/BackEnd/Timeline/Services/Mapper/UserMapper.cs index 42f88d8a..8855eef2 100644 --- a/BackEnd/Timeline/Services/Mapper/UserMapper.cs +++ b/BackEnd/Timeline/Services/Mapper/UserMapper.cs @@ -1,5 +1,5 @@ using Microsoft.AspNetCore.Mvc; -using System.Collections.Generic; +using System.Security.Claims; using System.Threading.Tasks; using Timeline.Controllers; using Timeline.Entities; @@ -8,7 +8,7 @@ using Timeline.Services.User; namespace Timeline.Services.Mapper { - public class UserMapper + public class UserMapper : IMapper { private readonly DatabaseContext _database; private readonly IUserPermissionService _userPermissionService; @@ -19,7 +19,7 @@ namespace Timeline.Services.Mapper _userPermissionService = userPermissionService; } - public async Task MapToHttp(UserEntity entity, IUrlHelper urlHelper) + public async Task MapAsync(UserEntity entity, IUrlHelper urlHelper, ClaimsPrincipal? user) { return new HttpUser( uniqueId: entity.UniqueId, @@ -33,15 +33,5 @@ namespace Timeline.Services.Mapper ) ); } - - public async Task> MapToHttp(List entities, IUrlHelper urlHelper) - { - var result = new List(); - foreach (var entity in entities) - { - result.Add(await MapToHttp(entity, urlHelper)); - } - return result; - } } } diff --git a/BackEnd/Timeline/Services/Timeline/TimelineServicesServiceCollectionExtensions.cs b/BackEnd/Timeline/Services/Timeline/TimelineServicesServiceCollectionExtensions.cs index 556800df..97b313cd 100644 --- a/BackEnd/Timeline/Services/Timeline/TimelineServicesServiceCollectionExtensions.cs +++ b/BackEnd/Timeline/Services/Timeline/TimelineServicesServiceCollectionExtensions.cs @@ -1,9 +1,5 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; namespace Timeline.Services.Timeline { -- cgit v1.2.3