Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pterodactyl
GitHub Repository: pterodactyl/panel
Path: blob/1.0-develop/app/Models/Traits/HasRealtimeIdentifier.php
14042 views
1
<?php
2
3
namespace Pterodactyl\Models\Traits;
4
5
use Ramsey\Uuid\Uuid;
6
use Illuminate\Support\Str;
7
use Webmozart\Assert\Assert;
8
use ParagonIE\ConstantTime\Base32;
9
use Illuminate\Database\Eloquent\Builder;
10
use Pterodactyl\Models\Attributes\Identifiable;
11
use Illuminate\Database\Eloquent\Casts\Attribute;
12
13
/**
14
* Support realtime identifiers on models that do not track an "identifier" column in
15
* the database. This allows us to make use of the existing data reliant on UUID columns
16
* while still allowing for output and querying against a more human readable identifier
17
* value.
18
*
19
* @property-read string $identifier
20
*
21
* @method static Builder whereIdentifier(string $identifier)
22
*
23
* @mixin \Illuminate\Database\Eloquent\Model
24
*/
25
trait HasRealtimeIdentifier
26
{
27
private static string $identifierPrefix;
28
29
private static string $identifierDataColumn;
30
31
protected function identifier(): Attribute
32
{
33
return Attribute::get(function () {
34
$bytes = Uuid::fromString($this->getRawOriginal(static::$identifierDataColumn))->getBytes();
35
36
return sprintf('%s_%s', static::$identifierPrefix, Base32::encodeUnpadded($bytes));
37
});
38
}
39
40
public function scopeWhereIdentifier(Builder $builder, string $identifier): void
41
{
42
if (!str_starts_with($identifier, $prefix = self::$identifierPrefix . '_')) {
43
$builder->whereRaw('0 = 1');
44
45
return;
46
}
47
48
$bytes = rescue(fn () => Base32::decode(Str::replaceFirst($prefix, '', $identifier)), report: false);
49
if (empty($bytes)) {
50
$builder->whereRaw('0 = 1');
51
52
return;
53
}
54
55
$builder->where(self::$identifierDataColumn, Uuid::fromBytes($bytes)->toString());
56
}
57
58
protected static function bootHasRealtimeIdentifier(): void
59
{
60
$attrs = (new \ReflectionClass(static::class))->getAttributes(Identifiable::class);
61
62
Assert::count(
63
$attrs,
64
1,
65
'The #[' . Identifiable::class . '] attribute must be set on ' . static::class . ' to use realtime identifiers.'
66
);
67
68
$instance = $attrs[0]->newInstance();
69
70
self::$identifierPrefix = $instance->prefix;
71
self::$identifierDataColumn = $instance->column;
72
}
73
}
74
75