diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index c4136cbd57..4730c59fc4 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -247,6 +247,7 @@ App::init() $teamWideRoles = \array_filter($adminRoles, fn ($role) => !str_starts_with($role, "project-")); foreach ($teamWideRoles as $teamRole) { $scopes = \array_merge($scopes, $roles[$teamRole]['scopes']); + $authorization->addRole($teamRole); } $projectId = $project->getId(); @@ -260,8 +261,12 @@ App::init() $projectSpecificRoles = \array_filter($adminRoles, fn ($role) => str_starts_with($role, "project-$projectId")); foreach ($projectSpecificRoles as $projectRole) { - $actualRole = explode('-', $projectRole)[2]; + $actualRole = \substr($projectRole, \strlen("project-$projectId-")); + if ($actualRole === '' || !isset($roles[$actualRole])) { + continue; + } $scopes = \array_merge($scopes, $roles[$actualRole]['scopes']); + $authorization->addRole($actualRole); } $authorization->setDefaultStatus(false); // Cancel security segmentation for admin users. diff --git a/src/Appwrite/Auth/Validator/Role.php b/src/Appwrite/Auth/Validator/Role.php index 2f9e17f4c6..0662eb3e70 100644 --- a/src/Appwrite/Auth/Validator/Role.php +++ b/src/Appwrite/Auth/Validator/Role.php @@ -79,12 +79,18 @@ class Role extends Validator $role = $value; if (str_starts_with($value, "project-")) { - $parts = explode("-", $value); - if (\count($parts) !== 3) { + $prefix = "project-"; + $rest = \substr($value, \strlen($prefix)); + $lastDash = \strrpos($rest, '-'); + if ($lastDash === false) { return false; } - $role = $parts[2]; + $projectId = \substr($rest, 0, $lastDash); + $role = \substr($rest, $lastDash + 1); + if ($projectId === '' || $role === '') { + return false; + } } if (!\in_array($role, $this->roles)) { diff --git a/src/Appwrite/Utopia/Database/Documents/User.php b/src/Appwrite/Utopia/Database/Documents/User.php index 1821e86f2b..c8482fa603 100644 --- a/src/Appwrite/Utopia/Database/Documents/User.php +++ b/src/Appwrite/Utopia/Database/Documents/User.php @@ -73,17 +73,28 @@ class User extends Document if ($projectId !== 'console') { $roles[] = Role::team($node['teamId'])->toString(); // Populate team-wide base role. } else { - $teamWideRoles = \array_filter($nodeRoles, fn ($role) => !str_starts_with($role, "project-")); + $projectRolePrefix = "project-"; + + $teamWideRoles = \array_filter($nodeRoles, fn ($role) => !str_starts_with($role, $projectRolePrefix)); $populateTeamWideRole = !str_starts_with($path, "/v1/projects") || !empty($teamWideRoles); if ($populateTeamWideRole) { $roles[] = Role::team($node['teamId'])->toString(); // Populate team-wide base role. } - $projectSpecificRoles = \array_filter($nodeRoles, fn ($role) => str_starts_with($role, "project-")); + $projectSpecificRoles = \array_filter($nodeRoles, fn ($role) => str_starts_with($role, $projectRolePrefix)); foreach ($projectSpecificRoles as $projectRole) { - $parts = explode("-", $projectRole); - $roles[] = Role::team($node['teamId'], "$parts[0]-$parts[1]")->toString(); // Populate project-wide base role. + $rest = \substr($projectRole, \strlen($projectRolePrefix)); + $lastDash = \strrpos($rest, '-'); + if ($lastDash === false) { + continue; + } + + $projectId = \substr($rest, 0, $lastDash); + if ($projectId === '') { + continue; + } + $roles[] = Role::team($node['teamId'], "{$projectRolePrefix}{$projectId}")->toString(); // Populate project-wide base role. } }