From 5fb0efa4e8fc746eb849fa27843e1a0a2addab6e Mon Sep 17 00:00:00 2001 From: Dominik Hebeler <dominik@suma-ev.de> Date: Fri, 20 Jan 2023 13:23:13 +0100 Subject: [PATCH] replaced basic auth with openid-connect --- .gitlab/deployment_scripts/update_secret.sh | 1 - chart/templates/deployment.yaml | 3 - .../app/Http/Controllers/AdminInterface.php | 4 +- metager/app/Http/Kernel.php | 35 ++-- metager/composer.json | 3 +- metager/composer.lock | 59 +++++- metager/config/auth.php | 8 +- metager/config/keycloak-web.php | 76 +++++++ metager/config/metager/metager.php | 4 - metager/database/seeders/DatabaseSeeder.php | 4 +- metager/database/seeders/UsersSeeder.php | 27 --- metager/routes/cookie.php | 11 +- metager/routes/session.php | 52 +++++ metager/routes/web.php | 194 ++++++++---------- 14 files changed, 312 insertions(+), 169 deletions(-) create mode 100644 metager/config/keycloak-web.php delete mode 100644 metager/database/seeders/UsersSeeder.php diff --git a/.gitlab/deployment_scripts/update_secret.sh b/.gitlab/deployment_scripts/update_secret.sh index 716b6e496..d4ba65939 100755 --- a/.gitlab/deployment_scripts/update_secret.sh +++ b/.gitlab/deployment_scripts/update_secret.sh @@ -14,7 +14,6 @@ kubectl -n $KUBE_NAMESPACE create secret generic ${HELM_RELEASE_NAME} \ --from-file=${BLACKLIST_DESCRIPTION_URL} \ --from-file=${BLACKLIST_DOMAINS} \ --from-file=${BLACKLIST_URL} \ - --from-file=${USERSEEDER} \ --dry-run=client \ --save-config \ -o yaml | \ diff --git a/chart/templates/deployment.yaml b/chart/templates/deployment.yaml index 9960163f7..abadeb5a5 100644 --- a/chart/templates/deployment.yaml +++ b/chart/templates/deployment.yaml @@ -75,9 +75,6 @@ spec: - name: secrets mountPath: /metager/metager_app/config/blacklistDescriptionUrl.txt subPath: BLACKLIST_DESCRIPTION_URL - - name: secrets - mountPath: /metager/metager_app/database/seeds/UsersSeeder.php - subPath: USERSEEDER - name: mglogs-persistent-storage mountPath: /metager/metager_app/storage/logs/metager readOnly: false diff --git a/metager/app/Http/Controllers/AdminInterface.php b/metager/app/Http/Controllers/AdminInterface.php index c373937e0..62efb2107 100644 --- a/metager/app/Http/Controllers/AdminInterface.php +++ b/metager/app/Http/Controllers/AdminInterface.php @@ -17,8 +17,6 @@ class AdminInterface extends Controller public function count(Request $request) { - - if ($request->input('out', 'web') === "web") { $days = $request->input("days", 28); $interface = $request->input('interface', 'all'); @@ -255,4 +253,4 @@ class AdminInterface extends Controller } return null; } -} +} \ No newline at end of file diff --git a/metager/app/Http/Kernel.php b/metager/app/Http/Kernel.php index e87e67928..dd37d8cb4 100644 --- a/metager/app/Http/Kernel.php +++ b/metager/app/Http/Kernel.php @@ -15,14 +15,14 @@ class Kernel extends HttpKernel * @var array */ protected $middleware = [ - \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class, - \Illuminate\Http\Middleware\HandleCors::class, - \App\Http\Middleware\TrustProxies::class, - \App\Http\Middleware\LocalizationRedirect::class, - \App\Http\Middleware\PreventRequestsDuringMaintenance::class, - \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, - \App\Http\Middleware\TrimStrings::class, - \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, + \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class, + \Illuminate\Http\Middleware\HandleCors::class, + \App\Http\Middleware\TrustProxies::class, + \App\Http\Middleware\LocalizationRedirect::class, + \App\Http\Middleware\PreventRequestsDuringMaintenance::class, + \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, + \App\Http\Middleware\TrimStrings::class, + \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, ]; /** @@ -32,26 +32,29 @@ class Kernel extends HttpKernel */ protected $middlewareGroups = [ 'web' => [ - \Illuminate\Routing\Middleware\SubstituteBindings::class, + \Illuminate\Routing\Middleware\SubstituteBindings::class, ], 'humanverification_routes' => [ - \Illuminate\Routing\Middleware\SubstituteBindings::class, - \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, + \Illuminate\Routing\Middleware\SubstituteBindings::class, + \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, ], 'api' => [ 'throttle:api', - \Illuminate\Routing\Middleware\SubstituteBindings::class, + \Illuminate\Routing\Middleware\SubstituteBindings::class, ], 'enableCookies' => [ - \Illuminate\Routing\Middleware\SubstituteBindings::class, - \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, + \Illuminate\Routing\Middleware\SubstituteBindings::class, + \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, ], 'session' => [ - \Illuminate\Routing\Middleware\SubstituteBindings::class, + \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, + \Illuminate\Session\Middleware\StartSession::class, + \Illuminate\View\Middleware\ShareErrorsFromSession::class, + \Illuminate\Routing\Middleware\SubstituteBindings::class, ], ]; @@ -80,4 +83,4 @@ class Kernel extends HttpKernel 'removekey' => \App\Http\Middleware\RemoveKey::class, 'allow-local-only' => AllowLocalOnly::class, ]; -} +} \ No newline at end of file diff --git a/metager/composer.json b/metager/composer.json index 7645fa407..b08b8ddb2 100644 --- a/metager/composer.json +++ b/metager/composer.json @@ -19,7 +19,8 @@ "mews/captcha": "^3.2.7", "promphp/prometheus_client_php": "^2.6.0", "symfony/dom-crawler": "^6.0", - "tio/laravel": "^1.20" + "tio/laravel": "^1.20", + "vizir/laravel-keycloak-web-guard": "^3.0" }, "require-dev": { "barryvdh/laravel-ide-helper": "^2.12", diff --git a/metager/composer.lock b/metager/composer.lock index b39915536..a20eaf0f8 100644 --- a/metager/composer.lock +++ b/metager/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "bef46997991684e2585a33612e100f13", + "content-hash": "1061199e4285925f49b2e6d4cb4b7a4d", "packages": [ { "name": "brick/math", @@ -5690,6 +5690,63 @@ }, "time": "2022-06-16T14:31:10+00:00" }, + { + "name": "vizir/laravel-keycloak-web-guard", + "version": "v3.0.1", + "source": { + "type": "git", + "url": "https://github.com/mariovalney/laravel-keycloak-web-guard.git", + "reference": "eb30758e4479aadde2a784594e18bf54fe6ae07a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mariovalney/laravel-keycloak-web-guard/zipball/eb30758e4479aadde2a784594e18bf54fe6ae07a", + "reference": "eb30758e4479aadde2a784594e18bf54fe6ae07a", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "^6.5|^7.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Vizir\\KeycloakWebGuard\\KeycloakWebGuardServiceProvider" + ], + "aliases": { + "KeycloakWeb": "Vizir\\KeycloakWebGuard\\Facades\\KeycloakWeb" + } + } + }, + "autoload": { + "psr-4": { + "Vizir\\KeycloakWebGuard\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mário Valney", + "email": "mariovalney@gmail.com" + } + ], + "description": "Simple Keycloak Guard to Laravel Web Routes", + "homepage": "https://github.com/Vizir/laravel-keycloak-web-guard", + "keywords": [ + "Authentication", + "jwt", + "keycloak", + "laravel" + ], + "support": { + "issues": "https://github.com/mariovalney/laravel-keycloak-web-guard/issues", + "source": "https://github.com/mariovalney/laravel-keycloak-web-guard/tree/v3.0.1" + }, + "time": "2022-09-28T17:31:42+00:00" + }, { "name": "vlucas/phpdotenv", "version": "v5.4.1", diff --git a/metager/config/auth.php b/metager/config/auth.php index 781750102..10c22fc52 100644 --- a/metager/config/auth.php +++ b/metager/config/auth.php @@ -37,7 +37,7 @@ return [ 'guards' => [ 'web' => [ - 'driver' => 'session', + 'driver' => 'keycloak-web', 'provider' => 'users', ], @@ -66,8 +66,8 @@ return [ 'providers' => [ 'users' => [ - 'driver' => 'eloquent', - 'model' => App\User::class, + 'driver' => 'keycloak-users', + 'model' => Vizir\KeycloakWebGuard\Models\KeycloakUser::class, ], // 'users' => [ @@ -99,4 +99,4 @@ return [ ], ], -]; +]; \ No newline at end of file diff --git a/metager/config/keycloak-web.php b/metager/config/keycloak-web.php new file mode 100644 index 000000000..47af73833 --- /dev/null +++ b/metager/config/keycloak-web.php @@ -0,0 +1,76 @@ +<?php + +return [ + /** + * Keycloak Url + * + * Generally https://your-server.com/auth + */ + 'base_url' => env('KEYCLOAK_BASE_URL', ''), + + /** + * Keycloak Realm + * + * Default is master + */ + 'realm' => env('KEYCLOAK_REALM', 'master'), + + /** + * The Keycloak Server realm public key (string). + * + * @see Keycloak >> Realm Settings >> Keys >> RS256 >> Public Key + */ + 'realm_public_key' => env('KEYCLOAK_REALM_PUBLIC_KEY', null), + + /** + * Keycloak Client ID + * + * @see Keycloak >> Clients >> Installation + */ + 'client_id' => env('KEYCLOAK_CLIENT_ID', null), + + /** + * Keycloak Client Secret + * + * @see Keycloak >> Clients >> Installation + */ + 'client_secret' => env('KEYCLOAK_CLIENT_SECRET', null), + + /** + * We can cache the OpenId Configuration + * The result from /realms/{realm-name}/.well-known/openid-configuration + * + * @link https://www.keycloak.org/docs/3.2/securing_apps/topics/oidc/oidc-generic.html + */ + 'cache_openid' => env('KEYCLOAK_CACHE_OPENID', false), + + /** + * Page to redirect after callback if there's no "intent" + * + * @see Vizir\KeycloakWebGuard\Controllers\AuthController::callback() + */ + 'redirect_url' => '/admin', + + /** + * The routes for authenticate + * + * Accept a string as the first parameter of route() or false to disable the route. + * + * The routes will receive the name "keycloak.{route}" and login/callback are required. + * So, if you make it false, you shoul register a named 'keycloak.login' route and extend + * the Vizir\KeycloakWebGuard\Controllers\AuthController controller. + */ + 'routes' => [ + 'login' => false, + 'logout' => false, + 'register' => false, + 'callback' => false, + ], + + /** + * GuzzleHttp Client options + * + * @link http://docs.guzzlephp.org/en/stable/request-options.html + */ + 'guzzle_options' => [], +]; \ No newline at end of file diff --git a/metager/config/metager/metager.php b/metager/config/metager/metager.php index 2c755febd..bb68b2926 100644 --- a/metager/config/metager/metager.php +++ b/metager/config/metager/metager.php @@ -4,10 +4,6 @@ return [ "browserverification_enabled" => true, "browserverification_whitelist" => [ ], - "admin" => [ - "user" => env("ADMIN_USER", "admin"), - "password" => env("ADMIN_PASSWORD", "admin"), - ], "affiliate_preference" => "adgoal", "botprotection" => [ "enabled" => env("BOT_PROTECTION", false), diff --git a/metager/database/seeders/DatabaseSeeder.php b/metager/database/seeders/DatabaseSeeder.php index ebc5e0e52..a78015ff6 100644 --- a/metager/database/seeders/DatabaseSeeder.php +++ b/metager/database/seeders/DatabaseSeeder.php @@ -13,6 +13,6 @@ class DatabaseSeeder extends Seeder */ public function run() { - $this->call(UsersSeeder::class); + // $this->call(UsersSeeder::class); } -} +} \ No newline at end of file diff --git a/metager/database/seeders/UsersSeeder.php b/metager/database/seeders/UsersSeeder.php deleted file mode 100644 index d1eeb1a80..000000000 --- a/metager/database/seeders/UsersSeeder.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -namespace Database\Seeders; - -use Illuminate\Database\Seeder; -use DB; -use Hash; - -class UsersSeeder extends Seeder -{ - /** - * Run the database seeds. - * - * @return void - */ - public function run() - { - DB::table('users')->truncate(); - DB::table('users')->insert( - [ - 'email' => config("metager.metager.admin.user"), - 'name' => config("metager.metager.admin.user"), - 'password' => Hash::make(config("metager.metager.admin.password")), - ] - ); - } -} diff --git a/metager/routes/cookie.php b/metager/routes/cookie.php index e8157f905..5d03d1dda 100644 --- a/metager/routes/cookie.php +++ b/metager/routes/cookie.php @@ -15,9 +15,12 @@ Route::group([ Route::get('generate-new', 'KeyController@generateNew')->name('changeKeyTwo'); Route::post('generate-new', 'KeyController@generateNewPost'); - Route::get('save-new', function () { - return view('keychangethree', ["title" => trans('titles.keychange'), "css" => [mix('css/keychange/index.css')]]); - })->name('changeKeyThree'); + Route::get( + 'save-new', + function () { + return view('keychangethree', ["title" => trans('titles.keychange'), "css" => [mix('css/keychange/index.css')]]); + } + )->name('changeKeyThree'); }); @@ -43,4 +46,4 @@ Route::group( Route::post('all-settings/removeAll', 'SettingsController@removeAllSettings')->name('removeAllSettings'); Route::get('load-settings', 'SettingsController@loadSettings')->name('loadSettings'); } -); +); \ No newline at end of file diff --git a/metager/routes/session.php b/metager/routes/session.php index b03ff8eb2..6bd60886d 100644 --- a/metager/routes/session.php +++ b/metager/routes/session.php @@ -1,2 +1,54 @@ <?php # In this File we collect all routes which require a session or other cookies to be active +Route::get('login', [Vizir\KeycloakWebGuard\Controllers\AuthController::class, "login"])->name('keycloak.login'); +Route::get('logout', [Vizir\KeycloakWebGuard\Controllers\AuthController::class, "logout"])->name('keycloak.logout'); +Route::get('callback', [Vizir\KeycloakWebGuard\Controllers\AuthController::class, "callback"])->name('keycloak.callback'); + +Route::group(['middleware' => ['keycloak-web'], 'prefix' => 'admin'], function () { + Route::get('fpm-status', [AdminInterface::class, "getFPMStatus"])->name("fpm-status"); + Route::get('count', 'AdminInterface@count'); + Route::get('count/count-data-total', [AdminInterface::class, 'getCountDataTotal']); + Route::get('count/count-data-until', [AdminInterface::class, 'getCountDataUntil']); + Route::get('timings', 'MetaGerSearch@searchTimings'); + Route::get('engine/stats.json', 'AdminInterface@engineStats'); + Route::get('check', 'AdminInterface@check'); + Route::get( + 'ip', + function (Request $request) { + dd($request->ip(), $_SERVER["AGENT"]); + } + ); + Route::get('bot', 'HumanVerification@botOverview')->name("admin_bot"); + Route::post('bot', 'HumanVerification@botOverviewChange'); + Route::get('bv', [HumanVerification::class, 'bv']); + Route::group( + ['prefix' => 'spam'], + function () { + Route::get('/', 'AdminSpamController@index'); + Route::post('/', 'AdminSpamController@ban'); + Route::get('jsonQueries', 'AdminSpamController@jsonQueries'); + Route::post('queryregexp', 'AdminSpamController@queryregexp'); + Route::post('deleteRegexp', 'AdminSpamController@deleteRegexp'); + } + ); + Route::get('stress', 'Stresstest@index'); + Route::get('stress/verify', 'Stresstest@index')->middleware('browserverification', 'humanverification'); + Route::get('adgoal', 'AdgoalTestController@index')->name("adgoal-index"); + Route::post('adgoal', 'AdgoalTestController@post')->name("adgoal-generate"); + Route::post('adgoal/generate-urls', 'AdgoalTestController@generateUrls')->name("adgoal-urls"); + + Route::group( + ['prefix' => 'affiliates'], + function () { + Route::get('/', 'AdgoalController@adminIndex'); + Route::get('/json/blacklist', 'AdgoalController@blacklistJson'); + Route::put('/json/blacklist', 'AdgoalController@addblacklistJson'); + Route::delete('/json/blacklist', 'AdgoalController@deleteblacklistJson'); + Route::get('/json/whitelist', 'AdgoalController@whitelistJson'); + Route::put('/json/whitelist', 'AdgoalController@addwhitelistJson'); + Route::delete('/json/whitelist', 'AdgoalController@deletewhitelistJson'); + Route::get('/json/hosts', 'AdgoalController@hostsJson'); + Route::get('/json/hosts/clicks', 'AdgoalController@hostClicksJson'); + } + ); +}); \ No newline at end of file diff --git a/metager/routes/web.php b/metager/routes/web.php index 803fb6a88..d5967d0e0 100644 --- a/metager/routes/web.php +++ b/metager/routes/web.php @@ -23,7 +23,7 @@ use Mcamara\LaravelLocalization\Facades\LaravelLocalization; | by your application. Just tell Laravel the URIs it should respond | to using a Closure or controller method. Build something great! | - */ +*/ Route::get("robots.txt", function (Request $request) { $responseData = ""; @@ -92,24 +92,30 @@ Route::get('tor', function () { }); Route::group(['prefix' => 'spende'], function () { - Route::get('/', function () { - return view('spende.spende') - ->with('title', trans('titles.spende')) - ->with('js', [mix('/js/donation.js')]) - ->with('navbarFocus', 'foerdern'); - })->name("spende"); + Route::get( + '/', + function () { + return view('spende.spende') + ->with('title', trans('titles.spende')) + ->with('js', [mix('/js/donation.js')]) + ->with('navbarFocus', 'foerdern'); + } + )->name("spende"); Route::post('/', 'MailController@donation'); Route::get('paypal', 'MailController@donationPayPalCallback')->name('paypal-callback'); - Route::get('danke/{data?}', function ($data) { - return view('spende.danke') - ->with('title', trans('titles.spende')) - ->with('navbarFocus', 'foerdern') - ->with('css', [mix('/css/spende/danke.css')]) - ->with('data', unserialize(base64_decode($data))); - })->name("danke"); + Route::get( + 'danke/{data?}', + function ($data) { + return view('spende.danke') + ->with('title', trans('titles.spende')) + ->with('navbarFocus', 'foerdern') + ->with('css', [mix('/css/spende/danke.css')]) + ->with('data', unserialize(base64_decode($data))); + } + )->name("danke"); }); Route::get('partnershops', function () { @@ -245,51 +251,11 @@ Route::get('plugin', function (Request $request) { ]); }); -Route::group(['middleware' => ['auth.basic'], 'prefix' => 'admin'], function () { - Route::get('fpm-status', [AdminInterface::class, "getFPMStatus"])->name("fpm-status"); - Route::get('count', 'AdminInterface@count'); - Route::get('count/count-data-total', [AdminInterface::class, 'getCountDataTotal']); - Route::get('count/count-data-until', [AdminInterface::class, 'getCountDataUntil']); - Route::get('timings', 'MetaGerSearch@searchTimings'); - Route::get('engine/stats.json', 'AdminInterface@engineStats'); - Route::get('check', 'AdminInterface@check'); - Route::get('ip', function (Request $request) { - dd($request->ip(), $_SERVER["AGENT"]); - }); - Route::get('bot', 'HumanVerification@botOverview')->name("admin_bot"); - Route::post('bot', 'HumanVerification@botOverviewChange'); - Route::get('bv', [HumanVerification::class, 'bv']); - Route::group(['prefix' => 'spam'], function () { - Route::get('/', 'AdminSpamController@index'); - Route::post('/', 'AdminSpamController@ban'); - Route::get('jsonQueries', 'AdminSpamController@jsonQueries'); - Route::post('queryregexp', 'AdminSpamController@queryregexp'); - Route::post('deleteRegexp', 'AdminSpamController@deleteRegexp'); - }); - Route::get('stress', 'Stresstest@index'); - Route::get('stress/verify', 'Stresstest@index')->middleware('browserverification', 'humanverification'); - Route::get('adgoal', 'AdgoalTestController@index')->name("adgoal-index"); - Route::post('adgoal', 'AdgoalTestController@post')->name("adgoal-generate"); - Route::post('adgoal/generate-urls', 'AdgoalTestController@generateUrls')->name("adgoal-urls"); - - Route::group(['prefix' => 'affiliates'], function () { - Route::get('/', 'AdgoalController@adminIndex'); - Route::get('/json/blacklist', 'AdgoalController@blacklistJson'); - Route::put('/json/blacklist', 'AdgoalController@addblacklistJson'); - Route::delete('/json/blacklist', 'AdgoalController@deleteblacklistJson'); - Route::get('/json/whitelist', 'AdgoalController@whitelistJson'); - Route::put('/json/whitelist', 'AdgoalController@addwhitelistJson'); - Route::delete('/json/whitelist', 'AdgoalController@deletewhitelistJson'); - Route::get('/json/hosts', 'AdgoalController@hostsJson'); - Route::get('/json/hosts/clicks', 'AdgoalController@hostClicksJson'); - }); -}); - Route::get('settings', function () { return redirect(LaravelLocalization::getLocalizedURL(LaravelLocalization::getCurrentLocale(), '/')); }); -Route::match(['get', 'post'], 'meta/meta.ger3', 'MetaGerSearch@search')->middleware('removekey', 'spam', 'browserverification', 'humanverification', 'useragentmaster')->name("resultpage"); +Route::match (['get', 'post'], 'meta/meta.ger3', 'MetaGerSearch@search')->middleware('removekey', 'spam', 'browserverification', 'humanverification', 'useragentmaster')->name("resultpage"); Route::get('meta/loadMore', 'MetaGerSearch@loadMore'); @@ -332,7 +298,7 @@ Route::get("lang", function () { if (array_key_exists("query", $components)) { $path .= "?" . $components["query"]; } - if (($host === $current_host || in_array($current_host, $allowed_hosts)) && preg_match("/^http(s)?:\/\//", $previous)) { // only if the host of that URL matches the current host + if (($host === $current_host || in_array($current_host, $allowed_hosts)) && preg_match("/^http(s)?:\/\//", $previous)) { // only if the host of that URL matches the current host $previous_url = LaravelLocalization::getLocalizedUrl(null, $path); } } @@ -349,52 +315,74 @@ Route::get('languages/edit/{from}/{to}/{exclude?}/{email?}', 'LanguageController Route::post('languages/edit/{from}/{to}/{exclude?}/{email?}', 'MailController@sendLanguageFile'); Route::group(['prefix' => 'app'], function () { - Route::get('/', function () { - return view('app') - ->with('title', trans('titles.app')) - ->with('navbarFocus', 'dienste'); - }); - Route::get('metager', function () { - return response()->streamDownload(function () { - $fh = null; - try { - $fh = fopen("https://gitlab.metager.de/open-source/app-en/-/raw/latest/app/release_manual/app-release_manual.apk", "r"); - while (!feof($fh)) { - echo (fread($fh, 1024)); - } - } catch (\Exception $e) { - abort(404); - } finally { - if ($fh != null) { - fclose($fh); - } - } - }, 'MetaGerSearch.apk', ["Content-Type" => "application/vnd.android.package-archive"]); - }); - Route::get('maps', function () { - return response()->streamDownload(function () { - $fh = null; - try { - $fh = fopen("https://gitlab.metager.de/open-source/metager-maps-android/raw/latest/app/release/app-release.apk?inline=false", "r"); - while (!feof($fh)) { - echo (fread($fh, 1024)); - } - } catch (\Exception $e) { - abort(404); - } finally { - if ($fh != null) { - fclose($fh); - } - } - }, 'MetaGerMaps.apk', ["Content-Type" => "application/vnd.android.package-archive"]); - }); - - Route::get('maps/version', function () { - $filePath = config("metager.metager.maps.version"); - $fileContents = file_get_contents($filePath); - return response($fileContents, 200) - ->header('Content-Type', 'text/plain'); - }); + Route::get( + '/', + function () { + return view('app') + ->with('title', trans('titles.app')) + ->with('navbarFocus', 'dienste'); + } + ); + Route::get( + 'metager', + function () { + return response()->streamDownload( + function () { + $fh = null; + try { + $fh = fopen("https://gitlab.metager.de/open-source/app-en/-/raw/latest/app/release_manual/app-release_manual.apk", "r"); + while (!feof($fh)) { + echo (fread($fh, 1024)); + } + } catch (\Exception $e) { + abort(404); + } finally { + if ($fh != null) { + fclose($fh); + } + } + } + , + 'MetaGerSearch.apk', + ["Content-Type" => "application/vnd.android.package-archive"] + ); + } + ); + Route::get( + 'maps', + function () { + return response()->streamDownload( + function () { + $fh = null; + try { + $fh = fopen("https://gitlab.metager.de/open-source/metager-maps-android/raw/latest/app/release/app-release.apk?inline=false", "r"); + while (!feof($fh)) { + echo (fread($fh, 1024)); + } + } catch (\Exception $e) { + abort(404); + } finally { + if ($fh != null) { + fclose($fh); + } + } + } + , + 'MetaGerMaps.apk', + ["Content-Type" => "application/vnd.android.package-archive"] + ); + } + ); + + Route::get( + 'maps/version', + function () { + $filePath = config("metager.metager.maps.version"); + $fileContents = file_get_contents($filePath); + return response($fileContents, 200) + ->header('Content-Type', 'text/plain'); + } + ); }); Route::group(["prefix" => "metrics", "middleware" => "allow-local-only"], function (Router $router) { @@ -410,4 +398,4 @@ Route::group(['prefix' => 'health-check'], function () { Route::get('liveness', 'HealthcheckController@liveness'); Route::get('liveness-scheduler', 'HealthcheckController@livenessScheduler'); Route::get('liveness-worker', 'HealthcheckController@livenessWorker'); -}); +}); \ No newline at end of file -- GitLab