refactor: reorganize project structure for better maintainability
- Move 45 debug/test files from root to organized scripts/ directories - Secure public/ directory by removing debug files (security improvement) - Create structured scripts organization: • scripts/debug/ (20 files) - Framework debugging tools • scripts/test/ (18 files) - Test and validation scripts • scripts/maintenance/ (5 files) - Maintenance utilities • scripts/dev/ (2 files) - Development tools Security improvements: - Removed all debug/test files from public/ directory - Only production files remain: index.php, health.php Root directory cleanup: - Reduced from 47 to 2 PHP files in root - Only essential production files: console.php, worker.php This improves: ✅ Security (no debug code in public/) ✅ Organization (clear separation of concerns) ✅ Maintainability (easy to find and manage scripts) ✅ Professional structure (clean root directory)
This commit is contained in:
108
src/Framework/MagicLinks/Services/InMemoryMagicLinkService.php
Normal file
108
src/Framework/MagicLinks/Services/InMemoryMagicLinkService.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\Smartlinks\Services;
|
||||
|
||||
use App\Framework\DateTime\Clock;
|
||||
use App\Framework\Smartlinks\SmartlinkData;
|
||||
use App\Framework\Smartlinks\SmartLinkToken;
|
||||
use App\Framework\Smartlinks\TokenAction;
|
||||
use App\Framework\Smartlinks\TokenConfig;
|
||||
use App\Framework\Ulid\UlidGenerator;
|
||||
|
||||
final class InMemorySmartLinkService implements SmartlinkService
|
||||
{
|
||||
private array $tokens = [];
|
||||
|
||||
public function __construct(
|
||||
private readonly UlidGenerator $ulidGenerator,
|
||||
private readonly Clock $clock
|
||||
) {
|
||||
}
|
||||
|
||||
public function generate(
|
||||
TokenAction $action,
|
||||
array $payload,
|
||||
?TokenConfig $config = null,
|
||||
?string $createdByIp = null,
|
||||
?string $userAgent = null
|
||||
): SmartlinkToken {
|
||||
$config ??= new TokenConfig();
|
||||
$id = $this->ulidGenerator->generate($this->clock);
|
||||
;
|
||||
$now = new \DateTimeImmutable();
|
||||
|
||||
$smartlinkData = new SmartlinkData(
|
||||
id: $id,
|
||||
action: $action,
|
||||
payload: $payload,
|
||||
expiresAt: $config->getExpiryDateTime(),
|
||||
createdAt: $now,
|
||||
oneTimeUse: $config->oneTimeUse,
|
||||
createdByIp: $createdByIp,
|
||||
userAgent: $userAgent
|
||||
);
|
||||
|
||||
$token = new SmartlinkToken($id);
|
||||
$this->tokens[$id] = $smartlinkData;
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
public function validate(SmartlinkToken $token): ?SmartlinkData
|
||||
{
|
||||
if (! isset($this->tokens[$token->value])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$data = $this->tokens[$token->value];
|
||||
|
||||
if (! $data->isValid()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function markAsUsed(SmartlinkToken $token): void
|
||||
{
|
||||
if (isset($this->tokens[$token->value])) {
|
||||
$data = $this->tokens[$token->value];
|
||||
$this->tokens[$token->value] = $data->withUsed(new \DateTimeImmutable());
|
||||
}
|
||||
}
|
||||
|
||||
public function revoke(SmartlinkToken $token): void
|
||||
{
|
||||
unset($this->tokens[$token->value]);
|
||||
}
|
||||
|
||||
public function exists(SmartlinkToken $token): bool
|
||||
{
|
||||
return isset($this->tokens[$token->value]) &&
|
||||
$this->tokens[$token->value]->isValid();
|
||||
}
|
||||
|
||||
public function getActiveTokens(int $limit = 100): array
|
||||
{
|
||||
return array_slice(
|
||||
array_filter($this->tokens, fn ($data) => $data->isValid()),
|
||||
0,
|
||||
$limit
|
||||
);
|
||||
}
|
||||
|
||||
public function cleanupExpired(): int
|
||||
{
|
||||
$count = 0;
|
||||
foreach ($this->tokens as $id => $data) {
|
||||
if ($data->isExpired()) {
|
||||
unset($this->tokens[$id]);
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user