Per request cache for permission checks (#2029)

Co-authored-by: MartinOscar <40749467+rmartinoscar@users.noreply.github.com>
Co-authored-by: Lance Pioch <lancepioch@gmail.com>
This commit is contained in:
xDev789
2025-12-28 08:00:59 +07:00
committed by GitHub
parent d72e075977
commit 5740c93032
2 changed files with 17 additions and 5 deletions

View File

@@ -39,6 +39,7 @@ use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Context;
use Illuminate\Support\Str;
use Illuminate\Validation\Rules\In;
use ResourceBundle;
@@ -333,12 +334,8 @@ class User extends Model implements AuthenticatableContract, AuthorizableContrac
return !$key ? $customization : $customization[$key->value];
}
protected function checkPermission(Server $server, string|SubuserPermission $permission = ''): bool
protected function hasPermission(Server $server, string $permission = ''): bool
{
if ($permission instanceof SubuserPermission) {
$permission = $permission->value;
}
if ($this->canned('update', $server) || $server->owner_id === $this->id) {
return true;
}
@@ -356,6 +353,17 @@ class User extends Model implements AuthenticatableContract, AuthorizableContrac
return in_array($permission, $subuser->permissions);
}
protected function checkPermission(Server $server, string|SubuserPermission $permission = ''): bool
{
if ($permission instanceof SubuserPermission) {
$permission = $permission->value;
}
$contextKey = "users.$this->id.servers.$server->id.$permission";
return Context::remember($contextKey, fn () => $this->hasPermission($server, $permission));
}
/**
* Laravel's policies strictly check for the existence of a real method,
* this checks if the ability is one of our permissions and then checks if the user can do it or not

View File

@@ -6,6 +6,7 @@ use App\Enums\SubuserPermission;
use App\Models\Subuser;
use App\Models\User;
use App\Tests\Integration\Api\Client\ClientApiIntegrationTestCase;
use Illuminate\Support\Facades\Context;
use Illuminate\Support\Facades\Http;
class UpdateSubuserTest extends ClientApiIntegrationTestCase
@@ -41,6 +42,9 @@ class UpdateSubuserTest extends ClientApiIntegrationTestCase
$this->actingAs($subuser->user)->postJson($endpoint, $data)->assertForbidden();
$this->actingAs($user)->postJson($endpoint, $data)->assertForbidden();
// When running the tests, the context is function-scoped instead of request-scoped, so we have to flush it
Context::flush();
$server->subusers()->where('user_id', $user->id)->update([
'permissions' => [
SubuserPermission::UserUpdate,