File: /home/xedaptot/ai.naniguide.com/app/Http/Controllers/Api/LicenseController.php
<?php
namespace App\Http\Controllers\Api;
use App\Helpers\LicenseHelper;
use App\Http\Controllers\Controller;
use App\Library\License;
use Illuminate\Http\Request;
/**
* POST /api/v1/license/refresh — refresh license state from verify.acellemail.com
* and return the current license snapshot in one JSON call.
*
* Mirrors the webapp "Refresh" button in Admin → Settings → License so support
* engineers don't need headless browser / console session to check license state
* after an upgrade.
*
* Auth: admin api_token + setting_general permission == 'yes' (same gate as webapp).
*/
class LicenseController extends Controller
{
public function refresh(Request $request)
{
$user = \Auth::guard('api')->user();
if (!$user || !$user->admin
|| $user->admin->getPermission('setting_general') !== 'yes') {
return response()->json(['status' => 'error', 'message' => 'Unauthorized'], 401);
}
$current = LicenseHelper::getCurrentLicense();
if (!$current) {
return response()->json([
'status' => 'error',
'message' => 'No license installed',
'license' => null,
], 404);
}
try {
LicenseHelper::refreshLicense();
} catch (\Throwable $e) {
// Refresh call failed — still return the locally-stored snapshot so caller
// can at least inspect whether the cached state is valid. Include the error.
return response()->json([
'status' => 'error',
'message' => $e->getMessage(),
'license' => $this->present(LicenseHelper::getCurrentLicense()),
], 400);
}
return response()->json([
'status' => 'success',
'license' => $this->present(LicenseHelper::getCurrentLicense()),
]);
}
/**
* Build a JSON-safe snapshot of a License object.
* Purchase code is masked (first 4 + last 4 chars) to avoid leaking via logs.
*
* @return array<string, mixed>|null
*/
private function present(?License $license): ?array
{
if (!$license) {
return null;
}
$supportedUntil = $license->getSupportedUntil();
$now = \Carbon\Carbon::now();
$daysRemaining = (int)$now->copy()->startOfDay()->diffInDays($supportedUntil->copy()->startOfDay(), false);
$code = (string)$license->getLicenseNumber();
$masked = strlen($code) > 8
? substr($code, 0, 4) . str_repeat('*', max(0, strlen($code) - 8)) . substr($code, -4)
: str_repeat('*', strlen($code));
return [
'purchase_code_masked' => $masked,
'type' => $license->getType(),
'status' => $license->isActive() ? License::STATUS_ACTIVE
: ($license->isExpired() ? License::STATUS_EXPIRED : License::STATUS_INACTIVE),
'is_active' => $license->isActive(),
'is_expired' => $license->isExpired(),
'supported_until' => $supportedUntil->toIso8601String(),
'supported_until_human' => $supportedUntil->toDayDateTimeString(),
'days_remaining' => $daysRemaining,
'buyer' => $license->getBuyer(),
];
}
}