Toolvana: production-ready media tools platform (CodeIgniter 4)
- 134-tool registry with programmatic SEO (unique titles/H1/descriptions, JSON-LD graphs, sitemap index, canonical 301 enforcement via required filter) - DB-backed job queue (SKIP LOCKED) with drivers: Ffmpeg, Images (GD), Pdf (qpdf/gs/poppler), Youtube (thumbnails), Qr (server-side PNG) - Security: SSRF guard, MIME validation, rate limits, API-key auth, bcrypt admin login, security headers - Admin panel: dashboard, tools/categories/guides CRUD, SEO audit, analytics, job inspector with retry, system health, feature flags - Docker deployment (nginx + web/api FPM pools + scalable workers), PHPUnit suite (19 tests / 1139 assertions), PWA manifest + service worker
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use CodeIgniter\Model;
|
||||
|
||||
final class ApiKeyModel extends Model
|
||||
{
|
||||
protected $table = 'api_keys';
|
||||
protected $primaryKey = 'id';
|
||||
protected $returnType = 'array';
|
||||
protected $useTimestamps = true;
|
||||
protected $allowedFields = [
|
||||
'name', 'key_hash', 'key_prefix', 'rate_limit_per_hour',
|
||||
'request_count', 'is_active', 'last_used_at',
|
||||
];
|
||||
|
||||
public function findByPlainKey(string $plain): ?array
|
||||
{
|
||||
$hash = hash('sha256', $plain);
|
||||
$key = $this->where('key_hash', $hash)->where('is_active', 1)->first();
|
||||
if ($key !== null) {
|
||||
$this->update((int) $key['id'], [
|
||||
'request_count' => (int) $key['request_count'] + 1,
|
||||
'last_used_at' => date('Y-m-d H:i:s'),
|
||||
]);
|
||||
}
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
||||
/** Creates a key and returns [row, plaintext] — plaintext shown exactly once. */
|
||||
public function issue(string $name, int $ratePerHour = 120): array
|
||||
{
|
||||
helper('text');
|
||||
$plain = 'tv_live_' . bin2hex(random_bytes(20));
|
||||
$row = [
|
||||
'name' => $name,
|
||||
'key_hash' => hash('sha256', $plain),
|
||||
'key_prefix' => substr($plain, 0, 12),
|
||||
'rate_limit_per_hour' => $ratePerHour,
|
||||
'is_active' => 1,
|
||||
];
|
||||
$this->insert($row);
|
||||
|
||||
return [$row, $plain];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user