mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
feedback
This commit is contained in:
@@ -297,7 +297,12 @@ Http::init()
|
||||
* whether the admin user has necessary permission on the project (sites, functions, etc. don't have permissions associated to them).
|
||||
*/
|
||||
if ($project->getId() !== 'console' && $mode === APP_MODE_ADMIN) {
|
||||
$input = new Input(Database::PERMISSION_READ, $project->getPermissionsByType(Database::PERMISSION_READ));
|
||||
$action = match ($route->getMethod()) {
|
||||
Request::METHOD_GET => Database::PERMISSION_READ,
|
||||
Request::METHOD_DELETE => Database::PERMISSION_DELETE,
|
||||
default => Database::PERMISSION_UPDATE,
|
||||
};
|
||||
$input = new Input($action, $project->getPermissionsByType($action));
|
||||
$initialStatus = $authorization->getStatus();
|
||||
$authorization->enable();
|
||||
if (!$authorization->isValid($input)) {
|
||||
|
||||
@@ -6,6 +6,7 @@ use Appwrite\Event\Build;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Action;
|
||||
use Appwrite\Platform\Modules\Compute\Validator\Specification as SpecificationValidator;
|
||||
use Appwrite\Platform\Permission as AppwritePermission;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
@@ -22,32 +23,7 @@ use Utopia\VCS\Exception\RepositoryNotFound;
|
||||
|
||||
class Base extends Action
|
||||
{
|
||||
/**
|
||||
* Permissions for resources in this project.
|
||||
*
|
||||
* @param string $teamId
|
||||
* @param string $projectId
|
||||
* @return string[]
|
||||
*/
|
||||
protected function getPermissions(string $teamId, string $projectId): array
|
||||
{
|
||||
return [
|
||||
// Team-wide permissions
|
||||
Permission::read(Role::team(ID::custom($teamId), 'owner')),
|
||||
Permission::read(Role::team(ID::custom($teamId), 'developer')),
|
||||
Permission::update(Role::team(ID::custom($teamId), 'owner')),
|
||||
Permission::update(Role::team(ID::custom($teamId), 'developer')),
|
||||
Permission::delete(Role::team(ID::custom($teamId), 'owner')),
|
||||
Permission::delete(Role::team(ID::custom($teamId), 'developer')),
|
||||
// Project-wide permissions
|
||||
Permission::read(Role::team(ID::custom($teamId), "project-{$projectId}-owner")),
|
||||
Permission::read(Role::team(ID::custom($teamId), "project-{$projectId}-developer")),
|
||||
Permission::update(Role::team(ID::custom($teamId), "project-{$projectId}-owner")),
|
||||
Permission::update(Role::team(ID::custom($teamId), "project-{$projectId}-developer")),
|
||||
Permission::delete(Role::team(ID::custom($teamId), "project-{$projectId}-owner")),
|
||||
Permission::delete(Role::team(ID::custom($teamId), "project-{$projectId}-developer")),
|
||||
];
|
||||
}
|
||||
use AppwritePermission;
|
||||
|
||||
/**
|
||||
* Get default specification based on plan and available specifications.
|
||||
|
||||
@@ -3,29 +3,9 @@
|
||||
namespace Appwrite\Platform\Modules\Projects\Http\Projects;
|
||||
|
||||
use Appwrite\Platform\Action as AppwriteAction;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Helpers\Permission;
|
||||
use Utopia\Database\Helpers\Role;
|
||||
use Appwrite\Platform\Permission as AppwritePermission;
|
||||
|
||||
class Action extends AppwriteAction
|
||||
{
|
||||
protected function getPermissions(string $teamId, string $projectId): array
|
||||
{
|
||||
return [
|
||||
// Team-wide permissions
|
||||
Permission::read(Role::team(ID::custom($teamId), 'owner')),
|
||||
Permission::read(Role::team(ID::custom($teamId), 'developer')),
|
||||
Permission::update(Role::team(ID::custom($teamId), 'owner')),
|
||||
Permission::update(Role::team(ID::custom($teamId), 'developer')),
|
||||
Permission::delete(Role::team(ID::custom($teamId), 'owner')),
|
||||
Permission::delete(Role::team(ID::custom($teamId), 'developer')),
|
||||
// Project-wide permissions
|
||||
Permission::read(Role::team(ID::custom($teamId), "project-{$projectId}-owner")),
|
||||
Permission::read(Role::team(ID::custom($teamId), "project-{$projectId}-developer")),
|
||||
Permission::update(Role::team(ID::custom($teamId), "project-{$projectId}-owner")),
|
||||
Permission::update(Role::team(ID::custom($teamId), "project-{$projectId}-developer")),
|
||||
Permission::delete(Role::team(ID::custom($teamId), "project-{$projectId}-owner")),
|
||||
Permission::delete(Role::team(ID::custom($teamId), "project-{$projectId}-developer")),
|
||||
];
|
||||
}
|
||||
use AppwritePermission;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Appwrite\Platform;
|
||||
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Helpers\Role;
|
||||
use Utopia\Database\Helpers\Permission as DbPermission;
|
||||
|
||||
trait Permission
|
||||
{
|
||||
/**
|
||||
* Permissions for projects & project resources.
|
||||
*
|
||||
* @param string $teamId
|
||||
* @param string $projectId
|
||||
* @return array
|
||||
*/
|
||||
public function getPermissions(string $teamId, string $projectId): array
|
||||
{
|
||||
return [
|
||||
// Team-wide permissions
|
||||
DbPermission::read(Role::team(ID::custom($teamId), 'owner')),
|
||||
DbPermission::read(Role::team(ID::custom($teamId), 'developer')),
|
||||
DbPermission::update(Role::team(ID::custom($teamId), 'owner')),
|
||||
DbPermission::update(Role::team(ID::custom($teamId), 'developer')),
|
||||
DbPermission::delete(Role::team(ID::custom($teamId), 'owner')),
|
||||
DbPermission::delete(Role::team(ID::custom($teamId), 'developer')),
|
||||
// Project-wide permissions
|
||||
DbPermission::read(Role::team(ID::custom($teamId), "project-{$projectId}-owner")),
|
||||
DbPermission::read(Role::team(ID::custom($teamId), "project-{$projectId}-developer")),
|
||||
DbPermission::update(Role::team(ID::custom($teamId), "project-{$projectId}-owner")),
|
||||
DbPermission::update(Role::team(ID::custom($teamId), "project-{$projectId}-developer")),
|
||||
DbPermission::delete(Role::team(ID::custom($teamId), "project-{$projectId}-owner")),
|
||||
DbPermission::delete(Role::team(ID::custom($teamId), "project-{$projectId}-developer")),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -5941,4 +5941,102 @@ class ProjectsConsoleClientTest extends Scope
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test project specific permissions for project resources, in this case 'variables'.
|
||||
*/
|
||||
public function testProjectSpecificPermissionsForProjectResources(): void
|
||||
{
|
||||
$teamId = ID::unique();
|
||||
$projectIdA = $this->setupProject([
|
||||
'projectId' => ID::unique(),
|
||||
'name' => 'Project Test A',
|
||||
'region' => System::getEnv('_APP_REGION', 'default')
|
||||
], $teamId);
|
||||
$projectIdB = $this->setupProject([
|
||||
'projectId' => ID::unique(),
|
||||
'name' => 'Project Test B',
|
||||
'region' => System::getEnv('_APP_REGION', 'default')
|
||||
], $teamId, false);
|
||||
$teamOwnerEmail = 'team-' . ID::unique() . '-owner@localhost.test';
|
||||
$teamOwnerName = 'Team - owner';
|
||||
$teamDeveloperAndProjectAOwnerEmail = 'teamdeveloperandprojecta-' . ID::unique() . '-owner@localhost.test';
|
||||
$teamDeveloperAndProjectAOwnerName = 'Team Developer and Project A - owner';
|
||||
$projectAOwnerEmail = 'projecta-' . ID::unique() . '-owner@localhost.test';
|
||||
$projectAOwnerName = 'Project A - owner';
|
||||
$this->setupUserMembership([
|
||||
'teamId' => $teamId,
|
||||
'email' => $teamOwnerEmail,
|
||||
'name' => $teamOwnerName,
|
||||
'roles' => ["owner"],
|
||||
]);
|
||||
$this->setupUserMembership([
|
||||
'teamId' => $teamId,
|
||||
'email' => $teamDeveloperAndProjectAOwnerEmail,
|
||||
'name' => $teamDeveloperAndProjectAOwnerName,
|
||||
'roles' => ["developer", "project-$projectIdA-owner"],
|
||||
]);
|
||||
$this->setupUserMembership([
|
||||
'teamId' => $teamId,
|
||||
'email' => $projectAOwnerEmail,
|
||||
'name' => $projectAOwnerName,
|
||||
'roles' => ["project-$projectIdA-owner"],
|
||||
]);
|
||||
|
||||
$testCases = [
|
||||
['userEmail' => $teamOwnerEmail, 'accessibleProjectIds' => [$projectIdA, $projectIdB], 'inaccessibleProjectIds' => []],
|
||||
['userEmail' => $teamDeveloperAndProjectAOwnerEmail, 'accessibleProjectIds' => [$projectIdA, $projectIdB], 'inaccessibleProjectIds' => []],
|
||||
['userEmail' => $projectAOwnerEmail, 'accessibleProjectIds' => [$projectIdA], 'inaccessibleProjectIds' => [$projectIdB]],
|
||||
];
|
||||
|
||||
foreach ($testCases as $testCase) {
|
||||
$session = $this->client->call(Client::METHOD_POST, '/account/sessions/email', [
|
||||
'origin' => 'http://localhost',
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], [
|
||||
'email' => $testCase['userEmail'],
|
||||
'password' => 'password',
|
||||
]);
|
||||
$token = $session['cookies']['a_session_' . $this->getProject()['$id']];
|
||||
|
||||
foreach ($testCase['accessibleProjectIds'] as $projectId) {
|
||||
$variableId = ID::unique();
|
||||
$response = $this->client->call(Client::METHOD_POST, '/project/variables', [
|
||||
'origin' => 'http://localhost',
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $projectId,
|
||||
'x-appwrite-mode' => 'admin',
|
||||
'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $token,
|
||||
], [
|
||||
'key' => 'APP_TEST_' . $variableId,
|
||||
'value' => 'TESTINGVALUE',
|
||||
'secret' => false
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
$this->assertEquals('APP_TEST_' . $variableId, $response['body']['key']);
|
||||
$this->assertEquals('TESTINGVALUE', $response['body']['value']);
|
||||
}
|
||||
|
||||
foreach ($testCase['inaccessibleProjectIds'] as $projectId) {
|
||||
echo "processing user " . $testCase['userEmail'] . " for project " . $projectId . "\n";
|
||||
|
||||
$variableId = ID::unique();
|
||||
$response = $this->client->call(Client::METHOD_POST, '/project/variables', [
|
||||
'origin' => 'http://localhost',
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $projectId,
|
||||
'x-appwrite-mode' => 'admin',
|
||||
'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $token,
|
||||
], [
|
||||
'key' => 'APP_TEST_' . $variableId,
|
||||
'value' => 'TESTINGVALUE',
|
||||
'secret' => false
|
||||
]);
|
||||
|
||||
$this->assertEquals(404, $response['headers']['status-code']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user