instances added god may help

This commit is contained in:
2026-02-23 12:58:19 +01:00
parent 25370a1a55
commit 99db252f60
290 changed files with 9858 additions and 4914 deletions

View File

@@ -2,11 +2,10 @@
namespace MintyPHP\Http;
use MintyPHP\Repository\Access\RolePermissionRepository;
use MintyPHP\Repository\Access\UserRoleRepository;
use MintyPHP\Service\Auth\ApiTokenService;
use MintyPHP\Service\Tenant\TenantScopeService;
use MintyPHP\Service\User\UserService;
use MintyPHP\Service\Access\AccessServicesFactory;
use MintyPHP\Service\Auth\AuthScopeGateway;
use MintyPHP\Service\Auth\AuthServicesFactory;
use MintyPHP\Service\User\UserServicesFactory;
class ApiAuth
{
@@ -50,29 +49,35 @@ class ApiAuth
return false;
}
$result = ApiTokenService::validate($bearerToken);
$authServicesFactory = new AuthServicesFactory();
$scopeGateway = $authServicesFactory->createAuthScopeGateway();
$result = $authServicesFactory->createApiTokenService()->validate($bearerToken);
if ($result === null) {
return false;
}
$user = $result['user'];
$userId = (int) ($user['id'] ?? 0);
$userServicesFactory = new UserServicesFactory();
$userRoleRepository = $userServicesFactory->createUserRoleRepository();
$rolePermissionRepository = (new AccessServicesFactory())->createRolePermissionRepository();
$userTenantContextService = $userServicesFactory->createUserTenantContextService();
// Load permissions directly (bypass session cache)
$roleIds = UserRoleRepository::listRoleIdsByUserId($userId);
$permissions = RolePermissionRepository::listPermissionKeysByRoleIds($roleIds);
$roleIds = $userRoleRepository->listRoleIdsByUserId($userId);
$permissions = $rolePermissionRepository->listPermissionKeysByRoleIds($roleIds);
// Resolve tenant context
$tokenTenantId = $result['tenant_id'];
if ($tokenTenantId !== null) {
$userTenantIds = TenantScopeService::getUserTenantIds($userId);
$userTenantIds = $scopeGateway->getUserTenantIds($userId);
if (!in_array($tokenTenantId, $userTenantIds, true)) {
return false;
}
$currentTenantId = $tokenTenantId;
self::$tokenTenantId = $tokenTenantId;
} else {
$currentTenantId = UserService::getCurrentTenantId($userId);
$currentTenantId = $userTenantContextService->getCurrentTenantId($userId);
self::$tokenTenantId = null;
}
@@ -141,7 +146,8 @@ class ApiAuth
*/
public static function requireResourceAccess(string $resource, int $resourceId): void
{
if (!TenantScopeService::canAccess($resource, $resourceId, self::userId())) {
$scopeGateway = (new AuthServicesFactory())->createAuthScopeGateway();
if (!$scopeGateway->canAccess($resource, $resourceId, self::userId())) {
ApiResponse::notFound();
}
self::requireTokenTenantAccess($resource, $resourceId);
@@ -158,7 +164,8 @@ class ApiAuth
ApiResponse::forbidden();
}
if (!TenantScopeService::resourceBelongsToTenant($resource, $resourceId, $tenantId)) {
$scopeGateway = (new AuthServicesFactory())->createAuthScopeGateway();
if (!$scopeGateway->resourceBelongsToTenant($resource, $resourceId, $tenantId)) {
ApiResponse::notFound();
}
}

View File

@@ -2,9 +2,10 @@
namespace MintyPHP\Http;
use MintyPHP\Service\Audit\ApiAuditService;
use MintyPHP\Service\Security\RateLimiterService;
use MintyPHP\Service\Settings\SettingService;
use MintyPHP\Service\Security\SecurityServicesFactory;
use MintyPHP\Service\Settings\SettingGateway;
use MintyPHP\Service\Settings\SettingServicesFactory;
class ApiBootstrap
{
@@ -17,6 +18,10 @@ class ApiBootstrap
private static bool $initialized = false;
private static bool $shutdownRegistered = false;
private static ?SecurityServicesFactory $securityServicesFactory = null;
private static ?RateLimiterService $rateLimiterService = null;
private static ?SettingServicesFactory $settingServicesFactory = null;
private static ?SettingGateway $settingGateway = null;
/**
* Initialize the API request context.
@@ -36,7 +41,7 @@ class ApiBootstrap
}
self::registerShutdownHandler();
ApiAuditService::startRequestContext();
\auditServicesFactory()->createApiAuditService()->startRequestContext();
self::setCorsHeaders();
if (strtoupper($_SERVER['REQUEST_METHOD'] ?? '') === 'OPTIONS') {
@@ -63,7 +68,7 @@ class ApiBootstrap
return;
}
$allowedOrigins = array_fill_keys(SettingService::getApiCorsAllowedOrigins(), true);
$allowedOrigins = array_fill_keys(self::settings()->getApiCorsAllowedOrigins(), true);
if (!isset($allowedOrigins[$origin])) {
return;
}
@@ -89,7 +94,7 @@ class ApiBootstrap
if ($statusCode <= 0) {
$statusCode = 200;
}
ApiAuditService::finish($statusCode);
\auditServicesFactory()->createApiAuditService()->finish($statusCode);
return;
}
@@ -100,7 +105,7 @@ class ApiBootstrap
if ($statusCode <= 0) {
$statusCode = 200;
}
ApiAuditService::finish($statusCode);
\auditServicesFactory()->createApiAuditService()->finish($statusCode);
return;
}
@@ -108,7 +113,7 @@ class ApiBootstrap
if ($statusCode < 400) {
$statusCode = 500;
}
ApiAuditService::finish($statusCode, 'fatal_error');
\auditServicesFactory()->createApiAuditService()->finish($statusCode, 'fatal_error');
});
}
@@ -154,7 +159,7 @@ class ApiBootstrap
$ip = 'unknown';
}
$ipResult = RateLimiterService::hit(
$ipResult = self::rateLimiter()->hit(
self::API_RATE_SCOPE_IP,
$ip,
self::API_RATE_LIMIT_IP,
@@ -170,7 +175,7 @@ class ApiBootstrap
return;
}
$tokenResult = RateLimiterService::hit(
$tokenResult = self::rateLimiter()->hit(
self::API_RATE_SCOPE_TOKEN,
strtolower($selector) . '|' . $ip,
self::API_RATE_LIMIT_TOKEN,
@@ -198,4 +203,32 @@ class ApiBootstrap
return $selector;
}
private static function settings(): SettingGateway
{
if (self::$settingGateway instanceof SettingGateway) {
return self::$settingGateway;
}
if (!(self::$settingServicesFactory instanceof SettingServicesFactory)) {
self::$settingServicesFactory = new SettingServicesFactory();
}
self::$settingGateway = self::$settingServicesFactory->createSettingGateway();
return self::$settingGateway;
}
private static function rateLimiter(): RateLimiterService
{
if (self::$rateLimiterService instanceof RateLimiterService) {
return self::$rateLimiterService;
}
if (!(self::$securityServicesFactory instanceof SecurityServicesFactory)) {
self::$securityServicesFactory = new SecurityServicesFactory();
}
self::$rateLimiterService = self::$securityServicesFactory->createRateLimiterService();
return self::$rateLimiterService;
}
}

View File

@@ -2,8 +2,6 @@
namespace MintyPHP\Http;
use MintyPHP\Service\Audit\ApiAuditService;
class ApiResponse
{
public static function success(array $data = [], int $status = 200): never
@@ -139,7 +137,7 @@ class ApiResponse
}
if ($body === null) {
ApiAuditService::finish($status, $errorCode);
\auditServicesFactory()->createApiAuditService()->finish($status, $errorCode);
die();
}
@@ -152,7 +150,7 @@ class ApiResponse
}
header('Content-Type: application/json; charset=utf-8');
ApiAuditService::finish($status, $errorCode);
\auditServicesFactory()->createApiAuditService()->finish($status, $errorCode);
die($json);
}
}