feat : add sms service , run test one
complete test base , authorize tested , add sms servicerelease
parent
5c5cbc99e6
commit
f4fa5e5e1b
|
@ -1,5 +1,6 @@
|
|||
namespace NetinaShop.Api.Controller;
|
||||
|
||||
|
||||
public class AuthController : ICarterModule
|
||||
{
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ public class BlogController : ICarterModule
|
|||
}
|
||||
repositoryWrapper.SetRepository<Blog>().Add(ent);
|
||||
await repositoryWrapper.SaveChangesAsync(cancellationToken);
|
||||
return TypedResults.Ok();
|
||||
return TypedResults.Ok(ent.AdaptToSDto());
|
||||
}
|
||||
|
||||
// PUT:Update Entity
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
@NetinaShopApi_HostAddress = http://localhost:32770
|
||||
@BaseApiAddress = {{NetinaShopApi_HostAddress}}/api
|
||||
@page = 0
|
||||
@deleteId = 7fe89459-6405-48c3-b1dc-eab67b3d0a90
|
||||
|
||||
GET {{BaseApiAddress}}/blog?page={{page}}
|
||||
Authorization:Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJKd3RJRCI6IjgwNmM0NmYyIiwidW5pcXVlX25hbWUiOiJuZXRpbmFzaG9wIiwiU2lnblVwU3RhdHVzIjoiMCIsIm5hbWVpZCI6ImJjNTIxNzVlLTY0MzYtNGRjMC05OGY0LTE2ZDM5ZGZhZTIyZiIsImVtYWlsIjoiaW5mb0BuZXRpbmFzaG9wLmlvIiwiZ2VuZGVyIjoiRmVtYWxlIiwibmJmIjoxNzA0MTk5NjE1LCJleHAiOjE3MDU0OTU2MTUsImlhdCI6MTcwNDE5OTYxNSwiaXNzIjoiQnJpemNvIiwiYXVkIjoiQnJpemNvIn0.e1RdLu9x6aGYdgmLYthgSFq0CVlw7T09d1flanOO6FlFcfQu7FGpq9jgSjwje9VIf14nVQ3imCepGF4NvJoEsw
|
||||
|
||||
###
|
||||
|
||||
POST {{BaseApiAddress}}/blog
|
||||
Content-Type:application/json
|
||||
Authorization:Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJKd3RJRCI6IjgwNmM0NmYyIiwidW5pcXVlX25hbWUiOiJuZXRpbmFzaG9wIiwiU2lnblVwU3RhdHVzIjoiMCIsIm5hbWVpZCI6ImJjNTIxNzVlLTY0MzYtNGRjMC05OGY0LTE2ZDM5ZGZhZTIyZiIsImVtYWlsIjoiaW5mb0BuZXRpbmFzaG9wLmlvIiwiZ2VuZGVyIjoiRmVtYWxlIiwibmJmIjoxNzA0MTk5NjE1LCJleHAiOjE3MDU0OTU2MTUsImlhdCI6MTcwNDE5OTYxNSwiaXNzIjoiQnJpemNvIiwiYXVkIjoiQnJpemNvIn0.e1RdLu9x6aGYdgmLYthgSFq0CVlw7T09d1flanOO6FlFcfQu7FGpq9jgSjwje9VIf14nVQ3imCepGF4NvJoEsw
|
||||
|
||||
{
|
||||
"title": "string",
|
||||
"content": "string",
|
||||
"tags": "string",
|
||||
"readingTime": 0,
|
||||
"summery": "string",
|
||||
"isSuggested": true,
|
||||
"categoryId": "9dcc16a9-914c-4f97-aa56-fe7257418e41",
|
||||
"categoryName": "string"
|
||||
}
|
||||
|
||||
###
|
||||
DELETE {{BaseApiAddress}}/blog/{{deleteId}}
|
||||
Authorization:Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJKd3RJRCI6IjgwNmM0NmYyIiwidW5pcXVlX25hbWUiOiJuZXRpbmFzaG9wIiwiU2lnblVwU3RhdHVzIjoiMCIsIm5hbWVpZCI6ImJjNTIxNzVlLTY0MzYtNGRjMC05OGY0LTE2ZDM5ZGZhZTIyZiIsImVtYWlsIjoiaW5mb0BuZXRpbmFzaG9wLmlvIiwiZ2VuZGVyIjoiRmVtYWxlIiwibmJmIjoxNzA0MTk5NjE1LCJleHAiOjE3MDU0OTU2MTUsImlhdCI6MTcwNDE5OTYxNSwiaXNzIjoiQnJpemNvIiwiYXVkIjoiQnJpemNvIn0.e1RdLu9x6aGYdgmLYthgSFq0CVlw7T09d1flanOO6FlFcfQu7FGpq9jgSjwje9VIf14nVQ3imCepGF4NvJoEsw
|
|
@ -0,0 +1,16 @@
|
|||
@NetinaShopApi_HostAddress = http://localhost:32770
|
||||
@BaseApiAddress = {{NetinaShopApi_HostAddress}}/api
|
||||
@page = 0
|
||||
|
||||
GET {{BaseApiAddress}}/blog/category?page={{page}}
|
||||
Authorization:Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJKd3RJRCI6IjgwNmM0NmYyIiwidW5pcXVlX25hbWUiOiJuZXRpbmFzaG9wIiwiU2lnblVwU3RhdHVzIjoiMCIsIm5hbWVpZCI6ImJjNTIxNzVlLTY0MzYtNGRjMC05OGY0LTE2ZDM5ZGZhZTIyZiIsImVtYWlsIjoiaW5mb0BuZXRpbmFzaG9wLmlvIiwiZ2VuZGVyIjoiRmVtYWxlIiwibmJmIjoxNzA0MTk5NjE1LCJleHAiOjE3MDU0OTU2MTUsImlhdCI6MTcwNDE5OTYxNSwiaXNzIjoiQnJpemNvIiwiYXVkIjoiQnJpemNvIn0.e1RdLu9x6aGYdgmLYthgSFq0CVlw7T09d1flanOO6FlFcfQu7FGpq9jgSjwje9VIf14nVQ3imCepGF4NvJoEsw
|
||||
|
||||
###
|
||||
POST {{BaseApiAddress}}/blog/category
|
||||
Authorization:Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJKd3RJRCI6IjgwNmM0NmYyIiwidW5pcXVlX25hbWUiOiJuZXRpbmFzaG9wIiwiU2lnblVwU3RhdHVzIjoiMCIsIm5hbWVpZCI6ImJjNTIxNzVlLTY0MzYtNGRjMC05OGY0LTE2ZDM5ZGZhZTIyZiIsImVtYWlsIjoiaW5mb0BuZXRpbmFzaG9wLmlvIiwiZ2VuZGVyIjoiRmVtYWxlIiwibmJmIjoxNzA0MTk5NjE1LCJleHAiOjE3MDU0OTU2MTUsImlhdCI6MTcwNDE5OTYxNSwiaXNzIjoiQnJpemNvIiwiYXVkIjoiQnJpemNvIn0.e1RdLu9x6aGYdgmLYthgSFq0CVlw7T09d1flanOO6FlFcfQu7FGpq9jgSjwje9VIf14nVQ3imCepGF4NvJoEsw
|
||||
Content-Type:application/json
|
||||
|
||||
{
|
||||
"name": "بی نام",
|
||||
"description": "دسته بندی عمومی"
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
@NetinaShopApi_HostAddress = http://localhost:32770
|
||||
@BaseApiAddress = {{NetinaShopApi_HostAddress}}/api
|
||||
|
||||
POST {{BaseApiAddress}}/auth/login/password
|
||||
Content-Type:application/json
|
||||
|
||||
{
|
||||
"UserName":"netinashop",
|
||||
"Password":"eF79o4P4BopCUbUK"
|
||||
}
|
||||
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
@NetinaShop.Api_HostAddress = http://localhost:5173
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
using NetinaShop.Repository.Abstracts;
|
||||
|
||||
namespace NetinaShop.Api.Services;
|
||||
|
||||
public class CurrentUserService : ICurrentUserService
|
||||
{
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
|
||||
public CurrentUserService(IHttpContextAccessor httpContextAccessor)
|
||||
{
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
}
|
||||
|
||||
public string? UserId => _httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||
public string? RoleName => _httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.Role);
|
||||
public string? UserName => _httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.Name);
|
||||
public List<string>? Permissions => _httpContextAccessor.HttpContext?.User?.FindAll("Permission")?.Select(c => c.Value)?.ToList();
|
||||
}
|
|
@ -193,13 +193,17 @@ public class ApplySummariesOperationFilter : IOperationFilter
|
|||
public void Apply(OpenApiOperation operation, OperationFilterContext context)
|
||||
{
|
||||
var controllerActionDescriptor = context.ApiDescription.ActionDescriptor as ControllerActionDescriptor;
|
||||
if (controllerActionDescriptor == null) return;
|
||||
if (controllerActionDescriptor == null)
|
||||
{
|
||||
operation.Summary = context.ApiDescription.ActionDescriptor.DisplayName;
|
||||
return;
|
||||
}
|
||||
|
||||
var pluralizer = new Pluralizer();
|
||||
|
||||
|
||||
var actionName = controllerActionDescriptor.ActionName;
|
||||
var singularizeName = pluralizer.Singularize(controllerActionDescriptor.ControllerName);
|
||||
var pluralizeName = pluralizer.Pluralize(singularizeName);
|
||||
var pluralizeName = pluralizer.Pluralize(controllerActionDescriptor.DisplayName);
|
||||
|
||||
var parameterCount = operation.Parameters.Where(p => p.Name != "version" && p.Name != "api-version").Count();
|
||||
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
public class BlogLDto : BaseDto<BlogLDto , Blog>
|
||||
{
|
||||
public string Title { get; internal set; } = string.Empty;
|
||||
public string Content { get; internal set; } = string.Empty;
|
||||
public string Tags { get; internal set; } = string.Empty;
|
||||
public int ReadingTime { get; internal set; }
|
||||
public string Summery { get; internal set; } = string.Empty;
|
||||
public bool IsSuggested { get; internal set; }
|
||||
public Guid CategoryId { get; internal set; }
|
||||
public string Title { get; set; } = string.Empty;
|
||||
public string Content { get; set; } = string.Empty;
|
||||
public string Tags { get; set; } = string.Empty;
|
||||
public int ReadingTime { get; set; }
|
||||
public string Summery { get; set; } = string.Empty;
|
||||
public bool IsSuggested { get; set; }
|
||||
public Guid CategoryId { get; set; }
|
||||
public string CategoryName { get; set; } = string.Empty;
|
||||
public List<StorageFileSDto> Files { get; internal set; } = new();
|
||||
}
|
|
@ -2,6 +2,6 @@
|
|||
|
||||
public class BlogCategorySDto : BaseDto<BlogCategorySDto , BlogCategory>
|
||||
{
|
||||
public string Name { get; internal set; } = string.Empty;
|
||||
public string Description { get; internal set; } = string.Empty;
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string Description { get; set; } = string.Empty;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
namespace NetinaShop.Infrastructure.Models;
|
||||
|
||||
public static class RestAddress
|
||||
{
|
||||
public static string BaseKaveNegar { get => "https://api.kavenegar.com/v1/"; }
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
namespace NetinaShop.Infrastructure.Models.RestApi.KaveNegar;
|
||||
|
||||
public class KaveNegarResponse
|
||||
{
|
||||
public KaveNegarReturn Return { get; set; }
|
||||
public KaveNegarResponseEntry[] entries { get; set; }
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
namespace NetinaShop.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 NetinaShop.Infrastructure.Models.RestApi.KaveNegar;
|
||||
|
||||
public class KaveNegarReturn
|
||||
{
|
||||
public int status { get; set; }
|
||||
public string message { get; set; }
|
||||
}
|
|
@ -19,6 +19,22 @@
|
|||
|
||||
<ItemGroup>
|
||||
<Folder Include="Models\" />
|
||||
<Folder Include="Services\" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Microsoft.Extensions.Hosting" />
|
||||
<Using Include="Microsoft.Extensions.Logging" />
|
||||
<Using Include="Microsoft.Extensions.Options" />
|
||||
<Using Include="NetinaShop.Common.Models" />
|
||||
<Using Include="NetinaShop.Common.Models.Api" />
|
||||
<Using Include="NetinaShop.Common.Models.Exception" />
|
||||
<Using Include="NetinaShop.Core.Abstracts" />
|
||||
<Using Include="NetinaShop.Domain.Models.Settings" />
|
||||
<Using Include="NetinaShop.Infrastructure.Models.RestApi.KaveNegar" />
|
||||
<Using Include="NetinaShop.Infrastructure.RestServices" />
|
||||
<Using Include="Refit" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
namespace NetinaShop.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,13 @@
|
|||
using NetinaShop.Infrastructure.Models;
|
||||
|
||||
namespace NetinaShop.Infrastructure.RestServices;
|
||||
|
||||
public interface IRestApiWrapper : IScopedDependency
|
||||
{
|
||||
IKaveNegarRestApi KaveNegarRestApi { get; }
|
||||
}
|
||||
|
||||
public class RestApiWrapper : IRestApiWrapper
|
||||
{
|
||||
public IKaveNegarRestApi KaveNegarRestApi => RestService.For<IKaveNegarRestApi>(RestAddress.BaseKaveNegar);
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
namespace NetinaShop.Infrastructure.Services;
|
||||
|
||||
public class SmsService : ISmsService
|
||||
{
|
||||
private readonly IRestApiWrapper _restApiWrapper;
|
||||
private readonly ILogger<SmsService> _logger;
|
||||
private readonly IHostEnvironment _environment;
|
||||
private readonly SiteSettings _siteSettings;
|
||||
public SmsService(
|
||||
IRestApiWrapper restApiWrapper,
|
||||
IOptionsSnapshot<SiteSettings> optionsSnapshot,
|
||||
ILogger<SmsService> logger,
|
||||
IHostEnvironment environment)
|
||||
{
|
||||
_restApiWrapper = restApiWrapper;
|
||||
_logger = logger;
|
||||
_environment = environment;
|
||||
_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)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
var rest = await _restApiWrapper.KaveNegarRestApi.SendLookUp(_siteSettings.KaveNegarApiKey, phoneNumber,
|
||||
verifyCode, null, null, null, "login-brizco");
|
||||
|
||||
if (rest.Return.status != 200 && _environment.IsProduction())
|
||||
throw new BaseApiException(ApiResultStatusCode.SendSmsError, rest.Return.message);
|
||||
}
|
||||
catch (ApiException apiException)
|
||||
{
|
||||
if (_environment.IsProduction())
|
||||
throw ;
|
||||
else
|
||||
_logger.LogError(apiException.Message);
|
||||
}
|
||||
catch (Exception apiException)
|
||||
{
|
||||
if (_environment.IsProduction())
|
||||
throw;
|
||||
else
|
||||
_logger.LogError(apiException.Message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -5,4 +5,5 @@ public interface ICurrentUserService : IScopedDependency
|
|||
string? UserId { get; }
|
||||
string? RoleName { get; }
|
||||
string? UserName { get; }
|
||||
public List<string>? Permissions { get; }
|
||||
}
|
|
@ -93,7 +93,8 @@ public class DbInitializerService : IDbInitializerService
|
|||
{
|
||||
customerRole = new ApplicationRole
|
||||
{
|
||||
Name = "مشتری",
|
||||
Name = "Customer",
|
||||
PersianName = "مشتری",
|
||||
EnglishName = "Customer",
|
||||
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue