diff --git a/app/Console/Commands/SyncSubscriptionKeys.php b/app/Console/Commands/SyncSubscriptionKeys.php deleted file mode 100644 index 9e8f228..0000000 --- a/app/Console/Commands/SyncSubscriptionKeys.php +++ /dev/null @@ -1,109 +0,0 @@ -error('Missing endpoint.'); - return self::FAILURE; - } - - $response = Http::asJson() - ->acceptJson() - ->timeout(20) - ->retry(3, 1000) - ->post($endpoint.'/api/membership/keys', [ - 'payload' => base64_encode(Crypt::encryptString('get-active-keys')), - ]); - - if (! $response->successful()) { - $this->error('Subscription API request failed: HTTP ' . $response->status()); - return self::FAILURE; - } - - try { - $decrypted = Crypt::decryptString(base64_decode($response->json('payload'))); - $activeKeys = json_decode($decrypted, true, flags: JSON_THROW_ON_ERROR); - } catch (DecryptException $e) { - $this->error('Could not decrypt API response.'); - return self::FAILURE; - } catch (\JsonException $e) { - $this->error('API returned invalid JSON.'); - return self::FAILURE; - } - - if (! is_array($activeKeys)) { - $this->error('API response payload was not an array.'); - return self::FAILURE; - } - - $activeKeys = collect($activeKeys) - ->filter(fn ($key) => is_string($key) && $key !== '') - ->values() - ->all(); - - $this->markInactiveUsers($activeKeys); - $this->markActiveUsers($activeKeys); - - return self::SUCCESS; - } - - private function markInactiveUsers(array $activeKeys) - { - User::query() - ->whereNotNull('subscription_key') - ->whereNotIn('subscription_key', $activeKeys) - ->chunk(100, function ($users) { - foreach($users as $user) { - if ($user->hasRole(UserRole::SUPPORTER)) { - Log::info("Removed Supporter Role from {$user->name}"); - $user->removeRole(UserRole::SUPPORTER); - } - } - }); - } - - private function markActiveUsers(array $activeKeys) - { - User::query() - ->whereNotNull('subscription_key') - ->whereIn('subscription_key', $activeKeys) - ->chunk(100, function ($users) { - foreach($users as $user) { - if (!$user->hasRole(UserRole::SUPPORTER)) { - Log::info("Added Supporter Role for {$user->name}"); - $user->addRole(UserRole::SUPPORTER); - } - } - }); - } -} diff --git a/app/Http/Controllers/ProfileController.php b/app/Http/Controllers/ProfileController.php index e1f0065..6df0242 100644 --- a/app/Http/Controllers/ProfileController.php +++ b/app/Http/Controllers/ProfileController.php @@ -95,16 +95,6 @@ class ProfileController extends Controller ]); } - /** - * Display the user's subscription page. - */ - public function subscription(Request $request): View - { - return view('profile.subscription', [ - 'user' => $request->user(), - ]); - } - /** * Update user settings. */ diff --git a/app/Livewire/UserSubscription.php b/app/Livewire/UserSubscription.php deleted file mode 100644 index 5e2c2ae..0000000 --- a/app/Livewire/UserSubscription.php +++ /dev/null @@ -1,75 +0,0 @@ - 'required|string|size:48', - ]; - - public function mount(User $user) - { - $this->userId = $user ? $user->id : auth()->user()->id; - $this->subscriptionKey = $user->subscription_key ?? ''; - $this->isActive = $user->hasRole(UserRole::SUPPORTER) ?? false; - } - - public function applyKey(SubscriptionService $subscriptionService) - { - $this->validate(); - - $rateLimitKey = "apply-subscription:{$this->userId}"; - $rateLimitMinutes = 60 * 5; // 5 minutes - - // Rate Limit to prevent users trying random keys - if (RateLimiter::tooManyAttempts($rateLimitKey, 1)) { - $seconds = RateLimiter::availableIn($rateLimitKey); - $this->addError('subscriptionKey', "Too many attempts. Try again in {$seconds} seconds."); - return; - } - - RateLimiter::hit($rateLimitKey, $rateLimitMinutes); - - // Check if token is already being used - $alreadyUsed = User::where('subscription_key', $this->subscriptionKey) - ->whereNot('id', $this->userId) - ->exists(); - - if ($alreadyUsed) { - $this->addError('subscriptionKey', 'Key already used!'); - return; - } - - $user = User::where('id', $this->userId)->firstOrFail(); - - // Verify token - $success = $subscriptionService->checkSubscriptionStatus($user, $this->subscriptionKey); - if (!$success) { - $this->addError('subscriptionKey', 'Invalid Key! If you believe this is a bug, please report this to the admin!'); - return; - } - - $user->subscription_key = $this->subscriptionKey; - $user->save(); - $this->isActive = true; - } - - public function render() - { - return view('livewire.user-subscription'); - } -} diff --git a/app/Models/User.php b/app/Models/User.php index 2e5ba2b..8598f60 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -31,7 +31,6 @@ class User extends Authenticatable implements HasPasskeys // Discord 'discord_id', 'discord_avatar', - 'subscription_key', ]; /** @@ -42,7 +41,6 @@ class User extends Authenticatable implements HasPasskeys protected $hidden = [ 'password', 'remember_token', - 'subscription_key', ]; /** diff --git a/app/Services/SubscriptionService.php b/app/Services/SubscriptionService.php deleted file mode 100644 index 3f4f7c6..0000000 --- a/app/Services/SubscriptionService.php +++ /dev/null @@ -1,79 +0,0 @@ - $subscriptionKey, - 'timestamp' => now()->timestamp, - 'nonce' => Str::uuid()->toString(), - ], JSON_THROW_ON_ERROR))); - } - - /** - * Gets the subscription status from the subscription service. - */ - private function getSubscriptionStatus(string $subscriptionKey): array | null - { - try { - $payload = $this->generateEncryptedPayload($subscriptionKey); - - $response = Http::post(config('services.subscription_service_host').'/api/membership/verify', [ - 'payload' => $payload, - ]); - - if (! $response->successful()) { - logger()->error('Subscription Service API error', [ - 'status' => $response->status(), - 'body' => $response->body(), - ]); - - return null; - } - - $encryptedResponse = $response->json('payload'); - - $json = json_decode( - Crypt::decryptString($encryptedResponse), - true, - flags: JSON_THROW_ON_ERROR - ); - - return $json; - } catch (Exception $e) { - logger()->error('getSubscriptionStatus Exception', [ - 'details' => $e, - ]); - } - - return null; - } - - public function checkSubscriptionStatus(User $user, string $subscriptionKey): bool - { - $subscriptionStatus = $this->getSubscriptionStatus($subscriptionKey); - if (!$subscriptionStatus) { - return false; - } - - if ($subscriptionStatus['valid'] === true && - $subscriptionStatus['active'] === true) { - $user->addRole(UserRole::SUPPORTER); - return true; - } - - $user->removeRole(UserRole::SUPPORTER); - return true; - } -} diff --git a/config/services.php b/config/services.php index 82feb3d..9cf8b55 100644 --- a/config/services.php +++ b/config/services.php @@ -54,9 +54,4 @@ return [ 'server' => env('MATRIX_SERVER'), 'shared_secret' => env('MATRIX_SHARED_SECRET'), ], - - /** - * Subscription Service - */ - 'subscription_service_host' => env('SUBSCRIPTION_SERVICE_HOST'), ]; diff --git a/database/migrations/2026_07_18_115452_drop_subscription_key_from_users_table.php b/database/migrations/2026_07_18_115452_drop_subscription_key_from_users_table.php new file mode 100644 index 0000000..22022d3 --- /dev/null +++ b/database/migrations/2026_07_18_115452_drop_subscription_key_from_users_table.php @@ -0,0 +1,31 @@ +dropColumn('subscription_key'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + $table->string('subscription_key', 64) + ->unique() + ->nullable() + ->after('roles'); + }); + } +}; diff --git a/resources/views/livewire/user-subscription.blade.php b/resources/views/livewire/user-subscription.blade.php deleted file mode 100644 index c13f49f..0000000 --- a/resources/views/livewire/user-subscription.blade.php +++ /dev/null @@ -1,54 +0,0 @@ -
- Your current membership status for unlimited 4k Downloads. -
-- Paste your subscription key to apply the membership status. -
-