update lisensi prosess
tests / ci (push) Has been cancelled

This commit is contained in:
Wian Drs
2026-08-25 13:43:55 +07:00
parent 1e80be180e
commit 60946ddf37
58 changed files with 2903 additions and 165 deletions
+14
View File
@@ -1,9 +1,12 @@
<?php
use App\Enums\LicenseStatus;
use App\Jobs\SyncDeviceBaseCredential;
use App\Jobs\SyncDeviceUser;
use App\Models\Device;
use App\Models\DeviceUserAssignment;
use App\Models\License;
use App\Services\LicenseEntitlementService;
use Illuminate\Foundation\Inspiring;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Schedule;
@@ -12,8 +15,16 @@ Artisan::command('inspire', function () {
$this->comment(Inspiring::quote());
})->purpose('Display an inspiring quote');
Schedule::call(function (): void {
License::withoutGlobalScope('tenant')->where('status', LicenseStatus::Active->value)->where('expires_at', '<=', now())->get()->each(fn (License $license) => $license->update(['status' => $license->grace_until?->isFuture() ? LicenseStatus::Grace : LicenseStatus::Expired]));
License::withoutGlobalScope('tenant')->where('status', LicenseStatus::Grace->value)->where('grace_until', '<=', now())->update(['status' => LicenseStatus::Expired]);
})->everyMinute()->name('update-license-statuses')->withoutOverlapping();
Schedule::call(function (): void {
DeviceUserAssignment::withoutGlobalScope('tenant')->where('sync_status', 'pending')->orderBy('last_attempted_at')->limit(100)->get()->each(function (DeviceUserAssignment $assignment): void {
if (! app(LicenseEntitlementService::class)->allowsUse($assignment->tenant_id)) {
return;
}
if (DeviceUserAssignment::withoutGlobalScope('tenant')->whereKey($assignment->id)->where('sync_status', 'pending')->update(['sync_status' => 'queued'])) {
SyncDeviceUser::dispatch($assignment->tenant_id, $assignment->id);
}
@@ -22,6 +33,9 @@ Schedule::call(function (): void {
Schedule::call(function (): void {
Device::withoutGlobalScope('tenant')->where('base_sync_status', 'pending')->orderBy('base_sync_attempted_at')->limit(100)->get()->each(function (Device $device): void {
if (! app(LicenseEntitlementService::class)->allowsUse($device->tenant_id)) {
return;
}
if (Device::withoutGlobalScope('tenant')->whereKey($device->id)->where('base_sync_status', 'pending')->update(['base_sync_status' => 'queued'])) {
SyncDeviceBaseCredential::dispatch($device->tenant_id, $device->id);
}
+19
View File
@@ -1,13 +1,17 @@
<?php
use App\Http\Controllers\Administration\BillingOrderController;
use App\Http\Controllers\Administration\TenantController;
use App\Http\Controllers\Administration\UserController;
use App\Http\Controllers\BillingController;
use App\Http\Controllers\CheckoutController;
use App\Http\Controllers\DashboardController;
use App\Http\Controllers\DeviceAccessUserController;
use App\Http\Controllers\DeviceActivationController;
use App\Http\Controllers\DeviceController;
use App\Http\Controllers\DeviceCredentialController;
use App\Http\Controllers\DeviceUserSyncController;
use App\Http\Controllers\PaymentWebhookController;
use App\Http\Controllers\RevealTenantBasePasswordController;
use App\Http\Controllers\TenantDevicePolicyController;
use App\Http\Controllers\TenantDeviceSettingController;
@@ -15,9 +19,22 @@ use App\Http\Controllers\TenantEncryptionController;
use Illuminate\Support\Facades\Route;
Route::inertia('/', 'welcome')->name('home');
Route::inertia('/documentation/deployment', 'documentation/deployment')->name('documentation.deployment');
Route::get('/checkout/{order}', [CheckoutController::class, 'show'])->name('checkout.show');
Route::get('/checkout/{order}/return', [CheckoutController::class, 'returned'])->name('checkout.return');
Route::post('/checkout/{order}/retry', [CheckoutController::class, 'retry'])->middleware('throttle:5,1')->name('checkout.retry');
Route::post('/payments/{gateway}/callback', PaymentWebhookController::class)->middleware('throttle:120,1')->name('payments.webhook');
Route::get('/downloads/self-hosted', function () {
$package = collect(glob(base_path('dist/radiq-ndm-self-hosted-*.zip')))->sortDesc()->first();
abort_unless($package && is_file($package), 404, 'Paket self-hosted belum tersedia.');
return response()->download($package, basename($package));
})->middleware('throttle:10,1')->name('downloads.self-hosted');
Route::middleware(['auth', 'verified'])->group(function () {
Route::get('dashboard', DashboardController::class)->name('dashboard');
Route::get('billing', [BillingController::class, 'index'])->name('billing.index');
Route::post('billing/checkout', [BillingController::class, 'store'])->middleware('throttle:5,1')->name('billing.checkout');
Route::resource('devices', DeviceController::class);
Route::resource('devices.credentials', DeviceCredentialController::class)->only(['store', 'update', 'destroy']);
Route::resource('device-users', DeviceAccessUserController::class)->parameters(['device-users' => 'deviceAccessUser'])->except('show');
@@ -30,6 +47,8 @@ Route::middleware(['auth', 'verified'])->group(function () {
Route::post('devices/{device}/activate', DeviceActivationController::class)->middleware('throttle:6,1')->name('devices.activate');
Route::prefix('administration')->name('administration.')->group(function () {
Route::get('billing-orders', [BillingOrderController::class, 'index'])->name('billing-orders.index');
Route::patch('billing-orders/{order}/approve', [BillingOrderController::class, 'approve'])->name('billing-orders.approve');
Route::resource('tenants', TenantController::class)->except('show');
Route::prefix('tenants/{tenant}')->middleware('admin.tenant')->scopeBindings()->group(function () {
Route::resource('users', UserController::class)->except('show');