From 871d09bd96602f91f12187d5b8fc40efb743030d Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Tue, 17 Sep 2024 13:20:27 +0200 Subject: [PATCH] Feat: Move more functions to the PrivateKey Model --- app/Models/PrivateKey.php | 48 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/app/Models/PrivateKey.php b/app/Models/PrivateKey.php index e683e08b1..79f36ccf8 100644 --- a/app/Models/PrivateKey.php +++ b/app/Models/PrivateKey.php @@ -7,6 +7,7 @@ use Illuminate\Support\Facades\Storage; use Illuminate\Validation\ValidationException; use phpseclib3\Crypt\PublicKeyLoader; use DanHarrin\LivewireRateLimiting\WithRateLimiting; +use Illuminate\Support\Facades\DB; #[OA\Schema( description: 'Private Key model', @@ -33,6 +34,7 @@ class PrivateKey extends BaseModel 'private_key', 'is_git_related', 'team_id', + 'fingerprint', ]; protected $casts = [ @@ -49,6 +51,14 @@ class PrivateKey extends BaseModel 'private_key' => ['The private key is invalid.'], ]); } + + $key->fingerprint = self::generateFingerprint($key->private_key); + + if (self::fingerprintExists($key->fingerprint, $key->id)) { + throw ValidationException::withMessages([ + 'private_key' => ['This private key already exists.'], + ]); + } }); static::deleted(function ($key) { @@ -195,4 +205,42 @@ class PrivateKey extends BaseModel $this->delete(); } + + private static function privateKeyExists($key) + { + $publicKey = self::extractPublicKeyFromPrivate($key->private_key); + if (!$publicKey) { + return false; + } + + $existingKey = DB::table('private_keys') + ->where('team_id', $key->team_id) + ->where('id', '!=', $key->id) + ->whereRaw('? = (SELECT public_key FROM private_keys WHERE id = private_keys.id)', [$publicKey]) + ->exists(); + + return $existingKey; + } + + public static function generateFingerprint($privateKey) + { + try { + $key = PublicKeyLoader::load($privateKey); + $publicKey = $key->getPublicKey(); + return $publicKey->getFingerprint('sha256'); + } catch (\Throwable $e) { + return null; + } + } + + private static function fingerprintExists($fingerprint, $excludeId = null) + { + $query = self::where('fingerprint', $fingerprint); + + if ($excludeId) { + $query->where('id', '!=', $excludeId); + } + + return $query->exists(); + } }