config db

release/production
Amir Hossein Khademi 2023-10-13 16:25:34 +03:30
parent 02abd6ddf3
commit 49bb2d2b09
46 changed files with 1230 additions and 167 deletions

View File

@ -1,8 +1,56 @@
{
"ConnectionStrings": {
"Postgres": "User ID=postgres;Password=root;Host=localhost;Port=5432;Database=iGarsonDB;",
"PostgresServer": "Host=pg-0,pg-1;Username=igarsonAgent;Password=xHTpBf4wC+bBeNg2pL6Ga7VEWKFJx7VPEUpqxwPFfOc2YYTVwFQuHfsiqoVeT9+6;Database=BrizcoDB;Load Balance Hosts=true;Target Session Attributes=primary;Application Name=iGLS"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
"Microsoft": "None",
"Microsoft.Hosting.Lifetime": "Information",
"Microsoft.AspNetCore.SignalR": "Debug",
"Microsoft.AspNetCore.Http.Connections": "Debug"
}
}
}
},
"SiteSettings": {
"BaseUrl": "http://localhost:32769",
"UserSetting": {
"Username": "Root",
"Email": "info@brizco.io",
"Password": "root1234",
"Phone": "09211111111",
"RoleName": "RootAdmin",
"FirstName": "همه کاره",
"LastName": "سیستم"
},
"JwtSettings": {
"SecretKey": "pg8mt74/bk5yx2mr23Zvsu/81Z2czAycEo9ewcm34AndD8SFDXGqBiYv_YaHosseinYaAli_ABOOOOOOOOOLFAZL_BIMEH_JAD_NASABE_YA_GHARIBAL_GHORABA_@@@@_06/0CZWyAqy2H6Xpjp0npg8mt74/bk5yx2mr23Zvsu/81Z2czAycEo9ewcm34AndD8SFDXGqBiYvACLB0dED9vjy+h5sK1BnB30=",
"Issuer": "Brizco",
"Audience": "Brizco",
"ExpireAddDay": "15"
}
},
"IpRateLimiting": {
"EnableEndpointRateLimiting": false,
"StackBlockedRequests": false,
"RealIpHeader": "X-Real-IP",
"ClientIdHeader": "X-ClientId",
"HttpStatusCode": 429,
"IpWhitelist": [ "127.0.0.1", "::1/10", "192.168.0.0/24" ],
"EndpointWhitelist": [ "get:/api/license", "*:/api/status" ],
"ClientWhitelist": [ "dev-id-1", "dev-id-2" ],
"GeneralRules": [
{
"Endpoint": "*",
"Period": "1m",
"Limit": 60
},
{
"Endpoint": "*",
"Period": "15m",
"Limit": 250
}
]
},
"AllowedHosts": "*"
}

View File

@ -13,10 +13,11 @@
}
},
"SiteSettings": {
"BaseUrl": "http://localhost:32769",
"UserSetting": {
"Username": "Root",
"Email": "igarson_admin@vnfco.ir",
"Password": "root1234",
"Username": "root",
"Email": "info@brizco.io",
"Password": "JXZXdG9lYI58qzsYzCnO",
"Phone": "09211111111",
"RoleName": "RootAdmin",
"FirstName": "همه کاره",
@ -24,8 +25,8 @@
},
"JwtSettings": {
"SecretKey": "pg8mt74/bk5yx2mr23Zvsu/81Z2czAycEo9ewcm34AndD8SFDXGqBiYv_YaHosseinYaAli_ABOOOOOOOOOLFAZL_BIMEH_JAD_NASABE_YA_GHARIBAL_GHORABA_@@@@_06/0CZWyAqy2H6Xpjp0npg8mt74/bk5yx2mr23Zvsu/81Z2czAycEo9ewcm34AndD8SFDXGqBiYvACLB0dED9vjy+h5sK1BnB30=",
"Issuer": "iGarson",
"Audience": "iGarson",
"Issuer": "Brizco",
"Audience": "Brizco",
"ExpireAddDay": "15"
}
},

View File

@ -57,6 +57,7 @@
<Using Include="Brizco.Common.Models.Entity" />
<Using Include="Brizco.Common.Models.Exception" />
<Using Include="Brizco.Common.Models.Mapper" />
<Using Include="Brizco.Core.EntityServices.Abstracts" />
<Using Include="Brizco.Domain.CommandQueries.Commands" />
<Using Include="Brizco.Domain.CommandQueries.Queries" />
<Using Include="Brizco.Domain.Dtos.RequestDtos" />

View File

@ -1,6 +1,6 @@
using Brizco.Common.Models.Api;
using Brizco.Core.BaseServices;
using Brizco.Core.BaseServices.Abstracts;
using Brizco.Core.CoreServices.Abstracts;
using Microsoft.AspNetCore.Authorization.Infrastructure;
namespace Brizco.Api.Controllers;
@ -16,6 +16,9 @@ public class AuthController : ICarterModule
group.MapPost("login/password", LoginWithPassword)
.WithDisplayName("LoginWithPassword")
.HasApiVersion(1.0);
group.MapPost("login/swagger", LoginSwagger)
.WithDisplayName("LoginSwagger")
.HasApiVersion(1.0);
group.MapPost("login/code", LoginWithVerifyCode)
.WithDisplayName("LoginWithVerifyCode")
@ -25,7 +28,7 @@ public class AuthController : ICarterModule
.WithDisplayName("GetVerifyCodeCode")
.HasApiVersion(1.0);
group.MapPut("forgetpassword", ForgetPassword)
group.MapPut("forget/password", ForgetPassword)
.WithDisplayName("ForgetPassword")
.HasApiVersion(1.0);
@ -54,8 +57,13 @@ public class AuthController : ICarterModule
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));
public async Task<IResult> LoginSwagger(HttpContext ctx, IAccountService accountService, CancellationToken cancellationToken)
{
var username = ctx.Request.Form["username"];
var password = ctx.Request.Form["password"];
return TypedResults.Json(await accountService.LoginWithPasswordAsync(username, password, cancellationToken));
}
}

View File

@ -5,9 +5,11 @@ public class ComplexController : ICarterModule
public virtual void AddRoutes(IEndpointRouteBuilder app)
{
var group = app.NewVersionedApi("Complex").MapGroup($"api/complex");
var group = app.NewVersionedApi("Complex")
.MapGroup($"api/complex")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser());
group.MapGet("{page}", GetAllAsync)
group.MapGet("", GetAllAsync)
.WithDisplayName("GetAllComplex")
.HasApiVersion(1.0);
@ -26,7 +28,7 @@ public class ComplexController : ICarterModule
}
// GET:Get All Entity
public async Task<IResult> GetAllAsync(int page,ISender sender, CancellationToken cancellationToken)
public async Task<IResult> GetAllAsync([FromQuery] int page,ISender sender, CancellationToken cancellationToken)
=> TypedResults.Ok(await sender.Send(new GetComplexesQuery(page), cancellationToken));
// GET:Get An Entity By Id

View File

@ -0,0 +1,51 @@
namespace Brizco.Api.Controllers;
public class RoleController : ICarterModule
{
public RoleController()
{
}
public virtual void AddRoutes(IEndpointRouteBuilder app)
{
var group = app.NewVersionedApi("Role")
.MapGroup($"api/role")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser());
group.MapGet("", GetAllAsync)
.WithDisplayName("GetAllRoles")
.HasApiVersion(1.0);
group.MapGet("{id}", GetAsync)
.WithDisplayName("GetOneRole")
.HasApiVersion(1.0);
group.MapPost("", Post)
.HasApiVersion(1.0);
group.MapPut("", Put)
.HasApiVersion(1.0);
group.MapDelete("", Delete)
.HasApiVersion(1.0);
}
// GET:Get All Entity
public async Task<IResult> GetAllAsync([FromQuery] int page, IUserService userService, CancellationToken cancellationToken)
=> TypedResults.Ok(await userService.GetRolesAsync(page, cancellationToken));
// GET:Get An Entity By Id
public async Task<IResult> GetAsync(Guid id, IUserService userService, CancellationToken cancellationToken)
=> TypedResults.Ok(await userService.GetRoleAsync(id));
// POST:Create Entity
public async Task<IResult> Post([FromBody] RoleActionRequestDto request, IUserService userService, CancellationToken cancellationToken)
=> TypedResults.Ok(await userService.CreateRoleAsync(request));
// PUT:Update Entity
public async Task<IResult> Put([FromBody] RoleActionRequestDto request, IUserService userService, CancellationToken cancellationToken)
=> TypedResults.Ok(await userService.EditRoleAsync(request));
// DELETE:Delete Entity
public async Task<IResult> Delete(Guid id, IUserService userService, CancellationToken cancellationToken)
=> TypedResults.Ok(await userService.RemoveRoleAsync(id));
}

View File

@ -6,9 +6,11 @@ public class ShiftController : ICarterModule
}
public virtual void AddRoutes(IEndpointRouteBuilder app)
{
var group = app.NewVersionedApi("Shift").MapGroup($"api/shift");
var group = app.NewVersionedApi("Shift")
.MapGroup($"api/shift")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser());
group.MapGet("{page}", GetAllAsync)
group.MapGet("", GetAllAsync)
.WithDisplayName("GetAllShift")
.HasApiVersion(1.0);
@ -32,7 +34,7 @@ public class ShiftController : ICarterModule
}
// GET:Get All Entity
public async Task<IResult> GetAllAsync(int page,ISender sender, CancellationToken cancellationToken)
public async Task<IResult> GetAllAsync([FromQuery] int page,ISender sender, CancellationToken cancellationToken)
=> TypedResults.Ok(await sender.Send(new GetShiftsQuery(page), cancellationToken));
// GET:Get An Entity By Id

View File

@ -7,9 +7,11 @@ public class TaskController : ICarterModule
}
public virtual void AddRoutes(IEndpointRouteBuilder app)
{
var group = app.NewVersionedApi("Task").MapGroup($"api/task");
var group = app.NewVersionedApi("Task")
.MapGroup($"api/task")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser());
group.MapGet("{page}", GetAllAsync)
group.MapGet("", GetAllAsync)
.WithDisplayName("GetAllTask")
.HasApiVersion(1.0);
@ -28,7 +30,7 @@ public class TaskController : ICarterModule
}
// GET:Get All Entity
public async Task<IResult> GetAllAsync(int page,ISender sender, CancellationToken cancellationToken)
public async Task<IResult> GetAllAsync([FromQuery] int page,ISender sender, CancellationToken cancellationToken)
=> TypedResults.Ok(await sender.Send(new GetTasksQuery(page), cancellationToken));
// GET:Get An Entity By Id

View File

@ -0,0 +1,54 @@
using Brizco.Core.EntityServices;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace Brizco.Api.Controllers;
public class UserController : ICarterModule
{
public UserController()
{
}
public virtual void AddRoutes(IEndpointRouteBuilder app)
{
var group = app.NewVersionedApi("User")
.MapGroup($"api/user")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser());
group.MapGet("", GetAllAsync)
.WithDisplayName("GetAllUser")
.HasApiVersion(1.0);
group.MapGet("{id}", GetAsync)
.WithDisplayName("GetOneUser")
.HasApiVersion(1.0);
group.MapPost("", Post)
.HasApiVersion(1.0);
group.MapPut("", Put)
.HasApiVersion(1.0);
group.MapDelete("", Delete)
.HasApiVersion(1.0);
}
// GET:Get All Entity
public async Task<IResult> GetAllAsync([FromQuery]int page, IUserService userService, CancellationToken cancellationToken)
=> TypedResults.Ok(await userService.GetUsersAsync(page,cancellationToken));
// GET:Get An Entity By Id
public async Task<IResult> GetAsync(Guid id, IUserService userService, CancellationToken cancellationToken)
=> TypedResults.Ok(await userService.GetUserAsync(id));
// POST:Create Entity
public async Task<IResult> Post([FromBody] UserActionRequestDto request, IUserService userService, CancellationToken cancellationToken)
=> TypedResults.Ok(await userService.CreateUserAsync(request,cancellationToken));
// PUT:Update Entity
public async Task<IResult> Put([FromBody] UserActionRequestDto request, IUserService userService, CancellationToken cancellationToken)
=> TypedResults.Ok(await userService.EditUserAsync(request,cancellationToken));
// DELETE:Delete Entity
public async Task<IResult> Delete(Guid id, IUserService userService, CancellationToken cancellationToken)
=> TypedResults.Ok(await userService.RemoveUserAsync(id, cancellationToken));
}

View File

@ -59,7 +59,7 @@ public static class SwaggerConfiguration
#region Security
var url = $"{baseUrl}/api/v1/user/LoginSwagger";
var url = $"{baseUrl}/api/auth/login/swagger";
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Type = SecuritySchemeType.OAuth2,

View File

@ -58,6 +58,7 @@
<Using Include="Microsoft.AspNetCore.Identity" />
<Using Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" />
<Using Include="Microsoft.EntityFrameworkCore" />
<Using Include="Microsoft.EntityFrameworkCore.ChangeTracking" />
<Using Include="Microsoft.EntityFrameworkCore.Infrastructure" />
<Using Include="Microsoft.Extensions.DependencyInjection" />
<Using Include="Microsoft.Extensions.Logging" />

View File

@ -1,4 +1,5 @@
using Brizco.Domain.Entities.User;
using Brizco.Domain.Entities.Complex;
using Brizco.Domain.Entities.User;
using Microsoft.AspNetCore.Identity;
namespace Brizco.Repository.Handlers.Complex;
@ -31,13 +32,26 @@ public class CreateComplexUserCommandHandler : IRequestHandler<CreateComplexUser
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));
if (user == null)
throw new AppException("User not found", ApiResultStatusCode.NotFound);
var complexUser = await _repositoryWrapper.SetRepository<ComplexUser>()
.TableNoTracking
.FirstOrDefaultAsync(f => f.ComplexId == request.ComplexId && f.UserId == request.UserId, cancellationToken);
if (complexUser != null)
throw new AppException("این کاربر در این رستوران وجود دارد");
complexUser = complex.AddComplexUser(request.UserId);
foreach (var roleId in request.RoleIds)
{
var role = await _roleManager.FindByIdAsync(roleId.ToString());
var result = await _userManager.AddToRoleAsync(user, role.Name);
if (!result.Succeeded)
throw new AppException(string.Join('|', result.Errors));
complexUser.AddRole(role.Id);
}
_repositoryWrapper.SetRepository<ComplexUser>().Add(complexUser);
await _repositoryWrapper.SaveChangesAsync(cancellationToken);
await _repositoryWrapper.CommitAsync(cancellationToken);
return complexUser.AdaptToSDto();

View File

@ -18,7 +18,7 @@ public class DeleteComplexUserCommandHandler : IRequestHandler<DeleteComplexUser
await _repositoryWrapper.BeginTransaction(cancellationToken);
var complexUser = await _repositoryWrapper.SetRepository<ComplexUser>()
.TableNoTracking
.FirstOrDefaultAsync(c => c.Id == request.ComplexUserId, cancellationToken);
.FirstOrDefaultAsync(c => c.ComplexId == request.ComplexId && c.UserId == request.UserId, cancellationToken);
if (complexUser == null)
throw new AppException("ComplexUser not found", ApiResultStatusCode.NotFound);

View File

@ -0,0 +1,32 @@
using Brizco.Domain.Entities.Complex;
using Microsoft.IdentityModel.Tokens;
namespace Brizco.Repository.Handlers.Complex;
public class GetComplexUsersQueryHandler : IRequestHandler<GetComplexUsersQuery, List<ComplexUserSDto>>
{
private readonly IRepositoryWrapper _repositoryWrapper;
public GetComplexUsersQueryHandler(IRepositoryWrapper repositoryWrapper)
{
_repositoryWrapper = repositoryWrapper;
}
public async Task<List<ComplexUserSDto>> Handle(GetComplexUsersQuery request, CancellationToken cancellationToken)
{
if (!request.ComplexId.IsNullOrEmpty() && Guid.TryParse(request.ComplexId, out Guid complexId))
return await _repositoryWrapper.SetRepository<ComplexUser>().TableNoTracking
.Where(c => c.ComplexId == complexId)
.OrderByDescending(s => s.CreatedAt)
.Skip(request.Page * 15).Take(15)
.Select(ComplexUserMapper.ProjectToSDto)
.ToListAsync(cancellationToken);
return await _repositoryWrapper.SetRepository<ComplexUser>().TableNoTracking
.OrderByDescending(s => s.CreatedAt)
.Skip(request.Page * 15).Take(15)
.Select(ComplexUserMapper.ProjectToSDto)
.ToListAsync(cancellationToken);
}
}

View File

@ -0,0 +1,80 @@
using Brizco.Domain.Entities.Complex;
using Brizco.Domain.Entities.User;
using StackExchange.Redis;
namespace Brizco.Repository.Handlers.Complex;
public class UpdateComplexUserCommandHandler : IRequestHandler<UpdateComplexUserCommand, bool>
{
private readonly IRepositoryWrapper _repositoryWrapper;
private readonly UserManager<ApplicationUser> _userManager;
private readonly RoleManager<ApplicationRole> _roleManager;
public UpdateComplexUserCommandHandler(IRepositoryWrapper repositoryWrapper,
UserManager<ApplicationUser> userManager,
RoleManager<ApplicationRole> roleManager)
{
_repositoryWrapper = repositoryWrapper;
_userManager = userManager;
_roleManager = roleManager;
}
public async Task<bool> Handle(UpdateComplexUserCommand request, CancellationToken cancellationToken)
{
try
{
await _repositoryWrapper.BeginTransaction(cancellationToken);
var complexUser = await _repositoryWrapper.SetRepository<ComplexUser>().TableNoTracking
.FirstOrDefaultAsync(c => c.UserId == request.UserId && c.ComplexId==request.ComplexId , cancellationToken);
if (complexUser == null)
throw new AppException("ComplexUser not found", ApiResultStatusCode.NotFound);
var complexUserRoles = await _repositoryWrapper.SetRepository<ComplexUserRole>()
.TableNoTracking
.Where(cur => cur.ComplexUserId == complexUser.Id)
.ToListAsync(cancellationToken);
var user = await _userManager.FindByIdAsync(complexUser.UserId.ToString());
if (user == null)
throw new AppException("User not found", ApiResultStatusCode.NotFound);
foreach (var userRole in complexUserRoles.ToList())
{
if(request.RoleIds.Contains(userRole.RoleId))
{
complexUserRoles.Remove(userRole);
request.RoleIds.Remove(userRole.RoleId);
}
}
foreach (var userRole in complexUserRoles)
{
_repositoryWrapper.SetRepository<ComplexUserRole>().Delete(userRole);
var role = await _roleManager.FindByIdAsync(userRole.RoleId.ToString());
var result = await _userManager.RemoveFromRoleAsync(user, role.Name);
if (!result.Succeeded)
throw new AppException(string.Join('|', result.Errors));
}
foreach (var roleId in request.RoleIds)
{
var role = await _roleManager.FindByIdAsync(roleId.ToString());
var result = await _userManager.AddToRoleAsync(user, role.Name);
if (!result.Succeeded)
throw new AppException(string.Join('|', result.Errors));
var userRole = complexUser.AddRole(role.Id);
_repositoryWrapper.SetRepository<ComplexUserRole>().Add(userRole);
}
await _repositoryWrapper.SaveChangesAsync(cancellationToken);
await _repositoryWrapper.CommitAsync(cancellationToken);
return true;
}
catch (Exception)
{
await _repositoryWrapper.RollBackAsync(cancellationToken);
throw;
}
}
}

View File

@ -12,7 +12,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace Brizco.Repository.Migrations
{
[DbContext(typeof(ApplicationContext))]
[Migration("20230919130824_Init")]
[Migration("20230920133908_Init")]
partial class Init
{
/// <inheritdoc />
@ -106,9 +106,6 @@ namespace Brizco.Repository.Migrations
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("RoleId")
.HasColumnType("uuid");
b.Property<Guid>("UserId")
.HasColumnType("uuid");
@ -116,13 +113,56 @@ namespace Brizco.Repository.Migrations
b.HasIndex("ComplexId");
b.HasIndex("RoleId");
b.HasIndex("UserId");
b.ToTable("ComplexUsers", "public");
});
modelBuilder.Entity("Brizco.Domain.Entities.Complex.ComplexUserRole", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid>("ComplexUserId")
.HasColumnType("uuid");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp without time zone");
b.Property<string>("CreatedBy")
.IsRequired()
.HasColumnType("text");
b.Property<bool>("IsRemoved")
.HasColumnType("boolean");
b.Property<DateTime>("ModifiedAt")
.HasColumnType("timestamp without time zone");
b.Property<string>("ModifiedBy")
.IsRequired()
.HasColumnType("text");
b.Property<DateTime>("RemovedAt")
.HasColumnType("timestamp without time zone");
b.Property<string>("RemovedBy")
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("RoleId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("ComplexUserId");
b.HasIndex("RoleId");
b.ToTable("ComplexUserRoles", "public");
});
modelBuilder.Entity("Brizco.Domain.Entities.Shift.Shift", b =>
{
b.Property<Guid>("Id")
@ -603,6 +643,10 @@ namespace Brizco.Repository.Migrations
b.Property<int>("Gender")
.HasColumnType("integer");
b.Property<string>("InternationalId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("LastName")
.IsRequired()
.HasColumnType("text");
@ -786,12 +830,6 @@ namespace Brizco.Repository.Migrations
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.HasOne("Brizco.Domain.Entities.User.ApplicationRole", "Role")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.HasOne("Brizco.Domain.Entities.User.ApplicationUser", "User")
.WithMany()
.HasForeignKey("UserId")
@ -800,11 +838,28 @@ namespace Brizco.Repository.Migrations
b.Navigation("Complex");
b.Navigation("Role");
b.Navigation("User");
});
modelBuilder.Entity("Brizco.Domain.Entities.Complex.ComplexUserRole", b =>
{
b.HasOne("Brizco.Domain.Entities.Complex.ComplexUser", "ComplexUser")
.WithMany("Roles")
.HasForeignKey("ComplexUserId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.HasOne("Brizco.Domain.Entities.User.ApplicationRole", "Role")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("ComplexUser");
b.Navigation("Role");
});
modelBuilder.Entity("Brizco.Domain.Entities.Shift.Shift", b =>
{
b.HasOne("Brizco.Domain.Entities.Complex.Complex", "Complex")
@ -996,6 +1051,11 @@ namespace Brizco.Repository.Migrations
b.Navigation("Users");
});
modelBuilder.Entity("Brizco.Domain.Entities.Complex.ComplexUser", b =>
{
b.Navigation("Roles");
});
modelBuilder.Entity("Brizco.Domain.Entities.Shift.Shift", b =>
{
b.Navigation("Days");

View File

@ -45,6 +45,7 @@ namespace Brizco.Repository.Migrations
Id = table.Column<Guid>(type: "uuid", nullable: false),
FirstName = table.Column<string>(type: "text", nullable: false),
LastName = table.Column<string>(type: "text", nullable: false),
InternationalId = table.Column<string>(type: "text", nullable: false),
BirthDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
Gender = table.Column<int>(type: "integer", nullable: false),
SignUpStatus = table.Column<int>(type: "integer", nullable: false),
@ -190,6 +191,41 @@ namespace Brizco.Repository.Migrations
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(
name: "Logins",
schema: "public",
@ -234,49 +270,6 @@ namespace Brizco.Repository.Migrations
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(
name: "RoleClaims",
schema: "public",
@ -489,6 +482,41 @@ namespace Brizco.Repository.Migrations
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateTable(
name: "ComplexUserRoles",
schema: "public",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
ComplexUserId = 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_ComplexUserRoles", x => x.Id);
table.ForeignKey(
name: "FK_ComplexUserRoles_ComplexUsers_ComplexUserId",
column: x => x.ComplexUserId,
principalSchema: "public",
principalTable: "ComplexUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_ComplexUserRoles_Roles_RoleId",
column: x => x.RoleId,
principalSchema: "public",
principalTable: "Roles",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateTable(
name: "ShiftPlanUsers",
schema: "public",
@ -530,18 +558,24 @@ namespace Brizco.Repository.Migrations
table: "Claims",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_ComplexUserRoles_ComplexUserId",
schema: "public",
table: "ComplexUserRoles",
column: "ComplexUserId");
migrationBuilder.CreateIndex(
name: "IX_ComplexUserRoles_RoleId",
schema: "public",
table: "ComplexUserRoles",
column: "RoleId");
migrationBuilder.CreateIndex(
name: "IX_ComplexUsers_ComplexId",
schema: "public",
table: "ComplexUsers",
column: "ComplexId");
migrationBuilder.CreateIndex(
name: "IX_ComplexUsers_RoleId",
schema: "public",
table: "ComplexUsers",
column: "RoleId");
migrationBuilder.CreateIndex(
name: "IX_ComplexUsers_UserId",
schema: "public",
@ -673,7 +707,7 @@ namespace Brizco.Repository.Migrations
schema: "public");
migrationBuilder.DropTable(
name: "ComplexUsers",
name: "ComplexUserRoles",
schema: "public");
migrationBuilder.DropTable(
@ -712,6 +746,10 @@ namespace Brizco.Repository.Migrations
name: "UserRoles",
schema: "public");
migrationBuilder.DropTable(
name: "ComplexUsers",
schema: "public");
migrationBuilder.DropTable(
name: "ShiftPlans",
schema: "public");

View File

@ -103,9 +103,6 @@ namespace Brizco.Repository.Migrations
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("RoleId")
.HasColumnType("uuid");
b.Property<Guid>("UserId")
.HasColumnType("uuid");
@ -113,13 +110,56 @@ namespace Brizco.Repository.Migrations
b.HasIndex("ComplexId");
b.HasIndex("RoleId");
b.HasIndex("UserId");
b.ToTable("ComplexUsers", "public");
});
modelBuilder.Entity("Brizco.Domain.Entities.Complex.ComplexUserRole", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid>("ComplexUserId")
.HasColumnType("uuid");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp without time zone");
b.Property<string>("CreatedBy")
.IsRequired()
.HasColumnType("text");
b.Property<bool>("IsRemoved")
.HasColumnType("boolean");
b.Property<DateTime>("ModifiedAt")
.HasColumnType("timestamp without time zone");
b.Property<string>("ModifiedBy")
.IsRequired()
.HasColumnType("text");
b.Property<DateTime>("RemovedAt")
.HasColumnType("timestamp without time zone");
b.Property<string>("RemovedBy")
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("RoleId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("ComplexUserId");
b.HasIndex("RoleId");
b.ToTable("ComplexUserRoles", "public");
});
modelBuilder.Entity("Brizco.Domain.Entities.Shift.Shift", b =>
{
b.Property<Guid>("Id")
@ -600,6 +640,10 @@ namespace Brizco.Repository.Migrations
b.Property<int>("Gender")
.HasColumnType("integer");
b.Property<string>("InternationalId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("LastName")
.IsRequired()
.HasColumnType("text");
@ -783,12 +827,6 @@ namespace Brizco.Repository.Migrations
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.HasOne("Brizco.Domain.Entities.User.ApplicationRole", "Role")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.HasOne("Brizco.Domain.Entities.User.ApplicationUser", "User")
.WithMany()
.HasForeignKey("UserId")
@ -797,11 +835,28 @@ namespace Brizco.Repository.Migrations
b.Navigation("Complex");
b.Navigation("Role");
b.Navigation("User");
});
modelBuilder.Entity("Brizco.Domain.Entities.Complex.ComplexUserRole", b =>
{
b.HasOne("Brizco.Domain.Entities.Complex.ComplexUser", "ComplexUser")
.WithMany("Roles")
.HasForeignKey("ComplexUserId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.HasOne("Brizco.Domain.Entities.User.ApplicationRole", "Role")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("ComplexUser");
b.Navigation("Role");
});
modelBuilder.Entity("Brizco.Domain.Entities.Shift.Shift", b =>
{
b.HasOne("Brizco.Domain.Entities.Complex.Complex", "Complex")
@ -993,6 +1048,11 @@ namespace Brizco.Repository.Migrations
b.Navigation("Users");
});
modelBuilder.Entity("Brizco.Domain.Entities.Complex.ComplexUser", b =>
{
b.Navigation("Roles");
});
modelBuilder.Entity("Brizco.Domain.Entities.Shift.Shift", b =>
{
b.Navigation("Days");

View File

@ -1,6 +1,4 @@
using Brizco.Repository.Models;
using Brizco.Repository.Repositories.UnitOfWork;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Storage;
namespace Brizco.Repository.Repositories.Base;
@ -14,6 +12,7 @@ public class RepositoryWrapper : IRepositoryWrapper
}
public IBaseRepository<T> SetRepository<T>() where T : ApiEntity => new BaseRepository<T>(_context);
public async Task RollBackAsync(CancellationToken cancellationToken)
{
@ -27,9 +26,9 @@ public class RepositoryWrapper : IRepositoryWrapper
throw new ArgumentNullException(nameof(_currentTransaction));
await _currentTransaction.CommitAsync(cancellationToken);
}
public async Task BeginTransaction()
public async Task BeginTransaction(CancellationToken cancellationToken)
{
_currentTransaction = await _context.Database.BeginTransactionAsync();
_currentTransaction = await _context.Database.BeginTransactionAsync(cancellationToken);
}
public async Task SaveChangesAsync(CancellationToken cancellationToken = default)
{

View File

@ -16,7 +16,6 @@
</ItemGroup>
<ItemGroup>
<Folder Include="EntityServices\Abstracts\" />
<Folder Include="Models\Api\" />
</ItemGroup>
@ -25,12 +24,14 @@
</ItemGroup>
<ItemGroup>
<Using Include="Brizco.Common.Extensions" />
<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.CoreServices.Abstracts" />
<Using Include="Brizco.Core.EntityServices.Abstracts" />
<Using Include="Brizco.Domain.CommandQueries.Commands" />
<Using Include="Brizco.Domain.Dtos.RequestDtos" />
@ -43,6 +44,7 @@
<Using Include="MediatR" />
<Using Include="Microsoft.AspNetCore.Identity" />
<Using Include="Microsoft.EntityFrameworkCore" />
<Using Include="Microsoft.IdentityModel.Tokens" />
</ItemGroup>
</Project>

View File

@ -1,4 +1,4 @@
namespace Brizco.Core.BaseServices.Abstracts;
namespace Brizco.Core.CoreServices.Abstracts;
public interface IAccountService : IScopedDependency
{

View File

@ -0,0 +1,6 @@
namespace Brizco.Core.CoreServices.Abstracts;
public interface IPageService
{
}

View File

@ -1,12 +1,4 @@
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;
namespace Brizco.Core.CoreServices;
public class AccountService : IAccountService
{
@ -18,6 +10,7 @@ public class AccountService : IAccountService
private readonly IRepositoryWrapper _repositoryWrapper;
private readonly ISmsService _smsService;
private readonly IComplexService _complexService;
private readonly IUserService _userService;
public AccountService(
UserManager<ApplicationUser> userManager,
@ -26,7 +19,8 @@ public class AccountService : IAccountService
ICurrentUserService currentUserService,
IRepositoryWrapper repositoryWrapper,
ISmsService smsService,
IComplexService complexService)
IComplexService complexService,
IUserService userService)
{
_userManager = userManager;
_userSignInManager = userSignInManager;
@ -35,6 +29,7 @@ public class AccountService : IAccountService
_repositoryWrapper = repositoryWrapper;
_smsService = smsService;
_complexService = complexService;
_userService = userService;
}
@ -76,17 +71,8 @@ public class AccountService : IAccountService
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));
}
user = await _userService.CreateUserAsync(phoneNumber);
var token = await _userManager.GenerateTwoFactorTokenAsync(user, "Phone");
await _smsService.SendVerifyCodeAsync(newPhoneNumber, token);
return user.SignUpStatus;
@ -121,7 +107,7 @@ public class AccountService : IAccountService
user.PhoneNumberConfirmed = true;
user.SignUpStatus = SignUpStatus.PhoneNumberVerified;
var result = await _userManager.UpdateAsync(user);
if(!result.Succeeded)
if (!result.Succeeded)
throw new AppException(string.Join('|', result.Errors));
}
return await CompleteLogin(user, cancellationToken);
@ -171,11 +157,18 @@ public class AccountService : IAccountService
.TableNoTracking
.Where(mcu => mcu.UserId == user.Id)
.OrderByDescending(o => o.CreatedAt)
.ToListAsync(cancellationToken);
var lastComplex = complexUsers.FirstOrDefault();
.FirstOrDefaultAsync(cancellationToken);
if(complexUsers == null)
return await _jwtService.Generate<ApplicationUserSDto, ApplicationUser>(user);
var complexUserRoles = await _repositoryWrapper.SetRepository<ComplexUserRole>()
.TableNoTracking
.Where(c=>c.ComplexUserId==complexUsers.Id)
.OrderByDescending(o => o.CreatedAt)
.FirstOrDefaultAsync(cancellationToken);
AccessToken<ApplicationUserSDto> jwt;
if (lastComplex != null)
jwt = await _jwtService.Generate<ApplicationUserSDto, ApplicationUser>(user, lastComplex.ComplexId, lastComplex.RoleId);
if (complexUserRoles != null)
jwt = await _jwtService.Generate<ApplicationUserSDto, ApplicationUser>(user, complexUsers.ComplexId, complexUserRoles.RoleId);
else
jwt = await _jwtService.Generate<ApplicationUserSDto, ApplicationUser>(user);

View File

@ -0,0 +1,19 @@
namespace Brizco.Core.EntityServices.Abstracts;
public interface IUserService : IScopedDependency
{
Task<List<ComplexUserSDto>> GetUsersAsync(int page = 0, CancellationToken cancellationToken = default);
Task<ApplicationUserSDto> GetUserAsync(Guid userId);
Task<ApplicationUser> CreateUserAsync(string phoneNumber);
Task<ApplicationUser> CreateUserAsync(UserActionRequestDto request, CancellationToken cancellationToken);
Task<bool> EditUserAsync(UserActionRequestDto request, CancellationToken cancellationToken);
Task<bool> EditUserProfileAsync(UserActionRequestDto request, CancellationToken cancellationToken);
Task<bool> RemoveUserAsync(Guid userId, CancellationToken cancellationToken);
Task<List<ApplicationRole>> GetRolesAsync(int page = 0, CancellationToken cancellationToken = default);
Task<RoleActionRequestDto> GetRoleAsync(Guid roleId);
Task<ApplicationRole> CreateRoleAsync(RoleActionRequestDto request);
Task<bool> EditRoleAsync(RoleActionRequestDto request);
Task<bool> RemoveRoleAsync(Guid roleId);
}

View File

@ -36,7 +36,7 @@ public class ComplexService : IComplexService
foreach (var claim in ApplicationClaims.ManagerClaims)
await _roleManager.AddClaimAsync(managerRole, claim);
var complexUser = await _sender.Send(new CreateComplexUserCommand(complex.Id, managerUserId, managerRole.Id), cancellationToken);
var complexUser = await _sender.Send(new CreateComplexUserCommand(complex.Id, managerUserId, new List<Guid>{ managerRole.Id }), cancellationToken);
return complex;
}

View File

@ -0,0 +1,287 @@
using System.Security.Claims;
using System.Threading;
using Brizco.Domain.CommandQueries.Queries;
using Brizco.Domain.Mappers;
using Mapster;
namespace Brizco.Core.EntityServices;
public class UserService : IUserService
{
private readonly ICurrentUserService _currentUserService;
private readonly UserManager<ApplicationUser> _userManager;
private readonly RoleManager<ApplicationRole> _roleManager;
private readonly ISender _sender;
public UserService(ICurrentUserService currentUserService,
UserManager<ApplicationUser> userManager,
RoleManager<ApplicationRole> roleManager,
ISender sender)
{
_currentUserService = currentUserService;
_userManager = userManager;
_roleManager = roleManager;
_sender = sender;
}
public async Task<List<ComplexUserSDto>> GetUsersAsync(int page = 0, CancellationToken cancellationToken = default)
{
if (_currentUserService.ComplexId.IsNullOrEmpty())
throw new AppException("Wrong authorize token , ComplexId needed");
if (!Guid.TryParse(_currentUserService.ComplexId, out Guid complexId))
throw new AppException("Wrong authorize token , ComplexId needed");
var complexUsers = await _sender.Send(new GetComplexUsersQuery(complexId.ToString(), page),cancellationToken);
return complexUsers;
}
public async Task<ApplicationUserSDto> GetUserAsync(Guid userId)
=> (await _userManager.FindByIdAsync(userId.ToString())).AdaptToSDto();
public async Task<ApplicationUser> CreateUserAsync(string phoneNumber)
{
var 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));
return user;
}
public async Task<ApplicationUser> CreateUserAsync(UserActionRequestDto request, CancellationToken cancellationToken)
{
if (_currentUserService.ComplexId.IsNullOrEmpty())
throw new AppException("Wrong authorize token , ComplexId needed");
if (!Guid.TryParse(_currentUserService.ComplexId, out Guid complexId))
throw new AppException("Wrong authorize token , ComplexId needed");
var user = new ApplicationUser
{
UserName = request.PhoneNumber,
PhoneNumber = request.PhoneNumber,
FirstName = request.FirstName,
LastName = request.LastName,
InternationalId = request.InternationalId,
BirthDate = request.BirthDate,
Gender = request.Gender,
SignUpStatus = SignUpStatus.SignUpCompleted
};
if (!request.Password.IsNullOrEmpty())
{
var result = await _userManager.CreateAsync(user, request.Password);
if (!result.Succeeded)
throw new AppException(string.Join('|', result.Errors));
}
else
{
var result = await _userManager.CreateAsync(user);
if (!result.Succeeded)
throw new AppException(string.Join('|', result.Errors));
}
await _sender.Send(new CreateComplexUserCommand(complexId, user.Id, request.RoleIds), cancellationToken);
return user;
}
public async Task<bool> EditUserAsync(UserActionRequestDto request, CancellationToken cancellationToken)
{
if (_currentUserService.ComplexId.IsNullOrEmpty())
throw new AppException("Wrong authorize token , ComplexId needed");
if (!Guid.TryParse(_currentUserService.ComplexId, out Guid complexId))
throw new AppException("Wrong authorize token , ComplexId needed");
if (_currentUserService.UserId == null)
throw new AppException("Wrong authorize token , UserId needed");
var user = await _userManager.FindByIdAsync(_currentUserService.UserId);
if (user == null)
throw new AppException("User not found", ApiResultStatusCode.NotFound);
user.LastName = request.LastName;
user.FirstName = request.FirstName;
user.UserName = request.PhoneNumber;
user.PhoneNumber = request.PhoneNumber;
user.FirstName = request.FirstName;
user.LastName = request.LastName;
user.InternationalId = request.InternationalId;
user.BirthDate = request.BirthDate;
user.Gender = request.Gender;
var result = await _userManager.UpdateAsync(user);
if (!result.Succeeded)
throw new AppException(string.Join('|', result.Errors));
if (!request.Password.IsNullOrEmpty())
{
if (await _userManager.HasPasswordAsync(user))
await _userManager.RemovePasswordAsync(user);
var addPassResult = await _userManager.AddPasswordAsync(user, request.Password);
if (!addPassResult.Succeeded)
throw new AppException(string.Join('|', addPassResult.Errors));
}
await _sender.Send(new UpdateComplexUserCommand(user.Id, complexId, request.RoleIds), cancellationToken);
return true;
}
public async Task<bool> EditUserProfileAsync(UserActionRequestDto request, CancellationToken cancellationToken)
{
if (_currentUserService.UserId == null)
throw new AppException("Wrong authorize token , UserId needed");
var user = await _userManager.FindByIdAsync(_currentUserService.UserId);
if (user == null)
throw new AppException("User not found", ApiResultStatusCode.NotFound);
user.LastName = request.LastName;
user.FirstName = request.FirstName;
user.UserName = request.PhoneNumber;
user.PhoneNumber = request.PhoneNumber;
user.FirstName = request.FirstName;
user.LastName = request.LastName;
user.InternationalId = request.InternationalId;
user.BirthDate = request.BirthDate;
user.Gender = request.Gender;
var result = await _userManager.UpdateAsync(user);
if (!result.Succeeded)
throw new AppException(string.Join('|', result.Errors));
if (!request.Password.IsNullOrEmpty())
{
if (await _userManager.HasPasswordAsync(user))
await _userManager.RemovePasswordAsync(user);
var addPassResult = await _userManager.AddPasswordAsync(user, request.Password);
if (!addPassResult.Succeeded)
throw new AppException(string.Join('|', addPassResult.Errors));
}
return true;
}
public async Task<bool> RemoveUserAsync(Guid userId, CancellationToken cancellationToken)
{
if (_currentUserService.ComplexId.IsNullOrEmpty())
throw new AppException("Wrong authorize token , ComplexId needed");
if (!Guid.TryParse(_currentUserService.ComplexId, out Guid complexId))
throw new AppException("Wrong authorize token , ComplexId needed");
var user = await _userManager.FindByIdAsync(userId.ToString());
if (user == null)
throw new AppException("User not found", ApiResultStatusCode.NotFound);
var removeResult = await _userManager.DeleteAsync(user);
if (!removeResult.Succeeded)
throw new AppException(string.Join('|', removeResult.Errors));
await _sender.Send(new DeleteComplexUserCommand(userId, complexId), cancellationToken);
return true;
}
public async Task<List<ApplicationRole>> GetRolesAsync(int page = 0,CancellationToken cancellationToken = default)
{
if (_currentUserService.ComplexId.IsNullOrEmpty())
throw new AppException("Wrong authorize token , ComplexId needed");
if (!Guid.TryParse(_currentUserService.ComplexId, out Guid complexId))
throw new AppException("Wrong authorize token , ComplexId needed");
var roles = await _roleManager.Roles
.Where(r=>r.ComplexId==complexId)
.Skip(page * 15)
.Take(15)
.ToListAsync(cancellationToken);
return roles;
}
public async Task<RoleActionRequestDto> GetRoleAsync(Guid roleId)
{
var role = (await _roleManager.FindByIdAsync(roleId.ToString()));
if (role == null)
throw new AppException("نقش پیدا نشد",ApiResultStatusCode.NotFound);
var roleDto = role.Adapt<RoleActionRequestDto>();
roleDto.Permissions = (await _roleManager.GetClaimsAsync(role))
.Where(c => c.Type == CustomClaimType.Permission)
.Select(c => c.Value)
.ToList();
return roleDto;
}
public async Task<ApplicationRole> CreateRoleAsync(RoleActionRequestDto request)
{
if (_currentUserService.ComplexId.IsNullOrEmpty())
throw new AppException("Wrong authorize token , ComplexId needed");
if (!Guid.TryParse(_currentUserService.ComplexId, out Guid complexId))
throw new AppException("Wrong authorize token , ComplexId wrong");
if (request.EnglishName.IsNullOrEmpty())
throw new AppException("لطفا نام انگلیسی را وارد کنید");
var applicationRole = new ApplicationRole
{
ComplexId = complexId,
EnglishName = request.EnglishName,
PersianName = request.PersianName,
Description = request.Description,
Name = $"{request.EnglishName}_{complexId.ToString()}"
};
var createRoleResult = await _roleManager.CreateAsync(applicationRole);
if (!createRoleResult.Succeeded)
throw new AppException(string.Join('|', createRoleResult.Errors));
foreach (var claim in request.Permissions)
await _roleManager.AddClaimAsync(applicationRole, new Claim(CustomClaimType.Permission, claim));
return applicationRole;
}
public async Task<bool> EditRoleAsync(RoleActionRequestDto request)
{
if (_currentUserService.ComplexId.IsNullOrEmpty())
throw new AppException("Wrong authorize token , ComplexId needed");
if (!Guid.TryParse(_currentUserService.ComplexId, out Guid complexId))
throw new AppException("Wrong authorize token , ComplexId wrong");
if (request.EnglishName.IsNullOrEmpty())
throw new AppException("لطفا نام انگلیسی را وارد کنید");
var applicationRole = await _roleManager.FindByIdAsync(request.RoleId.ToString());
if (applicationRole == null)
throw new AppException("نقش پیدا نشد");
applicationRole.ComplexId = complexId;
applicationRole.EnglishName = request.EnglishName;
applicationRole.PersianName = request.PersianName;
applicationRole.Description = request.Description;
applicationRole.Name = $"{request.EnglishName}_{complexId.ToString()}";
var createRoleResult = await _roleManager.UpdateAsync(applicationRole);
if (!createRoleResult.Succeeded)
throw new AppException(string.Join('|', createRoleResult.Errors));
var roleClaims = (await _roleManager.GetClaimsAsync(applicationRole)).Where(c => c.Type == CustomClaimType.Permission).ToList();
foreach (var roleClaim in roleClaims.ToList())
{
if (request.Permissions.Contains(roleClaim.Value))
{
roleClaims.Remove(roleClaim);
request.Permissions.Remove(roleClaim.Value);
}
}
foreach (var claim in request.Permissions)
await _roleManager.AddClaimAsync(applicationRole, new Claim(CustomClaimType.Permission, claim));
foreach (var claim in roleClaims)
await _roleManager.RemoveClaimAsync(applicationRole, claim);
return true;
}
public async Task<bool> RemoveRoleAsync(Guid roleId)
{
var applicationRole = await _roleManager.FindByIdAsync(roleId.ToString());
if (applicationRole == null)
throw new AppException("User not found", ApiResultStatusCode.NotFound);
var removeResult = await _roleManager.DeleteAsync(applicationRole);
if (!removeResult.Succeeded)
throw new AppException(string.Join('|', removeResult.Errors));
return true;
}
}

View File

@ -66,6 +66,7 @@
<ItemGroup>
<Folder Include="Dtos\LargDtos\" />
<Folder Include="Dtos\ResponseDto\" />
<Folder Include="Dtos\RequestDtos\" />
<Folder Include="Models\Settings\" />
</ItemGroup>

View File

@ -3,14 +3,19 @@
public sealed record CreateComplexCommand(string Name, string Address, string SupportPhone)
: 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)
: IRequest<bool>;
public sealed record DeleteComplexCommand(Guid Id)
: IRequest<bool>;
public sealed record CreateComplexUserCommand(Guid ComplexId, Guid UserId, List<Guid> RoleIds)
: IRequest<ComplexUserSDto>;
public sealed record UpdateComplexUserCommand(Guid UserId,Guid ComplexId,List<Guid> RoleIds)
: IRequest<bool>;
public sealed record DeleteComplexUserCommand(Guid UserId, Guid ComplexId)
: IRequest<bool>;

View File

@ -1,6 +1,4 @@
using Brizco.Domain.Entities.Shift;
namespace Brizco.Domain.CommandQueries.Commands;
namespace Brizco.Domain.CommandQueries.Commands;
public sealed record CreateTaskCommand(TaskType Type,
string Title,
@ -15,7 +13,8 @@ int Amount,
PurchaseAmountType AmountType,
List<Guid> Users,
List<Guid> Shifts,
List<Guid> Roles) : IRequest<TaskLDto>;
List<Guid> Roles,
List<DayOfWeek> Days) : IRequest<TaskLDto>;
public sealed record UpdateTaskCommand(Guid Id,
TaskType Type,
@ -31,7 +30,8 @@ public sealed record UpdateTaskCommand(Guid Id,
PurchaseAmountType AmountType,
List<Guid> Users,
List<Guid> Shifts,
List<Guid> Roles) : IRequest<bool>;
List<Guid> Roles,
List<DayOfWeek> Days) : IRequest<bool>;
public sealed record DeleteTaskCommand(Guid Id)

View File

@ -4,4 +4,8 @@ public sealed record GetComplexesQuery(int Page = 0) :
IRequest<List<ComplexSDto>>;
public sealed record GetComplexQuery(Guid Id) :
IRequest<ComplexSDto>;
IRequest<ComplexSDto>;
public sealed record GetComplexUsersQuery(string ComplexId,int Page = 0) :
IRequest<List<ComplexUserSDto>>;

View File

@ -0,0 +1,11 @@
namespace Brizco.Domain.Dtos.RequestDtos;
public class RoleActionRequestDto
{
public Guid RoleId { get; set; }
public Guid ComplexId { get; set; }
public string Description { get; set; } = string.Empty;
public string EnglishName { get; set; } = string.Empty;
public string PersianName { get; set; } = string.Empty;
public List<string> Permissions { get; set; } = new();
}

View File

@ -0,0 +1,17 @@
namespace Brizco.Domain.Dtos.RequestDtos;
public class UserActionRequestDto
{
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 string InternationalId { get; set; } = string.Empty;
public string Password { get; set; } = string.Empty;
public List<Guid> RoleIds { get; set; } = new();
public string SelectedRoleName { get; set; } = string.Empty;
public string SelectedComplexName { get; set; } = string.Empty;
}

View File

@ -12,4 +12,5 @@ public class ApplicationUserSDto : BaseDto<ApplicationUserSDto,ApplicationUser>
public SignUpStatus SignUpStatus { get; set; }
public string SelectedRoleName { get; set; } = string.Empty;
public string SelectedComplexName { get; set; } = string.Empty;
public string InternationalId { get; set; } = string.Empty;
}

View File

@ -0,0 +1,14 @@
using Brizco.Domain.Entities.Complex;
namespace Brizco.Domain.Dtos.SmallDtos;
public class ComplexUserRoleSDto : BaseDto<ComplexUserRoleSDto,ComplexUserRole>
{
public Guid RoleId { get; set; }
public Guid ComplexUserId { get; set; }
public Guid UserId { get; set; }
public Guid ComplexId { get; set; }
}

View File

@ -4,6 +4,11 @@ namespace Brizco.Domain.Dtos.SmallDtos;
public class ComplexUserSDto : BaseDto<ComplexUserSDto,ComplexUser>
{
public string FirstName { get; set; } = string.Empty;
public string LastName { get; set; } = string.Empty;
public string InternationalId { get; set; } = string.Empty;
public string ComplexName { get; set; } = string.Empty;
public Guid UserId { get; set; }
public Guid ComplexId { get; set; }
}

View File

@ -7,10 +7,24 @@ public partial class Complex
return new Complex(name,address,supportPhone);
}
public ComplexUser AddComplexUser(Guid userId, Guid roleId)
public ComplexUser AddComplexUser(Guid userId)
{
var complex = new ComplexUser(userId, this.Id, roleId);
var complex = ComplexUser.Create(userId, this.Id);
this.Users.Add(complex);
return complex;
}
}
}
public partial class ComplexUser
{
public static ComplexUser Create(Guid userId,Guid complexId)
{
return new ComplexUser(userId,complexId);
}
public ComplexUserRole AddRole(Guid roleId)
{
var role = new ComplexUserRole(this.Id, roleId);
this.Roles.Add(role);
return role;
}
}

View File

@ -3,24 +3,23 @@
namespace Brizco.Domain.Entities.Complex;
[AdaptTwoWays("[name]SDto", IgnoreAttributes = new[] { typeof(AdaptIgnoreAttribute) }, MapType = MapType.Map | MapType.MapToTarget | MapType.Projection)]
[GenerateMapper]
public class ComplexUser : ApiEntity
public partial class ComplexUser : ApiEntity
{
public ComplexUser()
{
}
public ComplexUser(Guid userId, Guid complexId, Guid roleId)
public ComplexUser(Guid userId, Guid complexId)
{
UserId = userId;
ComplexId = complexId;
RoleId = roleId;
}
public Guid UserId { 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 Complex? Complex { get; internal set; }
public List<ComplexUserRole> Roles { get; internal set; } = new();
}

View File

@ -0,0 +1,22 @@
using Brizco.Domain.Entities.User;
namespace Brizco.Domain.Entities.Complex;
[AdaptTwoWays("[name]SDto", IgnoreAttributes = new[] { typeof(AdaptIgnoreAttribute) }, MapType = MapType.Map | MapType.MapToTarget | MapType.Projection)]
[GenerateMapper]
public class ComplexUserRole : ApiEntity
{
public ComplexUserRole()
{
}
public ComplexUserRole(Guid complexUserId, Guid roleId)
{
ComplexUserId = complexUserId;
RoleId = roleId;
}
public Guid ComplexUserId { get; internal set; }
public ComplexUser? ComplexUser { get; internal set; }
public Guid RoleId { get; internal set; }
public ApplicationRole? Role { get; internal set; }
}

View File

@ -10,10 +10,11 @@ public class ShiftDay : ApiEntity
internal ShiftDay(DayOfWeek dayOfWeek,Guid shiftId)
{
DayOfWeek = dayOfWeek;
ShiftId = shiftId;
}
public DayOfWeek DayOfWeek { get; private set; }
public DayOfWeek DayOfWeek { get; internal set; }
public Guid ShiftId { get; private set; }
public Shift? Shift { get; private set; }
public Guid ShiftId { get; internal set; }
public Shift? Shift { get; internal set; }
}

View File

@ -32,6 +32,15 @@ public partial class Task
complexId);
}
public TaskDay SetDay(DayOfWeek dayOfWeek)
{
var taskDay = new TaskDay(dayOfWeek, Id);
Days.Add(taskDay);
return taskDay;
}
public void AddShift(params Guid[] shiftIds)
{
foreach (var shiftId in shiftIds)

View File

@ -60,5 +60,7 @@ public partial class Task : ApiEntity
public List<TaskShift> Shifts { get; internal set; } = new();
public List<TaskDay> Days { get; internal set; }
public List<TaskRole> Roles { get; internal set; } = new();
}

View File

@ -0,0 +1,20 @@
namespace Brizco.Domain.Entities.Task;
public class TaskDay
{
public TaskDay()
{
}
internal TaskDay(DayOfWeek dayOfWeek, Guid shiftId)
{
DayOfWeek = dayOfWeek;
TaskId = shiftId;
}
public DayOfWeek DayOfWeek { get; internal set; }
public Guid TaskId { get; internal set; }
public Task? Task { get; internal set; }
}

View File

@ -1,9 +1,12 @@
namespace Brizco.Domain.Entities.User;
[AdaptTwoWays("[name]SDto", IgnoreAttributes = new[] { typeof(AdaptIgnoreAttribute) }, MapType = MapType.Map | MapType.MapToTarget | MapType.Projection)]
[GenerateMapper]
public class ApplicationUser : IdentityUser<Guid>
{
public string FirstName { get; set; } = string.Empty;
public string LastName { get; set; } = string.Empty;
public string InternationalId { get; set; } = string.Empty;
public DateTime BirthDate { get; set; }
public Gender Gender { get; set; }
public SignUpStatus SignUpStatus { get; set; }

View File

@ -0,0 +1,99 @@
using System;
using System.Linq.Expressions;
using Brizco.Domain.Dtos.SmallDtos;
using Brizco.Domain.Entities.User;
namespace Brizco.Domain.Mappers
{
public static partial class ApplicationUserMapper
{
public static ApplicationUser AdaptToApplicationUser(this ApplicationUserSDto p1)
{
return p1 == null ? null : new ApplicationUser()
{
FirstName = p1.FirstName,
LastName = p1.LastName,
InternationalId = p1.InternationalId,
BirthDate = p1.BirthDate,
Gender = p1.Gender,
SignUpStatus = p1.SignUpStatus,
Id = p1.Id,
PhoneNumber = p1.PhoneNumber
};
}
public static ApplicationUser AdaptTo(this ApplicationUserSDto p2, ApplicationUser p3)
{
if (p2 == null)
{
return null;
}
ApplicationUser result = p3 ?? new ApplicationUser();
result.FirstName = p2.FirstName;
result.LastName = p2.LastName;
result.InternationalId = p2.InternationalId;
result.BirthDate = p2.BirthDate;
result.Gender = p2.Gender;
result.SignUpStatus = p2.SignUpStatus;
result.Id = p2.Id;
result.PhoneNumber = p2.PhoneNumber;
return result;
}
public static Expression<Func<ApplicationUserSDto, ApplicationUser>> ProjectToApplicationUser => p4 => new ApplicationUser()
{
FirstName = p4.FirstName,
LastName = p4.LastName,
InternationalId = p4.InternationalId,
BirthDate = p4.BirthDate,
Gender = p4.Gender,
SignUpStatus = p4.SignUpStatus,
Id = p4.Id,
PhoneNumber = p4.PhoneNumber
};
public static ApplicationUserSDto AdaptToSDto(this ApplicationUser p5)
{
return p5 == null ? null : new ApplicationUserSDto()
{
PhoneNumber = p5.PhoneNumber,
FirstName = p5.FirstName,
LastName = p5.LastName,
BirthDate = p5.BirthDate,
Gender = p5.Gender,
SignUpStatus = p5.SignUpStatus,
InternationalId = p5.InternationalId,
Id = p5.Id
};
}
public static ApplicationUserSDto AdaptTo(this ApplicationUser p6, ApplicationUserSDto p7)
{
if (p6 == null)
{
return null;
}
ApplicationUserSDto result = p7 ?? new ApplicationUserSDto();
result.PhoneNumber = p6.PhoneNumber;
result.FirstName = p6.FirstName;
result.LastName = p6.LastName;
result.BirthDate = p6.BirthDate;
result.Gender = p6.Gender;
result.SignUpStatus = p6.SignUpStatus;
result.InternationalId = p6.InternationalId;
result.Id = p6.Id;
return result;
}
public static Expression<Func<ApplicationUser, ApplicationUserSDto>> ProjectToSDto => p8 => new ApplicationUserSDto()
{
PhoneNumber = p8.PhoneNumber,
FirstName = p8.FirstName,
LastName = p8.LastName,
BirthDate = p8.BirthDate,
Gender = p8.Gender,
SignUpStatus = p8.SignUpStatus,
InternationalId = p8.InternationalId,
Id = p8.Id
};
}
}

View File

@ -0,0 +1,69 @@
using System;
using System.Linq.Expressions;
using Brizco.Domain.Dtos.SmallDtos;
using Brizco.Domain.Entities.Complex;
namespace Brizco.Domain.Mappers
{
public static partial class ComplexUserRoleMapper
{
public static ComplexUserRole AdaptToComplexUserRole(this ComplexUserRoleSDto p1)
{
return p1 == null ? null : new ComplexUserRole()
{
ComplexUserId = p1.ComplexUserId,
RoleId = p1.RoleId,
Id = p1.Id
};
}
public static ComplexUserRole AdaptTo(this ComplexUserRoleSDto p2, ComplexUserRole p3)
{
if (p2 == null)
{
return null;
}
ComplexUserRole result = p3 ?? new ComplexUserRole();
result.ComplexUserId = p2.ComplexUserId;
result.RoleId = p2.RoleId;
result.Id = p2.Id;
return result;
}
public static Expression<Func<ComplexUserRoleSDto, ComplexUserRole>> ProjectToComplexUserRole => p4 => new ComplexUserRole()
{
ComplexUserId = p4.ComplexUserId,
RoleId = p4.RoleId,
Id = p4.Id
};
public static ComplexUserRoleSDto AdaptToSDto(this ComplexUserRole p5)
{
return p5 == null ? null : new ComplexUserRoleSDto()
{
RoleId = p5.RoleId,
ComplexUserId = p5.ComplexUserId,
Id = p5.Id
};
}
public static ComplexUserRoleSDto AdaptTo(this ComplexUserRole p6, ComplexUserRoleSDto p7)
{
if (p6 == null)
{
return null;
}
ComplexUserRoleSDto result = p7 ?? new ComplexUserRoleSDto();
result.RoleId = p6.RoleId;
result.ComplexUserId = p6.ComplexUserId;
result.Id = p6.Id;
return result;
}
public static Expression<Func<ComplexUserRole, ComplexUserRoleSDto>> ProjectToSDto => p8 => new ComplexUserRoleSDto()
{
RoleId = p8.RoleId,
ComplexUserId = p8.ComplexUserId,
Id = p8.Id
};
}
}

View File

@ -1,4 +1,5 @@
using Brizco.Domain.Entities.Shift;
using Brizco.Domain.Entities.Complex;
using Brizco.Domain.Entities.Shift;
using Mapster;
namespace Brizco.Domain;
@ -8,8 +9,14 @@ public class MapsterRegister : IRegister
public void Register(TypeAdapterConfig config)
{
config.NewConfig<Shift, ShiftSDto>()
.Map("Days", org => org.Days != null ? org.Days.Select(d=>d.DayOfWeek).ToList()
: new List<DayOfWeek>())
.Map("Days", org => org.Days != null ? org.Days.Select(d=>d.DayOfWeek).ToList() : new List<DayOfWeek>())
.TwoWays();
config.NewConfig<ComplexUser, ComplexUserSDto>()
.Map(s=>s.ComplexName,o=>o.Complex!=null ? o.Complex.Name : string.Empty)
.Map(s=>s.FirstName,o=>o.User!=null ? o.User.FirstName : string.Empty)
.Map(s=>s.LastName,o=>o.User!=null ? o.User.LastName : string.Empty)
.Map(s=>s.InternationalId,o=>o.User!=null ? o.User.InternationalId : string.Empty)
.TwoWays();
}
}