This commit is contained in:
King
2025-09-28 16:57:35 +03:30
parent 4241523443
commit 9fcc5d9276
24 changed files with 961 additions and 21 deletions

View File

@@ -1,19 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="11.2.2" />
<PackageReference Include="Foursat.CMSMicroservice.Protobuf" Version="0.0.116" />
<PackageReference Include="Mapster" Version="7.3.0" />
<PackageReference Include="Mapster.DependencyInjection" Version="1.0.0" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="11.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BackOffice.BFF.Domain\BackOffice.BFF.Domain.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="11.2.2" />
<PackageReference Include="Foursat.CMSMicroservice.Protobuf" Version="0.0.116" />
<PackageReference Include="Mapster" Version="7.3.0" />
<PackageReference Include="Mapster.DependencyInjection" Version="1.0.0" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="11.0.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.14.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BackOffice.BFF.Domain\BackOffice.BFF.Domain.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BackOffice.BFF.Application.Common.Interfaces;
public interface IAfrinoIdpService
{
Task<bool> SendOtp(string mobile);
Task<string> VerifyOtp(string mobile, string otpCode);
Task<string> CreateUser(string mobile);
Task<bool> AddRole(string mobile, string role);
}

View File

@@ -0,0 +1,10 @@
namespace BackOffice.BFF.Application.Common.Mappings;
public class OtpProfile : IRegister
{
void IRegister.Register(TypeAdapterConfig config)
{
//config.NewConfig<Source,Destination>()
// .Map(dest => dest.FullName, src => $"{src.Firstname} {src.Lastname}");
}
}

View File

@@ -0,0 +1,7 @@
namespace BackOffice.BFF.Application.OtpCQ.Commands.SendOtp;
public record SendOtpCommand : IRequest<Unit>
{
//شماره موبایل
public string Mobile { get; init; }
}

View File

@@ -0,0 +1,22 @@
using BackOffice.BFF.Application.Common.Interfaces;
namespace BackOffice.BFF.Application.OtpCQ.Commands.SendOtp;
public class SendOtpCommandHandler : IRequestHandler<SendOtpCommand, Unit>
{
private readonly IApplicationContractContext _context;
private readonly IAfrinoIdpService _afrinoIdpService;
public SendOtpCommandHandler(IApplicationContractContext context, IAfrinoIdpService afrinoIdpService)
{
_context = context;
_afrinoIdpService = afrinoIdpService;
}
public async Task<Unit> Handle(SendOtpCommand request, CancellationToken cancellationToken)
{
if (!await _afrinoIdpService.SendOtp(request.Mobile))
throw new Exception(message: "خطا در ارسال OTP");
return Unit.Value;
}
}

View File

@@ -0,0 +1,16 @@
namespace BackOffice.BFF.Application.OtpCQ.Commands.SendOtp;
public class SendOtpCommandValidator : AbstractValidator<SendOtpCommand>
{
public SendOtpCommandValidator()
{
RuleFor(model => model.Mobile)
.NotEmpty();
}
public Func<object, string, Task<IEnumerable<string>>> ValidateValue => async (model, propertyName) =>
{
var result = await ValidateAsync(ValidationContext<SendOtpCommand>.CreateWithOptions((SendOtpCommand)model, x => x.IncludeProperties(propertyName)));
if (result.IsValid)
return Array.Empty<string>();
return result.Errors.Select(e => e.ErrorMessage);
};
}

View File

@@ -0,0 +1,11 @@
namespace BackOffice.BFF.Application.OtpCQ.Commands.VerifyOtpCode;
public record VerifyOtpCodeCommand : IRequest<VerifyOtpCodeResponseDto>
{
//شماره موبایل
public string Mobile { get; init; }
//رمز پویا
public string Code { get; init; }
//شناسه پدر
public long? ParentId { get; init; }
}

View File

@@ -0,0 +1,46 @@
namespace BackOffice.BFF.Application.OtpCQ.Commands.VerifyOtpCode;
using System.IdentityModel.Tokens.Jwt;
public class VerifyOtpCodeCommandHandler : IRequestHandler<VerifyOtpCodeCommand, VerifyOtpCodeResponseDto>
{
private readonly IApplicationContractContext _context;
private readonly IAfrinoIdpService _afrinoIdpService;
public VerifyOtpCodeCommandHandler(IApplicationContractContext context, IAfrinoIdpService afrinoIdpService)
{
_context = context;
_afrinoIdpService = afrinoIdpService;
}
public async Task<VerifyOtpCodeResponseDto> Handle(VerifyOtpCodeCommand request, CancellationToken cancellationToken)
{
var response = await _afrinoIdpService.VerifyOtp(mobile: request.Mobile, otpCode: request.Code);
return new VerifyOtpCodeResponseDto()
{
Token = response
};
}
public static string? GetUserIdFromToken(string token)
{
if (string.IsNullOrWhiteSpace(token))
{
throw new ArgumentException("توکن نمی‌تواند خالی باشد.");
}
var handler = new JwtSecurityTokenHandler();
if (!handler.CanReadToken(token))
{
throw new ArgumentException("توکن نامعتبر است.");
}
var jwtToken = handler.ReadJwtToken(token);
// بررسی اینکه آیا claim مربوط به userId موجود است
var userIdClaim = jwtToken.Claims.FirstOrDefault(c => c.Type == "UserId");
return userIdClaim?.Value;
}
}

View File

@@ -0,0 +1,18 @@
namespace BackOffice.BFF.Application.OtpCQ.Commands.VerifyOtpCode;
public class VerifyOtpCodeCommandValidator : AbstractValidator<VerifyOtpCodeCommand>
{
public VerifyOtpCodeCommandValidator()
{
RuleFor(model => model.Mobile)
.NotEmpty();
RuleFor(model => model.Code)
.NotEmpty();
}
public Func<object, string, Task<IEnumerable<string>>> ValidateValue => async (model, propertyName) =>
{
var result = await ValidateAsync(ValidationContext<VerifyOtpCodeCommand>.CreateWithOptions((VerifyOtpCodeCommand)model, x => x.IncludeProperties(propertyName)));
if (result.IsValid)
return Array.Empty<string>();
return result.Errors.Select(e => e.ErrorMessage);
};
}

View File

@@ -0,0 +1,7 @@
namespace BackOffice.BFF.Application.OtpCQ.Commands.VerifyOtpCode;
public class VerifyOtpCodeResponseDto
{
//توکن
public string Token { get; set; }
}