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;
|
namespace NetinaShop.Api.Controller;
|
||||||
|
|
||||||
|
|
||||||
public class AuthController : ICarterModule
|
public class AuthController : ICarterModule
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ public class BlogController : ICarterModule
|
||||||
}
|
}
|
||||||
repositoryWrapper.SetRepository<Blog>().Add(ent);
|
repositoryWrapper.SetRepository<Blog>().Add(ent);
|
||||||
await repositoryWrapper.SaveChangesAsync(cancellationToken);
|
await repositoryWrapper.SaveChangesAsync(cancellationToken);
|
||||||
return TypedResults.Ok();
|
return TypedResults.Ok(ent.AdaptToSDto());
|
||||||
}
|
}
|
||||||
|
|
||||||
// PUT:Update Entity
|
// 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)
|
public void Apply(OpenApiOperation operation, OperationFilterContext context)
|
||||||
{
|
{
|
||||||
var controllerActionDescriptor = context.ApiDescription.ActionDescriptor as ControllerActionDescriptor;
|
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 pluralizer = new Pluralizer();
|
||||||
|
|
||||||
var actionName = controllerActionDescriptor.ActionName;
|
var actionName = controllerActionDescriptor.ActionName;
|
||||||
var singularizeName = pluralizer.Singularize(controllerActionDescriptor.ControllerName);
|
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();
|
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 class BlogLDto : BaseDto<BlogLDto , Blog>
|
||||||
{
|
{
|
||||||
public string Title { get; internal set; } = string.Empty;
|
public string Title { get; set; } = string.Empty;
|
||||||
public string Content { get; internal set; } = string.Empty;
|
public string Content { get; set; } = string.Empty;
|
||||||
public string Tags { get; internal set; } = string.Empty;
|
public string Tags { get; set; } = string.Empty;
|
||||||
public int ReadingTime { get; internal set; }
|
public int ReadingTime { get; set; }
|
||||||
public string Summery { get; internal set; } = string.Empty;
|
public string Summery { get; set; } = string.Empty;
|
||||||
public bool IsSuggested { get; internal set; }
|
public bool IsSuggested { get; set; }
|
||||||
public Guid CategoryId { get; internal set; }
|
public Guid CategoryId { get; set; }
|
||||||
public string CategoryName { get; set; } = string.Empty;
|
public string CategoryName { get; set; } = string.Empty;
|
||||||
public List<StorageFileSDto> Files { get; internal set; } = new();
|
public List<StorageFileSDto> Files { get; internal set; } = new();
|
||||||
}
|
}
|
|
@ -2,6 +2,6 @@
|
||||||
|
|
||||||
public class BlogCategorySDto : BaseDto<BlogCategorySDto , BlogCategory>
|
public class BlogCategorySDto : BaseDto<BlogCategorySDto , BlogCategory>
|
||||||
{
|
{
|
||||||
public string Name { get; internal set; } = string.Empty;
|
public string Name { get; set; } = string.Empty;
|
||||||
public string Description { get; internal 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>
|
<ItemGroup>
|
||||||
<Folder Include="Models\" />
|
<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>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</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? UserId { get; }
|
||||||
string? RoleName { get; }
|
string? RoleName { get; }
|
||||||
string? UserName { get; }
|
string? UserName { get; }
|
||||||
|
public List<string>? Permissions { get; }
|
||||||
}
|
}
|
|
@ -93,7 +93,8 @@ public class DbInitializerService : IDbInitializerService
|
||||||
{
|
{
|
||||||
customerRole = new ApplicationRole
|
customerRole = new ApplicationRole
|
||||||
{
|
{
|
||||||
Name = "مشتری",
|
Name = "Customer",
|
||||||
|
PersianName = "مشتری",
|
||||||
EnglishName = "Customer",
|
EnglishName = "Customer",
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue