Files
xSaherElmIds/Providers/XApplicationProvider/XApplicationProvider+ApiKeyUsage.cs
T
2026-10-05 17:37:28 +03:30

531 lines
18 KiB
C#

using System;
using System.Linq;
using xModels.Dtos;
using System.Threading;
using xCommons.Extensions;
using xIdentityModels.Dtos;
using xExceptions.Constants;
using System.Threading.Tasks;
using xIdentityModels.Models;
using System.Linq.Expressions;
using xDataService.Extensions;
using System.Collections.Generic;
using xIdentityModels.Extensions;
using Microsoft.EntityFrameworkCore;
using System.Runtime.CompilerServices;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.ChangeTracking;
namespace xIds.Providers
{
public partial class XApplicationProvider
{
//
#region ApiKeyUsage ...
/// <summary>
/// Add Specified Item ...
/// </summary>
/// <param name="item"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<XApiKeyUsageDto> AddApiKeyUsageAsync(
XApiKeyUsageDto item,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
)
{
//
// Validate ...
if (!item.IsValidForAdd())
{
XException.InvalidArgs.Throw();
}
//
// Check ApiKey Exists ...
var apiKey = await dbContext.ApiKeys
.FirstOrDefaultAsync(x => x.Id == item.ApiKeyId);
if (apiKey.IsNullOrDefault())
{
XException.NotFound.Throw();
}
//
// Check apiKey Activation ...
if (!apiKey.IsActive())
{
XException.NotAllowed.Throw();
}
//
var entity = item.MapConvert<XApiKeyUsage, XApiKeyUsageDto>();
var entry = await dbContext.ApiKeyUsages.AddAsync(
entity: entity,
cancellationToken: cancellationToken
);
var changes = await dbContext.SaveChangesAsync(cancellationToken);
if (
changes <= 0 ||
entry.IsNull() ||
entry.Entity.IsNullOrDefault()
)
{
XException.ActionFailed.Throw();
}
//
var result = await EnrichAsync(
source: entry.Entity,
cancellationToken: cancellationToken
);
return result;
}
/// <summary>
/// Update Specified Item ...
/// </summary>
/// <param name="id"></param>
/// <param name="item"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<XApiKeyUsageDto> UpdateApiKeyUsageAsync(
long id,
XApiKeyUsageDto item,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
)
{
//
// Validate ...
if (
id <= 0 ||
id != item.Id ||
!item.IsValidForAdd() ||
item.IsNullOrDefault()
)
{
XException.InvalidArgs.Throw();
}
//
// Check Item Exists ...
var exists = dbContext.ApiKeyUsages.FirstOrDefault(x => x.Id == id);
if (exists.IsNullOrDefault())
{
XException.NotFound.Throw();
}
//
// Update Data on Exists Entity ...
exists = exists.UpdateData(
updateWith: item,
propertyWhiteList: [
nameof(XApiKeyUsage.ApiKeyId),
nameof(XApiKeyUsage.Endpoint),
nameof(XApiKeyUsage.ClientIP),
nameof(XApiKeyUsage.HttpMethod),
nameof(XApiKeyUsage.StatusCode),
nameof(XApiKeyUsage.RequestedOn),
nameof(XApiKeyUsage.ResponseTimeMs),
]
);
//
var entry = dbContext.ApiKeyUsages.Attach(exists);
entry.State = EntityState.Modified;
//
var changes = await dbContext.SaveChangesAsync(cancellationToken);
if (
changes <= 0 ||
entry.IsNull() ||
entry.Entity.IsNullOrDefault()
)
{
XException.ActionFailed.Throw();
}
//
var result = await EnrichAsync(
source: entry.Entity,
cancellationToken: cancellationToken
);
return result;
}
/// <summary>
/// Remove Specified Item ...
/// </summary>
/// <param name="id"></param>
/// <param name="softDelete"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<XApiKeyUsageDto> RemoveApiKeyUsageAsync(
long id,
bool softDelete = true,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
)
{
//
// Validate ...
if (id <= 0)
{
XException.InvalidArgs.Throw();
}
//
// Retrieve Exists Entity ...
var exists = await dbContext.ApiKeyUsages
.FirstOrDefaultAsync(x => x.Id == id && !x.Deleted);
if (exists.IsNullOrDefault())
{
XException.NotFound.Throw();
}
//
EntityEntry<XApiKeyUsage> entry = null;
if (softDelete)
{
//
exists.Deleted = true;
entry = dbContext.ApiKeyUsages.Update(exists);
}
else
{
entry = dbContext.ApiKeyUsages.Remove(exists);
}
//
var changes = await dbContext.SaveChangesAsync(cancellationToken);
if (
changes <= 0 ||
entry.IsNull() ||
entry.Entity.IsNull()
)
{
XException.ActionFailed.Throw();
}
//
var result = await EnrichAsync(
source: entry.Entity,
cancellationToken: cancellationToken
);
return result;
}
/// <summary>
/// Retrieve an Item by Providing it's ID ...
/// </summary>
/// <param name="id"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="userInfo"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<XApiKeyUsageDto> GetApiKeyUsageAsync(
long id,
bool ignoreSoftDeleteds = true,
XUserClaimsInfoDto userInfo = null,
Func<IQueryable<XApiKeyUsage>, IIncludableQueryable<XApiKeyUsage, object>> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
// Validate ...
if (id <= 0)
{
XException.InvalidArgs.Throw();
}
//
// Prepare Condition ...
Expression<Func<XApiKeyUsage, bool>> predicate = x =>
!ignoreSoftDeleteds || !x.Deleted;
//
// Retrieve Queryable ...
var queryable = GetApiKeyUsagesQeryable(
orderBuilder: null,
predicate: predicate,
includeBuilder: includeBuilder
);
//
var entity = await queryable.FirstOrDefaultAsync(
predicate: x => x.Id == id,
cancellationToken: cancellationToken
);
if (entity.IsNullOrDefault())
{
XException.NotFound.Throw();
}
//
var result = await EnrichAsync(
source: entity,
cancellationToken: cancellationToken
);
return result;
}
/// <summary>
/// Retrieve all Items ...
/// </summary>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="userInfo"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<IEnumerable<XApiKeyUsageDto>> GetAllApiKeyUsageAsync(
bool ignoreSoftDeleteds = true,
XUserClaimsInfoDto userInfo = null,
Func<IQueryable<XApiKeyUsage>, IOrderedQueryable<XApiKeyUsage>> orderBuilder = null,
Func<IQueryable<XApiKeyUsage>, IIncludableQueryable<XApiKeyUsage, object>> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
Expression<Func<XApiKeyUsage, bool>> predicate = x =>
!ignoreSoftDeleteds || !x.Deleted;
var queryable = GetApiKeyUsagesQeryable(
predicate: predicate,
orderBuilder: orderBuilder,
includeBuilder: includeBuilder
);
//
var items = await queryable.ToListAsync(cancellationToken);
var result = await EnrichRangeAsync(
sources: items,
cancellationToken: cancellationToken
);
return result;
}
/// <summary>
/// Retrieve all Items as Async Enumerable ...
/// </summary>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="userInfo"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async IAsyncEnumerable<XApiKeyUsageDto> GetAllApiKeyUsageAsAsyncEnumerable(
bool ignoreSoftDeleteds = true,
XUserClaimsInfoDto userInfo = null,
Func<IQueryable<XApiKeyUsage>, IOrderedQueryable<XApiKeyUsage>> orderBuilder = null,
Func<IQueryable<XApiKeyUsage>, IIncludableQueryable<XApiKeyUsage, object>> includeBuilder = null,
[EnumeratorCancellation]
CancellationToken cancellationToken = default
)
{
//
Expression<Func<XApiKeyUsage, bool>> predicate = x =>
!ignoreSoftDeleteds || !x.Deleted;
var queryable = GetApiKeyUsagesQeryable(
predicate: predicate,
orderBuilder: orderBuilder,
includeBuilder: includeBuilder
);
//
var enumerator = queryable.AsAsyncEnumerable();
await foreach (var item in enumerator)
{
//
// Handle Cancellation Token ...
if (cancellationToken.IsCancellationRequested)
{
yield break;
}
//
var dto = await EnrichAsync(
source: item,
cancellationToken: cancellationToken
);
yield return dto;
}
}
/// <summary>
/// Find an Item By Providing a Conditional Expression ...
/// </summary>
/// <param name="predicate"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="userInfo"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<XApiKeyUsageDto> FindOneApiKeyUsageAsync(
Expression<Func<XApiKeyUsage, bool>> predicate,
bool ignoreSoftDeleteds = true,
XUserClaimsInfoDto userInfo = null,
Func<IQueryable<XApiKeyUsage>, IIncludableQueryable<XApiKeyUsage, object>> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
Expression<Func<XApiKeyUsage, bool>> _predicate = x => !ignoreSoftDeleteds || !x.Deleted;
var queryable = GetApiKeyUsagesQeryable(
orderBuilder: null,
predicate: _predicate,
includeBuilder: includeBuilder
);
//
var entity = (await queryable
.ToListAsync(cancellationToken))
.FirstOrDefault(x => predicate.Compile()(x));
//
var result = await EnrichAsync(
source: entity,
cancellationToken: cancellationToken
);
return result;
}
/// <summary>
/// Find a Collection of Items By Providing a Conditional Expression ...
/// </summary>
/// <param name="predicate"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="userInfo"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<IEnumerable<XApiKeyUsageDto>> FindManyApiKeyUsageAsync(
Expression<Func<XApiKeyUsage, bool>> predicate,
bool ignoreSoftDeleteds = true,
XUserClaimsInfoDto userInfo = null,
Func<IQueryable<XApiKeyUsage>, IOrderedQueryable<XApiKeyUsage>> orderBuilder = null,
Func<IQueryable<XApiKeyUsage>, IIncludableQueryable<XApiKeyUsage, object>> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
Expression<Func<XApiKeyUsage, bool>> _predicate = x => !ignoreSoftDeleteds || !x.Deleted;
var queryable = GetApiKeyUsagesQeryable(
orderBuilder: null,
predicate: _predicate,
includeBuilder: includeBuilder
);
//
var entities = (await queryable
.ToListAsync(cancellationToken))
.Where(x => predicate.Compile()(x))
.ToList();
//
var result = await EnrichRangeAsync(
sources: entities,
cancellationToken: cancellationToken
);
return result;
}
/// <summary>
/// Retrieve Items based on XQuery Pagination Structure ...
/// </summary>
/// <param name="query"></param>
/// <param name="ignoreSoftDeleteds"></param>
/// <param name="userInfo"></param>
/// <param name="predicate"></param>
/// <param name="orderBuilder"></param>
/// <param name="includeBuilder"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<XQueryResult<XApiKeyUsageDto>> QueryApiKeyUsageAsync(
XQuery query,
bool ignoreSoftDeleteds = true,
XUserClaimsInfoDto userInfo = null,
Expression<Func<XApiKeyUsage, bool>> predicate = null,
Func<IQueryable<XApiKeyUsage>, IOrderedQueryable<XApiKeyUsage>> orderBuilder = null,
Func<IQueryable<XApiKeyUsage>, IIncludableQueryable<XApiKeyUsage, object>> includeBuilder = null,
CancellationToken cancellationToken = default
)
{
//
// Normalize Query ...
query = NormalizeQuery(query, configuration);
//
var items = await GetAllApiKeyUsageAsync(
userInfo: userInfo,
orderBuilder: orderBuilder,
includeBuilder: includeBuilder,
cancellationToken: cancellationToken,
ignoreSoftDeleteds: ignoreSoftDeleteds
);
var totalItemsCount = items.Count();
//
// Apply Filter ...
if (!query.Filter.IsNullOrEmpty())
{
//
items = items
.ApplyFilter(query.Filter);
}
int filteredItemsCount = items.Count();
//
// Count Pages ...
var totalPagesCount = query.CountPages(totalItemsCount);
var filteredPagesCount = query.CountPages(filteredItemsCount);
//
// Apply Paging and Sorting ...
if (totalItemsCount > 0 &&
filteredItemsCount > 0
)
{
//
// Apply Sorting ...
items = items
.ToList()
.ApplySorting(
query.SortBy,
query.IsAscending
);
//
// Apply Paging ...
items = items
.ToList()
.ApplyPaging(
query.Page,
query.PageSize
);
}
//
// Prepare Result ...
var result = new XQueryResult<XApiKeyUsageDto>
{
Page = query.Page,
Items = [.. items],
PageSize = query.PageSize,
TotalPages = totalPagesCount,
TotalItems = totalItemsCount,
TotalFilteredPages = filteredPagesCount,
TotalFilteredItems = filteredItemsCount
};
//
return result;
}
#endregion
}
}