Initial commit device-management
tests / ci (push) Has been cancelled

This commit is contained in:
Wian Drs
2026-08-25 09:42:00 +07:00
commit 1e80be180e
1159 changed files with 149545 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
<?php
use App\Http\Controllers\Api\V1\TenantController;
use Illuminate\Support\Facades\Route;
Route::prefix('v1')->middleware('auth:sanctum')->group(function (): void {
Route::apiResource('tenants', TenantController::class);
});
+29
View File
@@ -0,0 +1,29 @@
<?php
use App\Jobs\SyncDeviceBaseCredential;
use App\Jobs\SyncDeviceUser;
use App\Models\Device;
use App\Models\DeviceUserAssignment;
use Illuminate\Foundation\Inspiring;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Schedule;
Artisan::command('inspire', function () {
$this->comment(Inspiring::quote());
})->purpose('Display an inspiring quote');
Schedule::call(function (): void {
DeviceUserAssignment::withoutGlobalScope('tenant')->where('sync_status', 'pending')->orderBy('last_attempted_at')->limit(100)->get()->each(function (DeviceUserAssignment $assignment): void {
if (DeviceUserAssignment::withoutGlobalScope('tenant')->whereKey($assignment->id)->where('sync_status', 'pending')->update(['sync_status' => 'queued'])) {
SyncDeviceUser::dispatch($assignment->tenant_id, $assignment->id);
}
});
})->everyFiveMinutes()->name('retry-pending-device-users')->withoutOverlapping();
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 (Device::withoutGlobalScope('tenant')->whereKey($device->id)->where('base_sync_status', 'pending')->update(['base_sync_status' => 'queued'])) {
SyncDeviceBaseCredential::dispatch($device->tenant_id, $device->id);
}
});
})->everyFiveMinutes()->name('retry-pending-base-credentials')->withoutOverlapping();
+34
View File
@@ -0,0 +1,34 @@
<?php
use App\Http\Controllers\Settings\ProfileController;
use App\Http\Controllers\Settings\SecurityController;
use Illuminate\Auth\Middleware\RequirePassword;
use Illuminate\Support\Facades\Route;
Route::middleware(['auth'])->group(function () {
Route::redirect('settings', '/settings/profile');
Route::get('settings/profile', [ProfileController::class, 'edit'])->name('profile.edit');
Route::patch('settings/profile', [ProfileController::class, 'update'])->name('profile.update');
});
Route::middleware(['auth', 'verified'])->group(function () {
Route::delete('settings/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
Route::get('settings/security', [SecurityController::class, 'edit'])
->middleware(RequirePassword::class)
->name('security.edit');
Route::put('settings/password', [SecurityController::class, 'update'])
->middleware('throttle:6,1')
->name('user-password.update');
Route::inertia('settings/appearance', 'settings/appearance')->name('appearance.edit');
});
Route::get('.well-known/passkey-endpoints', function () {
return response()->json([
'enroll' => route('security.edit'),
'manage' => route('security.edit'),
]);
})->name('well-known.passkeys');
+42
View File
@@ -0,0 +1,42 @@
<?php
use App\Http\Controllers\Administration\TenantController;
use App\Http\Controllers\Administration\UserController;
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\RevealTenantBasePasswordController;
use App\Http\Controllers\TenantDevicePolicyController;
use App\Http\Controllers\TenantDeviceSettingController;
use App\Http\Controllers\TenantEncryptionController;
use Illuminate\Support\Facades\Route;
Route::inertia('/', 'welcome')->name('home');
Route::middleware(['auth', 'verified'])->group(function () {
Route::get('dashboard', DashboardController::class)->name('dashboard');
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');
Route::post('device-user-assignments/{assignment}/sync', DeviceUserSyncController::class)->middleware('throttle:12,1')->name('device-user-assignments.sync');
Route::put('device-policy', TenantDevicePolicyController::class)->name('device-policy.update');
Route::get('device-settings', [TenantDeviceSettingController::class, 'edit'])->name('device-settings.edit');
Route::put('device-settings', [TenantDeviceSettingController::class, 'update'])->name('device-settings.update');
Route::post('device-settings/reveal-password', RevealTenantBasePasswordController::class)->middleware('throttle:3,10')->name('device-settings.reveal-password');
Route::post('device-settings/rotate-key', TenantEncryptionController::class)->middleware('throttle:2,10')->name('device-settings.rotate-key');
Route::post('devices/{device}/activate', DeviceActivationController::class)->middleware('throttle:6,1')->name('devices.activate');
Route::prefix('administration')->name('administration.')->group(function () {
Route::resource('tenants', TenantController::class)->except('show');
Route::prefix('tenants/{tenant}')->middleware('admin.tenant')->scopeBindings()->group(function () {
Route::resource('users', UserController::class)->except('show');
Route::put('users/{user}/password', [UserController::class, 'resetPassword'])->name('users.password');
Route::patch('users/{user}/toggle-active', [UserController::class, 'toggleActive'])->name('users.toggle-active');
});
});
});
require __DIR__.'/settings.php';