This commit is contained in:
2023-12-01 20:47:42 +02:00
parent a09fc7ece3
commit 045f60e373
39 changed files with 1252 additions and 945 deletions
@@ -5,7 +5,6 @@ using Core.Extensions;
using IdentityModel;
using Microsoft.AspNetCore.Mvc;
using MyOffice.Web.Models;
using static IdentityServer4.Models.IdentityResources;
public class BaseApiController : ControllerBase
{
@@ -0,0 +1,121 @@
namespace MyOffice.Web.Controllers;
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using Core;
using Core.Extensions;
using Models.Account;
using Services.Account;
using Services.Account.Domain;
using Infrastructure.Attributes;
using Services.Identity;
[Authorize]
[ApiController]
[Route("api/[controller]")]
public class SettingsAccountCategoryController : BaseApiController
{
private readonly ILogger<SettingsAccountController> _logger;
private readonly IMapper _mapper;
private readonly AccountService _accountService;
private readonly IContextProvider _contextProvider;
public SettingsAccountCategoryController(
ILogger<SettingsAccountController> logger,
IMapper mapper,
AccountService accountService,
IContextProvider contextProvider
)
{
_logger = logger;
_mapper = mapper;
_accountService = accountService;
_contextProvider = contextProvider;
}
[HttpGet("~/api/settings/account-categories")]
public object AccountCategories()
{
var list = _accountService.GetAllCategories(UserId);
return OkResponse(_mapper.Map<List<AccountCategoryViewModel>>(list).OrderBy(x => x.Name));
}
[HttpGet("~/api/settings/account-categories/{id}")]
public object AccountCategory([AsGuid] string id)
{
var exec = _accountService.GetCategory(UserId, id.AsGuid());
switch (exec.Status)
{
case GeneralExecStatus.not_found:
case GeneralExecStatus.failure:
return ProblemBadResponse("Account category not found.");
case GeneralExecStatus.success:
return _mapper.Map<AccountCategoryViewModel>(exec.Result!);
default:
throw new NotSupportedException(exec.Status.ToString());
}
}
[HttpPost("~/api/settings/account-categories")]
public object AccountCategoriesAdd(AccountCategoryViewModel request)
{
var exec = _accountService.CategoryAdd(UserId, new AccountCategoryDto { Name = request.Name! });
switch (exec.Status)
{
case GeneralExecStatus.success:
return exec.Result!;
case GeneralExecStatus.failure:
case GeneralExecStatus.not_found:
return ProblemBadResponse("Adding account category failed.");
default:
throw new NotSupportedException(exec.Status.ToString());
}
}
[HttpPut("~/api/settings/account-categories/{id}")]
public object AccountCategoriesEdit([AsGuid] string id, AccountCategoryViewModel request)
{
var exec = _accountService.CategoryUpdate(UserId, id.AsGuid(), new AccountCategoryDto { Name = request.Name! });
switch (exec.Status)
{
case GeneralExecStatus.success:
return exec.Result!;
case GeneralExecStatus.failure:
case GeneralExecStatus.not_found:
return ProblemBadResponse("Update account category failed.");
default:
throw new NotSupportedException(exec.Status.ToString());
}
}
[HttpDelete("~/api/settings/account-categories/{id}")]
public object AccountCategoriesDelete([AsGuid] string id)
{
var exec = _accountService.CategoryRemove(UserId, id.AsGuid());
switch (exec.Status)
{
case AccountCategoryRemoveResult.success:
return exec.Result!;
case AccountCategoryRemoveResult.failure:
return ProblemBadResponse("Remove account category failed.");
case AccountCategoryRemoveResult.not_found:
return ProblemBadResponse("Account category not found.");
case AccountCategoryRemoveResult.accounts_exists:
return ProblemBadResponse("Account category have accounts.");
default:
throw new NotSupportedException(exec.Status.ToString());
}
}
}
@@ -35,101 +35,17 @@ public class SettingsAccountController : BaseApiController
_contextProvider = contextProvider;
}
[HttpGet("~/api/settings/account-categories")]
public object AccountCategories()
{
var list = _accountService.GetAllCategories(UserId);
return _mapper.Map<AccountCategoryViewModel[]>(list).OrderBy(x => x.Name);
}
[HttpGet("~/api/settings/account-categories/{id}")]
public object AccountCategory([AsGuid] string id)
{
var exec = _accountService.GetCategory(UserId, id.AsGuid());
switch (exec.Status)
{
case GeneralExecStatus.not_found:
case GeneralExecStatus.failure:
return ProblemBadResponse("Account category not found.");
case GeneralExecStatus.success:
return _mapper.Map<AccountCategoryViewModel>(exec.Result!);
default:
throw new NotSupportedException(exec.Status.ToString());
}
}
[HttpPost("~/api/settings/account-categories")]
public object AccountCategoriesAdd(AccountCategoryViewModel request)
{
var exec = _accountService.CategoryAdd(UserId, new AccountCategoryDto { Name = request.Name! });
switch (exec.Status)
{
case GeneralExecStatus.success:
return exec.Result!;
case GeneralExecStatus.failure:
case GeneralExecStatus.not_found:
return ProblemBadResponse("Adding account category failed.");
default:
throw new NotSupportedException(exec.Status.ToString());
}
}
[HttpPut("~/api/settings/account-categories/{id}")]
public object AccountCategoriesEdit([AsGuid] string id, AccountCategoryViewModel request)
{
var exec = _accountService.CategoryUpdate(UserId, id.AsGuid(), new AccountCategoryDto { Name = request.Name! });
switch (exec.Status)
{
case GeneralExecStatus.success:
return exec.Result!;
case GeneralExecStatus.failure:
case GeneralExecStatus.not_found:
return ProblemBadResponse("Update account category failed.");
default:
throw new NotSupportedException(exec.Status.ToString());
}
}
[HttpDelete("~/api/settings/account-categories/{id}")]
public object AccountCategoriesDelete([AsGuid] string id)
{
var exec = _accountService.CategoryRemove(UserId, id.AsGuid());
switch (exec.Status)
{
case AccountCategoryRemoveResult.success:
return exec.Result!;
case AccountCategoryRemoveResult.failure:
return ProblemBadResponse("Remove account category failed.");
case AccountCategoryRemoveResult.not_found:
return ProblemBadResponse("Account category not found.");
case AccountCategoryRemoveResult.accounts_exists:
return ProblemBadResponse("Account category have accounts.");
default:
throw new NotSupportedException(exec.Status.ToString());
}
}
[HttpGet("~/api/settings/accounts")]
public List<AccountViewModel> AccountsGet([AsGuid(true)] string? category)
public ObjectResult AccountsGet([AsGuid(true)] string? category)
{
var list = category.IsPresent()
? _accountService.GetByCategory(UserId, category!.AsGuid())
: _accountService.GetAllAccounts(UserId);
return _mapper.Map<List<AccountViewModel>>(list.OrderBy(x => x.Name));
return OkResponse(list.ToViewModel(_mapper));
}
[HttpPost("~/api/settings/accounts")]
//[HttpPost("~/api/settings/accounts")]
public object AccountsAdd(AccountViewModel request)
{
var exec = _accountService.AccountAdd(UserId, new AccountAdd
@@ -149,7 +65,7 @@ public class SettingsAccountController : BaseApiController
case AccountAddStatus.failure:
return ProblemBadResponse("Adding account failed.");
case AccountAddStatus.success:
return exec.Result!;
return _mapper.Map<AccountViewModel>(exec.Result!);
default:
throw new NotSupportedException(exec.Status.ToString());
@@ -180,7 +96,7 @@ public class SettingsAccountController : BaseApiController
case AccountEditStatus.failure:
return ProblemBadResponse("Adding account failed.");
case AccountEditStatus.success:
return exec.Result!;
return _mapper.Map<AccountViewModel>(exec.Result!);
default:
throw new NotSupportedException(exec.Status.ToString());
@@ -196,7 +112,7 @@ public class SettingsAccountController : BaseApiController
case GeneralExecStatus.not_found:
return ProblemBadResponse("Account not found.");
case GeneralExecStatus.success:
return exec.Result!;
return _mapper.Map<AccountViewModel>(exec.Result!);
default:
throw new NotSupportedException(exec.Status.ToString());
@@ -0,0 +1,50 @@
namespace MyOffice.Web.Infrastructure;
using System.Linq.Expressions;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
public static class RouteHelperExtensions
{
public static void Bind<T>(this IRouteBuilder routeBuilder, Expression<Func<T, ObjectResult>> expression)
{
System.Console.WriteLine("Bind");
System.Console.WriteLine(expression.Name);
System.Console.WriteLine(expression.Body.ToString());
routeBuilder.MapRoute("SettingsAccountAccountsGet", "api/settings/accounts", new { controller = "SettingsAccount", action = "AccountsGet" });
}
}
public class CustomRouter : IRouter
{
private readonly IRouter _defaultRouter;
private readonly string _controller;
private readonly string _action;
public CustomRouter(IRouter defaultRouter, string controller, string action)
{
_defaultRouter = defaultRouter;
_controller = controller;
_action = action;
}
public VirtualPathData? GetVirtualPath(VirtualPathContext context)
{
Console.WriteLine($"1:{context.RouteName}");
return null;
}
public async Task RouteAsync(RouteContext context)
{
var headers = context.HttpContext.Request.Headers;
var path = context.HttpContext.Request.Path.Value!.Split('/');
Console.WriteLine($"CustomRouter:{context.HttpContext.Request.Path.Value}");
context.RouteData.Values["controller"] = _controller;
context.RouteData.Values["action"] = _action;
await _defaultRouter.RouteAsync(context);
}
}
@@ -1,24 +1,13 @@
namespace MyOffice.Web.Models.Account
namespace MyOffice.Web.Models.Account;
using User;
public class AccessRightsViewModel
{
using Newtonsoft.Json;
using User;
public class AccessRightsViewModel
{
public UserViewModel User { get; set; } = null!;
public bool IsAllowRead { get; set; }
public bool IsAllowWrite { get; set; }
public bool IsAllowManage { get; set; }
public bool IsAllowDelete { get; set; }
public bool IsOwner { get; set; }
#region DEBUG
[JsonIgnore]
public Guid UserId { get; set; }
[JsonIgnore]
public Guid OwnerId { get; set; }
#endregion DEBUG
}
public UserViewModel? User { get; set; } = null!;
public bool AllowRead { get; set; }
public bool AllowWrite { get; set; }
public bool AllowManage { get; set; }
public bool AllowDelete { get; set; }
public bool IsOwner { get; set; }
}
@@ -5,7 +5,7 @@ using MyOffice.Services.Account.Domain;
using System.ComponentModel.DataAnnotations;
[Link(typeof(AccountCategoryDto))]
public class AccountCategoryViewModel
public class AccountCategoryViewModel: IResponseModel
{
public string? Id { get; set; }
+89 -37
View File
@@ -1,42 +1,94 @@
namespace MyOffice.Web.Models.Account
namespace MyOffice.Web.Models.Account;
using AutoMapper;
using MyOffice.Services.Account.Domain;
using MyOffice.Services.Identity;
using Newtonsoft.Json;
using System.ComponentModel.DataAnnotations;
public class AccountViewModel: IResponseModel
{
using Newtonsoft.Json;
using System.ComponentModel.DataAnnotations;
public string? Id { get; set; }
public class AccountViewModel
[Required]
public string Name { get; set; } = null!;
public string Type { get; set; } = null!;
[Required]
public string CurrencyId { get; set; } = null!;
public string? CurrencyName { get; set; }
public List<AccountCategoryViewModel>? Categories { get; set; }
[Required]
public string CategoryId { get; set; } = null!;
#region Permissions
public List<AccessRightsViewModel>? AccessRights { get; set; }
public bool AllowRead { get; set; }
public bool AllowWrite { get; set; }
public bool AllowDelete { get; set; }
public bool AllowManage { get; set; }
#endregion Permissions
}
public static class AccountViewModelExtensions
{
public static List<AccountViewModel> ToViewModel(this List<AccountDto> accounts, IMapper mapper)
{
public string? Id { get; set; }
[Required]
public string Name { get; set; } = null!;
public string Type { get; set; } = null!;
[Required]
public string CurrencyId { get; set; } = null!;
public string? CurrencyName { get; set; }
public bool AllowDelete { get; set; }
public bool AllowManage { get; set; }
public List<AccountCategoryViewModel>? Categories { get; set; }
[Required]
public string CategoryId { get; set; } = null!;
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public List<AccessRightsViewModel>? AccessRights { get; set; }
}
public class AccountAccessViewModel
{
public class AccountAccessItemViewModel
{
public string UserId { get; set; } = null!;
public bool AllowWrite { get; set; }
}
public string? Email { get; set; }
public bool AllowWrite { get; set; }
public List<AccountAccessItemViewModel> Accesses { get; set; } = null!;
return mapper.Map<List<AccountViewModel>>(accounts.OrderBy(x => x.Name));
}
}
public class AccountAccessViewModel
{
public class AccountAccessItemViewModel
{
public string UserId { get; set; } = null!;
public bool AllowWrite { get; set; }
}
public string? Email { get; set; }
public bool AllowWrite { get; set; }
public List<AccountAccessItemViewModel> Accesses { get; set; } = null!;
}
public class AccountViewModelProfile : Profile
{
public AccountViewModelProfile()
{
CreateMap<AccountDto, AccountViewModel>()
.ForMember(x => x.CurrencyId, o => o.MapFrom(x => x.CurrencyGlobalId))
.ForMember(x => x.CurrencyName, o => o.MapFrom(x => x.Currency!.Name))
.AfterMap<AccountViewModelMappingAction>()
;
CreateMap<AccountAccessDto, AccessRightsViewModel>()
.AfterMap<AccessRightsViewModelMappingAction>()
;
}
}
public class AccountViewModelMappingAction : IMappingAction<AccountDto, AccountViewModel>
{
public void Process(AccountDto source, AccountViewModel destination, ResolutionContext context)
{
}
}
public class AccessRightsViewModelMappingAction : IMappingAction<AccountAccessDto, AccessRightsViewModel>
{
private readonly IContextProvider _contextProvider;
public AccessRightsViewModelMappingAction(IContextProvider contextProvider)
{
_contextProvider = contextProvider;
}
public void Process(AccountAccessDto source, AccessRightsViewModel destination, ResolutionContext context)
{
}
}
@@ -3,14 +3,14 @@
using AutoMapper;
using MyOffice.Services.Currency.Domain;
using MyOffice.Services.Identity;
using Currency;
using Item;
using Motion;
using Services.Account.Domain;
using User;
using MyOffice.Services.Identity;
public class CustomResolver : IValueResolver<AccountAccessDto, AccessRightsViewModel, bool>
/*public class CustomResolver : IValueResolver<AccountAccessDto, AccessRightsViewModel, bool>
{
private readonly ILogger<CustomResolver> _logger;
private readonly IContextProvider _contextProvider;
@@ -28,11 +28,28 @@ public class CustomResolver : IValueResolver<AccountAccessDto, AccessRightsViewM
{
return source.OwnerId == _contextProvider.UserId;
}
}*/
public class PublicationSystemResolver : IMemberValueResolver<object, object, string, bool>
{
private readonly IContextProvider _contextProvider;
public PublicationSystemResolver(
IContextProvider contextProvider
)
{
this._contextProvider = contextProvider;
}
public bool Resolve(object source, object destination, string sourceMember, bool destMember, ResolutionContext context)
{
return true;
}
}
public class AccountViewModelProfile : Profile
public class AccountViewModelGeneralProfile : Profile
{
public AccountViewModelProfile()
public AccountViewModelGeneralProfile()
{
CreateMap<AccountDetailedDto, AccountDetailedViewModel>()
.ForMember(x => x.Account, o => o.MapFrom(x => x.Account))
@@ -42,26 +59,11 @@ public class AccountViewModelProfile : Profile
CreateMap<MyOffice.Data.Models.Users.User, UserViewModel>();
CreateMap<AccountDto, AccountViewModel>()
.ForMember(x => x.CurrencyId, o => o.MapFrom(x => x.CurrencyGlobalId))
.ForMember(x => x.CurrencyName, o => o.MapFrom(x => x.Currency!.Name))
.ForMember(x => x.AllowDelete, o => o.MapFrom(x => !x.HasMotions))
.ForMember(x => x.AllowManage, o => o.MapFrom(x => x.AccessRights!.Any(a => a.OwnerId == x.CurrentUserId)))
.ForMember(x => x.AccessRights, o => o.MapFrom((s, d) => s.OwnerId != s.CurrentUserId ? null : s.AccessRights))
;
CreateMap<AccountAccountCategoryDto, AccountCategoryViewModel>()
.ForMember(x => x.Id, o => o.MapFrom(x => x.CategoryId))
.ForMember(x => x.Name, o => o.MapFrom(x => x.Category!.Name))
;
CreateMap<AccountAccessDto, AccessRightsViewModel>()
.ForMember(x => x.IsAllowDelete, o => o.MapFrom(
(src, dst) => src.Account!.OwnerId == src.Account.CurrentUserId && src.UserId != src.Account.CurrentUserId))
.ForMember(x => x.IsOwner, o => o.MapFrom(
(src, dst) => src.OwnerId == src.UserId))
;
CreateMap<AccountAccessViewModel.AccountAccessItemViewModel, AccountAccessDto>()
.ForMember(x => x.IsAllowWrite, o => o.MapFrom(x => x.AllowWrite))
;
+9 -23
View File
@@ -1,25 +1,11 @@
namespace MyOffice.Web.Models.User
namespace MyOffice.Web.Models.User;
using Core.Extensions;
using MyOffice.Data.Models.Users;
public class UserViewModel
{
using Core.Extensions;
using MyOffice.Data.Models.Users;
public class UserViewModel
{
public string Id { get; set; } = null!;
public string UserName { get; set; } = null!;
public string Email { get; set; } = null!;
}
public static class UserViewModelExtensions
{
public static UserViewModel ToModel(this User user)
{
return new UserViewModel
{
Id = user.Id.ToShort(),
UserName = user.UserName,
Email = user.Email,
};
}
}
public string Id { get; set; } = null!;
public string UserName { get; set; } = null!;
public string Email { get; set; } = null!;
}
+4 -2
View File
@@ -44,6 +44,7 @@ using Services.Item;
using MyOffice.Services.Dashboard;
using MyOffice.Services.Identity;
using MyOffice.Services.Mapper;
using MyOffice.Services.Account.Domain;
//TODO: Data.Model only Repository and Service, response <-> mapper <-> web <-> mapper <-> service <-> repository
//TODO: Project management
@@ -252,8 +253,8 @@ public class Program
c.AllowNullCollections = true;
c.AllowNullDestinationValues = true;
},
typeof(AccountViewModelProfile),
typeof(AccountServiceProfile)
typeof(AccountDto).Assembly,
typeof(AccountViewModel).Assembly
);
}
@@ -421,6 +422,7 @@ public class Program
.AllowAnyMethod());
app.UseIdentityServer();
//app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();