feat: add routes, lang, tests, stubs, docs, and docker configurations

This commit is contained in:
2026-05-21 16:05:16 +07:00
parent fad70d096b
commit 28a06315b8
3385 changed files with 177070 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
<?php
use Laravel\Mcp\Facades\Mcp;
// Mcp::web('/mcp/demo', \App\Mcp\Servers\PublicServer::class);
+45
View File
@@ -0,0 +1,45 @@
<?php
use App\Http\Controllers\Api\AuthController;
use App\Http\Controllers\Api\DeviceTokenController;
use App\Http\Controllers\Api\HealthController;
use App\Http\Controllers\Api\MobileConfigController;
use App\Http\Controllers\Api\MobileLogController;
use App\Http\Controllers\Api\OtpController;
use Illuminate\Support\Facades\Route;
// Health check (no auth, no versioning)
Route::get('/health', [HealthController::class, 'check']);
// Fallback/Legacy routes for mobile apps not yet updated to v1
Route::post('/login', [AuthController::class, 'login'])->middleware('throttle:10,1');
Route::get('/app-config', [AuthController::class, 'getAppConfig'])->middleware('throttle:60,1');
Route::prefix('v1')->middleware('mobile-guard')->group(function () {
// Public endpoints
Route::post('/login', [AuthController::class, 'login'])->middleware('throttle:10,1');
Route::post('/register', [AuthController::class, 'register'])->middleware('throttle:5,1');
Route::post('/forgot-password', [AuthController::class, 'forgotPassword'])->middleware('throttle:5,1');
Route::get('/app-config', [AuthController::class, 'getAppConfig']);
Route::get('/mobile/sync', [MobileConfigController::class, 'sync']);
Route::post('/mobile/log', [MobileLogController::class, 'store'])->middleware('throttle:60,1');
// OTP
Route::post('/otp/send', [OtpController::class, 'send'])->middleware('throttle:5,1');
Route::post('/otp/verify', [OtpController::class, 'verify'])->middleware('throttle:5,1');
// Authenticated endpoints
Route::middleware('auth:sanctum')->group(function () {
Route::get('/user', [AuthController::class, 'user']);
Route::post('/logout', [AuthController::class, 'logout']);
Route::post('/profile/update', [AuthController::class, 'updateProfile']);
Route::post('/profile/avatar', [AuthController::class, 'updateAvatar']);
Route::post('/profile/password', [AuthController::class, 'updatePassword']);
Route::delete('/profile/delete', [AuthController::class, 'deleteAccount']);
Route::get('/dashboard', [AuthController::class, 'getDashboardData']);
// Device tokens for push notifications
Route::post('/devices/register', [DeviceTokenController::class, 'register']);
Route::delete('/devices/unregister', [DeviceTokenController::class, 'unregister']);
});
});
+79
View File
@@ -0,0 +1,79 @@
<?php
use App\Http\Controllers\Auth\AuthenticatedSessionController;
use App\Http\Controllers\Auth\ConfirmablePasswordController;
use App\Http\Controllers\Auth\EmailVerificationNotificationController;
use App\Http\Controllers\Auth\EmailVerificationPromptController;
use App\Http\Controllers\Auth\NewPasswordController;
use App\Http\Controllers\Auth\PasswordController;
use App\Http\Controllers\Auth\PasswordResetLinkController;
use App\Http\Controllers\Auth\RegisteredUserController;
use App\Http\Controllers\Auth\TwoFactorController;
use App\Http\Controllers\Auth\VerifyEmailController;
use Illuminate\Support\Facades\Route;
use Laragear\WebAuthn\Http\Routes as WebAuthn;
// ==============================
// Guest Routes (Belum Login)
// ==============================
Route::middleware('guest')->group(function () {
// WebAuthn Login
if (get_setting('webauthn_enabled', false)) {
WebAuthn::register();
}
// ==============================
// Under Maintenance Page
// ==============================
Route::view('/maintenance', 'auth.maintenance')->name('maintenance');
// {{-- Buat file resources/views/maintenance.blade.php --}}
// ==============================
// Register (di-redirect ke maintenance)
// ==============================
Route::get('register', [RegisteredUserController::class, 'create'])->name('register');
Route::post('register', [RegisteredUserController::class, 'store']);
// ==============================
// Login
// ==============================
Route::get('login', [AuthenticatedSessionController::class, 'create'])->name('login');
Route::post('login', [AuthenticatedSessionController::class, 'store']);
// ==============================
// 2FA Verification
// ==============================
Route::get('2fa', [TwoFactorController::class, 'index'])->name('2fa.index');
Route::post('2fa', [TwoFactorController::class, 'verify'])->middleware('throttle:5,1')->name('2fa.verify');
// ==============================
// Forgot / Reset Password
// ==============================
Route::get('forgot-password', [PasswordResetLinkController::class, 'create'])->name('password.request');
Route::post('forgot-password', [PasswordResetLinkController::class, 'store'])->name('password.email');
Route::get('reset-password/{token}', [NewPasswordController::class, 'create'])->name('password.reset');
Route::post('reset-password', [NewPasswordController::class, 'store'])->name('password.store');
});
// ==============================
// Authenticated Routes (Sudah Login)
// ==============================
Route::middleware('auth')->group(function () {
// Verify Email
Route::get('verify-email', EmailVerificationPromptController::class)->name('verification.notice');
Route::get('verify-email/{id}/{hash}', VerifyEmailController::class)
->middleware(['signed', 'throttle:6,1'])
->name('verification.verify');
Route::post('email/verification-notification', [EmailVerificationNotificationController::class, 'store'])
->middleware('throttle:6,1')
->name('verification.send');
// Confirm Password (Re-auth)
Route::get('confirm-password', [ConfirmablePasswordController::class, 'show'])->name('password.confirm');
Route::post('confirm-password', [ConfirmablePasswordController::class, 'store']);
// Update Password & Logout
Route::put('password', [PasswordController::class, 'update'])->name('password.update');
Route::post('logout', [AuthenticatedSessionController::class, 'destroy'])->name('logout');
});
+20
View File
@@ -0,0 +1,20 @@
<?php
use Illuminate\Support\Facades\Broadcast;
Broadcast::channel('App.Models.User.{id}', function ($user, $id) {
return (int) $user->id === (int) $id;
});
// 🛡️ ROLE BASED CHANNELS (Dynamic)
Broadcast::channel('roles.{roleName}', function ($user, $roleName) {
if ($user->hasAnyRole(['Developer', 'Administrator'])) {
return true;
}
return $user->hasRole($roleName);
});
Broadcast::channel('admin.monitoring', function ($user) {
return $user->can('view health and logs');
});
+99
View File
@@ -0,0 +1,99 @@
<?php
use App\Jobs\Monitoring\WorkerHeartbeatJob;
use App\Services\System\BackupManagementService;
use App\Services\System\MaintenanceManagementService;
use App\Services\SystemConfig\SystemConfigService;
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');
/**
* 1. Maintenance Mode Auto-Release
*/
Schedule::call(function () {
app(MaintenanceManagementService::class)->autoCheckAndRelease();
})->everyMinute();
/**
* 2. Queue Worker Heartbeat (Monitoring)
*/
Schedule::job(new WorkerHeartbeatJob)->everyMinute();
/**
* 3. Activity Log, Notification & Model Cleanup
*/
Schedule::command('activitylog:clean')->daily();
Schedule::command('model:prune')->dailyAt('03:00');
Schedule::command('telescope:prune --hours=48')->dailyAt('03:05');
/**
* 4. Weekly Backup Verification
*/
Schedule::command('backups:verify')->weeklyOn(1, '07:00'); // Every Monday at 07:00
/**
* 5. Weekly Permission Audit (logged only, no auto-fix)
*/
Schedule::command('permissions:audit --json')->weeklyOn(1, '07:05')
->sendOutputTo(storage_path('logs/permission-audit.log'));
/**
* 3. Dynamic Database Backup
*/
$settings = app(SystemConfigService::class)->all();
if (filter_var($settings['backup_db_enabled'] ?? false, FILTER_VALIDATE_BOOLEAN)) {
$frequency = $settings['backup_db_frequency'] ?? 'daily';
$time = $settings['backup_db_time'] ?? '02:00';
$backupTask = Schedule::call(function () {
$service = app(BackupManagementService::class);
$service->applyDynamicConfig();
$service->createBackup();
})->name('automated-db-backup')->withoutOverlapping();
$cleanupTask = Schedule::command('backup:clean')->name('automated-db-cleanup')->withoutOverlapping();
// Map frequency using switch for multi-statement arms
switch ($frequency) {
case 'hourly':
// hourlyAt expects minutes (0-59), not a time string (HH:mm)
$minute = (int) (str_contains($time, ':') ? explode(':', $time)[1] : $time);
$backupTask->hourlyAt($minute);
$cleanupTask->hourlyAt($minute);
break;
case 'weekly':
$backupTask->weeklyOn(0, $time);
$cleanupTask->weeklyOn(0, $time);
break;
case 'monthly':
$backupTask->monthlyOn(1, $time);
$cleanupTask->monthlyOn(1, $time);
break;
case 'daily':
default:
$backupTask->dailyAt($time);
$cleanupTask->dailyAt($time);
break;
}
}
/**
* 6. System Health Check Monitoring
*/
Schedule::command('system:health-check')->everyThirtyMinutes();
/**
* 7. AI System Health Digest (Weekly)
*/
Schedule::command('system:send-digest')->weeklyOn(1, '08:00');
/**
* 8. Real-time Dashboard Stats Broadcast (every minute via scheduler)
* Reverb pushes fresh stats to all connected admin.monitoring subscribers.
*/
Schedule::command('dashboard:broadcast-stats')->everyMinute()->withoutOverlapping();
+362
View File
@@ -0,0 +1,362 @@
<?php
/**
* ============================================================
*
* @project biiproject
*
* @author Andika Debi Putra
*
* @email andikadebiputra@gmail.com
*
* @website https://biiproject.com
*
* @copyright Copyright (c) 2026 Andika Debi Putra
* @license Proprietary - All Rights Reserved
*
* @version 1.0.0
*
* @created 2026-05-01
* ============================================================
*
* Unauthorized copying, modification, distribution, or use
* of this file is strictly prohibited without prior written
* permission from the author.
* ============================================================
*/
use App\Http\Controllers\AccessControl\ActionLogController;
use App\Http\Controllers\AccessControl\PermissionManagementController;
use App\Http\Controllers\AccessControl\RoleManagementController;
use App\Http\Controllers\AccessControl\UserManagementController;
use App\Http\Controllers\Admin\MobileSettingController;
use App\Http\Controllers\AI\AiAssistantController;
use App\Http\Controllers\AI\LogAnalysisController;
use App\Http\Controllers\Auth\SocialAuthController;
use App\Http\Controllers\DashboardController;
use App\Http\Controllers\ImpersonateController;
use App\Http\Controllers\LegalController;
use App\Http\Controllers\ProfileController;
use App\Http\Controllers\System\GlobalSearchController;
use App\Http\Controllers\SystemSettings\BackupRestoreController;
use App\Http\Controllers\SystemSettings\EditorUploadController;
use App\Http\Controllers\SystemSettings\MaintenanceModeController;
use App\Http\Controllers\SystemSettings\NotificationCenterController;
use App\Http\Controllers\SystemSettings\SessionManagerController;
use App\Http\Controllers\SystemSettings\SystemConfigController;
use App\Http\Controllers\SystemSettings\SystemMonitoringController;
use App\Services\SystemConfig\SystemConfigService;
use Illuminate\Support\Facades\Route;
// Public homepage
Route::get('/', function () {
if (! app(SystemConfigService::class)->get('enable_landing_page', true)) {
return redirect()->route('login');
}
return view('welcome');
})->name('homepage');
Route::get('/public-config', [SystemConfigController::class, 'publicConfig'])->name('system-config.public');
// LEGAL & CONTENT PAGES (UU PDP COMPLIANCE)
Route::get('/legal/re-agree', [LegalController::class, 'reAgree'])
->middleware('auth')
->name('legal.re-agree');
Route::post('/legal/re-agree', [LegalController::class, 'postReAgree'])
->middleware('auth')
->name('legal.re-agree.post');
Route::get('/legal/{type}', [LegalController::class, 'show'])->name('legal.show');
// UNIFIED SOCIAL OAUTH
// callback must come BEFORE the {provider} wildcard, otherwise /auth/callback
// resolves to redirect('callback') and 404s on the missing feature flag.
Route::get('/auth/callback', [SocialAuthController::class, 'callback']);
Route::get('/auth/{provider}', [SocialAuthController::class, 'redirect'])
->where('provider', 'google|facebook|github')
->name('auth.social');
// AUTHENTICATED AREA (ALL ROLES)
Route::middleware(['auth'])->group(function () {
// DASHBOARD (ALL ROLES)
Route::get('/dashboard', [DashboardController::class, 'index'])
->middleware(['permission:view dashboard', 'active-permission:view dashboard'])
->name('dashboard');
Route::post('/dashboard/widgets', [DashboardController::class, 'saveWidgetPreferences'])
->middleware(['permission:view dashboard'])
->name('dashboard.widgets.save');
Route::post('/dashboard/widgets/reset', [DashboardController::class, 'resetWidgetPreferences'])
->middleware(['permission:view dashboard'])
->name('dashboard.widgets.reset');
// PROFILE (ALL ROLES)
Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update');
Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
// IMPERSONATE (SPECIAL CASE)
// stop is intentionally auth-only — any impersonating user can stop (the original user may not hold the permission)
Route::post('/impersonate/stop', [ImpersonateController::class, 'stop'])
->name('impersonate.stop');
Route::post('/impersonate/{user}', [ImpersonateController::class, 'start'])
->middleware('permission:impersonate users')
->name('impersonate.start');
});
// ADMIN AREA (ADMIN + SUPERADMIN)
// USER MANAGEMENT
Route::get('/users', [UserManagementController::class, 'index'])
->middleware(['auth', 'permission:view user directory', 'active-permission:view user directory'])
->name('users');
Route::middleware(['auth', 'permission:manage user directory', 'active-permission:manage user directory'])->group(function () {
Route::post('/users', [UserManagementController::class, 'store'])->name('users.store');
Route::put('/users/{id}', [UserManagementController::class, 'update'])->name('users.update');
Route::delete('/users/{id}', [UserManagementController::class, 'destroy'])->name('users.destroy');
Route::post('/users/toggle-status', [UserManagementController::class, 'toggleStatus'])->name('users.toggle-status');
Route::post('/users/{id}/restore', [UserManagementController::class, 'restore'])->name('users.restore');
Route::delete('/users/{id}/force', [UserManagementController::class, 'forceDelete'])->name('users.force-delete');
// Bulk Actions
Route::post('/users/bulk-toggle-status', [UserManagementController::class, 'bulkToggleStatus'])->name('users.bulk-toggle-status');
Route::post('/users/bulk-delete', [UserManagementController::class, 'bulkDelete'])->name('users.bulk-delete');
Route::post('/users/bulk-restore', [UserManagementController::class, 'bulkRestore'])->name('users.bulk-restore');
Route::post('/users/bulk-force-delete', [UserManagementController::class, 'bulkForceDelete'])->name('users.bulk-force-delete');
});
// SUPER ADMIN ONLY AREA
// SYSTEM CONFIG
Route::get('/system-config', [SystemConfigController::class, 'index'])
->middleware(['auth', 'menu-permission:global settings'])
->name('system-config');
Route::middleware(['auth', 'menu-permission:global settings,manage'])->group(function () {
Route::put('/system-config', [SystemConfigController::class, 'update'])->name('system-config.update');
// Tab-scoped action routes — require manage permission for the specific tab
Route::post('/system-config/test-email', [SystemConfigController::class, 'testEmail'])
->middleware('tab-permission:global settings,notifications,manage')
->name('system-config.test-email');
Route::post('/system-config/test-sap', [SystemConfigController::class, 'testSapConnection'])
->middleware('tab-permission:global settings,sap-integration,manage')
->name('system-config.test-sap');
Route::post('/system-config/test-db', [SystemConfigController::class, 'testDatabaseConnection'])
->middleware('tab-permission:global settings,monitoring,manage')
->name('system-config.test-db');
Route::post('/system-config/ai-simulate', [SystemConfigController::class, 'simulateAi'])
->middleware('tab-permission:global settings,ai-config,manage')
->name('system-config.ai-simulate');
Route::get('/system-config/ai-stats', [SystemConfigController::class, 'getAiUsageStats'])
->middleware('tab-permission:global settings,ai-config')
->name('system-config.ai-stats');
Route::post('/editor/upload', [EditorUploadController::class, 'upload'])->name('editor.upload');
});
Route::middleware(['auth', 'permission:view maintenance mode'])->group(function () {
Route::get('/maintenance-mode', [MaintenanceModeController::class, 'index'])->name('maintenance-mode');
Route::post('/maintenance-mode/broadcast', [MaintenanceModeController::class, 'broadcast'])
->middleware(['permission:manage maintenance mode'])
->name('maintenance-mode.broadcast');
});
// BACKUP & RESTORE
Route::middleware(['auth', 'permission:view backup and storage'])->prefix('backup-restore')->group(function () {
Route::get('/', [BackupRestoreController::class, 'index'])->name('backup-restore.index');
Route::get('/download', [BackupRestoreController::class, 'download'])->name('backup-restore.download');
});
Route::middleware(['auth', 'permission:manage backup and storage'])->prefix('backup-restore')->group(function () {
Route::post('/create', [BackupRestoreController::class, 'create'])->name('backup-restore.create');
Route::post('/delete', [BackupRestoreController::class, 'destroy'])->name('backup-restore.delete');
Route::post('/restore', [BackupRestoreController::class, 'restore'])->name('backup-restore.restore');
Route::post('/test-connection', [BackupRestoreController::class, 'testConnection'])->name('backup-restore.test-connection');
Route::get('/google-auth', [BackupRestoreController::class, 'googleAuth'])->name('backup-restore.google-auth');
Route::get('/google-callback', [BackupRestoreController::class, 'googleCallback'])->name('backup-restore.google-callback');
});
// AI SELF HEALING
Route::middleware(['auth', 'role:Developer', 'permission:view ai self-healing', 'active-permission:view ai self-healing'])->prefix('ai-self-healing')->group(function () {
Route::get('/', [App\Http\Controllers\SystemSettings\AiSelfHealingController::class, 'index'])->name('ai-self-healing.index');
Route::middleware(['permission:manage ai self-healing', 'active-permission:manage ai self-healing'])->group(function () {
Route::post('/update', [App\Http\Controllers\SystemSettings\AiSelfHealingController::class, 'update'])->name('ai-self-healing.update');
Route::post('/clear', [App\Http\Controllers\SystemSettings\AiSelfHealingController::class, 'clearLogs'])->name('ai-self-healing.clear');
Route::get('/log/{id}', [App\Http\Controllers\SystemSettings\AiSelfHealingController::class, 'show'])->name('ai-self-healing.show');
Route::get('/stats', [App\Http\Controllers\SystemSettings\AiSelfHealingController::class, 'stats'])->name('ai-self-healing.stats');
Route::post('/log/{id}/retry', [App\Http\Controllers\SystemSettings\AiSelfHealingController::class, 'retry'])->name('ai-self-healing.retry');
Route::post('/log/{id}/rollback', [App\Http\Controllers\SystemSettings\AiSelfHealingController::class, 'rollback'])->name('ai-self-healing.rollback');
Route::post('/simulate-error', function () {
throw new \Exception('View [dashboard-missing-xyz] not found. Please clear view cache.');
})->name('ai-self-healing.simulate');
});
});
// MOBILE SETTINGS
Route::middleware(['auth', 'menu-permission:mobile settings'])->group(function () {
Route::get('/mobile-settings', [MobileSettingController::class, 'index'])->name('mobile-settings.index');
});
Route::middleware(['auth', 'menu-permission:mobile settings,manage'])->group(function () {
Route::put('/mobile-settings', [MobileSettingController::class, 'update'])->name('mobile-settings.update');
});
Route::get('/session-manager', [SessionManagerController::class, 'index'])
->middleware(['auth', 'menu-permission:active sessions'])
->name('session-manager');
Route::get('/session-manager/stats', [SessionManagerController::class, 'getStats'])
->middleware(['auth', 'menu-permission:active sessions'])
->name('session-manager.stats');
Route::delete('/session-manager/{id}', [SessionManagerController::class, 'destroy'])
->middleware(['auth', 'menu-permission:active sessions,manage'])
->name('session-manager.terminate');
// SYSTEM MONITORING (UNIFIED)
Route::middleware(['auth', 'menu-permission:health and logs', 'active-permission:view health and logs'])->group(function () {
Route::get('/system-monitoring', [SystemMonitoringController::class, 'index'])
->name('system-monitoring');
Route::get('/api/system-stats', [SystemMonitoringController::class, 'getStats'])
->name('system-monitoring.stats');
Route::post('/system-monitoring/logs/clear', [SystemMonitoringController::class, 'clearLogs'])
->middleware(['menu-permission:health and logs,manage'])
->name('system-monitoring.logs.clear');
Route::get('/system-monitoring/logs/download', [SystemMonitoringController::class, 'downloadLogs'])
->middleware(['menu-permission:health and logs,manage'])
->name('system-monitoring.logs.download');
Route::get('/system-monitoring/logs/datatable', [SystemMonitoringController::class, 'logsDataTable'])
->name('system-monitoring.logs.datatable');
// SAP Logs
Route::get('/system-monitoring/sap-logs/datatable', [SystemMonitoringController::class, 'sapLogsDataTable'])
->name('system-monitoring.sap-logs.datatable');
Route::get('/system-monitoring/sap-logs/download', [SystemMonitoringController::class, 'downloadSapLogs'])
->middleware(['menu-permission:health and logs,manage'])
->name('system-monitoring.sap-logs.download');
Route::post('/system-monitoring/sap-logs/clear', [SystemMonitoringController::class, 'clearSapLogs'])
->middleware(['menu-permission:health and logs,manage'])
->name('system-monitoring.sap-logs.clear');
// Mobile Logs
Route::get('/system-monitoring/mobile-logs/datatable', [SystemMonitoringController::class, 'mobileLogsDataTable'])
->name('system-monitoring.mobile-logs.datatable');
Route::get('/system-monitoring/mobile-logs/download', [SystemMonitoringController::class, 'downloadMobileLogs'])
->middleware(['menu-permission:health and logs,manage'])
->name('system-monitoring.mobile-logs.download');
Route::post('/system-monitoring/mobile-logs/clear', [SystemMonitoringController::class, 'clearMobileLogs'])
->middleware(['menu-permission:health and logs,manage'])
->name('system-monitoring.mobile-logs.clear');
// Background Jobs Management
Route::get('/system-monitoring/background-jobs/datatable', [SystemMonitoringController::class, 'backgroundJobsDataTable'])
->name('system-monitoring.background-jobs.datatable');
Route::post('/system-monitoring/background-jobs/clear', [SystemMonitoringController::class, 'clearFailedJobs'])
->middleware(['menu-permission:health and logs,manage'])
->name('system-monitoring.background-jobs.clear');
Route::post('/system-monitoring/background-jobs/retry/{id?}', [SystemMonitoringController::class, 'retryFailedJob'])
->middleware(['menu-permission:health and logs,manage'])
->name('system-monitoring.background-jobs.retry');
Route::post('/system-monitoring/background-jobs/delete-failed/{id}', [SystemMonitoringController::class, 'deleteFailedJob'])
->middleware(['menu-permission:health and logs,manage'])
->name('system-monitoring.background-jobs.delete-failed');
Route::get('/system-monitoring/background-jobs/download', [SystemMonitoringController::class, 'downloadBackgroundJobs'])
->middleware(['menu-permission:health and logs,manage'])
->name('system-monitoring.background-jobs.download');
Route::post('/system-monitoring/toggle-maintenance', [SystemMonitoringController::class, 'toggleMaintenance'])
->middleware(['menu-permission:health and logs,manage'])
->name('system-monitoring.maintenance.toggle');
// AI LOG ANALYSIS
Route::middleware(['role:Developer', 'permission:view ai log analysis', 'active-permission:view ai log analysis'])->group(function () {
Route::get('/api/ai/log-analysis', [LogAnalysisController::class, 'index'])
->name('ai.log-analysis.index');
Route::post('/api/ai/log-analysis/analyze', [LogAnalysisController::class, 'analyze'])
->name('ai.log-analysis.analyze');
Route::post('/api/ai/log-analysis/clear', [LogAnalysisController::class, 'clear'])
->name('ai.log-analysis.clear');
Route::get('/api/ai/security-audit', [SystemMonitoringController::class, 'securityAudit'])
->name('ai.security-audit');
});
// GLOBAL SEARCH
Route::get('/api/global-search', GlobalSearchController::class)
->name('global-search');
// AI ASSISTANT
Route::post('/api/ai/assistant/ask', [AiAssistantController::class, 'ask'])
->middleware(['role:Developer', 'permission:use ai assistant', 'active-permission:use ai assistant'])
->name('ai.assistant.ask');
});
// ACTION HISTORY
Route::middleware(['auth', 'menu-permission:action history'])->group(function () {
Route::get('/action-logs', [ActionLogController::class, 'index'])->name('action-logs');
Route::get('/action-logs/export', [ActionLogController::class, 'export'])
->middleware(['permission:export action history'])
->name('action-logs.export');
Route::post('/action-logs/clear', [ActionLogController::class, 'clear'])
->middleware(['permission:manage action history'])
->name('action-logs.clear');
});
// ROLE MANAGEMENT
Route::get('/roles', [RoleManagementController::class, 'index'])
->middleware(['auth', 'permission:view access rights'])
->name('roles');
Route::middleware(['auth', 'permission:manage access rights'])->group(function () {
Route::post('/roles', [RoleManagementController::class, 'store'])->name('roles.store');
Route::put('/roles/{id}', [RoleManagementController::class, 'update'])->name('roles.update');
Route::delete('/roles/{id}', [RoleManagementController::class, 'destroy'])->name('roles.destroy');
Route::post('/roles/toggle-status', [RoleManagementController::class, 'toggleStatus'])->name('roles.toggle-status');
Route::post('/roles/{id}/restore', [RoleManagementController::class, 'restore'])->name('roles.restore');
Route::delete('/roles/{id}/force', [RoleManagementController::class, 'forceDelete'])->name('roles.force-delete');
// Bulk Actions
Route::post('/roles/bulk-toggle-status', [RoleManagementController::class, 'bulkToggleStatus'])->name('roles.bulk-toggle-status');
Route::post('/roles/bulk-delete', [RoleManagementController::class, 'bulkDelete'])->name('roles.bulk-delete');
Route::post('/roles/bulk-restore', [RoleManagementController::class, 'bulkRestore'])->name('roles.bulk-restore');
Route::post('/roles/bulk-force-delete', [RoleManagementController::class, 'bulkForceDelete'])->name('roles.bulk-force-delete');
});
// PERMISSION MANAGEMENT
Route::get('/permissions', [PermissionManagementController::class, 'index'])
->middleware(['auth', 'permission:view access rights'])
->name('permissions');
Route::middleware(['auth', 'permission:manage access rights'])->group(function () {
Route::post('/permissions', [PermissionManagementController::class, 'store'])->name('permissions.store');
Route::put('/permissions/{id}', [PermissionManagementController::class, 'update'])->name('permissions.update');
Route::delete('/permissions/{id}', [PermissionManagementController::class, 'destroy'])->name('permissions.destroy');
Route::post('/permissions/toggle-status', [PermissionManagementController::class, 'toggleStatus'])->name('permissions.toggle-status');
});
// NOTIFICATION CENTER
Route::get('/notification-center', [NotificationCenterController::class, 'index'])
->middleware(['auth', 'permission:view notification center'])
->name('notification-center.index');
Route::get('/notification-center/api/recent', [NotificationCenterController::class, 'recentNotifications'])
->middleware(['auth', 'permission:view notification center'])
->name('notification-center.api.recent');
Route::middleware(['auth', 'permission:view notification center'])->group(function () {
Route::patch('/notification-center/{notification}/read', [NotificationCenterController::class, 'markAsRead'])->name('notification-center.read');
Route::patch('/notification-center/read-all', [NotificationCenterController::class, 'markAllAsRead'])->name('notification-center.read-all');
Route::delete('/notification-center/clear-read', [NotificationCenterController::class, 'clearRead'])->name('notification-center.clear-read');
Route::delete('/notification-center/{notification}', [NotificationCenterController::class, 'destroy'])->name('notification-center.destroy');
});
Route::middleware(['auth', 'permission:manage notification center', 'role:Developer|Administrator'])->group(function () {
Route::post('/notification-center', [NotificationCenterController::class, 'store'])->name('notification-center.store');
});
// AUTH ROUTES
require __DIR__.'/auth.php';
+356
View File
@@ -0,0 +1,356 @@
<?php
/**
* ============================================================
*
* @project biiproject
*
* @author Andika Debi Putra
*
* @email andikadebiputra@gmail.com
*
* @website https://biiproject.com
*
* @copyright Copyright (c) 2026 Andika Debi Putra
* @license Proprietary - All Rights Reserved
*
* @version 1.0.0
*
* @created 2026-05-01
* ============================================================
*
* Unauthorized copying, modification, distribution, or use
* of this file is strictly prohibited without prior written
* permission from the author.
* ============================================================
*/
use App\Http\Controllers\AccessControl\ActionLogController;
use App\Http\Controllers\AccessControl\PermissionManagementController;
use App\Http\Controllers\AccessControl\RoleManagementController;
use App\Http\Controllers\AccessControl\UserManagementController;
use App\Http\Controllers\Admin\MobileSettingController;
use App\Http\Controllers\AI\AiAssistantController;
use App\Http\Controllers\AI\LogAnalysisController;
use App\Http\Controllers\Auth\SocialAuthController;
use App\Http\Controllers\DashboardController;
use App\Http\Controllers\ImpersonateController;
use App\Http\Controllers\LegalController;
use App\Http\Controllers\ProfileController;
use App\Http\Controllers\System\GlobalSearchController;
use App\Http\Controllers\SystemSettings\BackupRestoreController;
use App\Http\Controllers\SystemSettings\EditorUploadController;
use App\Http\Controllers\SystemSettings\MaintenanceModeController;
use App\Http\Controllers\SystemSettings\NotificationCenterController;
use App\Http\Controllers\SystemSettings\SessionManagerController;
use App\Http\Controllers\SystemSettings\SystemConfigController;
use App\Http\Controllers\SystemSettings\SystemMonitoringController;
use App\Services\SystemConfig\SystemConfigService;
use Illuminate\Support\Facades\Route;
// Public homepage
Route::get('/', function () {
if (! app(SystemConfigService::class)->get('enable_landing_page', true)) {
return redirect()->route('login');
}
return view('welcome');
})->name('homepage');
Route::get('/public-config', [SystemConfigController::class, 'publicConfig'])->name('system-config.public');
// LEGAL & CONTENT PAGES (UU PDP COMPLIANCE)
Route::get('/legal/re-agree', [LegalController::class, 'reAgree'])
->middleware('auth')
->name('legal.re-agree');
Route::post('/legal/re-agree', [LegalController::class, 'postReAgree'])
->middleware('auth')
->name('legal.re-agree.post');
Route::get('/legal/{type}', [LegalController::class, 'show'])->name('legal.show');
// UNIFIED SOCIAL OAUTH
// callback must come BEFORE the {provider} wildcard, otherwise /auth/callback
// resolves to redirect('callback') and 404s on the missing feature flag.
Route::get('/auth/callback', [SocialAuthController::class, 'callback']);
Route::get('/auth/{provider}', [SocialAuthController::class, 'redirect'])
->where('provider', 'google|facebook|github')
->name('auth.social');
// AUTHENTICATED AREA (ALL ROLES)
Route::middleware(['auth'])->group(function () {
// DASHBOARD (ALL ROLES)
Route::get('/dashboard', [DashboardController::class, 'index'])
->middleware(['permission:view dashboard', 'active-permission:view dashboard'])
->name('dashboard');
Route::post('/dashboard/widgets', [DashboardController::class, 'saveWidgetPreferences'])
->middleware(['permission:view dashboard'])
->name('dashboard.widgets.save');
// PROFILE (ALL ROLES)
Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update');
Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
// IMPERSONATE (SPECIAL CASE)
Route::post('/impersonate/stop', [ImpersonateController::class, 'stop'])
->name('impersonate.stop');
Route::post('/impersonate/{user}', [ImpersonateController::class, 'start'])
->middleware('permission:impersonate users')
->name('impersonate.start');
});
// ADMIN AREA (ADMIN + SUPERADMIN)
// USER MANAGEMENT
Route::get('/users', [UserManagementController::class, 'index'])
->middleware(['auth', 'permission:view user directory', 'active-permission:view user directory'])
->name('users');
Route::middleware(['auth', 'permission:manage user directory', 'active-permission:manage user directory'])->group(function () {
Route::post('/users', [UserManagementController::class, 'store'])->name('users.store');
Route::put('/users/{id}', [UserManagementController::class, 'update'])->name('users.update');
Route::delete('/users/{id}', [UserManagementController::class, 'destroy'])->name('users.destroy');
Route::post('/users/toggle-status', [UserManagementController::class, 'toggleStatus'])->name('users.toggle-status');
Route::post('/users/{id}/restore', [UserManagementController::class, 'restore'])->name('users.restore');
Route::delete('/users/{id}/force', [UserManagementController::class, 'forceDelete'])->name('users.force-delete');
// Bulk Actions
Route::post('/users/bulk-toggle-status', [UserManagementController::class, 'bulkToggleStatus'])->name('users.bulk-toggle-status');
Route::post('/users/bulk-delete', [UserManagementController::class, 'bulkDelete'])->name('users.bulk-delete');
Route::post('/users/bulk-restore', [UserManagementController::class, 'bulkRestore'])->name('users.bulk-restore');
Route::post('/users/bulk-force-delete', [UserManagementController::class, 'bulkForceDelete'])->name('users.bulk-force-delete');
});
// SUPER ADMIN ONLY AREA
// SYSTEM CONFIG
Route::get('/system-config', [SystemConfigController::class, 'index'])
->middleware(['auth', 'permission:view global settings'])
->name('system-config');
Route::middleware(['auth', 'permission:manage global settings'])->group(function () {
Route::put('/system-config', [SystemConfigController::class, 'update'])->name('system-config.update');
// Tab-scoped action routes — require manage permission for the specific tab
Route::post('/system-config/test-email', [SystemConfigController::class, 'testEmail'])
->middleware('tab-permission:global settings,notification,manage')
->name('system-config.test-email');
Route::post('/system-config/test-sap', [SystemConfigController::class, 'testSapConnection'])
->middleware('tab-permission:global settings,sap-integration,manage')
->name('system-config.test-sap');
Route::post('/system-config/test-db', [SystemConfigController::class, 'testDatabaseConnection'])
->middleware('tab-permission:global settings,monitoring,manage')
->name('system-config.test-db');
Route::post('/system-config/ai-simulate', [SystemConfigController::class, 'simulateAi'])
->middleware('tab-permission:global settings,ai-config,manage')
->name('system-config.ai-simulate');
Route::get('/system-config/ai-stats', [SystemConfigController::class, 'getAiUsageStats'])
->middleware('tab-permission:global settings,ai-config')
->name('system-config.ai-stats');
Route::post('/editor/upload', [EditorUploadController::class, 'upload'])->name('editor.upload');
});
Route::middleware(['auth', 'permission:view maintenance mode'])->group(function () {
Route::get('/maintenance-mode', [MaintenanceModeController::class, 'index'])->name('maintenance-mode');
Route::post('/maintenance-mode/broadcast', [MaintenanceModeController::class, 'broadcast'])
->middleware(['permission:manage maintenance mode'])
->name('maintenance-mode.broadcast');
});
// BACKUP & RESTORE
Route::middleware(['auth', 'permission:view backup and storage'])->prefix('backup-restore')->group(function () {
Route::get('/', [BackupRestoreController::class, 'index'])->name('backup-restore.index');
Route::get('/download', [BackupRestoreController::class, 'download'])->name('backup-restore.download');
});
Route::middleware(['auth', 'permission:manage backup and storage'])->prefix('backup-restore')->group(function () {
Route::post('/create', [BackupRestoreController::class, 'create'])->name('backup-restore.create');
Route::post('/delete', [BackupRestoreController::class, 'destroy'])->name('backup-restore.delete');
Route::post('/restore', [BackupRestoreController::class, 'restore'])->name('backup-restore.restore');
Route::post('/test-connection', [BackupRestoreController::class, 'testConnection'])->name('backup-restore.test-connection');
Route::get('/google-auth', [BackupRestoreController::class, 'googleAuth'])->name('backup-restore.google-auth');
Route::get('/google-callback', [BackupRestoreController::class, 'googleCallback'])->name('backup-restore.google-callback');
});
// AI SELF HEALING
Route::middleware(['auth', 'role:Developer', 'permission:view ai self-healing', 'active-permission:view ai self-healing'])->prefix('ai-self-healing')->group(function () {
Route::get('/', [App\Http\Controllers\SystemSettings\AiSelfHealingController::class, 'index'])->name('ai-self-healing.index');
Route::middleware(['permission:manage ai self-healing', 'active-permission:manage ai self-healing'])->group(function () {
Route::post('/update', [App\Http\Controllers\SystemSettings\AiSelfHealingController::class, 'update'])->name('ai-self-healing.update');
Route::post('/clear', [App\Http\Controllers\SystemSettings\AiSelfHealingController::class, 'clearLogs'])->name('ai-self-healing.clear');
Route::get('/log/{id}', [App\Http\Controllers\SystemSettings\AiSelfHealingController::class, 'show'])->name('ai-self-healing.show');
Route::get('/stats', [App\Http\Controllers\SystemSettings\AiSelfHealingController::class, 'stats'])->name('ai-self-healing.stats');
Route::post('/log/{id}/retry', [App\Http\Controllers\SystemSettings\AiSelfHealingController::class, 'retry'])->name('ai-self-healing.retry');
Route::post('/log/{id}/rollback', [App\Http\Controllers\SystemSettings\AiSelfHealingController::class, 'rollback'])->name('ai-self-healing.rollback');
Route::post('/simulate-error', function () {
throw new \Exception('View [dashboard-missing-xyz] not found. Please clear view cache.');
})->name('ai-self-healing.simulate');
});
});
// MOBILE SETTINGS
Route::middleware(['auth', 'permission:view mobile settings'])->group(function () {
Route::get('/mobile-settings', [MobileSettingController::class, 'index'])->name('mobile-settings.index');
});
Route::middleware(['auth', 'permission:manage mobile settings'])->group(function () {
Route::put('/mobile-settings', [MobileSettingController::class, 'update'])->name('mobile-settings.update');
});
Route::get('/session-manager', [SessionManagerController::class, 'index'])
->middleware(['auth', 'permission:view active sessions'])
->name('session-manager');
Route::get('/session-manager/stats', [SessionManagerController::class, 'getStats'])
->middleware(['auth', 'permission:view active sessions'])
->name('session-manager.stats');
Route::delete('/session-manager/{id}', [SessionManagerController::class, 'destroy'])
->middleware(['auth', 'permission:manage active sessions'])
->name('session-manager.terminate');
// SYSTEM MONITORING (UNIFIED)
Route::middleware(['auth'])->group(function () {
Route::get('/system-monitoring', [SystemMonitoringController::class, 'index'])
->name('system-monitoring');
Route::get('/api/system-stats', [SystemMonitoringController::class, 'getStats'])
->name('system-monitoring.stats');
Route::post('/system-monitoring/logs/clear', [SystemMonitoringController::class, 'clearLogs'])
->middleware(['permission:manage health and logs'])
->name('system-monitoring.logs.clear');
Route::get('/system-monitoring/logs/download', [SystemMonitoringController::class, 'downloadLogs'])
->middleware(['permission:manage health and logs'])
->name('system-monitoring.logs.download');
Route::get('/system-monitoring/logs/datatable', [SystemMonitoringController::class, 'logsDataTable'])
->name('system-monitoring.logs.datatable');
// SAP Logs
Route::get('/system-monitoring/sap-logs/datatable', [SystemMonitoringController::class, 'sapLogsDataTable'])
->name('system-monitoring.sap-logs.datatable');
Route::get('/system-monitoring/sap-logs/download', [SystemMonitoringController::class, 'downloadSapLogs'])
->middleware(['permission:manage health and logs'])
->name('system-monitoring.sap-logs.download');
Route::post('/system-monitoring/sap-logs/clear', [SystemMonitoringController::class, 'clearSapLogs'])
->middleware(['permission:manage health and logs'])
->name('system-monitoring.sap-logs.clear');
// Mobile Logs
Route::get('/system-monitoring/mobile-logs/datatable', [SystemMonitoringController::class, 'mobileLogsDataTable'])
->name('system-monitoring.mobile-logs.datatable');
Route::get('/system-monitoring/mobile-logs/download', [SystemMonitoringController::class, 'downloadMobileLogs'])
->middleware(['permission:manage health and logs'])
->name('system-monitoring.mobile-logs.download');
Route::post('/system-monitoring/mobile-logs/clear', [SystemMonitoringController::class, 'clearMobileLogs'])
->middleware(['permission:manage health and logs'])
->name('system-monitoring.mobile-logs.clear');
// Background Jobs Management
Route::get('/system-monitoring/background-jobs/datatable', [SystemMonitoringController::class, 'backgroundJobsDataTable'])
->name('system-monitoring.background-jobs.datatable');
Route::post('/system-monitoring/background-jobs/clear', [SystemMonitoringController::class, 'clearFailedJobs'])
->middleware(['permission:manage health and logs'])
->name('system-monitoring.background-jobs.clear');
Route::post('/system-monitoring/background-jobs/retry/{id?}', [SystemMonitoringController::class, 'retryFailedJob'])
->middleware(['permission:manage health and logs'])
->name('system-monitoring.background-jobs.retry');
Route::post('/system-monitoring/background-jobs/delete-failed/{id}', [SystemMonitoringController::class, 'deleteFailedJob'])
->middleware(['permission:manage health and logs'])
->name('system-monitoring.background-jobs.delete-failed');
Route::get('/system-monitoring/background-jobs/download', [SystemMonitoringController::class, 'downloadBackgroundJobs'])
->middleware(['permission:manage health and logs'])
->name('system-monitoring.background-jobs.download');
Route::post('/system-monitoring/toggle-maintenance', [SystemMonitoringController::class, 'toggleMaintenance'])
->middleware(['permission:manage health and logs'])
->name('system-monitoring.maintenance.toggle');
// AI LOG ANALYSIS
Route::middleware(['role:Developer', 'permission:view ai log analysis', 'active-permission:view ai log analysis'])->group(function () {
Route::get('/api/ai/log-analysis', [LogAnalysisController::class, 'index'])
->name('ai.log-analysis.index');
Route::post('/api/ai/log-analysis/analyze', [LogAnalysisController::class, 'analyze'])
->name('ai.log-analysis.analyze');
Route::post('/api/ai/log-analysis/clear', [LogAnalysisController::class, 'clear'])
->name('ai.log-analysis.clear');
Route::get('/api/ai/security-audit', [SystemMonitoringController::class, 'securityAudit'])
->name('ai.security-audit');
});
// GLOBAL SEARCH
Route::get('/api/global-search', GlobalSearchController::class)
->name('global-search');
// AI ASSISTANT
Route::post('/api/ai/assistant/ask', [AiAssistantController::class, 'ask'])
->middleware(['role:Developer', 'permission:use ai assistant', 'active-permission:use ai assistant'])
->name('ai.assistant.ask');
});
// ACTION HISTORY
Route::middleware(['auth', 'permission:view action history'])->group(function () {
Route::get('/action-logs', [ActionLogController::class, 'index'])->name('action-logs');
Route::get('/action-logs/export', [ActionLogController::class, 'export'])->name('action-logs.export');
Route::post('/action-logs/clear', [ActionLogController::class, 'clear'])
->middleware(['permission:manage action history'])
->name('action-logs.clear');
});
// ROLE MANAGEMENT
Route::get('/roles', [RoleManagementController::class, 'index'])
->middleware(['auth', 'permission:view access rights'])
->name('roles');
Route::middleware(['auth', 'permission:manage access rights'])->group(function () {
Route::post('/roles', [RoleManagementController::class, 'store'])->name('roles.store');
Route::put('/roles/{id}', [RoleManagementController::class, 'update'])->name('roles.update');
Route::delete('/roles/{id}', [RoleManagementController::class, 'destroy'])->name('roles.destroy');
Route::post('/roles/toggle-status', [RoleManagementController::class, 'toggleStatus'])->name('roles.toggle-status');
Route::post('/roles/{id}/restore', [RoleManagementController::class, 'restore'])->name('roles.restore');
Route::delete('/roles/{id}/force', [RoleManagementController::class, 'forceDelete'])->name('roles.force-delete');
// Bulk Actions
Route::post('/roles/bulk-toggle-status', [RoleManagementController::class, 'bulkToggleStatus'])->name('roles.bulk-toggle-status');
Route::post('/roles/bulk-delete', [RoleManagementController::class, 'bulkDelete'])->name('roles.bulk-delete');
Route::post('/roles/bulk-restore', [RoleManagementController::class, 'bulkRestore'])->name('roles.bulk-restore');
Route::post('/roles/bulk-force-delete', [RoleManagementController::class, 'bulkForceDelete'])->name('roles.bulk-force-delete');
});
// PERMISSION MANAGEMENT
Route::get('/permissions', [PermissionManagementController::class, 'index'])
->middleware(['auth', 'permission:view access rights'])
->name('permissions');
Route::middleware(['auth', 'permission:manage access rights'])->group(function () {
Route::post('/permissions', [PermissionManagementController::class, 'store'])->name('permissions.store');
Route::put('/permissions/{id}', [PermissionManagementController::class, 'update'])->name('permissions.update');
Route::delete('/permissions/{id}', [PermissionManagementController::class, 'destroy'])->name('permissions.destroy');
Route::post('/permissions/toggle-status', [PermissionManagementController::class, 'toggleStatus'])->name('permissions.toggle-status');
});
// NOTIFICATION CENTER
Route::get('/notification-center', [NotificationCenterController::class, 'index'])
->middleware(['auth', 'permission:view notification center'])
->name('notification-center.index');
Route::get('/notification-center/api/recent', [NotificationCenterController::class, 'recentNotifications'])
->middleware(['auth', 'permission:view notification center'])
->name('notification-center.api.recent');
Route::middleware(['auth', 'permission:view notification center'])->group(function () {
Route::patch('/notification-center/{notification}/read', [NotificationCenterController::class, 'markAsRead'])->name('notification-center.read');
Route::patch('/notification-center/read-all', [NotificationCenterController::class, 'markAllAsRead'])->name('notification-center.read-all');
Route::delete('/notification-center/clear-read', [NotificationCenterController::class, 'clearRead'])->name('notification-center.clear-read');
Route::delete('/notification-center/{notification}', [NotificationCenterController::class, 'destroy'])->name('notification-center.destroy');
});
Route::middleware(['auth', 'permission:manage notification center', 'role:Developer|Administrator'])->group(function () {
Route::post('/notification-center', [NotificationCenterController::class, 'store'])->name('notification-center.store');
});
// AUTH ROUTES
require __DIR__.'/auth.php';