mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Implement project-specific permissions
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
namespace Appwrite\Auth\Validator;
|
||||
|
||||
use Utopia\Database\Validator\Roles;
|
||||
use Utopia\Validator;
|
||||
|
||||
class Role extends Validator
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected array $roles;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* Sets the acceptable roles.
|
||||
*
|
||||
* @param array $list
|
||||
* @param string $type of $list items
|
||||
*/
|
||||
public function __construct(array $roles)
|
||||
{
|
||||
$this->roles = $roles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Description
|
||||
*
|
||||
* Returns validator description
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Value must be one of (' . \implode(', ', $this->roles) . ' (or) in the format "project-<projectId>-<role>")';
|
||||
}
|
||||
|
||||
/**
|
||||
* Is array
|
||||
*
|
||||
* Function will return true if object is array.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isArray(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Type
|
||||
*
|
||||
* Returns validator type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getType(): string
|
||||
{
|
||||
return self::TYPE_STRING;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is valid
|
||||
*
|
||||
* Validation will pass if $value is in the white list array.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
public function isValid(mixed $value): bool
|
||||
{
|
||||
if (!\is_string($value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$role = $value;
|
||||
|
||||
if (str_starts_with($value, "project-")) {
|
||||
$parts = explode("-", $value);
|
||||
if (\count($parts) !== 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$role = $parts[2];
|
||||
}
|
||||
|
||||
if (!\in_array($role, $this->roles)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ use Utopia\Auth\Proofs\Token;
|
||||
use Utopia\Database\DateTime;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Helpers\Role;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
use Utopia\Database\Validator\Roles;
|
||||
|
||||
class User extends Document
|
||||
@@ -35,7 +36,7 @@ class User extends Document
|
||||
*
|
||||
* @return array<string>
|
||||
*/
|
||||
public function getRoles($authorization): array
|
||||
public function getRoles(Authorization $authorization, string $projectId = '', string $path = ''): array
|
||||
{
|
||||
$roles = [];
|
||||
|
||||
@@ -60,19 +61,34 @@ class User extends Document
|
||||
}
|
||||
|
||||
foreach ($this->getAttribute('memberships', []) as $node) {
|
||||
if (!isset($node['confirm']) || !$node['confirm']) {
|
||||
if (!isset($node['confirm']) || !$node['confirm'] || !isset($node['$id']) || !isset($node['teamId'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($node['$id']) && isset($node['teamId'])) {
|
||||
$roles[] = Role::team($node['teamId'])->toString();
|
||||
$roles[] = Role::member($node['$id'])->toString();
|
||||
// Role for this membership id.
|
||||
$roles[] = Role::member($node['$id'])->toString();
|
||||
|
||||
if (isset($node['roles'])) {
|
||||
foreach ($node['roles'] as $nodeRole) { // Set all team roles
|
||||
$roles[] = Role::team($node['teamId'], $nodeRole)->toString();
|
||||
}
|
||||
$nodeRoles = $node['roles'] ?? [];
|
||||
|
||||
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-"));
|
||||
$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-"));
|
||||
foreach ($projectSpecificRoles as $projectRole) {
|
||||
$parts = explode("-", $projectRole);
|
||||
$roles[] = Role::team($node['teamId'], "$parts[0]-$parts[1]")->toString(); // Populate project-wide base role.
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($nodeRoles as $nodeRole) {
|
||||
$roles[] = Role::team($node['teamId'], $nodeRole)->toString(); // Set all team roles
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user