update project
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Domain\SchoolCore\Files\Policies;
|
||||
|
||||
use App\Domain\SchoolCore\Context\SchoolContext;
|
||||
use App\Domain\SchoolCore\Contracts\FileAccessPolicyContract;
|
||||
|
||||
final class PaymentFileAccessPolicy implements FileAccessPolicyContract
|
||||
{
|
||||
/** @param array<string, mixed> $metadata */
|
||||
public function canAccess(SchoolContext $context, string $filePurpose, int $ownerId, array $metadata = []): bool
|
||||
{
|
||||
if ($filePurpose !== 'payment') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((int) ($metadata['school_id'] ?? 0) !== $context->schoolId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (in_array('finance', $context->actorRoleIds, true) || in_array('admin', $context->actorRoleIds, true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return (int) ($metadata['actor_related_owner_id'] ?? 0) === $ownerId
|
||||
&& (int) ($metadata['actor_user_id'] ?? $context->actorUserId) === $context->actorUserId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
# Files
|
||||
|
||||
Neutral SchoolCore module boundary. Keep domain-specific vocabulary in extension modules.
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Domain\SchoolCore\Files\Services;
|
||||
|
||||
use App\Domain\SchoolCore\Context\SchoolContext;
|
||||
use App\Domain\SchoolCore\Contracts\FileStorageServiceContract;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use RuntimeException;
|
||||
|
||||
final class LaravelLocalFileStorageService implements FileStorageServiceContract
|
||||
{
|
||||
public function store(SchoolContext $context, string $purpose, mixed $file, array $metadata = []): string
|
||||
{
|
||||
$directory = sprintf('schools/%d/%s', $context->schoolId, trim($purpose, '/'));
|
||||
|
||||
if (is_object($file) && method_exists($file, 'store')) {
|
||||
return $file->store($directory);
|
||||
}
|
||||
|
||||
throw new RuntimeException('Unsupported file payload. Pass an UploadedFile-compatible object.');
|
||||
}
|
||||
|
||||
public function resolvePath(SchoolContext $context, string $fileReference): string
|
||||
{
|
||||
$prefix = sprintf('schools/%d/', $context->schoolId);
|
||||
|
||||
if (! str_starts_with($fileReference, $prefix)) {
|
||||
throw new RuntimeException('File reference is outside the selected school context.');
|
||||
}
|
||||
|
||||
return Storage::path($fileReference);
|
||||
}
|
||||
|
||||
public function delete(SchoolContext $context, string $fileReference): void
|
||||
{
|
||||
$prefix = sprintf('schools/%d/', $context->schoolId);
|
||||
if (! str_starts_with($fileReference, $prefix)) {
|
||||
throw new RuntimeException('File reference is outside the selected school context.');
|
||||
}
|
||||
|
||||
Storage::delete($fileReference);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user