add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace MintyPHP\Http;
|
|
|
|
|
|
2026-03-04 15:56:58 +01:00
|
|
|
use MintyPHP\Repository\Access\RolePermissionRepository;
|
|
|
|
|
use MintyPHP\Repository\Access\UserRoleRepository;
|
|
|
|
|
use MintyPHP\Service\Access\AuthorizationService;
|
|
|
|
|
use MintyPHP\Service\Auth\ApiTokenService;
|
2026-03-13 11:31:33 +01:00
|
|
|
use MintyPHP\Service\Tenant\TenantScopeService;
|
2026-03-04 15:56:58 +01:00
|
|
|
use MintyPHP\Service\User\UserTenantContextService;
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
|
2026-03-06 00:44:52 +01:00
|
|
|
// Static facade for API authentication — state is set once per request during ApiBootstrap::init().
|
|
|
|
|
// Dependencies are injected as lazy resolvers so services are only instantiated when actually needed.
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
class ApiAuth
|
|
|
|
|
{
|
2026-03-13 11:31:33 +01:00
|
|
|
/** @var (callable(): TenantScopeService)|null */
|
2026-03-04 15:56:58 +01:00
|
|
|
private static $authScopeGatewayResolver = null;
|
|
|
|
|
|
|
|
|
|
/** @var (callable(): ApiTokenService)|null */
|
|
|
|
|
private static $apiTokenServiceResolver = null;
|
|
|
|
|
|
|
|
|
|
/** @var (callable(): UserRoleRepository)|null */
|
|
|
|
|
private static $userRoleRepositoryResolver = null;
|
|
|
|
|
|
|
|
|
|
/** @var (callable(): RolePermissionRepository)|null */
|
|
|
|
|
private static $rolePermissionRepositoryResolver = null;
|
|
|
|
|
|
|
|
|
|
/** @var (callable(): UserTenantContextService)|null */
|
|
|
|
|
private static $userTenantContextServiceResolver = null;
|
|
|
|
|
/** @var (callable(): AuthorizationService)|null */
|
|
|
|
|
private static $authorizationServiceResolver = null;
|
|
|
|
|
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
private static ?array $currentUser = null;
|
|
|
|
|
private static ?array $currentPermissions = null;
|
|
|
|
|
private static ?int $currentTenantId = null;
|
|
|
|
|
private static ?int $tokenTenantId = null;
|
|
|
|
|
private static ?array $currentTokenRecord = null;
|
|
|
|
|
private static bool $authenticated = false;
|
|
|
|
|
|
2026-03-04 15:56:58 +01:00
|
|
|
public static function configure(
|
|
|
|
|
callable $authScopeGatewayResolver,
|
|
|
|
|
callable $apiTokenServiceResolver,
|
|
|
|
|
callable $userRoleRepositoryResolver,
|
|
|
|
|
callable $rolePermissionRepositoryResolver,
|
|
|
|
|
callable $userTenantContextServiceResolver,
|
|
|
|
|
callable $authorizationServiceResolver
|
|
|
|
|
): void {
|
|
|
|
|
self::$authScopeGatewayResolver = $authScopeGatewayResolver;
|
|
|
|
|
self::$apiTokenServiceResolver = $apiTokenServiceResolver;
|
|
|
|
|
self::$userRoleRepositoryResolver = $userRoleRepositoryResolver;
|
|
|
|
|
self::$rolePermissionRepositoryResolver = $rolePermissionRepositoryResolver;
|
|
|
|
|
self::$userTenantContextServiceResolver = $userTenantContextServiceResolver;
|
|
|
|
|
self::$authorizationServiceResolver = $authorizationServiceResolver;
|
|
|
|
|
}
|
|
|
|
|
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
/**
|
|
|
|
|
* Extract the full Bearer token from the Authorization header.
|
|
|
|
|
*/
|
|
|
|
|
public static function extractBearerToken(): string
|
|
|
|
|
{
|
|
|
|
|
$header = trim((string) ($_SERVER['HTTP_AUTHORIZATION'] ?? ''));
|
|
|
|
|
if ($header === '') {
|
2026-03-06 00:44:52 +01:00
|
|
|
// Nginx with PHP-FPM may expose the header under this key instead
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
$header = trim((string) ($_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ?? ''));
|
|
|
|
|
}
|
|
|
|
|
if ($header === '' || stripos($header, 'Bearer ') !== 0) {
|
|
|
|
|
return '';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return trim(substr($header, 7));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Attempt to authenticate from Authorization: Bearer header.
|
|
|
|
|
*/
|
|
|
|
|
public static function authenticate(): bool
|
|
|
|
|
{
|
|
|
|
|
self::$currentUser = null;
|
|
|
|
|
self::$currentPermissions = null;
|
|
|
|
|
self::$currentTenantId = null;
|
|
|
|
|
self::$tokenTenantId = null;
|
|
|
|
|
self::$currentTokenRecord = null;
|
|
|
|
|
self::$authenticated = false;
|
|
|
|
|
|
|
|
|
|
$bearerToken = self::extractBearerToken();
|
|
|
|
|
if ($bearerToken === '') {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-04 15:56:58 +01:00
|
|
|
$scopeGateway = self::scopeGateway();
|
|
|
|
|
$result = self::apiTokenService()->validate($bearerToken);
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
if ($result === null) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$user = $result['user'];
|
|
|
|
|
$userId = (int) ($user['id'] ?? 0);
|
2026-03-04 15:56:58 +01:00
|
|
|
$userRoleRepository = self::userRoleRepository();
|
|
|
|
|
$rolePermissionRepository = self::rolePermissionRepository();
|
|
|
|
|
$userTenantContextService = self::userTenantContextService();
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
|
|
|
|
|
// Load permissions directly (bypass session cache)
|
2026-02-23 12:58:19 +01:00
|
|
|
$roleIds = $userRoleRepository->listRoleIdsByUserId($userId);
|
|
|
|
|
$permissions = $rolePermissionRepository->listPermissionKeysByRoleIds($roleIds);
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
|
2026-03-06 00:44:52 +01:00
|
|
|
// Resolve tenant context: a token may be scoped to a specific tenant,
|
|
|
|
|
// otherwise fall back to the user's active tenant context.
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
$tokenTenantId = $result['tenant_id'];
|
|
|
|
|
if ($tokenTenantId !== null) {
|
2026-03-06 00:44:52 +01:00
|
|
|
// Verify the token's tenant is still assigned to this user
|
2026-02-23 12:58:19 +01:00
|
|
|
$userTenantIds = $scopeGateway->getUserTenantIds($userId);
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
if (!in_array($tokenTenantId, $userTenantIds, true)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
$currentTenantId = $tokenTenantId;
|
|
|
|
|
self::$tokenTenantId = $tokenTenantId;
|
|
|
|
|
} else {
|
2026-02-23 12:58:19 +01:00
|
|
|
$currentTenantId = $userTenantContextService->getCurrentTenantId($userId);
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
self::$tokenTenantId = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self::$currentUser = $user;
|
|
|
|
|
self::$currentPermissions = $permissions;
|
|
|
|
|
self::$currentTenantId = $currentTenantId;
|
|
|
|
|
self::$currentTokenRecord = $result['token_record'];
|
|
|
|
|
self::$authenticated = true;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function isAuthenticated(): bool
|
|
|
|
|
{
|
|
|
|
|
return self::$authenticated;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function user(): ?array
|
|
|
|
|
{
|
|
|
|
|
return self::$currentUser;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function userId(): int
|
|
|
|
|
{
|
|
|
|
|
return (int) (self::$currentUser['id'] ?? 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function permissions(): array
|
|
|
|
|
{
|
|
|
|
|
return self::$currentPermissions ?? [];
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-04 15:56:58 +01:00
|
|
|
public static function can(string $ability, array $context = []): bool
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
{
|
2026-03-04 15:56:58 +01:00
|
|
|
$decision = self::authorizationService()->authorize($ability, [
|
|
|
|
|
'actor_user_id' => self::userId(),
|
|
|
|
|
'scoped_tenant_id' => self::scopedTenantId(),
|
|
|
|
|
...$context,
|
|
|
|
|
]);
|
|
|
|
|
return $decision->isAllowed();
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
}
|
|
|
|
|
|
2026-03-06 00:44:52 +01:00
|
|
|
// Effective tenant for data filtering — may come from token scope or user session.
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
public static function tenantId(): ?int
|
|
|
|
|
{
|
|
|
|
|
return self::$currentTenantId;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-06 00:44:52 +01:00
|
|
|
// Non-null only when the token itself was issued for a specific tenant.
|
|
|
|
|
// Used to restrict access in token-scoped requests (e.g. tenant integrations).
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
public static function scopedTenantId(): ?int
|
|
|
|
|
{
|
|
|
|
|
return self::$tokenTenantId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function tokenRecord(): ?array
|
|
|
|
|
{
|
|
|
|
|
return self::$currentTokenRecord;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function tokenId(): ?int
|
|
|
|
|
{
|
|
|
|
|
$id = (int) (self::$currentTokenRecord['id'] ?? 0);
|
|
|
|
|
return $id > 0 ? $id : null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function isTenantScopedToken(): bool
|
|
|
|
|
{
|
|
|
|
|
return (self::$tokenTenantId ?? 0) > 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Require both tenant-scope and token-tenant access for a resource.
|
|
|
|
|
*/
|
|
|
|
|
public static function requireResourceAccess(string $resource, int $resourceId): void
|
|
|
|
|
{
|
2026-03-04 15:56:58 +01:00
|
|
|
$scopeGateway = self::scopeGateway();
|
2026-02-23 12:58:19 +01:00
|
|
|
if (!$scopeGateway->canAccess($resource, $resourceId, self::userId())) {
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
ApiResponse::notFound();
|
|
|
|
|
}
|
|
|
|
|
self::requireTokenTenantAccess($resource, $resourceId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function requireTokenTenantAccess(string $resource, int $resourceId): void
|
|
|
|
|
{
|
|
|
|
|
if (!self::isTenantScopedToken()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$tenantId = (int) (self::$tokenTenantId ?? 0);
|
|
|
|
|
if ($tenantId <= 0) {
|
|
|
|
|
ApiResponse::forbidden();
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-04 15:56:58 +01:00
|
|
|
$scopeGateway = self::scopeGateway();
|
2026-02-23 12:58:19 +01:00
|
|
|
if (!$scopeGateway->resourceBelongsToTenant($resource, $resourceId, $tenantId)) {
|
2026-03-06 00:44:52 +01:00
|
|
|
// 404 instead of 403 — don't reveal that the resource exists in another tenant
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
ApiResponse::notFound();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Check if the current user can self-manage API tokens.
|
|
|
|
|
*/
|
|
|
|
|
public static function canSelfManageTokens(): bool
|
|
|
|
|
{
|
2026-03-04 15:56:58 +01:00
|
|
|
$decision = self::authorizationService()->authorize(
|
|
|
|
|
\MintyPHP\Service\Access\OperationsAuthorizationPolicy::ABILITY_API_TOKENS_SELF_MANAGE,
|
|
|
|
|
[
|
|
|
|
|
'actor_user_id' => self::userId(),
|
|
|
|
|
'scoped_tenant_id' => self::scopedTenantId(),
|
|
|
|
|
]
|
|
|
|
|
);
|
|
|
|
|
return $decision->isAllowed();
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function requireSelfManageTokens(): void
|
|
|
|
|
{
|
|
|
|
|
if (!self::canSelfManageTokens()) {
|
|
|
|
|
ApiResponse::forbidden('api_tokens_self_manage_forbidden');
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-03-04 15:56:58 +01:00
|
|
|
|
2026-03-13 11:31:33 +01:00
|
|
|
private static function scopeGateway(): TenantScopeService
|
2026-03-04 15:56:58 +01:00
|
|
|
{
|
2026-03-13 11:31:33 +01:00
|
|
|
return self::resolveDependency(self::$authScopeGatewayResolver, TenantScopeService::class, 'ApiAuth');
|
2026-03-04 15:56:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static function apiTokenService(): ApiTokenService
|
|
|
|
|
{
|
|
|
|
|
return self::resolveDependency(self::$apiTokenServiceResolver, ApiTokenService::class, 'ApiAuth');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static function userRoleRepository(): UserRoleRepository
|
|
|
|
|
{
|
|
|
|
|
return self::resolveDependency(self::$userRoleRepositoryResolver, UserRoleRepository::class, 'ApiAuth');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static function rolePermissionRepository(): RolePermissionRepository
|
|
|
|
|
{
|
|
|
|
|
return self::resolveDependency(self::$rolePermissionRepositoryResolver, RolePermissionRepository::class, 'ApiAuth');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static function userTenantContextService(): UserTenantContextService
|
|
|
|
|
{
|
|
|
|
|
return self::resolveDependency(self::$userTenantContextServiceResolver, UserTenantContextService::class, 'ApiAuth');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static function authorizationService(): AuthorizationService
|
|
|
|
|
{
|
|
|
|
|
return self::resolveDependency(self::$authorizationServiceResolver, AuthorizationService::class, 'ApiAuth');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static function resolveDependency(mixed $resolver, string $expectedClass, string $consumer): mixed
|
|
|
|
|
{
|
|
|
|
|
if (!is_callable($resolver)) {
|
|
|
|
|
throw new \RuntimeException($consumer . ' is not configured for dependency: ' . $expectedClass);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$service = $resolver();
|
|
|
|
|
if (!$service instanceof $expectedClass) {
|
|
|
|
|
throw new \RuntimeException($consumer . ' resolver returned invalid dependency: ' . $expectedClass);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $service;
|
|
|
|
|
}
|
|
|
|
|
|
add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00
|
|
|
}
|