53 lines
2.6 KiB
PHP
53 lines
2.6 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use Illuminate\Support\Facades\Crypt;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Str;
|
|
|
|
class LicenseService
|
|
{
|
|
public function issue(int $userId, int $purchaseId): void
|
|
{
|
|
if (DB::table('licenses')->where('purchase_id', $purchaseId)->exists()) {
|
|
return;
|
|
}
|
|
$key = 'TNX-'.Str::upper(bin2hex(random_bytes(20)));
|
|
DB::table('licenses')->insert(['user_id' => $userId, 'purchase_id' => $purchaseId, 'key_hash' => hash('sha256', $key), 'key_encrypted' => Crypt::encryptString($key), 'status' => 'active', 'device_limit' => 2, 'created_at' => now(), 'updated_at' => now()]);
|
|
}
|
|
|
|
public function activate(string $key, string $device): array
|
|
{
|
|
return DB::transaction(function () use ($key, $device) {
|
|
$license = DB::table('licenses')->where('key_hash', hash('sha256', $key))->lockForUpdate()->first();
|
|
abort_unless($license && $license->status === 'active', 403, 'Invalid or revoked license.');
|
|
$deviceHash = hash('sha256', $device);
|
|
$existing = DB::table('activations')->where('license_id', $license->id)->where('device_hash', $deviceHash)->first();
|
|
abort_if(! $existing && DB::table('activations')->where('license_id', $license->id)->count() >= $license->device_limit, 409, 'Device limit reached.');
|
|
$token = bin2hex(random_bytes(32));
|
|
DB::table('activations')->updateOrInsert(['license_id' => $license->id, 'device_hash' => $deviceHash], ['token_hash' => hash('sha256', $token), 'last_seen_at' => now(), 'created_at' => now(), 'updated_at' => now()]);
|
|
|
|
return ['activation_token' => $token, 'valid' => true, 'check_again_in' => 86400];
|
|
}, 3);
|
|
}
|
|
|
|
public function check(string $token, bool $deactivate = false): array
|
|
{
|
|
return DB::transaction(function () use ($token, $deactivate) {
|
|
$activation = DB::table('activations')->where('token_hash', hash('sha256', $token))->first();
|
|
abort_unless($activation, 403, 'Invalid activation.');
|
|
$license = DB::table('licenses')->where('id', $activation->license_id)->lockForUpdate()->first();
|
|
if ($deactivate) {
|
|
DB::table('activations')->where('id', $activation->id)->delete();
|
|
|
|
return ['deactivated' => true];
|
|
}
|
|
abort_unless($license->status === 'active', 403, 'License revoked.');
|
|
DB::table('activations')->where('id', $activation->id)->update(['last_seen_at' => now()]);
|
|
|
|
return ['valid' => true, 'check_again_in' => 86400];
|
|
}, 3);
|
|
}
|
|
}
|