Files
firefrost-services/services/modpack-version-checker/blueprint-extension/admin/controller.php
Claude (Chronicler #83 - The Compiler) 8872f67727 Phase 11D: Blueprint license activation, phone-home, and tier gating
- LicenseService.php: activate/validate/deactivate + 7-day grace period
- ValidateLicense.php: mvc:validate Artisan command (daily cron)
- Updated controller.php: license activation/deactivation in update handler
- Updated view.blade.php: order ID input, status indicator (green/yellow/red),
  grace/expired banners, dynamic pro-tier field gating, update-available card

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 20:36:55 -05:00

108 lines
4.0 KiB
PHP

<?php
namespace Pterodactyl\Http\Controllers\Admin\Extensions\modpackchecker;
use Illuminate\View\View;
use Illuminate\View\Factory as ViewFactory;
use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\BlueprintFramework\Libraries\ExtensionLibrary\Admin\BlueprintAdminLibrary as BlueprintExtensionLibrary;
use Pterodactyl\Http\Requests\Admin\AdminFormRequest;
use Pterodactyl\Services\LicenseService;
use Illuminate\Http\RedirectResponse;
class modpackcheckerExtensionController extends Controller
{
public function __construct(
private ViewFactory $view,
private BlueprintExtensionLibrary $blueprint,
private LicenseService $licenseService,
) {}
public function index(): View
{
$curseforge_api_key = $this->blueprint->dbGet('modpackchecker', 'curseforge_api_key');
$discord_webhook_url = $this->blueprint->dbGet('modpackchecker', 'discord_webhook_url');
$check_interval = $this->blueprint->dbGet('modpackchecker', 'check_interval');
if ($check_interval == '') {
$this->blueprint->dbSet('modpackchecker', 'check_interval', 'daily');
$check_interval = 'daily';
}
$license = $this->licenseService->getState();
return $this->view->make(
'admin.extensions.modpackchecker.index', [
'curseforge_api_key' => $curseforge_api_key,
'discord_webhook_url' => $discord_webhook_url,
'check_interval' => $check_interval,
'license' => $license,
'root' => '/admin/extensions/modpackchecker',
'blueprint' => $this->blueprint,
]
);
}
public function update(modpackcheckerSettingsFormRequest $request): RedirectResponse
{
// Handle license activation
$orderId = $request->input('order_id');
if (!empty($orderId)) {
$currentOrderId = $this->blueprint->dbGet('modpackchecker', 'order_id');
if ($orderId !== $currentOrderId) {
$result = $this->licenseService->activate($orderId);
if (!$result['success']) {
return redirect()
->route('admin.extensions.modpackchecker.index')
->with('error', 'License activation failed: ' . ($result['error'] ?? 'Unknown error'));
}
}
}
// Handle license deactivation
if ($request->input('deactivate_license') === '1') {
$this->licenseService->deactivate();
return redirect()
->route('admin.extensions.modpackchecker.index')
->with('success', 'License deactivated.');
}
// Save standard settings
$this->blueprint->dbSet('modpackchecker', 'curseforge_api_key', $request->input('curseforge_api_key') ?? '');
// Only save PRO-tier fields if licensed as professional
if ($this->licenseService->isProFeatureAllowed()) {
$this->blueprint->dbSet('modpackchecker', 'discord_webhook_url', $request->input('discord_webhook_url') ?? '');
$this->blueprint->dbSet('modpackchecker', 'check_interval', $request->input('check_interval') ?? 'daily');
}
return redirect()
->route('admin.extensions.modpackchecker.index')
->with('success', 'Settings saved successfully.');
}
}
class modpackcheckerSettingsFormRequest extends AdminFormRequest
{
public function rules(): array
{
return [
'order_id' => 'nullable|string|max:64',
'deactivate_license' => 'nullable|string',
'curseforge_api_key' => 'nullable|string|max:500',
'discord_webhook_url' => 'nullable|url|max:500',
'check_interval' => 'nullable|in:daily,12h,6h',
];
}
public function attributes(): array
{
return [
'order_id' => 'Order ID',
'curseforge_api_key' => 'CurseForge API Key',
'discord_webhook_url' => 'Discord Webhook URL',
'check_interval' => 'Check Interval',
];
}
}