use BookStack\Api\ApiDocsController;
use BookStack\Api\UserApiTokenController;
use BookStack\App\HomeController;
+use BookStack\App\MetaController;
use BookStack\Entities\Controllers as EntityControllers;
use BookStack\Http\Middleware\VerifyCsrfToken;
use BookStack\Permissions\PermissionsController;
use Illuminate\View\Middleware\ShareErrorsFromSession;
Route::get('/status', [SettingControllers\StatusController::class, 'show']);
-Route::get('/robots.txt', [HomeController::class, 'robots']);
-Route::get('/favicon.ico', [HomeController::class, 'favicon']);
-Route::get('/manifest.json', [HomeController::class, 'pwaManifest']);
+Route::get('/robots.txt', [MetaController::class, 'robots']);
+Route::get('/favicon.ico', [MetaController::class, 'favicon']);
+Route::get('/manifest.json', [MetaController::class, 'pwaManifest']);
+Route::get('/licenses', [MetaController::class, 'licenses']);
+Route::get('/opensearch.xml', [MetaController::class, 'opensearch']);
// Authenticated routes...
Route::middleware('auth')->group(function () {
Route::get('/search/chapter/{bookId}', [SearchController::class, 'searchChapter']);
Route::get('/search/entity/siblings', [SearchController::class, 'searchSiblings']);
Route::get('/search/entity-selector', [SearchController::class, 'searchForSelector']);
+ Route::get('/search/entity-selector-templates', [SearchController::class, 'templatesForSelector']);
Route::get('/search/suggest', [SearchController::class, 'searchSuggestions']);
// User Search
Route::get('/register/confirm/awaiting', [AccessControllers\ConfirmEmailController::class, 'showAwaiting']);
Route::post('/register/confirm/resend', [AccessControllers\ConfirmEmailController::class, 'resend']);
Route::get('/register/confirm/{token}', [AccessControllers\ConfirmEmailController::class, 'showAcceptForm']);
-Route::post('/register/confirm/accept', [AccessControllers\ConfirmEmailController::class, 'confirm']);
-Route::post('/register', [AccessControllers\RegisterController::class, 'postRegister']);
+Route::post('/register/confirm/accept', [AccessControllers\ConfirmEmailController::class, 'confirm'])->middleware('throttle:public');
+Route::post('/register', [AccessControllers\RegisterController::class, 'postRegister'])->middleware('throttle:public');
// SAML routes
Route::post('/saml2/login', [AccessControllers\Saml2Controller::class, 'login']);
// OIDC routes
Route::post('/oidc/login', [AccessControllers\OidcController::class, 'login']);
Route::get('/oidc/callback', [AccessControllers\OidcController::class, 'callback']);
+Route::post('/oidc/logout', [AccessControllers\OidcController::class, 'logout']);
// User invitation routes
-Route::get('/register/invite/{token}', [AccessControllers\UserInviteController::class, 'showSetPassword']);
-Route::post('/register/invite/{token}', [AccessControllers\UserInviteController::class, 'setPassword']);
+Route::get('/register/invite/{token}', [AccessControllers\UserInviteController::class, 'showSetPassword'])->middleware('throttle:public');
+Route::post('/register/invite/{token}', [AccessControllers\UserInviteController::class, 'setPassword'])->middleware('throttle:public');
// Password reset link request routes
Route::get('/password/email', [AccessControllers\ForgotPasswordController::class, 'showLinkRequestForm']);
-Route::post('/password/email', [AccessControllers\ForgotPasswordController::class, 'sendResetLinkEmail']);
+Route::post('/password/email', [AccessControllers\ForgotPasswordController::class, 'sendResetLinkEmail'])->middleware('throttle:public');
// Password reset routes
Route::get('/password/reset/{token}', [AccessControllers\ResetPasswordController::class, 'showResetForm']);
-Route::post('/password/reset', [AccessControllers\ResetPasswordController::class, 'reset']);
+Route::post('/password/reset', [AccessControllers\ResetPasswordController::class, 'reset'])->middleware('throttle:public');
// Metadata routes
Route::view('/help/wysiwyg', 'help.wysiwyg');
-Route::fallback([HomeController::class, 'notFound'])->name('fallback');
+Route::fallback([MetaController::class, 'notFound'])->name('fallback');