fix(ui): deny members on cloud tokens and OAuth settings without a 500

- /security/cloud-tokens returns 403 for members instead of crashing
  on a null token list
- /settings/oauth redirects non-admins to the dashboard; it used the
  missing route "home" and a wrong redirect return type
This commit is contained in:
Andras Bacsai
2026-10-06 06:59:22 +02:00
parent ca203bc9fa
commit e1f9e6fb39
3 changed files with 75 additions and 11 deletions
@@ -13,14 +13,10 @@ class CloudProviderTokens extends Component
public $tokens;
public function mount()
public function mount(): void
{
try {
$this->authorize('viewAny', CloudProviderToken::class);
$this->loadTokens();
} catch (\Throwable $e) {
return handleError($e, $this);
}
$this->authorize('viewAny', CloudProviderToken::class);
$this->loadTokens();
}
public function getListeners()
@@ -153,6 +149,8 @@ class CloudProviderTokens extends Component
public function render()
{
return view('livewire.security.cloud-provider-tokens');
return view('livewire.security.cloud-provider-tokens', [
'tokens' => $this->tokens ?? collect(),
]);
}
}
+3 -3
View File
@@ -5,9 +5,9 @@ namespace App\Livewire;
use App\Models\InstanceSettings;
use App\Models\OauthSetting;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Http\RedirectResponse;
use Illuminate\Validation\ValidationException;
use Livewire\Component;
use Livewire\Features\SupportRedirects\Redirector;
class SettingsOauth extends Component
{
@@ -57,10 +57,10 @@ class SettingsOauth extends Component
return $rules;
}
public function mount(?string $provider = null): ?RedirectResponse
public function mount(?string $provider = null): ?Redirector
{
if (! isInstanceAdmin()) {
return redirect()->route('home');
return redirect()->route('dashboard');
}
$this->settings = instanceSettings();
@@ -0,0 +1,66 @@
<?php
use App\Models\InstanceSettings;
use App\Models\OauthSetting;
use App\Models\Team;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Once;
uses(RefreshDatabase::class);
beforeEach(function () {
$this->withoutVite();
config()->set('app.maintenance.store', 'array');
InstanceSettings::forceCreate(['id' => 0]);
Once::flush();
OauthSetting::create(['provider' => 'authentik']);
$this->rootTeam = Team::forceCreate(['id' => 0, 'name' => 'Root Team', 'personal_team' => false, 'show_boarding' => false]);
});
function actingAsRootTeamMemberWithRole(string $role): User
{
$team = Team::find(0);
$user = User::factory()->create(['email_verified_at' => now()]);
$user->teams()->detach();
$user->teams()->attach($team, ['role' => $role]);
Team::query()->update(['show_boarding' => false]);
Cache::flush();
session(['currentTeam' => $team]);
test()->actingAs($user);
return $user;
}
it('forbids team members from the cloud tokens page', function () {
actingAsRootTeamMemberWithRole('member');
$this->get(route('security.cloud-tokens'))->assertForbidden();
});
it('shows the cloud tokens page to team admins and owners', function (string $role) {
actingAsRootTeamMemberWithRole($role);
$this->get(route('security.cloud-tokens'))
->assertSuccessful()
->assertSee('No cloud tokens');
})->with(['admin', 'owner']);
it('redirects team members from the oauth settings page to the dashboard', function (string $routeName, array $parameters) {
actingAsRootTeamMemberWithRole('member');
$this->get(route($routeName, $parameters))->assertRedirect(route('dashboard'));
})->with([
'oauth settings' => ['settings.oauth', []],
'oauth provider settings' => ['settings.oauth.provider', ['provider' => 'authentik']],
]);
it('shows the oauth settings page to instance admins', function (string $role) {
actingAsRootTeamMemberWithRole($role);
$this->get(route('settings.oauth'))->assertSuccessful()->assertSee('Authentik');
})->with(['admin', 'owner']);