erp-platform/api/src/Kurs.Platform.Application/PublicApi/PublicApiAppService.cs

281 lines
10 KiB
C#
Raw Normal View History

2025-05-06 06:45:49 +00:00
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Kurs.Platform.DynamicData;
using Kurs.Platform.Entities;
using Kurs.Platform.Extensions;
using Kurs.Platform.Queries;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Tracing;
using Volo.Abp.Uow;
namespace Kurs.Platform.PublicApis;
[Authorize]
[Route("api/app/public-api")]
public class PublicApiAppService : PlatformAppService
{
private readonly IRepository<PublicApi, Guid> repo;
private readonly IHttpContextAccessor httpContextAccessor;
private readonly IDataSourceManager dataSourceManager;
private readonly IDynamicDataManager dynamicDataManager;
public PublicApiAppService(
IRepository<PublicApi, Guid> repo,
IHttpContextAccessor httpContextAccessor,
IDataSourceManager dataSourceManager,
IDynamicDataManager dynamicDataManager)
{
this.repo = repo;
this.httpContextAccessor = httpContextAccessor;
this.dataSourceManager = dataSourceManager;
this.dynamicDataManager = dynamicDataManager;
}
[HttpGet("{**path}")]
[Authorize(PlatformConsts.AppCodes.PublicApis.Get)]
public async Task<IActionResult> GetAsync()
{
return await Execute("GET");
}
[HttpPost("{**path}")]
[Authorize(PlatformConsts.AppCodes.PublicApis.Post)]
public async Task<IActionResult> PostAsync()
{
return await Execute("POST");
}
private async Task<IActionResult> Execute(string method)
{
using var uow = UnitOfWorkManager.Begin(new AbpUnitOfWorkOptions(false), true);
try
{
// Request.Path = /api/app/public-api/yxcdfn/8
var path = httpContextAccessor.HttpContext.Request.Path.ToString()
.Replace("/api/app/public-api", "")
.EnsureStartsWith('/')
.EnsureEndsWith('/');
Logger.LogInformation("PublicApi çağrısı. Kullanıcı:{user} Path:[{method}]{path}", CurrentUser.UserName, "GET", path);
var api = await repo.FirstOrDefaultAsync(a => path.StartsWith(a.Url) && a.Method == method);
if (api is null)
{
Logger.LogInformation("PublicApi bulunamadı");
return new NotFoundResult();
}
Logger.LogInformation("PublicApi bulundu. {api}", api.Name);
var canUse = api.Permissions.Any(a =>
(a.ResourceType == "User" && a.ResourceId == CurrentUser.UserName) ||
(a.ResourceType == "Role" && CurrentUser.Roles.Contains(a.ResourceId)) ||
(a.ResourceType == "Global"));
if (!canUse)
{
Logger.LogWarning("PublicApi yetki yok");
return new UnauthorizedResult();
}
Dictionary<string, object> param = [];
// Parametreler:
// 1- Statik
foreach (var item in api.Parameters.Where(a => a.Type == PlatformConsts.PublicApiConsts.ParameterTypes.Static))
{
var value = GetDefaultValue(item.DefaultValue);
param.Add(item.Name, value);
}
// 2- Query
var queryParams = httpContextAccessor.HttpContext.Request.Query;
foreach (var item in api.Parameters.Where(a => a.Type == PlatformConsts.PublicApiConsts.ParameterTypes.Query))
{
if (queryParams.TryGetValue(item.Name, out var value))
{
param.Add(item.Name, value);
}
else
{
if (item.IsRequired)
{
throw new Volo.Abp.UserFriendlyException(L[PlatformConsts.AppErrorCodes.ParameterNotValid, item.Name]);
}
else
{
param.Add(item.Name, GetDefaultValue(item.DefaultValue));
}
}
}
// 3- Path
foreach (var item in api.Parameters.Where(a => a.Type == PlatformConsts.PublicApiConsts.ParameterTypes.Path && !a.Path.IsNullOrWhiteSpace()))
{
var itemPath = item.Path.EnsureStartsWith('/').EnsureEndsWith('/');
var index = itemPath.IndexOf($"/:{item.Name}/");
if (index == -1)
{
throw new Volo.Abp.UserFriendlyException(L[PlatformConsts.AppErrorCodes.ParameterNotValid, item.Name]);
}
var segmentCount = itemPath[..(index + 1)].Count(a => a == '/');
var value = path.GetSegment('/', segmentCount);
param.Add(item.Name, value ?? GetDefaultValue(item.DefaultValue));
}
// 4- Body
if (method == "POST")
{
var body = await httpContextAccessor.HttpContext.Request.ReadFormAsync();
foreach (var item in api.Parameters.Where(a => a.Type == PlatformConsts.PublicApiConsts.ParameterTypes.Body))
{
if (body.TryGetValue(item.Name, out var value))
{
param.Add(item.Name, value);
}
else
{
if (item.IsRequired)
{
throw new Volo.Abp.UserFriendlyException(L[PlatformConsts.AppErrorCodes.ParameterNotValid, item.Name]);
}
else
{
param.Add(item.Name, GetDefaultValue(item.DefaultValue));
}
}
}
}
Logger.LogInformation("Parametreler: {param}", param);
var (dynamicDataRepository, connectionString, _) = await dynamicDataManager.GetAsync(api.DataSourceCode == "!Tenant", api.DataSourceCode);
var result = await dynamicDataRepository.QueryAsync(api.Sql, connectionString, param);
Logger.LogInformation("Sonuç başarılı");
Logger.LogInformation("{result}", result);
await uow.CompleteAsync();
return new ObjectResult(result);
}
catch (Volo.Abp.UserFriendlyException ex)
{
Logger.LogException(ex);
await uow.RollbackAsync();
return new JsonResult(new
{
Message = ex.Message,
CorrelationId = LazyServiceProvider.GetRequiredService<ICorrelationIdProvider>().Get(),
})
{
StatusCode = 500,
};
}
catch (Exception ex)
{
Logger.LogException(ex);
await uow.RollbackAsync();
return new JsonResult(new
{
Message = L[PlatformConsts.AppErrorCodes.InternalError].Value,
CorrelationId = LazyServiceProvider.GetRequiredService<ICorrelationIdProvider>().Get()
})
{
StatusCode = 500,
};
}
}
private string GetDefaultValue(string strValue)
{
return strValue?.Replace(PlatformConsts.DefaultValues.UserId, CurrentUser.Id.ToString())
.Replace(PlatformConsts.DefaultValues.UserName, CurrentUser.UserName)
.Replace(PlatformConsts.DefaultValues.Roles, CurrentUser.Roles.JoinAsString("','"))
.Replace(PlatformConsts.DefaultValues.Now, Clock.Now.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture))
.Replace(PlatformConsts.DefaultValues.TenantId, CurrentTenant.Id.HasValue ? CurrentTenant.Id.ToString() : null);
}
}
//TODO: PublicApi rol, permission seed
/*
Token İsteği Örnek:
POST /connect/token HTTP/1.1
Host: localhost:44344
Content-Type: application/x-www-form-urlencoded
username=sedat%40kadifeteks.com
&password=...
&grant_type=password
&client_id=Platform_PublicApi
&scope=offline_access%20Platform
PublicApi Seed:
select * from PLanguage WHERE IsEnabled = @IsEnabled AND CultureName = @CultureName
INSERT INTO [dbo].[Orders]
([CustomerName]
,[ProductName]
,[OrderDate]
,[Quantity])
OUTPUT Inserted.*
VALUES
(@CustomerName, @ProductName, @OrderDate, @Quantity)
SELECT * FROM Orders WHERE Id = SCOPE_IDENTITY()
[{ "Type": "S", "Name": "CultureName", "DefaultValue": "ar" }]
[{ "Type": "Q", "Name": "CultureName", "DefaultValue": "ar" }]
[
{ "Type": "P", "Name": "IsEnabled", "DefaultValue": "en", "Path": "/yxcdfn/8/:IsEnabled/:CultureName/" },
{ "Type": "P", "Name": "CultureName", "DefaultValue": "en", "Path": "/yxcdfn/8/:IsEnabled/:CultureName/" }
]
[
{ "Type": "B", "Name": "CustomerName", "DefaultValue": "" },
{ "Type": "B", "Name": "ProductName", "DefaultValue": "" },
{ "Type": "B", "Name": "OrderDate", "DefaultValue": "@NOW" },
{ "Type": "B", "Name": "Quantity", "DefaultValue": "" }
]
Guid? TenantId
string Name
string Description
string Url -> https://platform-api.sozsoft.com/api/app/dinamik/yxfgu
string Method -> GET
string Params = [
{ Type: 'Static', Name: 'StartDate', DefaultValue: '234' },
{ Type: 'Query', Name: 'StartDate', DefaultValue: '', IsRequired: false },
{ Type: 'Path', Name: 'FaturaId', DefaultValue: '', Path: '/yxfgu/fatura/:FaturaId/kalem/357' },
{ Type: 'Path', Name: 'KalemId', DefaultValue: '', Path: '/yxfgu/fatura/xxx/kalem/:KalemId' },
{ Type: 'Body', Name: 'StartDate', DefaultValue: '' },
]
string Sql -> SELECT * FROM VSatislar WHERE MusteriId = @MusteriId AND StartDate >= @StartDate
string Permissions = [
{ ResourceType: 'User', ResourceId: 'sedat' },
{ ResourceType: 'User', ResourceId: 'vedat' },
]
Query Parameter
URL: https://platform-api.sozsoft.com/api/app/dinamik/yxfgu
Method: GET
Parameters: ?StartDate=2024-12-31&EndDate=2025-12-31
Path Parameter
URL: https://platform-api.sozsoft.com/api/app/dinamik/yxfgu/fatura/467/kalem/357
Method: GET
Parameters: FaturaId=467
Body Parameter
URL: https://platform-api.sozsoft.com/api/app/dinamik/yxfgu?UrunId=5
Method: POST
Parameters: ?StartDate=2024-12-31&EndDate=2025-12-31
Body: { Tutar: 2000, Tarih: '2024-12-31' }
*/