mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 21:13:12 +00:00
Org-wide create no longer depends on customer name. POST /workorders/board requires locationId and stamps WorkOrder.AccountId from Location.AccountId.
124 lines
4.6 KiB
C#
124 lines
4.6 KiB
C#
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.");
|
|
}
|
|
}
|
|
}
|