From e16c958e5ba47834dc1624e09ed8e5074a60d1c6 Mon Sep 17 00:00:00 2001 From: crupest Date: Wed, 28 Apr 2021 19:20:40 +0800 Subject: refator: ... --- BackEnd/Timeline/Auth/PrincipalExtensions.cs | 18 ++- BackEnd/Timeline/Auth/Resource.Designer.cs | 9 ++ BackEnd/Timeline/Auth/Resource.resx | 3 + .../Controllers/BookmarkTimelineController.cs | 9 +- .../Controllers/HighlightTimelineController.cs | 8 +- BackEnd/Timeline/Controllers/SearchController.cs | 13 +-- BackEnd/Timeline/Controllers/TimelineController.cs | 16 +-- .../Timeline/Controllers/TimelinePostController.cs | 22 ++-- BackEnd/Timeline/Controllers/TokenController.cs | 10 +- BackEnd/Timeline/Controllers/UserController.cs | 21 ++-- 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 - BackEnd/Timeline/Startup.cs | 4 +- BackEnd/Timeline/Timeline.csproj | 9 ++ 22 files changed, 424 insertions(+), 120 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 diff --git a/BackEnd/Timeline/Auth/PrincipalExtensions.cs b/BackEnd/Timeline/Auth/PrincipalExtensions.cs index 605f66f6..81c21969 100644 --- a/BackEnd/Timeline/Auth/PrincipalExtensions.cs +++ b/BackEnd/Timeline/Auth/PrincipalExtensions.cs @@ -4,9 +4,23 @@ using Timeline.Services.User; namespace Timeline.Auth { - internal static class PrincipalExtensions + public static class PrincipalExtensions { - internal static bool HasPermission(this ClaimsPrincipal principal, UserPermission permission) + public static long? GetUserId(this ClaimsPrincipal? principal) + { + if (principal is null) return null; + + var claim = principal.FindFirst(ClaimTypes.NameIdentifier); + if (claim == null) + return null; + + if (long.TryParse(claim.Value, out var value)) + return value; + + throw new InvalidOperationException(Resource.ExceptionUserIdentifierClaimBadFormat); + } + + public static bool HasPermission(this ClaimsPrincipal principal, UserPermission permission) { return principal.HasClaim( claim => claim.Type == AuthenticationConstants.PermissionClaimName && string.Equals(claim.Value, permission.ToString(), StringComparison.OrdinalIgnoreCase)); diff --git a/BackEnd/Timeline/Auth/Resource.Designer.cs b/BackEnd/Timeline/Auth/Resource.Designer.cs index e9ef970e..05394551 100644 --- a/BackEnd/Timeline/Auth/Resource.Designer.cs +++ b/BackEnd/Timeline/Auth/Resource.Designer.cs @@ -60,6 +60,15 @@ namespace Timeline.Auth { } } + /// + /// Looks up a localized string similar to User identitifier claim is of bad format.. + /// + internal static string ExceptionUserIdentifierClaimBadFormat { + get { + return ResourceManager.GetString("ExceptionUserIdentifierClaimBadFormat", resourceCulture); + } + } + /// /// Looks up a localized string similar to Token is found in authorization header. Token is {0} .. /// diff --git a/BackEnd/Timeline/Auth/Resource.resx b/BackEnd/Timeline/Auth/Resource.resx index 21f2b2de..88cdbd6b 100644 --- a/BackEnd/Timeline/Auth/Resource.resx +++ b/BackEnd/Timeline/Auth/Resource.resx @@ -117,6 +117,9 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + User identitifier claim is of bad format. + Token is found in authorization header. Token is {0} . diff --git a/BackEnd/Timeline/Controllers/BookmarkTimelineController.cs b/BackEnd/Timeline/Controllers/BookmarkTimelineController.cs index d941013f..e7ffa5c5 100644 --- a/BackEnd/Timeline/Controllers/BookmarkTimelineController.cs +++ b/BackEnd/Timeline/Controllers/BookmarkTimelineController.cs @@ -8,7 +8,6 @@ using Timeline.Models.Validation; using Timeline.Services.Api; using Timeline.Services.Mapper; using Timeline.Services.Timeline; -using Timeline.Services.User; namespace Timeline.Controllers { @@ -21,18 +20,18 @@ namespace Timeline.Controllers { private readonly IBookmarkTimelineService _service; private readonly ITimelineService _timelineService; - private readonly TimelineMapper _timelineMapper; + private readonly IGenericMapper _mapper; - public BookmarkTimelineController(IBookmarkTimelineService service, ITimelineService timelineService, TimelineMapper timelineMapper) + public BookmarkTimelineController(IBookmarkTimelineService service, ITimelineService timelineService, IGenericMapper mapper) { _service = service; _timelineService = timelineService; - _timelineMapper = timelineMapper; + _mapper = mapper; } private Task> Map(List timelines) { - return _timelineMapper.MapToHttp(timelines, Url, this.GetOptionalUserId(), this.UserHasPermission(UserPermission.AllTimelineManagement)); + return _mapper.MapListAsync(timelines, Url, User); } /// diff --git a/BackEnd/Timeline/Controllers/HighlightTimelineController.cs b/BackEnd/Timeline/Controllers/HighlightTimelineController.cs index 4facc4a1..4e739056 100644 --- a/BackEnd/Timeline/Controllers/HighlightTimelineController.cs +++ b/BackEnd/Timeline/Controllers/HighlightTimelineController.cs @@ -21,18 +21,18 @@ namespace Timeline.Controllers { private readonly IHighlightTimelineService _service; private readonly ITimelineService _timelineService; - private readonly TimelineMapper _timelineMapper; + private readonly IGenericMapper _mapper; - public HighlightTimelineController(IHighlightTimelineService service, ITimelineService timelineService, TimelineMapper timelineMapper) + public HighlightTimelineController(IHighlightTimelineService service, ITimelineService timelineService, IGenericMapper mapper) { _service = service; _timelineService = timelineService; - _timelineMapper = timelineMapper; + _mapper = mapper; } private Task> Map(List timelines) { - return _timelineMapper.MapToHttp(timelines, Url, this.GetOptionalUserId(), this.UserHasPermission(UserPermission.AllTimelineManagement)); + return _mapper.MapListAsync(timelines, Url, User); } /// diff --git a/BackEnd/Timeline/Controllers/SearchController.cs b/BackEnd/Timeline/Controllers/SearchController.cs index 33e50e59..76f3d8f2 100644 --- a/BackEnd/Timeline/Controllers/SearchController.cs +++ b/BackEnd/Timeline/Controllers/SearchController.cs @@ -7,7 +7,6 @@ using Timeline.Entities; using Timeline.Models.Http; using Timeline.Services.Api; using Timeline.Services.Mapper; -using Timeline.Services.User; namespace Timeline.Controllers { @@ -20,19 +19,17 @@ namespace Timeline.Controllers public class SearchController : Controller { private readonly ISearchService _service; - private readonly TimelineMapper _timelineMapper; - private readonly UserMapper _userMapper; + private readonly IGenericMapper _mapper; - public SearchController(ISearchService service, TimelineMapper timelineMapper, UserMapper userMapper) + public SearchController(ISearchService service, IGenericMapper mapper) { _service = service; - _timelineMapper = timelineMapper; - _userMapper = userMapper; + _mapper = mapper; } private Task> Map(List timelines) { - return _timelineMapper.MapToHttp(timelines, Url, this.GetOptionalUserId(), this.UserHasPermission(UserPermission.AllTimelineManagement)); + return _mapper.MapListAsync(timelines, Url, User); } /// @@ -62,7 +59,7 @@ namespace Timeline.Controllers { var searchResult = await _service.SearchUser(query); var users = searchResult.Items.Select(i => i.Item).ToList(); - return await _userMapper.MapToHttp(users, Url); + return await _mapper.MapListAsync(users, Url, User); } } } diff --git a/BackEnd/Timeline/Controllers/TimelineController.cs b/BackEnd/Timeline/Controllers/TimelineController.cs index c6b1f9ad..497d7893 100644 --- a/BackEnd/Timeline/Controllers/TimelineController.cs +++ b/BackEnd/Timeline/Controllers/TimelineController.cs @@ -1,5 +1,4 @@ -using AutoMapper; -using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using System; @@ -28,18 +27,15 @@ namespace Timeline.Controllers { private readonly IUserService _userService; private readonly ITimelineService _service; - - private readonly TimelineMapper _timelineMapper; - private readonly IMapper _mapper; + private readonly IGenericMapper _mapper; /// /// /// - public TimelineController(IUserService userService, ITimelineService service, TimelineMapper timelineMapper, IMapper mapper) + public TimelineController(IUserService userService, ITimelineService service, IGenericMapper mapper) { _userService = userService; _service = service; - _timelineMapper = timelineMapper; _mapper = mapper; } @@ -47,12 +43,12 @@ namespace Timeline.Controllers private Task Map(TimelineEntity timeline) { - return _timelineMapper.MapToHttp(timeline, Url, this.GetOptionalUserId(), UserHasAllTimelineManagementPermission); + return _mapper.MapAsync(timeline, Url, User); } private Task> Map(List timelines) { - return _timelineMapper.MapToHttp(timelines, Url, this.GetOptionalUserId(), UserHasAllTimelineManagementPermission); + return _mapper.MapListAsync(timelines, Url, User); } /// @@ -157,7 +153,7 @@ namespace Timeline.Controllers try { - await _service.ChangePropertyAsync(timelineId, _mapper.Map(body)); + await _service.ChangePropertyAsync(timelineId, _mapper.AutoMapperMap(body)); var t = await _service.GetTimelineAsync(timelineId); var result = await Map(t); return result; diff --git a/BackEnd/Timeline/Controllers/TimelinePostController.cs b/BackEnd/Timeline/Controllers/TimelinePostController.cs index cea873b0..2e1ed3a9 100644 --- a/BackEnd/Timeline/Controllers/TimelinePostController.cs +++ b/BackEnd/Timeline/Controllers/TimelinePostController.cs @@ -31,31 +31,31 @@ namespace Timeline.Controllers private readonly ITimelineService _timelineService; private readonly ITimelinePostService _postService; - private readonly TimelineMapper _timelineMapper; + private readonly IGenericMapper _mapper; private readonly MarkdownProcessor _markdownProcessor; /// /// /// - public TimelinePostController(ITimelineService timelineService, ITimelinePostService timelinePostService, TimelineMapper timelineMapper, MarkdownProcessor markdownProcessor) + public TimelinePostController(ITimelineService timelineService, ITimelinePostService timelinePostService, IGenericMapper mapper, MarkdownProcessor markdownProcessor) { _timelineService = timelineService; _postService = timelinePostService; - _timelineMapper = timelineMapper; + _mapper = mapper; _markdownProcessor = markdownProcessor; } private bool UserHasAllTimelineManagementPermission => this.UserHasPermission(UserPermission.AllTimelineManagement); - private Task Map(TimelinePostEntity post, string timelineName) + private Task Map(TimelinePostEntity post) { - return _timelineMapper.MapToHttp(post, timelineName, Url, this.GetOptionalUserId(), UserHasAllTimelineManagementPermission); + return _mapper.MapAsync(post, Url, User); } - private Task> Map(List posts, string timelineName) + private Task> Map(List posts) { - return _timelineMapper.MapToHttp(posts, timelineName, Url, this.GetOptionalUserId(), UserHasAllTimelineManagementPermission); + return _mapper.MapListAsync(posts, Url, User); } /// @@ -80,7 +80,7 @@ namespace Timeline.Controllers var posts = await _postService.GetPostsAsync(timelineId, modifiedSince, includeDeleted ?? false); - var result = await Map(posts, timeline); + var result = await Map(posts); return result; } @@ -104,7 +104,7 @@ namespace Timeline.Controllers } var post = await _postService.GetPostAsync(timelineId, postId); - var result = await Map(post, timeline); + var result = await Map(post); return result; } @@ -213,7 +213,7 @@ namespace Timeline.Controllers try { var post = await _postService.CreatePostAsync(timelineId, userId, createRequest); - var result = await Map(post, timeline); + var result = await Map(post); return result; } catch (TimelinePostCreateDataException e) @@ -245,7 +245,7 @@ namespace Timeline.Controllers } var entity = await _postService.PatchPostAsync(timelineId, post, new TimelinePostPatchRequest { Time = body.Time, Color = body.Color }); - var result = await Map(entity, timeline); + var result = await Map(entity); return Ok(result); } diff --git a/BackEnd/Timeline/Controllers/TokenController.cs b/BackEnd/Timeline/Controllers/TokenController.cs index 3b35fa13..e728ae6d 100644 --- a/BackEnd/Timeline/Controllers/TokenController.cs +++ b/BackEnd/Timeline/Controllers/TokenController.cs @@ -25,15 +25,15 @@ namespace Timeline.Controllers { private readonly IUserTokenManager _userTokenManager; private readonly ILogger _logger; - private readonly UserMapper _userMapper; + private readonly IGenericMapper _mapper; private readonly IClock _clock; /// - public TokenController(IUserTokenManager userTokenManager, ILogger logger, UserMapper userMapper, IClock clock) + public TokenController(IUserTokenManager userTokenManager, ILogger logger, IGenericMapper mapper, IClock clock) { _userTokenManager = userTokenManager; _logger = logger; - _userMapper = userMapper; + _mapper = mapper; _clock = clock; } @@ -72,7 +72,7 @@ namespace Timeline.Controllers return new HttpCreateTokenResponse { Token = result.Token, - User = await _userMapper.MapToHttp(result.User, Url) + User = await _mapper.MapAsync(result.User, Url, User) }; } catch (UserNotExistException e) @@ -113,7 +113,7 @@ namespace Timeline.Controllers ("Username", result.Username), ("Token", request.Token))); return new HttpVerifyTokenResponse { - User = await _userMapper.MapToHttp(result, Url) + User = await _mapper.MapAsync(result, Url, User) }; } catch (UserTokenTimeExpiredException e) diff --git a/BackEnd/Timeline/Controllers/UserController.cs b/BackEnd/Timeline/Controllers/UserController.cs index 38d5d70c..615eac2d 100644 --- a/BackEnd/Timeline/Controllers/UserController.cs +++ b/BackEnd/Timeline/Controllers/UserController.cs @@ -1,4 +1,3 @@ -using AutoMapper; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -28,17 +27,15 @@ namespace Timeline.Controllers private readonly IUserService _userService; private readonly IUserPermissionService _userPermissionService; private readonly IUserDeleteService _userDeleteService; - private readonly UserMapper _userMapper; - private readonly IMapper _mapper; + private readonly IGenericMapper _mapper; /// - public UserController(ILogger logger, IUserService userService, IUserPermissionService userPermissionService, IUserDeleteService userDeleteService, UserMapper userMapper, IMapper mapper) + public UserController(ILogger logger, IUserService userService, IUserPermissionService userPermissionService, IUserDeleteService userDeleteService, IGenericMapper mapper) { _logger = logger; _userService = userService; _userPermissionService = userPermissionService; _userDeleteService = userDeleteService; - _userMapper = userMapper; _mapper = mapper; } @@ -53,7 +50,7 @@ namespace Timeline.Controllers public async Task>> List() { var users = await _userService.GetUsersAsync(); - var result = await _userMapper.MapToHttp(users, Url); + var result = await _mapper.MapListAsync(users, Url, User); return result; } @@ -72,7 +69,7 @@ namespace Timeline.Controllers { var user = await _userService.CreateUserAsync( new CreateUserParams(body.Username, body.Password) { Nickname = body.Nickname }); - return await _userMapper.MapToHttp(user, Url); + return await _mapper.MapAsync(user, Url, User); } catch (EntityAlreadyExistException e) when (e.EntityName == EntityNames.User) { @@ -94,7 +91,7 @@ namespace Timeline.Controllers { var id = await _userService.GetUserIdByUsernameAsync(username); var user = await _userService.GetUserAsync(id); - return await _userMapper.MapToHttp(user, Url); + return await _mapper.MapAsync(user, Url, User); } catch (UserNotExistException e) { @@ -122,8 +119,8 @@ namespace Timeline.Controllers try { var id = await _userService.GetUserIdByUsernameAsync(username); - var user = await _userService.ModifyUserAsync(id, _mapper.Map(body)); - return await _userMapper.MapToHttp(user, Url); + var user = await _userService.ModifyUserAsync(id, _mapper.AutoMapperMap(body)); + return await _mapper.MapAsync(user, Url, User); } catch (UserNotExistException e) { @@ -149,8 +146,8 @@ namespace Timeline.Controllers return StatusCode(StatusCodes.Status403Forbidden, ErrorResponse.Common.CustomMessage_Forbid(UserController_Patch_Forbid_Password)); - var user = await _userService.ModifyUserAsync(this.GetUserId(), _mapper.Map(body)); - return await _userMapper.MapToHttp(user, Url); + var user = await _userService.ModifyUserAsync(this.GetUserId(), _mapper.AutoMapperMap(body)); + return await _mapper.MapAsync(user, Url, User); } } 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 { diff --git a/BackEnd/Timeline/Startup.cs b/BackEnd/Timeline/Startup.cs index b944b99b..994dd7bf 100644 --- a/BackEnd/Timeline/Startup.cs +++ b/BackEnd/Timeline/Startup.cs @@ -86,8 +86,6 @@ namespace Timeline services.AddAuthorization(); services.AddSingleton(); - services.AddAutoMapper(GetType().Assembly); - services.AddMappers(); services.AddDbContext((services, options) => { @@ -104,6 +102,8 @@ namespace Timeline services.AddTimelineServices(); + services.AddMappers(); + services.AddScoped(); services.AddScoped(); services.AddScoped(); diff --git a/BackEnd/Timeline/Timeline.csproj b/BackEnd/Timeline/Timeline.csproj index 3ddcecaf..3c2f3b85 100644 --- a/BackEnd/Timeline/Timeline.csproj +++ b/BackEnd/Timeline/Timeline.csproj @@ -148,6 +148,11 @@ True Resource.resx + + True + True + Resource.resx + True True @@ -257,6 +262,10 @@ ResXFileCodeGenerator Resource.Designer.cs + + ResXFileCodeGenerator + Resource.Designer.cs + ResXFileCodeGenerator Resource.Designer.cs -- cgit v1.2.3