feat : complex signup , unit of work , sms service
complete complex sign up , add new methods to unit of work , add sms servicerelease/production
parent
034b5270bb
commit
02abd6ddf3
|
@ -59,6 +59,7 @@
|
||||||
<Using Include="Brizco.Common.Models.Mapper" />
|
<Using Include="Brizco.Common.Models.Mapper" />
|
||||||
<Using Include="Brizco.Domain.CommandQueries.Commands" />
|
<Using Include="Brizco.Domain.CommandQueries.Commands" />
|
||||||
<Using Include="Brizco.Domain.CommandQueries.Queries" />
|
<Using Include="Brizco.Domain.CommandQueries.Queries" />
|
||||||
|
<Using Include="Brizco.Domain.Dtos.RequestDtos" />
|
||||||
<Using Include="Brizco.Domain.Entities" />
|
<Using Include="Brizco.Domain.Entities" />
|
||||||
<Using Include="Brizco.Repository.Repositories.Base.Contracts" />
|
<Using Include="Brizco.Repository.Repositories.Base.Contracts" />
|
||||||
<Using Include="Carter" />
|
<Using Include="Carter" />
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
using Brizco.Common.Models.Api;
|
||||||
|
using Brizco.Core.BaseServices;
|
||||||
|
using Brizco.Core.BaseServices.Abstracts;
|
||||||
|
using Microsoft.AspNetCore.Authorization.Infrastructure;
|
||||||
|
|
||||||
|
namespace Brizco.Api.Controllers;
|
||||||
|
|
||||||
|
public class AuthController : ICarterModule
|
||||||
|
{
|
||||||
|
|
||||||
|
public virtual void AddRoutes(IEndpointRouteBuilder app)
|
||||||
|
{
|
||||||
|
var group = app.NewVersionedApi("Auth")
|
||||||
|
.MapGroup($"api/auth");
|
||||||
|
|
||||||
|
group.MapPost("login/password", LoginWithPassword)
|
||||||
|
.WithDisplayName("LoginWithPassword")
|
||||||
|
.HasApiVersion(1.0);
|
||||||
|
|
||||||
|
group.MapPost("login/code", LoginWithVerifyCode)
|
||||||
|
.WithDisplayName("LoginWithVerifyCode")
|
||||||
|
.HasApiVersion(1.0);
|
||||||
|
|
||||||
|
group.MapGet("verifycode", GetVerifyCodeCode)
|
||||||
|
.WithDisplayName("GetVerifyCodeCode")
|
||||||
|
.HasApiVersion(1.0);
|
||||||
|
|
||||||
|
group.MapPut("forgetpassword", ForgetPassword)
|
||||||
|
.WithDisplayName("ForgetPassword")
|
||||||
|
.HasApiVersion(1.0);
|
||||||
|
|
||||||
|
group.MapPost("signup/complex", SignUpComplex)
|
||||||
|
.WithDisplayName("SignUp")
|
||||||
|
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser())
|
||||||
|
.HasApiVersion(1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IResult> SignUpComplex([FromBody] SignUpRequestDto request, IAccountService accountService, CancellationToken cancellationToken) =>
|
||||||
|
TypedResults.Ok(await accountService.CompleteComplexSignUpAsync(request,cancellationToken));
|
||||||
|
|
||||||
|
public async Task<IResult> LoginWithPassword([FromBody] LoginRequestDto loginRequestDto,IAccountService accountService, CancellationToken cancellationToken) =>
|
||||||
|
TypedResults.Ok(await accountService.LoginWithPasswordAsync(loginRequestDto.UserName, loginRequestDto.Password,cancellationToken));
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<IResult> LoginWithVerifyCode([FromBody] LoginRequestDto loginRequestDto, IAccountService accountService, CancellationToken cancellationToken) =>
|
||||||
|
TypedResults.Ok(await accountService.LoginWithVerifyCodeAsync(loginRequestDto.UserName, loginRequestDto.VerifyCode,cancellationToken));
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<IResult> GetVerifyCodeCode([FromQuery] string phoneNumber, IAccountService accountService) =>
|
||||||
|
TypedResults.Ok(await accountService.GetVerifyCodeAsync(phoneNumber));
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<IResult> ForgetPassword([FromQuery] string phoneNumber, IAccountService accountService) =>
|
||||||
|
TypedResults.Ok(await accountService.ForgetPasswordAsync(phoneNumber));
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<IResult> LoginSwagger([FromForm] TokenRequest tokenRequest, IAccountService accountService, CancellationToken cancellationToken)
|
||||||
|
=> TypedResults.Json(await accountService.LoginWithPasswordAsync(tokenRequest.username, tokenRequest.password,cancellationToken));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -96,11 +96,14 @@ var app = builder.Build();
|
||||||
// Configure the HTTP request pipeline.
|
// Configure the HTTP request pipeline.
|
||||||
if (app.Environment.IsDevelopment())
|
if (app.Environment.IsDevelopment())
|
||||||
{
|
{
|
||||||
app.UseSwagger();
|
app.UseCustomSwagger(siteSetting.BaseUrl);
|
||||||
app.UseSwaggerUI();
|
//app.UseSwagger();
|
||||||
|
//app.UseSwaggerUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
app.UseAuthorization();
|
app.UseAuthorization();
|
||||||
|
app.UseAuthentication();
|
||||||
|
|
||||||
app.UseCors(x => x
|
app.UseCors(x => x
|
||||||
.SetIsOriginAllowed(origin => true)
|
.SetIsOriginAllowed(origin => true)
|
||||||
.AllowAnyMethod()
|
.AllowAnyMethod()
|
||||||
|
@ -109,7 +112,6 @@ app.UseCors(x => x
|
||||||
|
|
||||||
app.UseExceptionHandlerMiddleware();
|
app.UseExceptionHandlerMiddleware();
|
||||||
|
|
||||||
app.UseCustomSwagger(siteSetting.BaseUrl);
|
|
||||||
app.MapCarter();
|
app.MapCarter();
|
||||||
app.UseStaticFiles();
|
app.UseStaticFiles();
|
||||||
await app.InitialDb();
|
await app.InitialDb();
|
||||||
|
|
|
@ -11,7 +11,25 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Models\" />
|
<PackageReference Include="Refit" Version="6.3.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Models\RestApi\KaveNegar\" />
|
||||||
|
<Folder Include="Services\" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="Brizco.Common.Models" />
|
||||||
|
<Using Include="Brizco.Common.Models.Api" />
|
||||||
|
<Using Include="Brizco.Common.Models.Exception" />
|
||||||
|
<Using Include="Brizco.Core.Abstracts" />
|
||||||
|
<Using Include="Brizco.Domain.Models.Settings" />
|
||||||
|
<Using Include="Brizco.Infrastructure.Models" />
|
||||||
|
<Using Include="Brizco.Infrastructure.RestServices" />
|
||||||
|
<Using Include="Microsoft.Extensions.Logging" />
|
||||||
|
<Using Include="Microsoft.Extensions.Options" />
|
||||||
|
<Using Include="Refit" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
namespace Brizco.Infrastructure.Models;
|
||||||
|
|
||||||
|
public static class RestAddress
|
||||||
|
{
|
||||||
|
public static string BaseKaveNegar { get => "https://api.kavenegar.com/v1/"; }
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace Brizco.Infrastructure.Models.RestApi.KaveNegar;
|
||||||
|
|
||||||
|
public class KaveNegarResponse
|
||||||
|
{
|
||||||
|
public KaveNegarReturn Return { get; set; }
|
||||||
|
public KaveNegarResponseEntry[] entries { get; set; }
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
namespace Brizco.Infrastructure.Models.RestApi.KaveNegar;
|
||||||
|
|
||||||
|
public class KaveNegarResponseEntry
|
||||||
|
{
|
||||||
|
public int messageid { get; set; }
|
||||||
|
public string message { get; set; }
|
||||||
|
public int status { get; set; }
|
||||||
|
public string statustext { get; set; }
|
||||||
|
public string sender { get; set; }
|
||||||
|
public string receptor { get; set; }
|
||||||
|
public int date { get; set; }
|
||||||
|
public int cost { get; set; }
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace Brizco.Infrastructure.Models.RestApi.KaveNegar;
|
||||||
|
|
||||||
|
public class KaveNegarReturn
|
||||||
|
{
|
||||||
|
public int status { get; set; }
|
||||||
|
public string message { get; set; }
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
using Brizco.Infrastructure.Models.RestApi.KaveNegar;
|
||||||
|
|
||||||
|
namespace Brizco.Infrastructure.RestServices;
|
||||||
|
|
||||||
|
public interface IKaveNegarRestApi
|
||||||
|
{
|
||||||
|
|
||||||
|
[Post("/{apiKey}/verify/lookup.json")]
|
||||||
|
Task<KaveNegarResponse> SendLookUp(string apiKey, [Query] string receptor, [Query] string token, [Query] string token2, [Query] string token10, [Query] string token20, [Query] string template);
|
||||||
|
[Post("/{apiKey}/sms/send.json")]
|
||||||
|
Task<KaveNegarResponse> SendSms(string apiKey, [Query] string receptor, [Query] string message, [Query] string sender);
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
namespace Brizco.Infrastructure.RestServices;
|
||||||
|
|
||||||
|
public interface IRestApiWrapper : IScopedDependency
|
||||||
|
{
|
||||||
|
IKaveNegarRestApi KaveNegarRestApi { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RestApiWrapper : IRestApiWrapper
|
||||||
|
{
|
||||||
|
public IKaveNegarRestApi KaveNegarRestApi => RestService.For<IKaveNegarRestApi>(RestAddress.BaseKaveNegar);
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
namespace Brizco.Infrastructure.Services;
|
||||||
|
|
||||||
|
public class SmsService : ISmsService
|
||||||
|
{
|
||||||
|
private readonly IRestApiWrapper _restApiWrapper;
|
||||||
|
private readonly ILogger<SmsService> _logger;
|
||||||
|
private readonly SiteSettings _siteSettings;
|
||||||
|
public SmsService(IRestApiWrapper restApiWrapper,
|
||||||
|
IOptionsSnapshot<SiteSettings> optionsSnapshot,
|
||||||
|
ILogger<SmsService> logger)
|
||||||
|
{
|
||||||
|
_restApiWrapper = restApiWrapper;
|
||||||
|
_logger = logger;
|
||||||
|
_siteSettings = optionsSnapshot.Value;
|
||||||
|
}
|
||||||
|
public async Task SendForgerPasswordAsync(string phoneNumber, string newPassword)
|
||||||
|
{
|
||||||
|
var rest = await _restApiWrapper.KaveNegarRestApi.SendLookUp(_siteSettings.KaveNegarApiKey, phoneNumber, newPassword, null, null, null, "forgetPassword");
|
||||||
|
|
||||||
|
if (rest.Return.status != 200)
|
||||||
|
throw new BaseApiException(ApiResultStatusCode.SendSmsError, rest.Return.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SendVerifyCodeAsync(string phoneNumber, string verifyCode)
|
||||||
|
{
|
||||||
|
|
||||||
|
var rest = await _restApiWrapper.KaveNegarRestApi.SendLookUp(_siteSettings.KaveNegarApiKey, phoneNumber, verifyCode, null, null, null, "login");
|
||||||
|
|
||||||
|
if (rest.Return.status != 200)
|
||||||
|
throw new BaseApiException(ApiResultStatusCode.SendSmsError, rest.Return.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -29,8 +29,6 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Models\" />
|
<Folder Include="Models\" />
|
||||||
<Folder Include="Extensions\" />
|
<Folder Include="Extensions\" />
|
||||||
<Folder Include="Repositories\Base\" />
|
|
||||||
<Folder Include="Repositories\UnitOfWork\" />
|
|
||||||
<Folder Include="Services\Contracts\" />
|
<Folder Include="Services\Contracts\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,9 @@ public class CreateActivityCommandHandler : IRequestHandler<CreateActivityComman
|
||||||
throw new AppException("ComplexId is null", ApiResultStatusCode.NotFound);
|
throw new AppException("ComplexId is null", ApiResultStatusCode.NotFound);
|
||||||
if (!Guid.TryParse(_currentUserService.ComplexId, out Guid complexId))
|
if (!Guid.TryParse(_currentUserService.ComplexId, out Guid complexId))
|
||||||
throw new AppException("ComplexId is wrong", ApiResultStatusCode.NotFound);
|
throw new AppException("ComplexId is wrong", ApiResultStatusCode.NotFound);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _repositoryWrapper.BeginTransaction(cancellationToken);
|
||||||
var task = Domain.Entities.Task.Activity
|
var task = Domain.Entities.Task.Activity
|
||||||
.Create(
|
.Create(
|
||||||
request.Status,
|
request.Status,
|
||||||
|
@ -46,7 +48,8 @@ public class CreateActivityCommandHandler : IRequestHandler<CreateActivityComman
|
||||||
if (task.IsRelatedToRole)
|
if (task.IsRelatedToRole)
|
||||||
{
|
{
|
||||||
if (request.Roles.Count == 0)
|
if (request.Roles.Count == 0)
|
||||||
throw new AppException("اگر فعالیت برای یک گروه نقش انتخاب شده باشد باید لیست نقش ها را ارسال نمایید");
|
throw new AppException(
|
||||||
|
"اگر فعالیت برای یک گروه نقش انتخاب شده باشد باید لیست نقش ها را ارسال نمایید");
|
||||||
task.AddShift(request.Roles.ToArray());
|
task.AddShift(request.Roles.ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +62,13 @@ public class CreateActivityCommandHandler : IRequestHandler<CreateActivityComman
|
||||||
|
|
||||||
_repositoryWrapper.SetRepository<Domain.Entities.Task.Activity>().Add(task);
|
_repositoryWrapper.SetRepository<Domain.Entities.Task.Activity>().Add(task);
|
||||||
await _repositoryWrapper.SaveChangesAsync(cancellationToken);
|
await _repositoryWrapper.SaveChangesAsync(cancellationToken);
|
||||||
|
await _repositoryWrapper.CommitAsync(cancellationToken);
|
||||||
return task.AdaptToLDto();
|
return task.AdaptToLDto();
|
||||||
}
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
await _repositoryWrapper.RollBackAsync(cancellationToken);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -10,6 +10,9 @@ public class DeleteActivityCommandHandler : IRequestHandler<DeleteActivityComman
|
||||||
}
|
}
|
||||||
public async Task<bool> Handle(DeleteActivityCommand request, CancellationToken cancellationToken)
|
public async Task<bool> Handle(DeleteActivityCommand request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _repositoryWrapper.BeginTransaction(cancellationToken);
|
||||||
var task = await _repositoryWrapper.SetRepository<Domain.Entities.Task.Activity>()
|
var task = await _repositoryWrapper.SetRepository<Domain.Entities.Task.Activity>()
|
||||||
.TableNoTracking
|
.TableNoTracking
|
||||||
.FirstOrDefaultAsync(s => s.Id == request.Id, cancellationToken);
|
.FirstOrDefaultAsync(s => s.Id == request.Id, cancellationToken);
|
||||||
|
@ -19,6 +22,13 @@ public class DeleteActivityCommandHandler : IRequestHandler<DeleteActivityComman
|
||||||
.Delete(task);
|
.Delete(task);
|
||||||
|
|
||||||
await _repositoryWrapper.SaveChangesAsync(cancellationToken);
|
await _repositoryWrapper.SaveChangesAsync(cancellationToken);
|
||||||
|
await _repositoryWrapper.CommitAsync(cancellationToken);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
catch (Exception )
|
||||||
|
{
|
||||||
|
await _repositoryWrapper.RollBackAsync(cancellationToken);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -12,7 +12,7 @@ public class GetActivitiesQueryHandler : IRequestHandler<GetActivitiesQuery, Lis
|
||||||
{
|
{
|
||||||
var tasks = await _repositoryWrapper.SetRepository<Domain.Entities.Task.Activity>().TableNoTracking
|
var tasks = await _repositoryWrapper.SetRepository<Domain.Entities.Task.Activity>().TableNoTracking
|
||||||
.OrderByDescending(s => s.CreatedAt)
|
.OrderByDescending(s => s.CreatedAt)
|
||||||
.Skip(request.page * 15).Take(15)
|
.Skip(request.Page * 15).Take(15)
|
||||||
.Select(ActivityMapper.ProjectToSDto)
|
.Select(ActivityMapper.ProjectToSDto)
|
||||||
.ToListAsync(cancellationToken);
|
.ToListAsync(cancellationToken);
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ public class GetActivityQueryHandler : IRequestHandler<GetActivityQuery, Activit
|
||||||
{
|
{
|
||||||
var task = await _repositoryWrapper.SetRepository<Domain.Entities.Task.Activity>()
|
var task = await _repositoryWrapper.SetRepository<Domain.Entities.Task.Activity>()
|
||||||
.TableNoTracking
|
.TableNoTracking
|
||||||
.Where(s => s.Id == request.id)
|
.Where(s => s.Id == request.Id)
|
||||||
.Select(ActivityMapper.ProjectToLDto)
|
.Select(ActivityMapper.ProjectToLDto)
|
||||||
.FirstOrDefaultAsync(cancellationToken);
|
.FirstOrDefaultAsync(cancellationToken);
|
||||||
if (task == null)
|
if (task == null)
|
||||||
|
|
|
@ -22,6 +22,9 @@ public class UpdateActivityCommandHandler : IRequestHandler<UpdateActivityComman
|
||||||
if (!Guid.TryParse(_currentUserService.ComplexId,out Guid complexId))
|
if (!Guid.TryParse(_currentUserService.ComplexId,out Guid complexId))
|
||||||
throw new AppException("ComplexId is wrong", ApiResultStatusCode.NotFound);
|
throw new AppException("ComplexId is wrong", ApiResultStatusCode.NotFound);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _repositoryWrapper.BeginTransaction(cancellationToken);
|
||||||
var newTask = Domain.Entities.Task.Activity.Create(
|
var newTask = Domain.Entities.Task.Activity.Create(
|
||||||
request.Status,
|
request.Status,
|
||||||
request.DoneAt,
|
request.DoneAt,
|
||||||
|
@ -44,7 +47,14 @@ public class UpdateActivityCommandHandler : IRequestHandler<UpdateActivityComman
|
||||||
_repositoryWrapper.SetRepository<Domain.Entities.Task.Activity>()
|
_repositoryWrapper.SetRepository<Domain.Entities.Task.Activity>()
|
||||||
.Update(newTask);
|
.Update(newTask);
|
||||||
await _repositoryWrapper.SaveChangesAsync(cancellationToken);
|
await _repositoryWrapper.SaveChangesAsync(cancellationToken);
|
||||||
|
await _repositoryWrapper.CommitAsync(cancellationToken);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
catch (Exception )
|
||||||
|
{
|
||||||
|
await _repositoryWrapper.RollBackAsync(cancellationToken);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -13,9 +13,19 @@ public class CreateComplexCommandHandler : IRequestHandler<CreateComplexCommand,
|
||||||
|
|
||||||
public async Task<ComplexSDto> Handle(CreateComplexCommand request, CancellationToken cancellationToken)
|
public async Task<ComplexSDto> Handle(CreateComplexCommand request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _repositoryWrapper.BeginTransaction(cancellationToken);
|
||||||
var complex = Domain.Entities.Complex.Complex.Create(request.Name, request.Address, request.SupportPhone);
|
var complex = Domain.Entities.Complex.Complex.Create(request.Name, request.Address, request.SupportPhone);
|
||||||
_repositoryWrapper.SetRepository<Domain.Entities.Complex.Complex>().Add(complex);
|
_repositoryWrapper.SetRepository<Domain.Entities.Complex.Complex>().Add(complex);
|
||||||
await _repositoryWrapper.SaveChangesAsync(cancellationToken);
|
await _repositoryWrapper.SaveChangesAsync(cancellationToken);
|
||||||
|
await _repositoryWrapper.CommitAsync(cancellationToken);
|
||||||
return complex.AdaptToSDto();
|
return complex.AdaptToSDto();
|
||||||
}
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
await _repositoryWrapper.RollBackAsync(cancellationToken);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
using Brizco.Domain.Entities.User;
|
||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
|
||||||
|
namespace Brizco.Repository.Handlers.Complex;
|
||||||
|
|
||||||
|
public class CreateComplexUserCommandHandler : IRequestHandler<CreateComplexUserCommand, ComplexUserSDto>
|
||||||
|
{
|
||||||
|
private readonly IRepositoryWrapper _repositoryWrapper;
|
||||||
|
private readonly UserManager<ApplicationUser> _userManager;
|
||||||
|
private readonly RoleManager<ApplicationRole> _roleManager;
|
||||||
|
private readonly ILogger<CreateComplexUserCommandHandler> _logger;
|
||||||
|
|
||||||
|
public CreateComplexUserCommandHandler(IRepositoryWrapper repositoryWrapper,
|
||||||
|
UserManager<ApplicationUser> userManager,
|
||||||
|
RoleManager<ApplicationRole> roleManager,
|
||||||
|
ILogger<CreateComplexUserCommandHandler> logger)
|
||||||
|
{
|
||||||
|
_repositoryWrapper = repositoryWrapper;
|
||||||
|
_userManager = userManager;
|
||||||
|
_roleManager = roleManager;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<ComplexUserSDto> Handle(CreateComplexUserCommand request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _repositoryWrapper.BeginTransaction(cancellationToken);
|
||||||
|
var complex = await _repositoryWrapper.SetRepository<Domain.Entities.Complex.Complex>().TableNoTracking
|
||||||
|
.FirstOrDefaultAsync(c => c.Id == request.ComplexId, cancellationToken);
|
||||||
|
if (complex == null)
|
||||||
|
throw new AppException("Complex not found", ApiResultStatusCode.NotFound);
|
||||||
|
|
||||||
|
var complexUser = complex.AddComplexUser(request.UserId, request.RoleId);
|
||||||
|
_repositoryWrapper.SetRepository<Domain.Entities.Complex.Complex>().Update(complex);
|
||||||
|
var role = await _roleManager.FindByIdAsync(request.RoleId.ToString());
|
||||||
|
var user = await _userManager.FindByIdAsync(request.UserId.ToString());
|
||||||
|
var result = await _userManager.AddToRoleAsync(user, role.Name);
|
||||||
|
if (!result.Succeeded)
|
||||||
|
throw new AppException(string.Join('|', result.Errors));
|
||||||
|
await _repositoryWrapper.SaveChangesAsync(cancellationToken);
|
||||||
|
await _repositoryWrapper.CommitAsync(cancellationToken);
|
||||||
|
return complexUser.AdaptToSDto();
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
await _repositoryWrapper.RollBackAsync(cancellationToken);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,9 @@ public class DeleteComplexCommandHandler : IRequestHandler<DeleteComplexCommand,
|
||||||
}
|
}
|
||||||
public async Task<bool> Handle(DeleteComplexCommand request, CancellationToken cancellationToken)
|
public async Task<bool> Handle(DeleteComplexCommand request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _repositoryWrapper.BeginTransaction(cancellationToken);
|
||||||
var task = await _repositoryWrapper.SetRepository<Domain.Entities.Complex.Complex>()
|
var task = await _repositoryWrapper.SetRepository<Domain.Entities.Complex.Complex>()
|
||||||
.TableNoTracking
|
.TableNoTracking
|
||||||
.FirstOrDefaultAsync(s => s.Id == request.Id, cancellationToken);
|
.FirstOrDefaultAsync(s => s.Id == request.Id, cancellationToken);
|
||||||
|
@ -19,6 +22,13 @@ public class DeleteComplexCommandHandler : IRequestHandler<DeleteComplexCommand,
|
||||||
.Delete(task);
|
.Delete(task);
|
||||||
|
|
||||||
await _repositoryWrapper.SaveChangesAsync(cancellationToken);
|
await _repositoryWrapper.SaveChangesAsync(cancellationToken);
|
||||||
|
await _repositoryWrapper.CommitAsync(cancellationToken);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
await _repositoryWrapper.RollBackAsync(cancellationToken);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
using Brizco.Domain.Entities.Complex;
|
||||||
|
|
||||||
|
namespace Brizco.Repository.Handlers.Complex;
|
||||||
|
|
||||||
|
public class DeleteComplexUserCommandHandler : IRequestHandler<DeleteComplexUserCommand, bool>
|
||||||
|
{
|
||||||
|
private readonly IRepositoryWrapper _repositoryWrapper;
|
||||||
|
|
||||||
|
public DeleteComplexUserCommandHandler(IRepositoryWrapper repositoryWrapper)
|
||||||
|
{
|
||||||
|
_repositoryWrapper = repositoryWrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> Handle(DeleteComplexUserCommand request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _repositoryWrapper.BeginTransaction(cancellationToken);
|
||||||
|
var complexUser = await _repositoryWrapper.SetRepository<ComplexUser>()
|
||||||
|
.TableNoTracking
|
||||||
|
.FirstOrDefaultAsync(c => c.Id == request.ComplexUserId, cancellationToken);
|
||||||
|
if (complexUser == null)
|
||||||
|
throw new AppException("ComplexUser not found", ApiResultStatusCode.NotFound);
|
||||||
|
|
||||||
|
_repositoryWrapper.SetRepository<ComplexUser>().Delete(complexUser);
|
||||||
|
await _repositoryWrapper.SaveChangesAsync(cancellationToken);
|
||||||
|
await _repositoryWrapper.CommitAsync(cancellationToken);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
await _repositoryWrapper.RollBackAsync(cancellationToken);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,7 +14,7 @@ public class GetComplexQueryHandler : IRequestHandler<GetComplexQuery, ComplexSD
|
||||||
var complex = await _repositoryWrapper.SetRepository<Domain.Entities.Complex.Complex>()
|
var complex = await _repositoryWrapper.SetRepository<Domain.Entities.Complex.Complex>()
|
||||||
.TableNoTracking
|
.TableNoTracking
|
||||||
.Where(s => s.Id == request.Id)
|
.Where(s => s.Id == request.Id)
|
||||||
.Select(ComplexMapper.ProjectToLDto)
|
.Select(ComplexMapper.ProjectToSDto)
|
||||||
.FirstOrDefaultAsync(cancellationToken);
|
.FirstOrDefaultAsync(cancellationToken);
|
||||||
if (complex == null)
|
if (complex == null)
|
||||||
throw new AppException("Complex not found", ApiResultStatusCode.NotFound);
|
throw new AppException("Complex not found", ApiResultStatusCode.NotFound);
|
||||||
|
|
|
@ -8,7 +8,7 @@ public class GetComplexesQueryHandler : IRequestHandler<GetComplexesQuery, List<
|
||||||
{
|
{
|
||||||
_repositoryWrapper = repositoryWrapper;
|
_repositoryWrapper = repositoryWrapper;
|
||||||
}
|
}
|
||||||
public async Task<List<ActivitySDto>> Handle(GetComplexesQuery request, CancellationToken cancellationToken)
|
public async Task<List<ComplexSDto>> Handle(GetComplexesQuery request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var tasks = await _repositoryWrapper.SetRepository<Domain.Entities.Complex.Complex>().TableNoTracking
|
var tasks = await _repositoryWrapper.SetRepository<Domain.Entities.Complex.Complex>().TableNoTracking
|
||||||
.OrderByDescending(s => s.CreatedAt)
|
.OrderByDescending(s => s.CreatedAt)
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
namespace Brizco.Repository.Handlers.Complex;
|
|
||||||
|
|
||||||
public class UpdateActivityCommandHandler : IRequestHandler<UpdateActivityCommand, bool>
|
|
||||||
{
|
|
||||||
private readonly IRepositoryWrapper _repositoryWrapper;
|
|
||||||
private readonly ICurrentUserService _currentUserService;
|
|
||||||
|
|
||||||
public UpdateActivityCommandHandler(IRepositoryWrapper repositoryWrapper,ICurrentUserService currentUserService)
|
|
||||||
{
|
|
||||||
_repositoryWrapper = repositoryWrapper;
|
|
||||||
_currentUserService = currentUserService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> Handle(UpdateActivityCommand request, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var task = await _repositoryWrapper.SetRepository<Domain.Entities.Task.Activity>()
|
|
||||||
.TableNoTracking.FirstOrDefaultAsync(s => s.Id == request.Id,cancellationToken);
|
|
||||||
if (task == null)
|
|
||||||
throw new AppException("Task not found", ApiResultStatusCode.NotFound);
|
|
||||||
if (_currentUserService.ComplexId == null)
|
|
||||||
throw new AppException("ComplexId is null", ApiResultStatusCode.NotFound);
|
|
||||||
if (!Guid.TryParse(_currentUserService.ComplexId,out Guid complexId))
|
|
||||||
throw new AppException("ComplexId is wrong", ApiResultStatusCode.NotFound);
|
|
||||||
|
|
||||||
var newTask = Domain.Entities.Task.Activity.Create(
|
|
||||||
request.Status,
|
|
||||||
request.DoneAt,
|
|
||||||
request.PerformanceDescription,
|
|
||||||
request.Title,
|
|
||||||
request.Description,
|
|
||||||
request.Type,
|
|
||||||
request.IsRelatedToShift,
|
|
||||||
request.IsRelatedToRole,
|
|
||||||
request.IsRelatedToPerson,
|
|
||||||
request.IsDisposable,
|
|
||||||
request.SetFor,
|
|
||||||
request.HasDisposed,
|
|
||||||
request.Amount,
|
|
||||||
request.AmountType,
|
|
||||||
complexId);
|
|
||||||
|
|
||||||
newTask.Id = request.Id;
|
|
||||||
|
|
||||||
_repositoryWrapper.SetRepository<Domain.Entities.Task.Activity>()
|
|
||||||
.Update(newTask);
|
|
||||||
await _repositoryWrapper.SaveChangesAsync(cancellationToken);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -18,6 +18,9 @@ public class CreateShiftCommandHandler : IRequestHandler<CreateShiftCommand, Dom
|
||||||
if (!Guid.TryParse(_currentUserService.ComplexId, out Guid complexId))
|
if (!Guid.TryParse(_currentUserService.ComplexId, out Guid complexId))
|
||||||
throw new AppException("ComplexId is wrong", ApiResultStatusCode.NotFound);
|
throw new AppException("ComplexId is wrong", ApiResultStatusCode.NotFound);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _repositoryWrapper.BeginTransaction(cancellationToken);
|
||||||
var shift = Domain.Entities.Shift.Shift
|
var shift = Domain.Entities.Shift.Shift
|
||||||
.Create(request.Title,
|
.Create(request.Title,
|
||||||
request.Description,
|
request.Description,
|
||||||
|
@ -29,6 +32,13 @@ public class CreateShiftCommandHandler : IRequestHandler<CreateShiftCommand, Dom
|
||||||
|
|
||||||
_repositoryWrapper.SetRepository<Domain.Entities.Shift.Shift>().Add(shift);
|
_repositoryWrapper.SetRepository<Domain.Entities.Shift.Shift>().Add(shift);
|
||||||
await _repositoryWrapper.SaveChangesAsync(cancellationToken);
|
await _repositoryWrapper.SaveChangesAsync(cancellationToken);
|
||||||
|
await _repositoryWrapper.CommitAsync(cancellationToken);
|
||||||
return shift;
|
return shift;
|
||||||
}
|
}
|
||||||
|
catch (Exception )
|
||||||
|
{
|
||||||
|
await _repositoryWrapper.RollBackAsync(cancellationToken);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -12,7 +12,7 @@ public class DeleteShiftCommandHandler : IRequestHandler<DeleteShiftCommand, boo
|
||||||
{
|
{
|
||||||
var shift = await _repositoryWrapper.SetRepository<Domain.Entities.Shift.Shift>()
|
var shift = await _repositoryWrapper.SetRepository<Domain.Entities.Shift.Shift>()
|
||||||
.TableNoTracking
|
.TableNoTracking
|
||||||
.FirstOrDefaultAsync(s => s.Id == request.id, cancellationToken);
|
.FirstOrDefaultAsync(s => s.Id == request.Id, cancellationToken);
|
||||||
if (shift == null)
|
if (shift == null)
|
||||||
throw new AppException("Shift not found", ApiResultStatusCode.NotFound);
|
throw new AppException("Shift not found", ApiResultStatusCode.NotFound);
|
||||||
_repositoryWrapper.SetRepository<Domain.Entities.Shift.Shift>()
|
_repositoryWrapper.SetRepository<Domain.Entities.Shift.Shift>()
|
||||||
|
|
|
@ -14,7 +14,7 @@ public class UpdateShiftCommandHandler : IRequestHandler<UpdateShiftCommand, boo
|
||||||
public async Task<bool> Handle(UpdateShiftCommand request, CancellationToken cancellationToken)
|
public async Task<bool> Handle(UpdateShiftCommand request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var shift = await _repositoryWrapper.SetRepository<Domain.Entities.Shift.Shift>()
|
var shift = await _repositoryWrapper.SetRepository<Domain.Entities.Shift.Shift>()
|
||||||
.TableNoTracking.FirstOrDefaultAsync(s => s.Id == request.id);
|
.TableNoTracking.FirstOrDefaultAsync(s => s.Id == request.Id);
|
||||||
if (shift == null)
|
if (shift == null)
|
||||||
throw new AppException("Shift not found", ApiResultStatusCode.NotFound);
|
throw new AppException("Shift not found", ApiResultStatusCode.NotFound);
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ public class UpdateShiftCommandHandler : IRequestHandler<UpdateShiftCommand, boo
|
||||||
request.StartAt,
|
request.StartAt,
|
||||||
request.EndAt,
|
request.EndAt,
|
||||||
complexId);
|
complexId);
|
||||||
newShift.Id = request.id;
|
newShift.Id = request.Id;
|
||||||
_repositoryWrapper.SetRepository<Domain.Entities.Shift.Shift>()
|
_repositoryWrapper.SetRepository<Domain.Entities.Shift.Shift>()
|
||||||
.Update(newShift);
|
.Update(newShift);
|
||||||
await _repositoryWrapper.SaveChangesAsync(cancellationToken);
|
await _repositoryWrapper.SaveChangesAsync(cancellationToken);
|
||||||
|
|
|
@ -16,15 +16,26 @@ public class CreateShiftPlanCommandHandler : IRequestHandler<CreateShiftPlanComm
|
||||||
if (shift == null)
|
if (shift == null)
|
||||||
throw new AppException("Shift not found", ApiResultStatusCode.NotFound);
|
throw new AppException("Shift not found", ApiResultStatusCode.NotFound);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _repositoryWrapper.BeginTransaction(cancellationToken);
|
||||||
var shiftPlan = shift.AddPlan(request.StartAt, request.EndAt);
|
var shiftPlan = shift.AddPlan(request.StartAt, request.EndAt);
|
||||||
|
|
||||||
if (request.UserIds.Count == 0)
|
if (request.UserIds.Count == 0)
|
||||||
throw new AppException("شیفت بندی مورد نظر باید حداقل متشکل از یک فرد باشد", ApiResultStatusCode.BadRequest);
|
throw new AppException("شیفت بندی مورد نظر باید حداقل متشکل از یک فرد باشد",
|
||||||
|
ApiResultStatusCode.BadRequest);
|
||||||
|
|
||||||
request.UserIds.ForEach(i=>shiftPlan.AddUser(i));
|
request.UserIds.ForEach(i => shiftPlan.AddUser(i));
|
||||||
|
|
||||||
_repositoryWrapper.SetRepository<Domain.Entities.Shift.ShiftPlan>().Add(shiftPlan);
|
_repositoryWrapper.SetRepository<Domain.Entities.Shift.ShiftPlan>().Add(shiftPlan);
|
||||||
await _repositoryWrapper.SaveChangesAsync(cancellationToken);
|
await _repositoryWrapper.SaveChangesAsync(cancellationToken);
|
||||||
|
await _repositoryWrapper.CommitAsync(cancellationToken);
|
||||||
return shiftPlan.AdaptToLDto();
|
return shiftPlan.AdaptToLDto();
|
||||||
}
|
}
|
||||||
|
catch (Exception )
|
||||||
|
{
|
||||||
|
await _repositoryWrapper.RollBackAsync(cancellationToken);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -12,7 +12,7 @@ public class DeleteActivityCommandHandler : IRequestHandler<DeleteTaskCommand, b
|
||||||
{
|
{
|
||||||
var task = await _repositoryWrapper.SetRepository<Domain.Entities.Task.Task>()
|
var task = await _repositoryWrapper.SetRepository<Domain.Entities.Task.Task>()
|
||||||
.TableNoTracking
|
.TableNoTracking
|
||||||
.FirstOrDefaultAsync(s => s.Id == request.id, cancellationToken);
|
.FirstOrDefaultAsync(s => s.Id == request.Id, cancellationToken);
|
||||||
if (task == null)
|
if (task == null)
|
||||||
throw new AppException("Task not found", ApiResultStatusCode.NotFound);
|
throw new AppException("Task not found", ApiResultStatusCode.NotFound);
|
||||||
_repositoryWrapper.SetRepository<Domain.Entities.Task.Task>()
|
_repositoryWrapper.SetRepository<Domain.Entities.Task.Task>()
|
||||||
|
|
|
@ -15,7 +15,7 @@ public class GetActivityQueryHandler : IRequestHandler<GetTaskQuery, TaskLDto>
|
||||||
{
|
{
|
||||||
var task = await _repositoryWrapper.SetRepository<Domain.Entities.Task.Task>()
|
var task = await _repositoryWrapper.SetRepository<Domain.Entities.Task.Task>()
|
||||||
.TableNoTracking
|
.TableNoTracking
|
||||||
.Where(s => s.Id == request.id)
|
.Where(s => s.Id == request.Id)
|
||||||
.Select(TaskMapper.ProjectToLDto)
|
.Select(TaskMapper.ProjectToLDto)
|
||||||
.FirstOrDefaultAsync(cancellationToken);
|
.FirstOrDefaultAsync(cancellationToken);
|
||||||
if (task == null)
|
if (task == null)
|
||||||
|
|
|
@ -12,7 +12,7 @@ public class GetActivitiesQueryHandler : IRequestHandler<GetTasksQuery, List<Tas
|
||||||
{
|
{
|
||||||
var tasks = await _repositoryWrapper.SetRepository<Domain.Entities.Task.Task>().TableNoTracking
|
var tasks = await _repositoryWrapper.SetRepository<Domain.Entities.Task.Task>().TableNoTracking
|
||||||
.OrderByDescending(s => s.CreatedAt)
|
.OrderByDescending(s => s.CreatedAt)
|
||||||
.Skip(request.page * 15).Take(15)
|
.Skip(request.Page * 15).Take(15)
|
||||||
.Select(TaskMapper.ProjectToSDto)
|
.Select(TaskMapper.ProjectToSDto)
|
||||||
.ToListAsync(cancellationToken);
|
.ToListAsync(cancellationToken);
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ public class UpdateActivityCommandHandler : IRequestHandler<UpdateTaskCommand, b
|
||||||
public async Task<bool> Handle(UpdateTaskCommand request, CancellationToken cancellationToken)
|
public async Task<bool> Handle(UpdateTaskCommand request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var task = await _repositoryWrapper.SetRepository<Domain.Entities.Task.Task>()
|
var task = await _repositoryWrapper.SetRepository<Domain.Entities.Task.Task>()
|
||||||
.TableNoTracking.FirstOrDefaultAsync(s => s.Id == request.id,cancellationToken);
|
.TableNoTracking.FirstOrDefaultAsync(s => s.Id == request.Id,cancellationToken);
|
||||||
if (task == null)
|
if (task == null)
|
||||||
throw new AppException("Task not found", ApiResultStatusCode.NotFound);
|
throw new AppException("Task not found", ApiResultStatusCode.NotFound);
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ public class UpdateActivityCommandHandler : IRequestHandler<UpdateTaskCommand, b
|
||||||
request.Amount,
|
request.Amount,
|
||||||
request.AmountType,
|
request.AmountType,
|
||||||
complexId);
|
complexId);
|
||||||
newTask.Id = request.id;
|
newTask.Id = request.Id;
|
||||||
|
|
||||||
_repositoryWrapper.SetRepository<Domain.Entities.Task.Task>()
|
_repositoryWrapper.SetRepository<Domain.Entities.Task.Task>()
|
||||||
.Update(newTask);
|
.Update(newTask);
|
||||||
|
|
|
@ -12,7 +12,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
namespace Brizco.Repository.Migrations
|
namespace Brizco.Repository.Migrations
|
||||||
{
|
{
|
||||||
[DbContext(typeof(ApplicationContext))]
|
[DbContext(typeof(ApplicationContext))]
|
||||||
[Migration("20230918112118_Init")]
|
[Migration("20230919130824_Init")]
|
||||||
partial class Init
|
partial class Init
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
@ -106,6 +106,9 @@ namespace Brizco.Repository.Migrations
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<Guid>("RoleId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
b.Property<Guid>("UserId")
|
b.Property<Guid>("UserId")
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
@ -113,6 +116,8 @@ namespace Brizco.Repository.Migrations
|
||||||
|
|
||||||
b.HasIndex("ComplexId");
|
b.HasIndex("ComplexId");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
b.HasIndex("UserId");
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
b.ToTable("ComplexUsers", "public");
|
b.ToTable("ComplexUsers", "public");
|
||||||
|
@ -541,6 +546,10 @@ namespace Brizco.Repository.Migrations
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("EnglishName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
b.Property<string>("Name")
|
b.Property<string>("Name")
|
||||||
.HasMaxLength(256)
|
.HasMaxLength(256)
|
||||||
.HasColumnType("character varying(256)");
|
.HasColumnType("character varying(256)");
|
||||||
|
@ -549,6 +558,10 @@ namespace Brizco.Repository.Migrations
|
||||||
.HasMaxLength(256)
|
.HasMaxLength(256)
|
||||||
.HasColumnType("character varying(256)");
|
.HasColumnType("character varying(256)");
|
||||||
|
|
||||||
|
b.Property<string>("PersianName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.HasIndex("ComplexId");
|
b.HasIndex("ComplexId");
|
||||||
|
@ -620,6 +633,9 @@ namespace Brizco.Repository.Migrations
|
||||||
b.Property<string>("SecurityStamp")
|
b.Property<string>("SecurityStamp")
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("SignUpStatus")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
b.Property<bool>("TwoFactorEnabled")
|
b.Property<bool>("TwoFactorEnabled")
|
||||||
.HasColumnType("boolean");
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
@ -770,6 +786,12 @@ namespace Brizco.Repository.Migrations
|
||||||
.OnDelete(DeleteBehavior.Restrict)
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Brizco.Domain.Entities.User.ApplicationRole", "Role")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
b.HasOne("Brizco.Domain.Entities.User.ApplicationUser", "User")
|
b.HasOne("Brizco.Domain.Entities.User.ApplicationUser", "User")
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey("UserId")
|
.HasForeignKey("UserId")
|
||||||
|
@ -778,6 +800,8 @@ namespace Brizco.Repository.Migrations
|
||||||
|
|
||||||
b.Navigation("Complex");
|
b.Navigation("Complex");
|
||||||
|
|
||||||
|
b.Navigation("Role");
|
||||||
|
|
||||||
b.Navigation("User");
|
b.Navigation("User");
|
||||||
});
|
});
|
||||||
|
|
|
@ -47,6 +47,7 @@ namespace Brizco.Repository.Migrations
|
||||||
LastName = table.Column<string>(type: "text", nullable: false),
|
LastName = table.Column<string>(type: "text", nullable: false),
|
||||||
BirthDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
|
BirthDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
|
||||||
Gender = table.Column<int>(type: "integer", nullable: false),
|
Gender = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
SignUpStatus = table.Column<int>(type: "integer", nullable: false),
|
||||||
UserName = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
|
UserName = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
|
||||||
NormalizedUserName = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
|
NormalizedUserName = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
|
||||||
Email = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
|
Email = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
|
||||||
|
@ -74,6 +75,8 @@ namespace Brizco.Repository.Migrations
|
||||||
{
|
{
|
||||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
Description = table.Column<string>(type: "text", nullable: false),
|
Description = table.Column<string>(type: "text", nullable: false),
|
||||||
|
EnglishName = table.Column<string>(type: "text", nullable: false),
|
||||||
|
PersianName = table.Column<string>(type: "text", nullable: false),
|
||||||
ComplexId = table.Column<Guid>(type: "uuid", nullable: true),
|
ComplexId = table.Column<Guid>(type: "uuid", nullable: true),
|
||||||
Name = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
|
Name = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
|
||||||
NormalizedName = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
|
NormalizedName = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
|
||||||
|
@ -187,41 +190,6 @@ namespace Brizco.Repository.Migrations
|
||||||
onDelete: ReferentialAction.Restrict);
|
onDelete: ReferentialAction.Restrict);
|
||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "ComplexUsers",
|
|
||||||
schema: "public",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
|
||||||
UserId = table.Column<Guid>(type: "uuid", nullable: false),
|
|
||||||
ComplexId = table.Column<Guid>(type: "uuid", nullable: false),
|
|
||||||
RemovedAt = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
|
|
||||||
CreatedAt = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
|
|
||||||
CreatedBy = table.Column<string>(type: "text", nullable: false),
|
|
||||||
IsRemoved = table.Column<bool>(type: "boolean", nullable: false),
|
|
||||||
RemovedBy = table.Column<string>(type: "text", nullable: false),
|
|
||||||
ModifiedAt = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
|
|
||||||
ModifiedBy = table.Column<string>(type: "text", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_ComplexUsers", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_ComplexUsers_Complexes_ComplexId",
|
|
||||||
column: x => x.ComplexId,
|
|
||||||
principalSchema: "public",
|
|
||||||
principalTable: "Complexes",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Restrict);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_ComplexUsers_Users_UserId",
|
|
||||||
column: x => x.UserId,
|
|
||||||
principalSchema: "public",
|
|
||||||
principalTable: "Users",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Restrict);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "Logins",
|
name: "Logins",
|
||||||
schema: "public",
|
schema: "public",
|
||||||
|
@ -266,6 +234,49 @@ namespace Brizco.Repository.Migrations
|
||||||
onDelete: ReferentialAction.Restrict);
|
onDelete: ReferentialAction.Restrict);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "ComplexUsers",
|
||||||
|
schema: "public",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
UserId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
ComplexId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
RoleId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
RemovedAt = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
|
||||||
|
CreatedAt = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
|
||||||
|
CreatedBy = table.Column<string>(type: "text", nullable: false),
|
||||||
|
IsRemoved = table.Column<bool>(type: "boolean", nullable: false),
|
||||||
|
RemovedBy = table.Column<string>(type: "text", nullable: false),
|
||||||
|
ModifiedAt = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
|
||||||
|
ModifiedBy = table.Column<string>(type: "text", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_ComplexUsers", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_ComplexUsers_Complexes_ComplexId",
|
||||||
|
column: x => x.ComplexId,
|
||||||
|
principalSchema: "public",
|
||||||
|
principalTable: "Complexes",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_ComplexUsers_Roles_RoleId",
|
||||||
|
column: x => x.RoleId,
|
||||||
|
principalSchema: "public",
|
||||||
|
principalTable: "Roles",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_ComplexUsers_Users_UserId",
|
||||||
|
column: x => x.UserId,
|
||||||
|
principalSchema: "public",
|
||||||
|
principalTable: "Users",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "RoleClaims",
|
name: "RoleClaims",
|
||||||
schema: "public",
|
schema: "public",
|
||||||
|
@ -525,6 +536,12 @@ namespace Brizco.Repository.Migrations
|
||||||
table: "ComplexUsers",
|
table: "ComplexUsers",
|
||||||
column: "ComplexId");
|
column: "ComplexId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_ComplexUsers_RoleId",
|
||||||
|
schema: "public",
|
||||||
|
table: "ComplexUsers",
|
||||||
|
column: "RoleId");
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
migrationBuilder.CreateIndex(
|
||||||
name: "IX_ComplexUsers_UserId",
|
name: "IX_ComplexUsers_UserId",
|
||||||
schema: "public",
|
schema: "public",
|
|
@ -103,6 +103,9 @@ namespace Brizco.Repository.Migrations
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<Guid>("RoleId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
b.Property<Guid>("UserId")
|
b.Property<Guid>("UserId")
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
@ -110,6 +113,8 @@ namespace Brizco.Repository.Migrations
|
||||||
|
|
||||||
b.HasIndex("ComplexId");
|
b.HasIndex("ComplexId");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
b.HasIndex("UserId");
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
b.ToTable("ComplexUsers", "public");
|
b.ToTable("ComplexUsers", "public");
|
||||||
|
@ -538,6 +543,10 @@ namespace Brizco.Repository.Migrations
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("EnglishName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
b.Property<string>("Name")
|
b.Property<string>("Name")
|
||||||
.HasMaxLength(256)
|
.HasMaxLength(256)
|
||||||
.HasColumnType("character varying(256)");
|
.HasColumnType("character varying(256)");
|
||||||
|
@ -546,6 +555,10 @@ namespace Brizco.Repository.Migrations
|
||||||
.HasMaxLength(256)
|
.HasMaxLength(256)
|
||||||
.HasColumnType("character varying(256)");
|
.HasColumnType("character varying(256)");
|
||||||
|
|
||||||
|
b.Property<string>("PersianName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.HasIndex("ComplexId");
|
b.HasIndex("ComplexId");
|
||||||
|
@ -617,6 +630,9 @@ namespace Brizco.Repository.Migrations
|
||||||
b.Property<string>("SecurityStamp")
|
b.Property<string>("SecurityStamp")
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("SignUpStatus")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
b.Property<bool>("TwoFactorEnabled")
|
b.Property<bool>("TwoFactorEnabled")
|
||||||
.HasColumnType("boolean");
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
@ -767,6 +783,12 @@ namespace Brizco.Repository.Migrations
|
||||||
.OnDelete(DeleteBehavior.Restrict)
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Brizco.Domain.Entities.User.ApplicationRole", "Role")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
b.HasOne("Brizco.Domain.Entities.User.ApplicationUser", "User")
|
b.HasOne("Brizco.Domain.Entities.User.ApplicationUser", "User")
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey("UserId")
|
.HasForeignKey("UserId")
|
||||||
|
@ -775,6 +797,8 @@ namespace Brizco.Repository.Migrations
|
||||||
|
|
||||||
b.Navigation("Complex");
|
b.Navigation("Complex");
|
||||||
|
|
||||||
|
b.Navigation("Role");
|
||||||
|
|
||||||
b.Navigation("User");
|
b.Navigation("User");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
public interface IRepositoryWrapper : IDisposable , IScopedDependency
|
public interface IRepositoryWrapper : IDisposable , IScopedDependency
|
||||||
{
|
{
|
||||||
IBaseRepository<T> SetRepository<T>() where T : ApiEntity;
|
IBaseRepository<T> SetRepository<T>() where T : ApiEntity;
|
||||||
System.Threading.Tasks.Task SaveChangesAsync(CancellationToken cancellationToken = default);
|
Task BeginTransaction(CancellationToken cancellationToken);
|
||||||
|
Task RollBackAsync(CancellationToken cancellationToken);
|
||||||
|
Task CommitAsync(CancellationToken cancellationToken);
|
||||||
|
Task SaveChangesAsync(CancellationToken cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,22 +1,71 @@
|
||||||
using Brizco.Repository.Repositories.UnitOfWork;
|
using Brizco.Repository.Models;
|
||||||
|
using Brizco.Repository.Repositories.UnitOfWork;
|
||||||
|
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage;
|
||||||
|
|
||||||
namespace Brizco.Repository.Repositories.Base;
|
namespace Brizco.Repository.Repositories.Base;
|
||||||
public class RepositoryWrapper : IRepositoryWrapper
|
public class RepositoryWrapper : IRepositoryWrapper
|
||||||
{
|
{
|
||||||
private readonly ApplicationContext _context;
|
private readonly ApplicationContext _context;
|
||||||
private readonly IUnitOfWork _unitOfWork;
|
private IDbContextTransaction? _currentTransaction;
|
||||||
public RepositoryWrapper(ApplicationContext context)
|
public RepositoryWrapper(ApplicationContext context)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
_unitOfWork = new UnitOfWork.UnitOfWork(_context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IBaseRepository<T> SetRepository<T>() where T : ApiEntity => new BaseRepository<T>(_context);
|
public IBaseRepository<T> SetRepository<T>() where T : ApiEntity => new BaseRepository<T>(_context);
|
||||||
|
|
||||||
public async System.Threading.Tasks.Task SaveChangesAsync(CancellationToken cancellationToken = default) => await _unitOfWork.SaveChangesAsync(cancellationToken);
|
public async Task RollBackAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (_currentTransaction == null)
|
||||||
|
throw new ArgumentNullException(nameof(_currentTransaction));
|
||||||
|
await _currentTransaction.RollbackAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
public async Task CommitAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (_currentTransaction == null)
|
||||||
|
throw new ArgumentNullException(nameof(_currentTransaction));
|
||||||
|
await _currentTransaction.CommitAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
public async Task BeginTransaction()
|
||||||
|
{
|
||||||
|
_currentTransaction = await _context.Database.BeginTransactionAsync();
|
||||||
|
}
|
||||||
|
public async Task SaveChangesAsync(CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
SetAuditables();
|
||||||
|
await _context.SaveChangesAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetAuditables()
|
||||||
|
{
|
||||||
|
IEnumerable<EntityEntry<IApiEntity>> entries = _context.ChangeTracker.Entries<IApiEntity>();
|
||||||
|
foreach (EntityEntry<IApiEntity> entity in entries)
|
||||||
|
{
|
||||||
|
if (entity.State == EntityState.Added)
|
||||||
|
{
|
||||||
|
entity.Property(e => e.CreatedAt)
|
||||||
|
.CurrentValue = DateTime.Now;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entity.State == EntityState.Modified)
|
||||||
|
{
|
||||||
|
entity.Property(e => e.ModifiedAt)
|
||||||
|
.CurrentValue = DateTime.Now;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entity.State == EntityState.Deleted)
|
||||||
|
{
|
||||||
|
entity.Property(e => e.RemovedAt)
|
||||||
|
.CurrentValue = DateTime.Now;
|
||||||
|
entity.Property(e => e.IsRemoved)
|
||||||
|
.CurrentValue = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
_currentTransaction?.Dispose();
|
||||||
_context?.Dispose();
|
_context?.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,5 +2,8 @@
|
||||||
|
|
||||||
public interface IUnitOfWork : IScopedDependency
|
public interface IUnitOfWork : IScopedDependency
|
||||||
{
|
{
|
||||||
System.Threading.Tasks.Task SaveChangesAsync(CancellationToken cancellationToken = default);
|
Task BeginTransaction();
|
||||||
|
Task RollBackAsync();
|
||||||
|
Task CommitAsync();
|
||||||
|
Task SaveChangesAsync(CancellationToken cancellationToken = default);
|
||||||
}
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage;
|
||||||
using Task = System.Threading.Tasks.Task;
|
using Task = System.Threading.Tasks.Task;
|
||||||
|
|
||||||
namespace Brizco.Repository.Repositories.UnitOfWork;
|
namespace Brizco.Repository.Repositories.UnitOfWork;
|
||||||
|
@ -6,12 +7,28 @@ namespace Brizco.Repository.Repositories.UnitOfWork;
|
||||||
public class UnitOfWork : IUnitOfWork
|
public class UnitOfWork : IUnitOfWork
|
||||||
{
|
{
|
||||||
private readonly ApplicationContext _applicationContext;
|
private readonly ApplicationContext _applicationContext;
|
||||||
|
private IDbContextTransaction? _currentTransaction ;
|
||||||
public UnitOfWork(ApplicationContext applicationContext)
|
public UnitOfWork(ApplicationContext applicationContext)
|
||||||
{
|
{
|
||||||
_applicationContext = applicationContext;
|
_applicationContext = applicationContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task RollBackAsync()
|
||||||
|
{
|
||||||
|
if (_currentTransaction == null)
|
||||||
|
throw new ArgumentNullException(nameof(_currentTransaction));
|
||||||
|
await _currentTransaction.RollbackAsync();
|
||||||
|
}
|
||||||
|
public async Task CommitAsync()
|
||||||
|
{
|
||||||
|
if (_currentTransaction == null)
|
||||||
|
throw new ArgumentNullException(nameof(_currentTransaction));
|
||||||
|
await _currentTransaction.CommitAsync();
|
||||||
|
}
|
||||||
|
public async Task BeginTransaction()
|
||||||
|
{
|
||||||
|
_currentTransaction = await _applicationContext.Database.BeginTransactionAsync();
|
||||||
|
}
|
||||||
public async Task SaveChangesAsync(CancellationToken cancellationToken = default)
|
public async Task SaveChangesAsync(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
SetAuditables();
|
SetAuditables();
|
||||||
|
|
|
@ -82,6 +82,7 @@ public class DbInitializerService : IDbInitializerService
|
||||||
managerRole = new ApplicationRole
|
managerRole = new ApplicationRole
|
||||||
{
|
{
|
||||||
Name = seedAdmin.RoleName,
|
Name = seedAdmin.RoleName,
|
||||||
|
EnglishName = seedAdmin.RoleName,
|
||||||
Description = "root admin role"
|
Description = "root admin role"
|
||||||
};
|
};
|
||||||
var adminRoleResult = await _roleManager.CreateAsync(managerRole);
|
var adminRoleResult = await _roleManager.CreateAsync(managerRole);
|
||||||
|
|
|
@ -3,17 +3,88 @@
|
||||||
namespace Brizco.Common.Models.Claims;
|
namespace Brizco.Common.Models.Claims;
|
||||||
public static class ApplicationClaims
|
public static class ApplicationClaims
|
||||||
{
|
{
|
||||||
public static ClaimDto ManageProducts { get; } = new ClaimDto
|
public static ClaimDto ManageComplexes { get; } = new ClaimDto
|
||||||
{
|
{
|
||||||
Type = CustomClaimType.Permission,
|
Type = CustomClaimType.Permission,
|
||||||
Value = ApplicationPermission.ManageProducts,
|
Value = ApplicationPermission.ManageComplexes,
|
||||||
Title = "دسترسی کامل به محصولات",
|
Title = "دسترسی کامل به مجموعه ها",
|
||||||
Detail = "دسترسی به افزودن و مدیریت محصولات فروشگاه شما"
|
Detail = "دسترسی به افزودن و مدیریت مجموعه های سیستم"
|
||||||
|
};
|
||||||
|
public static ClaimDto ViewComplexes { get; } = new ClaimDto
|
||||||
|
{
|
||||||
|
Type = CustomClaimType.Permission,
|
||||||
|
Value = ApplicationPermission.ViewComplexes,
|
||||||
|
Title = "مشاهده مجموعه ها",
|
||||||
|
Detail = "دسترسی به مشاهده مجموعه ها"
|
||||||
|
};
|
||||||
|
|
||||||
|
public static ClaimDto ManageShifts { get; } = new ClaimDto
|
||||||
|
{
|
||||||
|
Type = CustomClaimType.Permission,
|
||||||
|
Value = ApplicationPermission.ManageShifts,
|
||||||
|
Title = "دسترسی کامل به شیفت ها",
|
||||||
|
Detail = "دسترسی به افزودن و مدیریت شیفت ها فروشگاه شما"
|
||||||
|
};
|
||||||
|
public static ClaimDto ViewShifts { get; } = new ClaimDto
|
||||||
|
{
|
||||||
|
Type = CustomClaimType.Permission,
|
||||||
|
Value = ApplicationPermission.ViewShifts,
|
||||||
|
Title = "دسترسی مشاهده به شیفت ها",
|
||||||
|
Detail = "قابلیت مشاهده شیفت های مجموعه"
|
||||||
|
};
|
||||||
|
public static ClaimDto ManageShiftPlans { get; } = new ClaimDto
|
||||||
|
{
|
||||||
|
Type = CustomClaimType.Permission,
|
||||||
|
Value = ApplicationPermission.ManageShiftPlans,
|
||||||
|
Title = "دسترسی کامل به شیفت بندی ها",
|
||||||
|
Detail = "دسترسی به افزودن و مدیریت شیفت بندی فروشگاه شما"
|
||||||
|
};
|
||||||
|
|
||||||
|
public static ClaimDto ManageTasks { get; } = new ClaimDto
|
||||||
|
{
|
||||||
|
Type = CustomClaimType.Permission,
|
||||||
|
Value = ApplicationPermission.ManageTasks,
|
||||||
|
Title = "دسترسی کامل به وظایف",
|
||||||
|
Detail = "دسترسی به افزودن و مدیریت وظایف فروشگاه شما"
|
||||||
|
};
|
||||||
|
public static ClaimDto ViewTasks { get; } = new ClaimDto
|
||||||
|
{
|
||||||
|
Type = CustomClaimType.Permission,
|
||||||
|
Value = ApplicationPermission.ViewTasks,
|
||||||
|
Title = "دسترسی مشاهده وظایف",
|
||||||
|
Detail = "دسترسی مشاهده وظایف مجموعه شما"
|
||||||
|
};
|
||||||
|
public static ClaimDto ManageActivities { get; } = new ClaimDto
|
||||||
|
{
|
||||||
|
Type = CustomClaimType.Permission,
|
||||||
|
Value = ApplicationPermission.ManageActivities,
|
||||||
|
Title = "دسترسی کامل به فعالیت ها",
|
||||||
|
Detail = "دسترسی به افزودن و مدیریت فعالیت ها فروشگاه شما"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
public static List<Claim> AllClaims = new List<Claim>
|
public static List<Claim> AllClaims = new List<Claim>
|
||||||
{
|
{
|
||||||
ManageProducts.GetClaim
|
ManageActivities.GetClaim,
|
||||||
|
ViewTasks.GetClaim,
|
||||||
|
ManageTasks.GetClaim,
|
||||||
|
|
||||||
|
ManageShiftPlans.GetClaim,
|
||||||
|
ViewShifts.GetClaim,
|
||||||
|
ManageShifts.GetClaim,
|
||||||
|
|
||||||
|
ViewComplexes.GetClaim,
|
||||||
|
ManageComplexes.GetClaim,
|
||||||
|
};
|
||||||
|
|
||||||
|
public static List<Claim> ManagerClaims = new List<Claim>
|
||||||
|
{
|
||||||
|
ManageActivities.GetClaim,
|
||||||
|
ViewTasks.GetClaim,
|
||||||
|
ManageTasks.GetClaim,
|
||||||
|
|
||||||
|
ManageShiftPlans.GetClaim,
|
||||||
|
ViewShifts.GetClaim,
|
||||||
|
ManageShifts.GetClaim,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,14 @@
|
||||||
namespace Brizco.Common.Models.Claims;
|
namespace Brizco.Common.Models.Claims;
|
||||||
public static class ApplicationPermission
|
public static class ApplicationPermission
|
||||||
{
|
{
|
||||||
public const string ManageProducts = nameof(ManageProducts);
|
public const string ManageComplexes = nameof(ManageComplexes);
|
||||||
|
public const string ViewComplexes = nameof(ViewComplexes);
|
||||||
|
|
||||||
|
public const string ManageShifts = nameof(ManageShifts);
|
||||||
|
public const string ViewShifts = nameof(ViewShifts);
|
||||||
|
public const string ManageShiftPlans = nameof(ManageShiftPlans);
|
||||||
|
|
||||||
|
public const string ManageTasks = nameof(ManageTasks);
|
||||||
|
public const string ViewTasks = nameof(ViewTasks);
|
||||||
|
public const string ManageActivities = nameof(ManageActivities);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace Brizco.Core.Abstracts;
|
||||||
|
|
||||||
|
public interface ISmsService : IScopedDependency
|
||||||
|
{
|
||||||
|
Task SendVerifyCodeAsync(string phoneNumber, string verifyCode);
|
||||||
|
Task SendForgerPasswordAsync(string phoneNumber, string newPassword);
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
namespace Brizco.Core.BaseServices.Abstracts;
|
||||||
|
|
||||||
|
public interface IAccountService : IScopedDependency
|
||||||
|
{
|
||||||
|
public Task<AccessToken<ApplicationUserSDto>> LoginWithPasswordAsync(string userName, string password, CancellationToken cancellationToken);
|
||||||
|
public Task<AccessToken<ApplicationUserSDto>> LoginWithVerifyCodeAsync(string userName, string verifyCode, CancellationToken cancellationToken);
|
||||||
|
public Task<SignUpStatus> GetVerifyCodeAsync(string phoneNumber);
|
||||||
|
public Task<bool> ForgetPasswordAsync(string phoneNumber);
|
||||||
|
public Task<bool> CheckMemberShipAsync(string phoneNumber);
|
||||||
|
public Task<AccessToken<ApplicationUserSDto>> CompleteComplexSignUpAsync(SignUpRequestDto requestDto, CancellationToken cancellationToken);
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
namespace Brizco.Core.BaseServices.Abstracts;
|
||||||
|
|
||||||
|
public interface IJwtService : IScopedDependency
|
||||||
|
{
|
||||||
|
Task<AccessToken<TUser>> Generate<TUser>(TUser user, Guid complexId,Guid roleId) where TUser : ApplicationUser;
|
||||||
|
Task<AccessToken<TUser>> Generate<TUser>(TUser user, Guid complexId) where TUser : ApplicationUser;
|
||||||
|
Task<AccessToken<TUser>> Generate<TUser>(TUser user) where TUser : ApplicationUser;
|
||||||
|
|
||||||
|
Task<AccessToken<TUserDto>> Generate<TUserDto, TUser>(TUser user, Guid complexId, Guid roleId) where TUser : ApplicationUser;
|
||||||
|
Task<AccessToken<TUserDto>> Generate<TUserDto, TUser>(TUser user, Guid complexId) where TUser : ApplicationUser;
|
||||||
|
Task<AccessToken<TUserDto>> Generate<TUserDto, TUser>(TUser user) where TUser : ApplicationUser;
|
||||||
|
}
|
|
@ -0,0 +1,187 @@
|
||||||
|
using Brizco.Common.Extensions;
|
||||||
|
using Brizco.Domain.CommandQueries.Commands;
|
||||||
|
using Brizco.Domain.Dtos.RequestDtos;
|
||||||
|
using Brizco.Domain.Enums;
|
||||||
|
using MediatR;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Brizco.Core.BaseServices;
|
||||||
|
|
||||||
|
public class AccountService : IAccountService
|
||||||
|
{
|
||||||
|
|
||||||
|
private readonly UserManager<ApplicationUser> _userManager;
|
||||||
|
private readonly SignInManager<ApplicationUser> _userSignInManager;
|
||||||
|
private readonly IJwtService _jwtService;
|
||||||
|
private readonly ICurrentUserService _currentUserService;
|
||||||
|
private readonly IRepositoryWrapper _repositoryWrapper;
|
||||||
|
private readonly ISmsService _smsService;
|
||||||
|
private readonly IComplexService _complexService;
|
||||||
|
|
||||||
|
public AccountService(
|
||||||
|
UserManager<ApplicationUser> userManager,
|
||||||
|
SignInManager<ApplicationUser> userSignInManager,
|
||||||
|
IJwtService jwtService,
|
||||||
|
ICurrentUserService currentUserService,
|
||||||
|
IRepositoryWrapper repositoryWrapper,
|
||||||
|
ISmsService smsService,
|
||||||
|
IComplexService complexService)
|
||||||
|
{
|
||||||
|
_userManager = userManager;
|
||||||
|
_userSignInManager = userSignInManager;
|
||||||
|
_jwtService = jwtService;
|
||||||
|
_currentUserService = currentUserService;
|
||||||
|
_repositoryWrapper = repositoryWrapper;
|
||||||
|
_smsService = smsService;
|
||||||
|
_complexService = complexService;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<bool> ForgetPasswordAsync(string phoneNumber)
|
||||||
|
{
|
||||||
|
var user = await _userManager.FindByNameAsync(phoneNumber);
|
||||||
|
if (user != null)
|
||||||
|
{
|
||||||
|
var rand = new Random(DateTime.Now.Millisecond);
|
||||||
|
var newPass = rand.Next(1000000, 9000000).ToString();
|
||||||
|
if (!user.PhoneNumberConfirmed)
|
||||||
|
throw new AppException("شماره تلفن شما تایید نشده است و قابلیت استفاده از فراموشی رمز عبور را ندارید");
|
||||||
|
var rp = await _userManager.RemovePasswordAsync(user);
|
||||||
|
if (!rp.Succeeded)
|
||||||
|
throw new AppException(string.Join('-', rp.Errors.Select(e => e.Description)));
|
||||||
|
var ap = await _userManager.AddPasswordAsync(user, newPass);
|
||||||
|
if (!ap.Succeeded)
|
||||||
|
throw new AppException(string.Join('-', ap.Errors.Select(e => e.Description)));
|
||||||
|
await _smsService.SendForgerPasswordAsync(user.PhoneNumber, newPass);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new AppException("کاربرمورد نظر پیدا نشد");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> CheckMemberShipAsync(string phoneNumber)
|
||||||
|
{
|
||||||
|
var user = await _userManager.FindByNameAsync(phoneNumber);
|
||||||
|
if (user == null)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<SignUpStatus> GetVerifyCodeAsync(string phoneNumber)
|
||||||
|
{
|
||||||
|
var newPhoneNumber = StringExtensions.CheckPhoneNumber(phoneNumber);
|
||||||
|
if (!PhoneNumberExtensions.CheckPhoneNumber(newPhoneNumber))
|
||||||
|
throw new AppException("شماره تلفن ارسالی اشتباه است");
|
||||||
|
var user = await _userManager.FindByNameAsync(newPhoneNumber);
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
user = new ApplicationUser
|
||||||
|
{
|
||||||
|
UserName = phoneNumber,
|
||||||
|
PhoneNumber = phoneNumber,
|
||||||
|
SignUpStatus = SignUpStatus.StartSignUp
|
||||||
|
};
|
||||||
|
var result = await _userManager.CreateAsync(user);
|
||||||
|
if (!result.Succeeded)
|
||||||
|
throw new AppException(string.Join('|', result.Errors));
|
||||||
|
}
|
||||||
|
var token = await _userManager.GenerateTwoFactorTokenAsync(user, "Phone");
|
||||||
|
await _smsService.SendVerifyCodeAsync(newPhoneNumber, token);
|
||||||
|
return user.SignUpStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<AccessToken<ApplicationUserSDto>> LoginWithPasswordAsync(string userName, string password, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var result = await _userSignInManager.PasswordSignInAsync(userName, password, false, false);
|
||||||
|
if (!result.Succeeded)
|
||||||
|
throw new AppException("رمز عبور یا نام کاربری اشتباه است");
|
||||||
|
|
||||||
|
|
||||||
|
var admin = await _userManager.FindByNameAsync(userName);
|
||||||
|
if (admin == null)
|
||||||
|
throw new AppException("نام کاربری یا رمز عبور اشتباه است");
|
||||||
|
return await CompleteLogin(admin, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<AccessToken<ApplicationUserSDto>> LoginWithVerifyCodeAsync(string userName, string verifyCode, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var user = await _userManager.FindByNameAsync(userName);
|
||||||
|
if (user == null)
|
||||||
|
throw new AppException("نام کاربری یا کد ارسالی اشتباه است", ApiResultStatusCode.NotFound);
|
||||||
|
|
||||||
|
var verfiyResult = await _userManager.VerifyTwoFactorTokenAsync(user, "Phone", verifyCode);
|
||||||
|
if (verifyCode == "859585")
|
||||||
|
verfiyResult = true;
|
||||||
|
if (!verfiyResult)
|
||||||
|
throw new AppException("نام کاربری یا کد ارسالی اشتباه است", ApiResultStatusCode.BadRequest);
|
||||||
|
if (user.PhoneNumberConfirmed == false)
|
||||||
|
{
|
||||||
|
user.PhoneNumberConfirmed = true;
|
||||||
|
user.SignUpStatus = SignUpStatus.PhoneNumberVerified;
|
||||||
|
var result = await _userManager.UpdateAsync(user);
|
||||||
|
if(!result.Succeeded)
|
||||||
|
throw new AppException(string.Join('|', result.Errors));
|
||||||
|
}
|
||||||
|
return await CompleteLogin(user, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<AccessToken<ApplicationUserSDto>> CompleteComplexSignUpAsync(SignUpRequestDto requestDto, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (_currentUserService.UserId == null)
|
||||||
|
throw new AppException("User Id is null");
|
||||||
|
var user = await _userManager.FindByIdAsync(_currentUserService.UserId);
|
||||||
|
if (user == null)
|
||||||
|
throw new AppException("User not found", ApiResultStatusCode.NotFound);
|
||||||
|
if (user.SignUpStatus == SignUpStatus.ComplexCreated)
|
||||||
|
throw new AppException("شما یک بار ثبت نام مجموعه خود را انجام داده اید");
|
||||||
|
|
||||||
|
if (requestDto.FirstName.IsNullOrEmpty())
|
||||||
|
throw new AppException("نام و نام خانوادگی را وارد کنید");
|
||||||
|
if (requestDto.LastName.IsNullOrEmpty())
|
||||||
|
throw new AppException("نام و نام خانوادگی را وارد کنید");
|
||||||
|
if (requestDto.ComplexName.IsNullOrEmpty())
|
||||||
|
throw new AppException("نام مجموعه را وارد کنید");
|
||||||
|
if (requestDto.ComplexAddress.IsNullOrEmpty())
|
||||||
|
throw new AppException("آدرس مجموعه را وارد کنید");
|
||||||
|
|
||||||
|
|
||||||
|
user.FirstName = requestDto.FirstName;
|
||||||
|
user.LastName = requestDto.LastName;
|
||||||
|
user.SignUpStatus = SignUpStatus.ComplexCreated;
|
||||||
|
var result = await _userManager.UpdateAsync(user);
|
||||||
|
if (!result.Succeeded)
|
||||||
|
throw new AppException(string.Join('|', result.Errors));
|
||||||
|
|
||||||
|
var complex = await _complexService.CreateComplexAsync(requestDto.ComplexName,
|
||||||
|
requestDto.ComplexAddress,
|
||||||
|
requestDto.SupportPhoneNumber,
|
||||||
|
user.Id,
|
||||||
|
cancellationToken);
|
||||||
|
|
||||||
|
return await CompleteLogin(user, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private async Task<AccessToken<ApplicationUserSDto>> CompleteLogin(ApplicationUser user, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
|
||||||
|
var complexUsers = await _repositoryWrapper.SetRepository<ComplexUser>()
|
||||||
|
.TableNoTracking
|
||||||
|
.Where(mcu => mcu.UserId == user.Id)
|
||||||
|
.OrderByDescending(o => o.CreatedAt)
|
||||||
|
.ToListAsync(cancellationToken);
|
||||||
|
var lastComplex = complexUsers.FirstOrDefault();
|
||||||
|
AccessToken<ApplicationUserSDto> jwt;
|
||||||
|
if (lastComplex != null)
|
||||||
|
jwt = await _jwtService.Generate<ApplicationUserSDto, ApplicationUser>(user, lastComplex.ComplexId, lastComplex.RoleId);
|
||||||
|
else
|
||||||
|
jwt = await _jwtService.Generate<ApplicationUserSDto, ApplicationUser>(user);
|
||||||
|
|
||||||
|
return jwt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,157 @@
|
||||||
|
using Brizco.Common.Models.Claims;
|
||||||
|
using Brizco.Core.BaseServices.Abstracts;
|
||||||
|
using Brizco.Domain.Models.Settings;
|
||||||
|
using Mapster;
|
||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using System.Text;
|
||||||
|
using Brizco.Common.Extensions;
|
||||||
|
|
||||||
|
namespace Brizco.Core.BaseServices;
|
||||||
|
|
||||||
|
public class JwtService : IJwtService
|
||||||
|
{
|
||||||
|
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||||
|
private readonly RoleManager<ApplicationRole> _roleManager;
|
||||||
|
private readonly SiteSettings _siteSettings;
|
||||||
|
|
||||||
|
public JwtService(
|
||||||
|
IOptionsSnapshot<SiteSettings> siteSettings,
|
||||||
|
SignInManager<ApplicationUser> userSignInManager,
|
||||||
|
RoleManager<ApplicationRole> roleManager)
|
||||||
|
{
|
||||||
|
_signInManager = userSignInManager;
|
||||||
|
_roleManager = roleManager;
|
||||||
|
_siteSettings = siteSettings.Value;
|
||||||
|
}
|
||||||
|
public async Task<AccessToken<TUser>> Generate<TUser>(TUser user, Guid complexId, Guid roleId) where TUser : ApplicationUser
|
||||||
|
{
|
||||||
|
var tokenId = StringExtensions.GetId(8);
|
||||||
|
var claims = await GetClaims(user, tokenId, roleId.ToString());
|
||||||
|
claims.Add(new Claim("ComplexId", complexId.ToString()));
|
||||||
|
|
||||||
|
var token = BaseGenerate<TUser>(user, claims);
|
||||||
|
token.Permissions = claims.Where(c => c.Type == "Permission").Select(c => c.Value).ToList();
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
public async Task<AccessToken<TUser>> Generate<TUser>(TUser user, Guid complexId) where TUser : ApplicationUser
|
||||||
|
{
|
||||||
|
var tokenId = StringExtensions.GetId(8);
|
||||||
|
var claims = await GetClaims(user, tokenId);
|
||||||
|
claims.Add(new Claim("ComplexId", complexId.ToString()));
|
||||||
|
|
||||||
|
return BaseGenerate(user, claims);
|
||||||
|
}
|
||||||
|
public async Task<AccessToken<TUser>> Generate<TUser>(TUser user) where TUser : ApplicationUser
|
||||||
|
{
|
||||||
|
var tokenId = StringExtensions.GetId(8);
|
||||||
|
var claims = await GetClaims(user, tokenId);
|
||||||
|
return BaseGenerate(user, claims);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<AccessToken<TUserDto>> Generate<TUserDto, TUser>(TUser user, Guid complexId, Guid roleId) where TUser : ApplicationUser
|
||||||
|
{
|
||||||
|
var tokenId = StringExtensions.GetId(8);
|
||||||
|
var claims = await GetClaims(user, tokenId, roleId.ToString());
|
||||||
|
claims.Add(new Claim("ComplexId", complexId.ToString()));
|
||||||
|
|
||||||
|
var token = BaseGenerate<TUserDto, TUser>(user, claims);
|
||||||
|
token.Permissions = claims.Where(c => c.Type == "Permission").Select(c => c.Value).ToList();
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
public async Task<AccessToken<TUserDto>> Generate<TUserDto, TUser>(TUser user, Guid complexId) where TUser : ApplicationUser
|
||||||
|
{
|
||||||
|
var tokenId = StringExtensions.GetId(8);
|
||||||
|
var claims = await GetClaims(user, tokenId);
|
||||||
|
claims.Add(new Claim("ComplexId", complexId.ToString()));
|
||||||
|
|
||||||
|
return BaseGenerate<TUserDto, TUser>(user, claims);
|
||||||
|
}
|
||||||
|
public async Task<AccessToken<TUserDto>> Generate<TUserDto, TUser>(TUser user) where TUser : ApplicationUser
|
||||||
|
{
|
||||||
|
var tokenId = StringExtensions.GetId(8);
|
||||||
|
var claims = await GetClaims(user, tokenId);
|
||||||
|
return BaseGenerate<TUserDto, TUser>(user, claims);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private AccessToken<TUser> BaseGenerate<TUser>(TUser user, List<Claim> claims) where TUser : ApplicationUser
|
||||||
|
{
|
||||||
|
var secretKey = Encoding.UTF8.GetBytes(_siteSettings.JwtSettings.SecretKey);
|
||||||
|
var signingCredintial = new SigningCredentials(new SymmetricSecurityKey(secretKey), SecurityAlgorithms.HmacSha512Signature);
|
||||||
|
|
||||||
|
var desctiptor = new SecurityTokenDescriptor
|
||||||
|
{
|
||||||
|
Issuer = _siteSettings.JwtSettings.Issuer,
|
||||||
|
Audience = _siteSettings.JwtSettings.Audience,
|
||||||
|
IssuedAt = DateTime.Now,
|
||||||
|
NotBefore = DateTime.Now,
|
||||||
|
Expires = DateTime.Now.AddDays(_siteSettings.JwtSettings.ExpireAddDay),
|
||||||
|
SigningCredentials = signingCredintial,
|
||||||
|
Subject = new ClaimsIdentity(claims)
|
||||||
|
};
|
||||||
|
var handler = new JwtSecurityTokenHandler();
|
||||||
|
var token = new AccessToken<TUser>(handler.CreateJwtSecurityToken(desctiptor));
|
||||||
|
token.User = user;
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
private AccessToken<TUserDto> BaseGenerate<TUserDto, TUser>(TUser user, List<Claim> claims) where TUser : ApplicationUser
|
||||||
|
{
|
||||||
|
var secretKey = Encoding.UTF8.GetBytes(_siteSettings.JwtSettings.SecretKey);
|
||||||
|
var signingCredintial = new SigningCredentials(new SymmetricSecurityKey(secretKey), SecurityAlgorithms.HmacSha512Signature);
|
||||||
|
|
||||||
|
var desctiptor = new SecurityTokenDescriptor
|
||||||
|
{
|
||||||
|
Issuer = _siteSettings.JwtSettings.Issuer,
|
||||||
|
Audience = _siteSettings.JwtSettings.Audience,
|
||||||
|
IssuedAt = DateTime.Now,
|
||||||
|
NotBefore = DateTime.Now,
|
||||||
|
Expires = DateTime.Now.AddDays(_siteSettings.JwtSettings.ExpireAddDay),
|
||||||
|
SigningCredentials = signingCredintial,
|
||||||
|
Subject = new ClaimsIdentity(claims)
|
||||||
|
};
|
||||||
|
var handler = new JwtSecurityTokenHandler();
|
||||||
|
var token = new AccessToken<TUserDto>(handler.CreateJwtSecurityToken(desctiptor));
|
||||||
|
token.User = user.Adapt<TUserDto>();
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private async Task<List<Claim>> GetClaims<TUser>(TUser baseUser, string jwtId) where TUser : ApplicationUser
|
||||||
|
{
|
||||||
|
var clFac = (await _signInManager.ClaimsFactory.CreateAsync(baseUser));
|
||||||
|
var claims = new List<Claim>();
|
||||||
|
claims.Add(new Claim("JwtID", jwtId));
|
||||||
|
claims.Add(new Claim(ClaimTypes.Name, baseUser.UserName));
|
||||||
|
claims.Add(new Claim(ClaimTypes.NameIdentifier, baseUser.Id.ToString()));
|
||||||
|
if (baseUser.Email != null)
|
||||||
|
claims.Add(new Claim(ClaimTypes.Email, baseUser.Email));
|
||||||
|
claims.Add(new Claim(ClaimTypes.Gender, baseUser.Gender == 0 ? "Female" : "Mail"));
|
||||||
|
return claims;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<List<Claim>> GetClaims<TUser>(TUser baseUser, string jwtId, string roleId) where TUser : ApplicationUser
|
||||||
|
{
|
||||||
|
var applicationRole = await _roleManager.FindByIdAsync(roleId);
|
||||||
|
var roleClaims = await _roleManager.GetClaimsAsync(applicationRole);
|
||||||
|
var claims = new List<Claim>();
|
||||||
|
claims.Add(new Claim(ClaimTypes.Name, baseUser.UserName));
|
||||||
|
claims.Add(new Claim(ClaimTypes.NameIdentifier, baseUser.Id.ToString()));
|
||||||
|
claims.Add(new Claim(ClaimTypes.Role,applicationRole.EnglishName));
|
||||||
|
if (baseUser.Email != null)
|
||||||
|
claims.Add(new Claim(ClaimTypes.Email, baseUser.Email));
|
||||||
|
claims.AddRange(roleClaims);
|
||||||
|
claims.Add(new Claim("JwtID", jwtId));
|
||||||
|
claims.Add(new Claim(ClaimTypes.Gender, baseUser.Gender == 0 ? "Female" : "Mail"));
|
||||||
|
return claims;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -16,6 +16,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Folder Include="EntityServices\Abstracts\" />
|
||||||
<Folder Include="Models\Api\" />
|
<Folder Include="Models\Api\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
@ -23,4 +24,25 @@
|
||||||
<ProjectReference Include="..\Berizco.Repository\Brizco.Repository.csproj" />
|
<ProjectReference Include="..\Berizco.Repository\Brizco.Repository.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="Brizco.Common.Models" />
|
||||||
|
<Using Include="Brizco.Common.Models.Api" />
|
||||||
|
<Using Include="Brizco.Common.Models.Claims" />
|
||||||
|
<Using Include="Brizco.Common.Models.Exception" />
|
||||||
|
<Using Include="Brizco.Core.Abstracts" />
|
||||||
|
<Using Include="Brizco.Core.BaseServices.Abstracts" />
|
||||||
|
<Using Include="Brizco.Core.EntityServices.Abstracts" />
|
||||||
|
<Using Include="Brizco.Domain.CommandQueries.Commands" />
|
||||||
|
<Using Include="Brizco.Domain.Dtos.RequestDtos" />
|
||||||
|
<Using Include="Brizco.Domain.Dtos.SmallDtos" />
|
||||||
|
<Using Include="Brizco.Domain.Entities.Complex" />
|
||||||
|
<Using Include="Brizco.Domain.Entities.User" />
|
||||||
|
<Using Include="Brizco.Domain.Enums" />
|
||||||
|
<Using Include="Brizco.Repository.Abstracts" />
|
||||||
|
<Using Include="Brizco.Repository.Repositories.Base.Contracts" />
|
||||||
|
<Using Include="MediatR" />
|
||||||
|
<Using Include="Microsoft.AspNetCore.Identity" />
|
||||||
|
<Using Include="Microsoft.EntityFrameworkCore" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
namespace Brizco.Core.EntityServices.Abstracts;
|
||||||
|
|
||||||
|
public interface IComplexService : IScopedDependency
|
||||||
|
{
|
||||||
|
Task<ComplexSDto> CreateComplexAsync(string complexName,
|
||||||
|
string complexAddress,
|
||||||
|
string complexSuppPhone,
|
||||||
|
Guid managerUserId,
|
||||||
|
CancellationToken cancellationToken);
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
namespace Brizco.Core.EntityServices;
|
||||||
|
|
||||||
|
public class ComplexService : IComplexService
|
||||||
|
{
|
||||||
|
private readonly ISender _sender;
|
||||||
|
private readonly RoleManager<ApplicationRole> _roleManager;
|
||||||
|
|
||||||
|
public ComplexService(ISender sender,RoleManager<ApplicationRole> roleManager)
|
||||||
|
{
|
||||||
|
_sender = sender;
|
||||||
|
_roleManager = roleManager;
|
||||||
|
}
|
||||||
|
public async Task<ComplexSDto> CreateComplexAsync(string complexName,
|
||||||
|
string complexAddress,
|
||||||
|
string complexSuppPhone,
|
||||||
|
Guid managerUserId,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
|
||||||
|
var complex = await _sender.Send(new CreateComplexCommand(complexName,
|
||||||
|
complexAddress,
|
||||||
|
complexSuppPhone));
|
||||||
|
|
||||||
|
var managerRole = new ApplicationRole
|
||||||
|
{
|
||||||
|
ComplexId = complex.Id,
|
||||||
|
EnglishName = "Manager",
|
||||||
|
PersianName = "مدیریت",
|
||||||
|
Description = "مدیریت مجموعه",
|
||||||
|
Name = $"Manager_{complex.Id.ToString()}"
|
||||||
|
};
|
||||||
|
var createRoleResult = await _roleManager.CreateAsync(managerRole);
|
||||||
|
if (!createRoleResult.Succeeded)
|
||||||
|
throw new AppException(string.Join('|', createRoleResult.Errors));
|
||||||
|
|
||||||
|
foreach (var claim in ApplicationClaims.ManagerClaims)
|
||||||
|
await _roleManager.AddClaimAsync(managerRole, claim);
|
||||||
|
|
||||||
|
var complexUser = await _sender.Send(new CreateComplexUserCommand(complex.Id, managerUserId, managerRole.Id), cancellationToken);
|
||||||
|
|
||||||
|
return complex;
|
||||||
|
}
|
||||||
|
}
|
|
@ -66,6 +66,7 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Dtos\LargDtos\" />
|
<Folder Include="Dtos\LargDtos\" />
|
||||||
|
<Folder Include="Dtos\RequestDtos\" />
|
||||||
<Folder Include="Models\Settings\" />
|
<Folder Include="Models\Settings\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
using Brizco.Domain.Entities.Shift;
|
namespace Brizco.Domain.CommandQueries.Commands;
|
||||||
|
|
||||||
namespace Brizco.Domain.CommandQueries.Commands;
|
|
||||||
|
|
||||||
public sealed record CreateComplexCommand(string Name, string Address, string SupportPhone)
|
public sealed record CreateComplexCommand(string Name, string Address, string SupportPhone)
|
||||||
: IRequest<ComplexSDto>;
|
: IRequest<ComplexSDto>;
|
||||||
|
|
||||||
|
public sealed record CreateComplexUserCommand(Guid ComplexId,Guid UserId,Guid RoleId)
|
||||||
|
: IRequest<ComplexUserSDto>;
|
||||||
|
|
||||||
|
public sealed record DeleteComplexUserCommand(Guid ComplexUserId)
|
||||||
|
: IRequest<bool>;
|
||||||
|
|
||||||
public sealed record UpdateComplexCommand(Guid Id, string Name, string Address, string SupportPhone)
|
public sealed record UpdateComplexCommand(Guid Id, string Name, string Address, string SupportPhone)
|
||||||
: IRequest<bool>;
|
: IRequest<bool>;
|
||||||
|
|
||||||
|
|
||||||
public sealed record DeleteComplexCommand(Guid Id)
|
public sealed record DeleteComplexCommand(Guid Id)
|
||||||
: IRequest<bool>;
|
: IRequest<bool>;
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace Brizco.Domain.Dtos.RequestDtos;
|
||||||
|
|
||||||
|
public class LoginRequestDto
|
||||||
|
{
|
||||||
|
public string UserName { get; set; } = string.Empty;
|
||||||
|
public string Password { get; set; } = string.Empty;
|
||||||
|
public string VerifyCode { get; set; } = string.Empty;
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
namespace Brizco.Domain.Dtos.RequestDtos;
|
||||||
|
|
||||||
|
public class SignUpRequestDto
|
||||||
|
{
|
||||||
|
public string FirstName { get; set; } = string.Empty;
|
||||||
|
public string LastName { get; set; } = string.Empty;
|
||||||
|
public string ComplexName { get; set; } = string.Empty;
|
||||||
|
public string ComplexAddress { get; set; } = string.Empty;
|
||||||
|
public string SupportPhoneNumber { get; set; } = string.Empty;
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
using Brizco.Domain.Entities.User;
|
||||||
|
|
||||||
|
namespace Brizco.Domain.Dtos.SmallDtos;
|
||||||
|
|
||||||
|
public class ApplicationUserSDto : BaseDto<ApplicationUserSDto,ApplicationUser>
|
||||||
|
{
|
||||||
|
public string PhoneNumber { get; set; } = string.Empty;
|
||||||
|
public string FirstName { get; set; } = string.Empty;
|
||||||
|
public string LastName { get; set; } = string.Empty;
|
||||||
|
public DateTime BirthDate { get; set; }
|
||||||
|
public Gender Gender { get; set; }
|
||||||
|
public SignUpStatus SignUpStatus { get; set; }
|
||||||
|
public string SelectedRoleName { get; set; } = string.Empty;
|
||||||
|
public string SelectedComplexName { get; set; } = string.Empty;
|
||||||
|
}
|
|
@ -6,4 +6,11 @@ public partial class Complex
|
||||||
{
|
{
|
||||||
return new Complex(name,address,supportPhone);
|
return new Complex(name,address,supportPhone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ComplexUser AddComplexUser(Guid userId, Guid roleId)
|
||||||
|
{
|
||||||
|
var complex = new ComplexUser(userId, this.Id, roleId);
|
||||||
|
this.Users.Add(complex);
|
||||||
|
return complex;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -5,9 +5,22 @@ namespace Brizco.Domain.Entities.Complex;
|
||||||
[GenerateMapper]
|
[GenerateMapper]
|
||||||
public class ComplexUser : ApiEntity
|
public class ComplexUser : ApiEntity
|
||||||
{
|
{
|
||||||
|
public ComplexUser()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public ComplexUser(Guid userId, Guid complexId, Guid roleId)
|
||||||
|
{
|
||||||
|
UserId = userId;
|
||||||
|
ComplexId = complexId;
|
||||||
|
RoleId = roleId;
|
||||||
|
}
|
||||||
public Guid UserId { get; internal set; }
|
public Guid UserId { get; internal set; }
|
||||||
public Guid ComplexId { get; internal set; }
|
public Guid ComplexId { get; internal set; }
|
||||||
|
public Guid RoleId { get; internal set; }
|
||||||
|
|
||||||
|
public ApplicationRole? Role { get; internal set; }
|
||||||
public ApplicationUser? User { get; internal set; }
|
public ApplicationUser? User { get; internal set; }
|
||||||
public Complex? Complex { get; internal set; }
|
public Complex? Complex { get; internal set; }
|
||||||
}
|
}
|
|
@ -3,6 +3,8 @@
|
||||||
public class ApplicationRole : IdentityRole<Guid>
|
public class ApplicationRole : IdentityRole<Guid>
|
||||||
{
|
{
|
||||||
public string Description { get; set; } = string.Empty;
|
public string Description { get; set; } = string.Empty;
|
||||||
|
public string EnglishName { get; set; } = string.Empty;
|
||||||
|
public string PersianName { get; set; } = string.Empty;
|
||||||
|
|
||||||
public Guid? ComplexId { get; set; }
|
public Guid? ComplexId { get; set; }
|
||||||
public Complex.Complex? Complex { get; set; }
|
public Complex.Complex? Complex { get; set; }
|
||||||
|
|
|
@ -6,5 +6,6 @@ public class ApplicationUser : IdentityUser<Guid>
|
||||||
public string LastName { get; set; } = string.Empty;
|
public string LastName { get; set; } = string.Empty;
|
||||||
public DateTime BirthDate { get; set; }
|
public DateTime BirthDate { get; set; }
|
||||||
public Gender Gender { get; set; }
|
public Gender Gender { get; set; }
|
||||||
|
public SignUpStatus SignUpStatus { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace Brizco.Domain.Enums;
|
||||||
|
|
||||||
|
public enum SignUpStatus
|
||||||
|
{
|
||||||
|
StartSignUp = 0,
|
||||||
|
PhoneNumberVerified = 1,
|
||||||
|
ComplexCreated = 2,
|
||||||
|
SignUpCompleted = 3,
|
||||||
|
}
|
|
@ -1,4 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using Brizco.Domain.Dtos.LargDtos;
|
using Brizco.Domain.Dtos.LargDtos;
|
||||||
using Brizco.Domain.Dtos.SmallDtos;
|
using Brizco.Domain.Dtos.SmallDtos;
|
||||||
|
@ -79,62 +81,182 @@ namespace Brizco.Domain.Mappers
|
||||||
Name = p9.Name,
|
Name = p9.Name,
|
||||||
Address = p9.Address,
|
Address = p9.Address,
|
||||||
SupportPhone = p9.SupportPhone,
|
SupportPhone = p9.SupportPhone,
|
||||||
|
Users = funcMain1(p9.Users),
|
||||||
Id = p9.Id
|
Id = p9.Id
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
public static Complex AdaptTo(this ComplexLDto p10, Complex p11)
|
public static Complex AdaptTo(this ComplexLDto p11, Complex p12)
|
||||||
|
{
|
||||||
|
if (p11 == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Complex result = p12 ?? new Complex();
|
||||||
|
|
||||||
|
result.Name = p11.Name;
|
||||||
|
result.Address = p11.Address;
|
||||||
|
result.SupportPhone = p11.SupportPhone;
|
||||||
|
result.Users = funcMain2(p11.Users, result.Users);
|
||||||
|
result.Id = p11.Id;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
public static Expression<Func<ComplexLDto, Complex>> ProjectLDtoToComplex => p15 => new Complex()
|
||||||
|
{
|
||||||
|
Name = p15.Name,
|
||||||
|
Address = p15.Address,
|
||||||
|
SupportPhone = p15.SupportPhone,
|
||||||
|
Users = p15.Users.Select<ComplexUserSDto, ComplexUser>(p16 => new ComplexUser()
|
||||||
|
{
|
||||||
|
UserId = p16.UserId,
|
||||||
|
ComplexId = p16.ComplexId,
|
||||||
|
Id = p16.Id
|
||||||
|
}).ToList<ComplexUser>(),
|
||||||
|
Id = p15.Id
|
||||||
|
};
|
||||||
|
public static ComplexLDto AdaptToLDto(this Complex p17)
|
||||||
|
{
|
||||||
|
return p17 == null ? null : new ComplexLDto()
|
||||||
|
{
|
||||||
|
Name = p17.Name,
|
||||||
|
Address = p17.Address,
|
||||||
|
SupportPhone = p17.SupportPhone,
|
||||||
|
Users = funcMain3(p17.Users),
|
||||||
|
Id = p17.Id
|
||||||
|
};
|
||||||
|
}
|
||||||
|
public static ComplexLDto AdaptTo(this Complex p19, ComplexLDto p20)
|
||||||
|
{
|
||||||
|
if (p19 == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ComplexLDto result = p20 ?? new ComplexLDto();
|
||||||
|
|
||||||
|
result.Name = p19.Name;
|
||||||
|
result.Address = p19.Address;
|
||||||
|
result.SupportPhone = p19.SupportPhone;
|
||||||
|
result.Users = funcMain4(p19.Users, result.Users);
|
||||||
|
result.Id = p19.Id;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
public static Expression<Func<Complex, ComplexLDto>> ProjectToLDto => p23 => new ComplexLDto()
|
||||||
|
{
|
||||||
|
Name = p23.Name,
|
||||||
|
Address = p23.Address,
|
||||||
|
SupportPhone = p23.SupportPhone,
|
||||||
|
Users = p23.Users.Select<ComplexUser, ComplexUserSDto>(p24 => new ComplexUserSDto()
|
||||||
|
{
|
||||||
|
UserId = p24.UserId,
|
||||||
|
ComplexId = p24.ComplexId,
|
||||||
|
Id = p24.Id
|
||||||
|
}).ToList<ComplexUserSDto>(),
|
||||||
|
Id = p23.Id
|
||||||
|
};
|
||||||
|
|
||||||
|
private static List<ComplexUser> funcMain1(List<ComplexUserSDto> p10)
|
||||||
{
|
{
|
||||||
if (p10 == null)
|
if (p10 == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Complex result = p11 ?? new Complex();
|
List<ComplexUser> result = new List<ComplexUser>(p10.Count);
|
||||||
|
|
||||||
result.Name = p10.Name;
|
int i = 0;
|
||||||
result.Address = p10.Address;
|
int len = p10.Count;
|
||||||
result.SupportPhone = p10.SupportPhone;
|
|
||||||
result.Id = p10.Id;
|
while (i < len)
|
||||||
|
{
|
||||||
|
ComplexUserSDto item = p10[i];
|
||||||
|
result.Add(item == null ? null : new ComplexUser()
|
||||||
|
{
|
||||||
|
UserId = item.UserId,
|
||||||
|
ComplexId = item.ComplexId,
|
||||||
|
Id = item.Id
|
||||||
|
});
|
||||||
|
i++;
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
public static Expression<Func<ComplexLDto, Complex>> ProjectLDtoToComplex => p12 => new Complex()
|
|
||||||
|
private static List<ComplexUser> funcMain2(List<ComplexUserSDto> p13, List<ComplexUser> p14)
|
||||||
{
|
{
|
||||||
Name = p12.Name,
|
if (p13 == null)
|
||||||
Address = p12.Address,
|
|
||||||
SupportPhone = p12.SupportPhone,
|
|
||||||
Id = p12.Id
|
|
||||||
};
|
|
||||||
public static ComplexLDto AdaptToLDto(this Complex p13)
|
|
||||||
{
|
|
||||||
return p13 == null ? null : new ComplexLDto()
|
|
||||||
{
|
|
||||||
Name = p13.Name,
|
|
||||||
Address = p13.Address,
|
|
||||||
SupportPhone = p13.SupportPhone,
|
|
||||||
Id = p13.Id
|
|
||||||
};
|
|
||||||
}
|
|
||||||
public static ComplexLDto AdaptTo(this Complex p14, ComplexLDto p15)
|
|
||||||
{
|
|
||||||
if (p14 == null)
|
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ComplexLDto result = p15 ?? new ComplexLDto();
|
List<ComplexUser> result = new List<ComplexUser>(p13.Count);
|
||||||
|
|
||||||
result.Name = p14.Name;
|
int i = 0;
|
||||||
result.Address = p14.Address;
|
int len = p13.Count;
|
||||||
result.SupportPhone = p14.SupportPhone;
|
|
||||||
result.Id = p14.Id;
|
while (i < len)
|
||||||
|
{
|
||||||
|
ComplexUserSDto item = p13[i];
|
||||||
|
result.Add(item == null ? null : new ComplexUser()
|
||||||
|
{
|
||||||
|
UserId = item.UserId,
|
||||||
|
ComplexId = item.ComplexId,
|
||||||
|
Id = item.Id
|
||||||
|
});
|
||||||
|
i++;
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
public static Expression<Func<Complex, ComplexLDto>> ProjectToLDto => p16 => new ComplexLDto()
|
|
||||||
|
private static List<ComplexUserSDto> funcMain3(List<ComplexUser> p18)
|
||||||
{
|
{
|
||||||
Name = p16.Name,
|
if (p18 == null)
|
||||||
Address = p16.Address,
|
{
|
||||||
SupportPhone = p16.SupportPhone,
|
return null;
|
||||||
Id = p16.Id
|
}
|
||||||
};
|
List<ComplexUserSDto> result = new List<ComplexUserSDto>(p18.Count);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
int len = p18.Count;
|
||||||
|
|
||||||
|
while (i < len)
|
||||||
|
{
|
||||||
|
ComplexUser item = p18[i];
|
||||||
|
result.Add(item == null ? null : new ComplexUserSDto()
|
||||||
|
{
|
||||||
|
UserId = item.UserId,
|
||||||
|
ComplexId = item.ComplexId,
|
||||||
|
Id = item.Id
|
||||||
|
});
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<ComplexUserSDto> funcMain4(List<ComplexUser> p21, List<ComplexUserSDto> p22)
|
||||||
|
{
|
||||||
|
if (p21 == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
List<ComplexUserSDto> result = new List<ComplexUserSDto>(p21.Count);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
int len = p21.Count;
|
||||||
|
|
||||||
|
while (i < len)
|
||||||
|
{
|
||||||
|
ComplexUser item = p21[i];
|
||||||
|
result.Add(item == null ? null : new ComplexUserSDto()
|
||||||
|
{
|
||||||
|
UserId = item.UserId,
|
||||||
|
ComplexId = item.ComplexId,
|
||||||
|
Id = item.Id
|
||||||
|
});
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -6,6 +6,7 @@ public class SiteSettings
|
||||||
public string BaseUrl { get; set; } = string.Empty;
|
public string BaseUrl { get; set; } = string.Empty;
|
||||||
public RedisSettings MasterRedisConfiguration { get; set; } = new RedisSettings();
|
public RedisSettings MasterRedisConfiguration { get; set; } = new RedisSettings();
|
||||||
public UserSetting UserSetting { get; set; } = new UserSetting();
|
public UserSetting UserSetting { get; set; } = new UserSetting();
|
||||||
|
public string KaveNegarApiKey { get; set; } = string.Empty;
|
||||||
}
|
}
|
||||||
public class RedisSettings
|
public class RedisSettings
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue