shoc-backend/SeaHaven.Services/Implementation/WorkOrderAccountResolver.cs

125 lines
4.6 KiB
C#
Raw Normal View History

using System.Security.Claims;
using SeaHaven.DataServices.Interfaces;
using SeaHaven.Services.Exceptions;
using SeaHaven.Services.Helpers;
using SeaHaven.Services.Interfaces;
namespace SeaHaven.Services.Implementation
{
public class WorkOrderAccountResolver : IWorkOrderAccountResolver
{
private readonly IAccountDataService _accounts;
private readonly ILocationDataService _locations;
public WorkOrderAccountResolver(IAccountDataService accounts, ILocationDataService locations)
{
_accounts = accounts;
_locations = locations;
}
public int? ResolveAccountFilter(ClaimsPrincipal user)
{
return WorkOrderMediaAuthorization.ResolveMediaScope(user) switch
{
MediaAccountScope.Account account => account.AccountId,
MediaAccountScope.OrgWide => null,
_ => throw new WorkOrderBoardValidationException(
"Forbidden",
"You are not allowed to access work orders without account scope.")
};
}
public async Task<int> ResolveForAuthenticatedCreateAsync(
ClaimsPrincipal user,
string? customer,
CancellationToken cancellationToken = default)
{
switch (WorkOrderMediaAuthorization.ResolveMediaScope(user))
{
case MediaAccountScope.Account account:
return account.AccountId;
case MediaAccountScope.OrgWide:
return await ResolveRequiredFromCustomerAsync(customer, cancellationToken);
default:
throw new WorkOrderBoardValidationException(
"Forbidden",
"You are not allowed to create work orders without account scope.");
}
}
public async Task<int> ResolveForBoardCreateAsync(
ClaimsPrincipal user,
int? locationId,
CancellationToken cancellationToken = default)
{
if (locationId is not int id || id <= 0)
{
throw new WorkOrderBoardValidationException(
"InvalidValue",
"locationId is required.");
}
var (exists, locationAccountId) = await _locations.GetAccountScopeAsync(id, cancellationToken);
if (!exists)
{
throw new WorkOrderBoardValidationException(
"NotFound",
"Location was not found.");
}
if (locationAccountId is not int resolvedAccountId)
{
throw new WorkOrderBoardValidationException(
"AccountUnresolved",
"Work order account could not be resolved from location.");
}
switch (WorkOrderMediaAuthorization.ResolveMediaScope(user))
{
case MediaAccountScope.Account account:
if (account.AccountId != resolvedAccountId)
{
throw new WorkOrderBoardValidationException(
"Forbidden",
"You are not allowed to create a work order for this location.");
}
return account.AccountId;
case MediaAccountScope.OrgWide:
return resolvedAccountId;
default:
throw new WorkOrderBoardValidationException(
"Forbidden",
"You are not allowed to create work orders without account scope.");
}
}
public Task<int> ResolveForUnauthenticatedCreateAsync(
string? customer,
CancellationToken cancellationToken = default)
=> ResolveRequiredFromCustomerAsync(customer, cancellationToken);
public Task<int?> TryResolveFromCustomerAsync(
string? customer,
CancellationToken cancellationToken = default)
=> _accounts.TryGetUniqueActiveIdByExactNameAsync(customer, cancellationToken);
private async Task<int> ResolveRequiredFromCustomerAsync(
string? customer,
CancellationToken cancellationToken)
{
var resolved = await TryResolveFromCustomerAsync(customer, cancellationToken);
if (resolved is int accountId)
return accountId;
throw new WorkOrderBoardValidationException(
"AccountUnresolved",
"Work order account could not be resolved from customer.");
}
}
}