diff --git a/src/app/Providers/AppServiceProvider.php b/src/app/Providers/AppServiceProvider.php index e78673c8..458c4b83 100644 --- a/src/app/Providers/AppServiceProvider.php +++ b/src/app/Providers/AppServiceProvider.php @@ -1,172 +1,173 @@ format('Y-m-d h:i:s'); } elseif ($ipv && is_string($entry) && strlen($entry) == ($ipv == 6 ? 16 : 4)) { // binary IP address? use HEX representation return '0x' . bin2hex($entry); } return $entry; }, $array); return implode(', ', $serialized); } /** * Bootstrap any application services. * * @return void */ public function boot() { \App\Domain::observe(\App\Observers\DomainObserver::class); \App\Entitlement::observe(\App\Observers\EntitlementObserver::class); \App\Group::observe(\App\Observers\GroupObserver::class); \App\GroupSetting::observe(\App\Observers\GroupSettingObserver::class); \App\Meet\Room::observe(\App\Observers\Meet\RoomObserver::class); \App\PackageSku::observe(\App\Observers\PackageSkuObserver::class); \App\PlanPackage::observe(\App\Observers\PlanPackageObserver::class); \App\Resource::observe(\App\Observers\ResourceObserver::class); \App\ResourceSetting::observe(\App\Observers\ResourceSettingObserver::class); \App\SharedFolder::observe(\App\Observers\SharedFolderObserver::class); \App\SharedFolderAlias::observe(\App\Observers\SharedFolderAliasObserver::class); \App\SharedFolderSetting::observe(\App\Observers\SharedFolderSettingObserver::class); \App\SignupCode::observe(\App\Observers\SignupCodeObserver::class); \App\SignupInvitation::observe(\App\Observers\SignupInvitationObserver::class); \App\Transaction::observe(\App\Observers\TransactionObserver::class); \App\User::observe(\App\Observers\UserObserver::class); \App\UserAlias::observe(\App\Observers\UserAliasObserver::class); \App\UserSetting::observe(\App\Observers\UserSettingObserver::class); \App\VerificationCode::observe(\App\Observers\VerificationCodeObserver::class); \App\Wallet::observe(\App\Observers\WalletObserver::class); \App\PowerDNS\Domain::observe(\App\Observers\PowerDNS\DomainObserver::class); \App\PowerDNS\Record::observe(\App\Observers\PowerDNS\RecordObserver::class); Schema::defaultStringLength(191); // Log SQL queries in debug mode if (\config('app.debug')) { DB::listen(function ($query) { \Log::debug( sprintf( '[SQL] %s [%s]: %.4f sec.', $query->sql, self::serializeSQLBindings($query->bindings, $query->sql), $query->time / 1000 ) ); }); } // Register some template helpers Blade::directive( 'theme_asset', function ($path) { $path = trim($path, '/\'"'); return ""; } ); Builder::macro( 'withEnvTenantContext', function (string $table = null) { $tenantId = \config('app.tenant_id'); if ($tenantId) { /** @var Builder $this */ return $this->where(($table ? "$table." : "") . "tenant_id", $tenantId); } /** @var Builder $this */ return $this->whereNull(($table ? "$table." : "") . "tenant_id"); } ); Builder::macro( 'withObjectTenantContext', function (object $object, string $table = null) { $tenantId = $object->tenant_id; if ($tenantId) { /** @var Builder $this */ return $this->where(($table ? "$table." : "") . "tenant_id", $tenantId); } /** @var Builder $this */ return $this->whereNull(($table ? "$table." : "") . "tenant_id"); } ); Builder::macro( 'withSubjectTenantContext', function (string $table = null) { if ($user = auth()->user()) { $tenantId = $user->tenant_id; } else { $tenantId = \config('app.tenant_id'); } if ($tenantId) { /** @var Builder $this */ return $this->where(($table ? "$table." : "") . "tenant_id", $tenantId); } /** @var Builder $this */ return $this->whereNull(($table ? "$table." : "") . "tenant_id"); } ); // Query builder 'whereLike' mocro Builder::macro( 'whereLike', function (string $column, string $search, int $mode = 0) { $search = addcslashes($search, '%_'); switch ($mode) { case 2: $search .= '%'; break; case 1: $search = '%' . $search; break; default: $search = '%' . $search . '%'; } /** @var Builder $this */ return $this->where($column, 'like', $search); } ); } } diff --git a/src/app/Providers/AuthServiceProvider.php b/src/app/Providers/AuthServiceProvider.php index ae50a36e..f9b1019e 100644 --- a/src/app/Providers/AuthServiceProvider.php +++ b/src/app/Providers/AuthServiceProvider.php @@ -1,57 +1,41 @@ */ protected $policies = [ - // 'App\Model' => 'App\Policies\ModelPolicy', ]; /** * Register any authentication / authorization services. * * @return void */ public function boot() { $this->registerPolicies(); - // Hashes all secrets and thus makes them non-recoverable - /* Passport::hashClientSecrets(); */ - // Only enable routes for access tokens - Passport::routes( - function ($router) { - $router->forAccessTokens(); - - // Override the default route to avoid rate-limiting. - Route::post('/token', [ - 'uses' => 'AccessTokenController@issueToken', - 'as' => 'passport.token', - ]); - } - ); - Passport::tokensCan([ 'api' => 'Access API', 'mfa' => 'Access MFA API', ]); Passport::tokensExpireIn(now()->addMinutes(\config('auth.token_expiry_minutes'))); Passport::refreshTokensExpireIn(now()->addMinutes(\config('auth.refresh_token_expiry_minutes'))); Passport::personalAccessTokensExpireIn(now()->addMonths(6)); Passport::useClientModel(\App\Auth\PassportClient::class); Passport::tokenModel()::observe(\App\Observers\Passport\TokenObserver::class); } } diff --git a/src/composer.json b/src/composer.json index 9b63dd62..e3c31fc4 100644 --- a/src/composer.json +++ b/src/composer.json @@ -1,87 +1,87 @@ { "name": "kolab/kolab4", "type": "project", "description": "Kolab 4", "keywords": [ "framework", "laravel" ], "license": "MIT", "repositories": [ { "type": "vcs", "url": "https://git.kolab.org/diffusion/PNL/php-net_ldap3.git" } ], "require": { "php": "^8.0", "bacon/bacon-qr-code": "^2.0", "barryvdh/laravel-dompdf": "^2.0.0", "doctrine/dbal": "^3.3.2", "dyrynda/laravel-nullable-fields": "^4.2.0", "guzzlehttp/guzzle": "^7.4.1", "kolab/net_ldap3": "dev-master", "laravel/framework": "^9.2", "laravel/horizon": "^5.9", "laravel/octane": "^1.2", - "laravel/passport": "^10.3", + "laravel/passport": "^11.3", "laravel/tinker": "^2.7", "mlocati/spf-lib": "^3.1", "mollie/laravel-mollie": "^2.19", "moontoast/math": "^1.2", "pear/crypt_gpg": "^1.6.6", "predis/predis": "^1.1.10", "spatie/laravel-translatable": "^5.2", "spomky-labs/otphp": "~10.0.0", "stripe/stripe-php": "^7.29" }, "require-dev": { "code-lts/doctum": "^5.5.1", "laravel/dusk": "~6.22.0", "nunomaduro/larastan": "^2.0", "phpstan/phpstan": "^1.4", "phpunit/phpunit": "^9", "squizlabs/php_codesniffer": "^3.6" }, "config": { "optimize-autoloader": true, "preferred-install": "dist", "sort-packages": true }, "extra": { "laravel": { "dont-discover": [] } }, "autoload": { "psr-4": { "App\\": "app/" }, "classmap": [ "database/seeds", "include" ] }, "autoload-dev": { "psr-4": { "Tests\\": "tests/" } }, "minimum-stability": "stable", "prefer-stable": true, "scripts": { "post-autoload-dump": [ "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump", "@php artisan package:discover --ansi" ], "post-update-cmd": [ "@php artisan vendor:publish --tag=laravel-assets --ansi --force" ], "post-root-package-install": [ "@php -r \"file_exists('.env') || copy('.env.example', '.env');\"" ], "post-create-project-cmd": [ "@php artisan key:generate --ansi" ] } } diff --git a/src/routes/web.php b/src/routes/web.php index 43cfea5f..d4b2e94e 100644 --- a/src/routes/web.php +++ b/src/routes/web.php @@ -1,31 +1,58 @@ \config('app.website_domain'), ], function () { Route::get('content/page/{page}', Controllers\ContentController::class . '@pageContent') ->where('page', '(.*)'); Route::get('content/faq/{page}', Controllers\ContentController::class . '@faqContent') ->where('page', '(.*)'); Route::fallback( function () { // Return 404 for requests to the API end-points that do not exist if (strpos(request()->path(), 'api/') === 0) { return Controllers\Controller::errorResponse(404); } $env = \App\Utils::uiEnv(); return view($env['view'])->with('env', $env); } ); } ); + +Route::group( + [ + 'prefix' => 'oauth' + ], + function () { + // We manually specify a subset of endpoints from https://github.com/laravel/passport/blob/11.x/routes/web.php + // after having disabled automatic routes via Passport::ignoreRoutes() + Route::post('/token', [ + 'uses' => '\Laravel\Passport\Http\Controllers\AccessTokenController@issueToken', + 'as' => 'token', + // 'middleware' => 'throttle', + ]); + + Route::middleware(['web', 'auth'])->group(function () { + Route::get('/tokens', [ + 'uses' => '\Laravel\Passport\Http\Controllers\AuthorizedAccessTokenController@forUser', + 'as' => 'tokens.index', + ]); + + Route::delete('/tokens/{token_id}', [ + 'uses' => '\Laravel\Passport\Http\Controllers\AuthorizedAccessTokenController@destroy', + 'as' => 'tokens.destroy', + ]); + }); + } +);