Files
jabali-panel/routes/web.php
2026-02-02 03:11:45 +02:00

167 lines
5.9 KiB
PHP

<?php
use App\Http\Controllers\AutoconfigController;
use App\Http\Controllers\AutoDiscoverController;
use App\Http\Controllers\BackupDownloadController;
use App\Http\Controllers\ImpersonationController;
use App\Http\Controllers\LanguageController;
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
return redirect('/jabali-panel');
});
Route::get('/login', function () {
return redirect('/jabali-panel/login');
})->name('login');
Route::get('/register', function () {
return redirect('/jabali-panel/register');
});
/*
|--------------------------------------------------------------------------
| Two-Factor Authentication Challenge
|--------------------------------------------------------------------------
*/
Route::get('/jabali-panel/two-factor-challenge', \App\Filament\Jabali\Pages\Auth\TwoFactorChallenge::class)
->middleware('web')
->name('filament.jabali.auth.two-factor-challenge');
Route::get('/jabali-admin/two-factor-challenge', \App\Filament\Admin\Pages\Auth\TwoFactorChallenge::class)
->middleware('web')
->name('filament.admin.auth.two-factor-challenge');
/*
|--------------------------------------------------------------------------
| Email Auto-Configuration Routes
|--------------------------------------------------------------------------
|
| These routes handle automatic email client configuration for:
| - Microsoft Outlook (Autodiscover)
| - Mozilla Thunderbird (Autoconfig)
| - iOS/macOS Mail (Mobile Config Profile)
|
*/
// Microsoft Autodiscover (Outlook, Windows Mail, mobile Exchange clients)
Route::match(['get', 'post'], '/autodiscover/autodiscover.xml', [AutoDiscoverController::class, 'discover']);
Route::match(['get', 'post'], '/Autodiscover/Autodiscover.xml', [AutoDiscoverController::class, 'discover']);
Route::match(['get', 'post'], '/AutoDiscover/AutoDiscover.xml', [AutoDiscoverController::class, 'discover']);
// Mozilla Autoconfig (Thunderbird, K-9 Mail, other standards-compliant clients)
Route::get('/mail/config-v1.1.xml', [AutoconfigController::class, 'config']);
Route::get('/.well-known/autoconfig/mail/config-v1.1.xml', [AutoconfigController::class, 'config']);
Route::get('/autoconfig/{domain}/config-v1.1.xml', [AutoconfigController::class, 'configForDomain']);
// iOS/macOS Mobile Configuration Profile
Route::get('/mail/profile/{domain}', [AutoconfigController::class, 'mobileProfile']);
/*
|--------------------------------------------------------------------------
| Admin Impersonation
|--------------------------------------------------------------------------
|
| Allows administrators to login as a user using a one-time token.
| Opens in a new tab with a separate session.
|
*/
Route::get('/impersonate/start/{user}', [ImpersonationController::class, 'start'])
->middleware('auth:admin')
->name('impersonate.start');
Route::get('/impersonate/stop', [ImpersonationController::class, 'stop'])
->middleware('auth:web')
->name('impersonate.stop');
Route::get('/impersonate/{token}', [ImpersonationController::class, 'impersonate'])
->name('impersonate');
/*
|--------------------------------------------------------------------------
| User Panel Backup Download
|--------------------------------------------------------------------------
*/
Route::get('/jabali-panel/backup-download', [BackupDownloadController::class, 'download'])
->middleware(['web', 'auth'])
->name('filament.jabali.pages.backup-download');
/*
|--------------------------------------------------------------------------
| Admin Panel Backup Download
|--------------------------------------------------------------------------
*/
Route::get('/jabali-admin/backup-download', [BackupDownloadController::class, 'adminDownload'])
->middleware(['web', 'auth'])
->name('filament.admin.pages.backup-download');
/*
|--------------------------------------------------------------------------
| Language Switcher
|--------------------------------------------------------------------------
*/
Route::get('/language/{locale}', [LanguageController::class, 'switch'])
->name('language.switch');
/*
|--------------------------------------------------------------------------
| Webmail SSO
|--------------------------------------------------------------------------
|
| Generates SSO token and redirects to Roundcube webmail.
| Opens in new tab, so uses signed URL for security.
|
*/
Route::get('/webmail-sso/{mailbox}', function (\App\Models\Mailbox $mailbox) {
// Verify user owns this mailbox
if ($mailbox->user_id !== auth()->id()) {
abort(403);
}
$password = $mailbox->plain_password;
if ($password) {
// Create SSO token for auto-login
$token = bin2hex(random_bytes(32));
$tokenData = [
'email' => $mailbox->email,
'password' => $password,
'expires' => time() + 300,
];
file_put_contents('/tmp/roundcube_sso_'.$token, json_encode($tokenData));
chmod('/tmp/roundcube_sso_'.$token, 0600);
return redirect('/webmail/jabali-sso.php?token='.$token);
}
$hasPasswordHash = ! empty($mailbox->password_hash);
$masterConfigPath = '/etc/jabali/roundcube-sso.conf';
if ($hasPasswordHash && file_exists($masterConfigPath)) {
$token = bin2hex(random_bytes(32));
$tokenData = [
'login_as' => $mailbox->email,
'use_master' => true,
'expires' => time() + 300,
];
file_put_contents('/tmp/roundcube_sso_'.$token, json_encode($tokenData));
chmod('/tmp/roundcube_sso_'.$token, 0600);
return redirect('/webmail/jabali-sso.php?token='.$token);
}
// No stored password - show message about needing to reset password first
// This happens after restore when password_encrypted isn't set
return response()->view('webmail-password-required', [
'email' => $mailbox->email,
'mailbox_id' => $mailbox->id,
'has_password_hash' => $hasPasswordHash,
]);
})->middleware(['web', 'auth'])->name('webmail.sso');