mirror of
https://github.com/appwrite/appwrite
synced 2026-05-06 06:48:22 +00:00
Merge branch '1.6.x' of https://github.com/appwrite/appwrite into feat-payload-response-type
This commit is contained in:
commit
ac2fa382a7
10 changed files with 206 additions and 74 deletions
|
|
@ -28,6 +28,8 @@ RUN \
|
|||
apk add boost boost-dev; \
|
||||
fi
|
||||
|
||||
RUN apk add libwebp
|
||||
|
||||
WORKDIR /usr/src/code
|
||||
|
||||
COPY --from=composer /usr/local/src/vendor /usr/src/code/vendor
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ $member = [
|
|||
'files.read',
|
||||
'files.write',
|
||||
'projects.read',
|
||||
'projects.write',
|
||||
'locale.read',
|
||||
'avatars.read',
|
||||
'execution.read',
|
||||
|
|
@ -49,6 +48,7 @@ $admins = [
|
|||
'collections.write',
|
||||
'platforms.read',
|
||||
'platforms.write',
|
||||
'projects.write',
|
||||
'keys.read',
|
||||
'keys.write',
|
||||
'webhooks.read',
|
||||
|
|
|
|||
|
|
@ -1199,7 +1199,7 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId')
|
|||
App::post('/v1/projects/:projectId/keys')
|
||||
->desc('Create key')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('scope', 'keys.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'createKey')
|
||||
|
|
@ -1249,7 +1249,7 @@ App::post('/v1/projects/:projectId/keys')
|
|||
App::get('/v1/projects/:projectId/keys')
|
||||
->desc('List keys')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.read')
|
||||
->label('scope', 'keys.read')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'listKeys')
|
||||
|
|
@ -1281,7 +1281,7 @@ App::get('/v1/projects/:projectId/keys')
|
|||
App::get('/v1/projects/:projectId/keys/:keyId')
|
||||
->desc('Get key')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.read')
|
||||
->label('scope', 'keys.read')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'getKey')
|
||||
|
|
@ -1315,7 +1315,7 @@ App::get('/v1/projects/:projectId/keys/:keyId')
|
|||
App::put('/v1/projects/:projectId/keys/:keyId')
|
||||
->desc('Update key')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('scope', 'keys.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'updateKey')
|
||||
|
|
@ -1361,7 +1361,7 @@ App::put('/v1/projects/:projectId/keys/:keyId')
|
|||
App::delete('/v1/projects/:projectId/keys/:keyId')
|
||||
->desc('Delete key')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('scope', 'keys.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'deleteKey')
|
||||
|
|
@ -1436,7 +1436,7 @@ App::post('/v1/projects/:projectId/platforms')
|
|||
->desc('Create platform')
|
||||
->groups(['api', 'projects'])
|
||||
->label('audits.event', 'platforms.create')
|
||||
->label('scope', 'projects.write')
|
||||
->label('scope', 'platforms.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'createPlatform')
|
||||
|
|
@ -1486,7 +1486,7 @@ App::post('/v1/projects/:projectId/platforms')
|
|||
App::get('/v1/projects/:projectId/platforms')
|
||||
->desc('List platforms')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.read')
|
||||
->label('scope', 'platforms.read')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'listPlatforms')
|
||||
|
|
@ -1518,7 +1518,7 @@ App::get('/v1/projects/:projectId/platforms')
|
|||
App::get('/v1/projects/:projectId/platforms/:platformId')
|
||||
->desc('Get platform')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.read')
|
||||
->label('scope', 'platforms.read')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'getPlatform')
|
||||
|
|
@ -1552,7 +1552,7 @@ App::get('/v1/projects/:projectId/platforms/:platformId')
|
|||
App::put('/v1/projects/:projectId/platforms/:platformId')
|
||||
->desc('Update platform')
|
||||
->groups(['api', 'projects'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('scope', 'platforms.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'updatePlatform')
|
||||
|
|
@ -1600,7 +1600,7 @@ App::delete('/v1/projects/:projectId/platforms/:platformId')
|
|||
->desc('Delete platform')
|
||||
->groups(['api', 'projects'])
|
||||
->label('audits.event', 'platforms.delete')
|
||||
->label('scope', 'projects.write')
|
||||
->label('scope', 'platforms.write')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.namespace', 'projects')
|
||||
->label('sdk.method', 'deletePlatform')
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ use Utopia\Validator\ArrayList;
|
|||
use Utopia\Validator\Assoc;
|
||||
use Utopia\Validator\Host;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\WhiteList;
|
||||
|
||||
App::post('/v1/teams')
|
||||
->desc('Create team')
|
||||
|
|
@ -394,7 +395,17 @@ App::post('/v1/teams/:teamId/memberships')
|
|||
->param('email', '', new Email(), 'Email of the new team member.', true)
|
||||
->param('userId', '', new UID(), 'ID of the user to be added to a team.', true)
|
||||
->param('phone', '', new Phone(), 'Phone number. Format this number with a leading \'+\' and a country code, e.g., +16175551212.', true)
|
||||
->param('roles', [], new ArrayList(new Key(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 32 characters long.')
|
||||
->param('roles', [], function (Document $project) {
|
||||
if ($project->getId() === 'console') {
|
||||
;
|
||||
$roles = array_keys(Config::getParam('roles', []));
|
||||
array_filter($roles, function ($role) {
|
||||
return !in_array($role, [Auth::USER_ROLE_APPS, Auth::USER_ROLE_GUESTS, Auth::USER_ROLE_USERS]);
|
||||
});
|
||||
return new ArrayList(new WhiteList($roles), APP_LIMIT_ARRAY_PARAMS_SIZE);
|
||||
}
|
||||
return new ArrayList(new Key(), APP_LIMIT_ARRAY_PARAMS_SIZE);
|
||||
}, 'Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 32 characters long.', false, ['project'])
|
||||
->param('url', '', fn ($clients) => new Host($clients), 'URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.', true, ['clients']) // TODO add our own built-in confirm page
|
||||
->param('name', '', new Text(128), 'Name of the new team member. Max length: 128 chars.', true)
|
||||
->inject('response')
|
||||
|
|
@ -868,7 +879,17 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId')
|
|||
->label('sdk.response.model', Response::MODEL_MEMBERSHIP)
|
||||
->param('teamId', '', new UID(), 'Team ID.')
|
||||
->param('membershipId', '', new UID(), 'Membership ID.')
|
||||
->param('roles', [], new ArrayList(new Key(), APP_LIMIT_ARRAY_PARAMS_SIZE), 'An array of strings. Use this param to set the user\'s roles in the team. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 32 characters long.')
|
||||
->param('roles', [], function (Document $project) {
|
||||
if ($project->getId() === 'console') {
|
||||
;
|
||||
$roles = array_keys(Config::getParam('roles', []));
|
||||
array_filter($roles, function ($role) {
|
||||
return !in_array($role, [Auth::USER_ROLE_APPS, Auth::USER_ROLE_GUESTS, Auth::USER_ROLE_USERS]);
|
||||
});
|
||||
return new ArrayList(new WhiteList($roles), APP_LIMIT_ARRAY_PARAMS_SIZE);
|
||||
}
|
||||
return new ArrayList(new Key(), APP_LIMIT_ARRAY_PARAMS_SIZE);
|
||||
}, 'An array of strings. Use this param to set the user\'s roles in the team. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' roles are allowed, each 32 characters long.', false, ['project'])
|
||||
->inject('request')
|
||||
->inject('response')
|
||||
->inject('user')
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@ App::patch('/v1/mock/functions-v2')
|
|||
App::post('/v1/mock/api-key-unprefixed')
|
||||
->desc('Create API Key (without standard prefix)')
|
||||
->groups(['mock', 'api', 'projects'])
|
||||
->label('scope', 'projects.write')
|
||||
->label('scope', 'public')
|
||||
->label('docs', false)
|
||||
->param('projectId', '', new UID(), 'Project ID.')
|
||||
->inject('response')
|
||||
|
|
|
|||
|
|
@ -160,42 +160,22 @@ App::init()
|
|||
->inject('session')
|
||||
->inject('servers')
|
||||
->inject('mode')
|
||||
->action(function (App $utopia, Request $request, Database $dbForConsole, Document $project, Document $user, ?Document $session, array $servers, string $mode) {
|
||||
->inject('team')
|
||||
->action(function (App $utopia, Request $request, Database $dbForConsole, Document $project, Document $user, ?Document $session, array $servers, string $mode, Document $team) {
|
||||
$route = $utopia->getRoute();
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
/**
|
||||
* ACL Check
|
||||
*/
|
||||
/** Default role */
|
||||
$roles = Config::getParam('roles', []);
|
||||
$role = ($user->isEmpty())
|
||||
? Role::guests()->toString()
|
||||
: Role::users()->toString();
|
||||
|
||||
// Add user roles
|
||||
$memberships = $user->find('teamId', $project->getAttribute('teamId'), 'memberships');
|
||||
|
||||
if ($memberships) {
|
||||
foreach ($memberships->getAttribute('roles', []) as $memberRole) {
|
||||
switch ($memberRole) {
|
||||
case 'owner':
|
||||
$role = Auth::USER_ROLE_OWNER;
|
||||
break;
|
||||
case 'admin':
|
||||
$role = Auth::USER_ROLE_ADMIN;
|
||||
break;
|
||||
case 'developer':
|
||||
$role = Auth::USER_ROLE_DEVELOPER;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$roles = Config::getParam('roles', []);
|
||||
$scope = $route->getLabel('scope', 'none'); // Allowed scope for chosen route
|
||||
$scopes = $roles[$role]['scopes']; // Allowed scopes for user role
|
||||
/** Allowed Scopes for the role */
|
||||
$scopes = $roles[$role]['scopes'];
|
||||
|
||||
$apiKey = $request->getHeader('x-appwrite-key', '');
|
||||
|
||||
|
|
@ -294,13 +274,38 @@ App::init()
|
|||
}
|
||||
}
|
||||
}
|
||||
// Admin User Authentication
|
||||
elseif (($project->getId() === 'console' && !$team->isEmpty() && !$user->isEmpty()) || ($project->getId() !== 'console' && !$user->isEmpty() && $mode === APP_MODE_ADMIN)) {
|
||||
$teamId = $team->getId();
|
||||
$adminRoles = [];
|
||||
$memberships = $user->getAttribute('memberships', []);
|
||||
foreach ($memberships as $membership) {
|
||||
if ($membership->getAttribute('confirm', false) === true && $membership->getAttribute('teamId') === $teamId) {
|
||||
$adminRoles = $membership->getAttribute('roles', []);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($adminRoles)) {
|
||||
throw new Exception(Exception::USER_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
$scopes = []; // reset scope if admin
|
||||
foreach ($adminRoles as $role) {
|
||||
$scopes = \array_merge($scopes, $roles[$role]['scopes']);
|
||||
}
|
||||
|
||||
Authorization::setDefaultStatus(false); // Cancel security segmentation for admin users.
|
||||
}
|
||||
|
||||
$scopes = \array_unique($scopes);
|
||||
|
||||
Authorization::setRole($role);
|
||||
|
||||
foreach (Auth::getRoles($user) as $authRole) {
|
||||
Authorization::setRole($authRole);
|
||||
}
|
||||
|
||||
/** Do not allow access to disabled services */
|
||||
$service = $route->getLabel('sdk.namespace', '');
|
||||
if (!empty($service)) {
|
||||
if (
|
||||
|
|
@ -311,14 +316,14 @@ App::init()
|
|||
throw new Exception(Exception::GENERAL_SERVICE_DISABLED);
|
||||
}
|
||||
}
|
||||
if (!\in_array($scope, $scopes)) {
|
||||
if ($project->isEmpty()) { // Check if permission is denied because project is missing
|
||||
throw new Exception(Exception::PROJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
/** Do now allow access if scope is not allowed */
|
||||
$scope = $route->getLabel('scope', 'none');
|
||||
if (!\in_array($scope, $scopes)) {
|
||||
throw new Exception(Exception::GENERAL_UNAUTHORIZED_SCOPE, $user->getAttribute('email', 'User') . ' (role: ' . \strtolower($roles[$role]['label']) . ') missing scope (' . $scope . ')');
|
||||
}
|
||||
|
||||
/** Do not allow access to blocked accounts */
|
||||
if (false === $user->getAttribute('status')) { // Account is blocked
|
||||
throw new Exception(Exception::USER_BLOCKED);
|
||||
}
|
||||
|
|
|
|||
49
app/init.php
49
app/init.php
|
|
@ -41,6 +41,7 @@ use Appwrite\Network\Validator\Email;
|
|||
use Appwrite\Network\Validator\Origin;
|
||||
use Appwrite\OpenSSL\OpenSSL;
|
||||
use Appwrite\URL\URL as AppwriteURL;
|
||||
use Appwrite\Utopia\Request;
|
||||
use MaxMind\Db\Reader;
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use Swoole\Database\PDOProxy;
|
||||
|
|
@ -1258,13 +1259,13 @@ App::setResource('user', function ($mode, $project, $console, $request, $respons
|
|||
$user = new Document([]);
|
||||
}
|
||||
|
||||
if (APP_MODE_ADMIN === $mode) {
|
||||
if ($user->find('teamInternalId', $project->getAttribute('teamInternalId'), 'memberships')) {
|
||||
Authorization::setDefaultStatus(false); // Cancel security segmentation for admin users.
|
||||
} else {
|
||||
$user = new Document([]);
|
||||
}
|
||||
}
|
||||
// if (APP_MODE_ADMIN === $mode) {
|
||||
// if ($user->find('teamInternalId', $project->getAttribute('teamInternalId'), 'memberships')) {
|
||||
// Authorization::setDefaultStatus(false); // Cancel security segmentation for admin users.
|
||||
// } else {
|
||||
// $user = new Document([]);
|
||||
// }
|
||||
// }
|
||||
|
||||
$authJWT = $request->getHeader('x-appwrite-jwt', '');
|
||||
|
||||
|
|
@ -1341,7 +1342,7 @@ App::setResource('console', function () {
|
|||
'$collection' => ID::custom('projects'),
|
||||
'description' => 'Appwrite core engine',
|
||||
'logo' => '',
|
||||
'teamId' => -1,
|
||||
'teamId' => null,
|
||||
'webhooks' => [],
|
||||
'keys' => [],
|
||||
'platforms' => [
|
||||
|
|
@ -1769,3 +1770,35 @@ App::setResource('requestTimestamp', function ($request) {
|
|||
App::setResource('plan', function (array $plan = []) {
|
||||
return [];
|
||||
});
|
||||
|
||||
|
||||
App::setResource('team', function (Document $project, Database $dbForConsole, App $utopia, Request $request) {
|
||||
$teamInternalId = '';
|
||||
if ($project->getId() !== 'console') {
|
||||
$teamInternalId = $project->getAttribute('teamInternalId', '');
|
||||
} else {
|
||||
$route = $utopia->match($request);
|
||||
$path = $route->getPath();
|
||||
if (str_starts_with($path, '/v1/projects/:projectId')) {
|
||||
$uri = $request->getURI();
|
||||
$pid = explode('/', $uri)[3];
|
||||
$p = Authorization::skip(fn () => $dbForConsole->getDocument('projects', $pid));
|
||||
$teamInternalId = $p->getAttribute('teamInternalId', '');
|
||||
} elseif ($path === '/v1/projects') {
|
||||
$teamId = $request->getParam('teamId', '');
|
||||
$team = Authorization::skip(fn () => $dbForConsole->getDocument('teams', $teamId));
|
||||
return $team;
|
||||
}
|
||||
}
|
||||
|
||||
$team = Authorization::skip(function () use ($dbForConsole, $teamInternalId) {
|
||||
return $dbForConsole->findOne('teams', [
|
||||
Query::equal('$internalId', [$teamInternalId]),
|
||||
]);
|
||||
});
|
||||
|
||||
if (!$team) {
|
||||
$team = new Document([]);
|
||||
}
|
||||
return $team;
|
||||
}, ['project', 'dbForConsole', 'utopia', 'request']);
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ class ProjectsConsoleClientTest extends Scope
|
|||
'region' => 'default'
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
$this->assertEquals(401, $response['headers']['status-code']);
|
||||
|
||||
return [
|
||||
'projectId' => $projectId,
|
||||
|
|
@ -546,7 +546,7 @@ class ProjectsConsoleClientTest extends Scope
|
|||
'name' => '',
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
$this->assertEquals(401, $response['headers']['status-code']);
|
||||
|
||||
return ['projectId' => $projectId];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ trait TeamsBaseClient
|
|||
$this->assertNotEmpty($response['body']['userEmail']);
|
||||
$this->assertNotEmpty($response['body']['teamId']);
|
||||
$this->assertNotEmpty($response['body']['teamName']);
|
||||
$this->assertCount(2, $response['body']['roles']);
|
||||
$this->assertCount(1, $response['body']['roles']);
|
||||
$this->assertEquals(false, (new DatetimeValidator())->isValid($response['body']['joined'])); // is null in DB
|
||||
$this->assertEquals(false, $response['body']['confirm']);
|
||||
|
||||
|
|
@ -203,7 +203,7 @@ trait TeamsBaseClient
|
|||
], $this->getHeaders()), [
|
||||
'email' => $email,
|
||||
'name' => $name,
|
||||
'roles' => ['admin', 'editor'],
|
||||
'roles' => ['developer'],
|
||||
'url' => 'http://localhost:5000/join-us#title'
|
||||
]);
|
||||
|
||||
|
|
@ -214,7 +214,7 @@ trait TeamsBaseClient
|
|||
$this->assertEquals($email, $response['body']['userEmail']);
|
||||
$this->assertNotEmpty($response['body']['teamId']);
|
||||
$this->assertNotEmpty($response['body']['teamName']);
|
||||
$this->assertCount(2, $response['body']['roles']);
|
||||
$this->assertCount(1, $response['body']['roles']);
|
||||
$this->assertEquals(false, (new DatetimeValidator())->isValid($response['body']['joined'])); // is null in DB
|
||||
$this->assertEquals(false, $response['body']['confirm']);
|
||||
|
||||
|
|
@ -255,7 +255,7 @@ trait TeamsBaseClient
|
|||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'userId' => 'abcdefdg',
|
||||
'roles' => ['admin', 'editor'],
|
||||
'roles' => ['developer'],
|
||||
'url' => 'http://localhost:5000/join-us#title'
|
||||
]);
|
||||
|
||||
|
|
@ -270,7 +270,7 @@ trait TeamsBaseClient
|
|||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'userId' => $userId,
|
||||
'roles' => ['admin', 'editor'],
|
||||
'roles' => ['developer'],
|
||||
'url' => 'http://localhost:5000/join-us#title'
|
||||
]);
|
||||
|
||||
|
|
@ -281,7 +281,7 @@ trait TeamsBaseClient
|
|||
$this->assertEquals($secondEmail, $response['body']['userEmail']);
|
||||
$this->assertNotEmpty($response['body']['teamId']);
|
||||
$this->assertNotEmpty($response['body']['teamName']);
|
||||
$this->assertCount(2, $response['body']['roles']);
|
||||
$this->assertCount(1, $response['body']['roles']);
|
||||
$this->assertEquals(false, (new DateTimeValidator())->isValid($response['body']['joined'])); // is null in DB
|
||||
$this->assertEquals(false, $response['body']['confirm']);
|
||||
|
||||
|
|
@ -301,7 +301,7 @@ trait TeamsBaseClient
|
|||
], $this->getHeaders()), [
|
||||
'email' => $email,
|
||||
'name' => 'Friend User',
|
||||
'roles' => ['admin', 'editor'],
|
||||
'roles' => ['developer'],
|
||||
'url' => 'http://localhost:5000/join-us#title'
|
||||
]);
|
||||
|
||||
|
|
@ -313,7 +313,7 @@ trait TeamsBaseClient
|
|||
], $this->getHeaders()), [
|
||||
'email' => 'dasdkaskdjaskdjasjkd',
|
||||
'name' => $name,
|
||||
'roles' => ['admin', 'editor'],
|
||||
'roles' => ['developer'],
|
||||
'url' => 'http://localhost:5000/join-us#title'
|
||||
]);
|
||||
|
||||
|
|
@ -337,7 +337,7 @@ trait TeamsBaseClient
|
|||
], $this->getHeaders()), [
|
||||
'email' => $email,
|
||||
'name' => $name,
|
||||
'roles' => ['admin', 'editor'],
|
||||
'roles' => ['developer'],
|
||||
'url' => 'http://example.com/join-us#title' // bad url
|
||||
]);
|
||||
|
||||
|
|
@ -413,7 +413,7 @@ trait TeamsBaseClient
|
|||
$this->assertNotEmpty($response['body']['$id']);
|
||||
$this->assertNotEmpty($response['body']['userId']);
|
||||
$this->assertNotEmpty($response['body']['teamId']);
|
||||
$this->assertCount(2, $response['body']['roles']);
|
||||
$this->assertCount(1, $response['body']['roles']);
|
||||
$this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['joined']));
|
||||
$this->assertEquals(true, $response['body']['confirm']);
|
||||
$session = $response['cookies']['a_session_' . $this->getProject()['$id']];
|
||||
|
|
@ -571,7 +571,7 @@ trait TeamsBaseClient
|
|||
/**
|
||||
* Test for SUCCESS
|
||||
*/
|
||||
$roles = ['admin', 'editor', 'uncle'];
|
||||
$roles = ['editor', 'uncle'];
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid, array_merge([
|
||||
'origin' => 'http://localhost',
|
||||
'content-type' => 'application/json',
|
||||
|
|
@ -587,7 +587,6 @@ trait TeamsBaseClient
|
|||
$this->assertCount(count($roles), $response['body']['roles']);
|
||||
$this->assertEquals($roles[0], $response['body']['roles'][0]);
|
||||
$this->assertEquals($roles[1], $response['body']['roles'][1]);
|
||||
$this->assertEquals($roles[2], $response['body']['roles'][2]);
|
||||
|
||||
/**
|
||||
* Test for unknown team
|
||||
|
|
|
|||
|
|
@ -28,12 +28,13 @@ class TeamsConsoleClientTest extends Scope
|
|||
// Create a user account before we create a invite so we can check if the user has permissions when it shouldn't
|
||||
$user = $this->client->call(Client::METHOD_POST, '/account', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => 'console'], [
|
||||
'userId' => 'unique()',
|
||||
'email' => $email,
|
||||
'password' => $password,
|
||||
'name' => $name,
|
||||
], false);
|
||||
'x-appwrite-project' => 'console'
|
||||
], [
|
||||
'userId' => 'unique()',
|
||||
'email' => $email,
|
||||
'password' => $password,
|
||||
'name' => $name,
|
||||
], false);
|
||||
|
||||
$this->assertEquals(201, $user['headers']['status-code']);
|
||||
|
||||
|
|
@ -46,7 +47,7 @@ class TeamsConsoleClientTest extends Scope
|
|||
], $this->getHeaders()), [
|
||||
'email' => $email,
|
||||
'name' => $name,
|
||||
'roles' => ['admin', 'editor'],
|
||||
'roles' => ['developer'],
|
||||
'url' => 'http://localhost:5000/join-us#title'
|
||||
]);
|
||||
|
||||
|
|
@ -76,4 +77,75 @@ class TeamsConsoleClientTest extends Scope
|
|||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/** @depends testUpdateTeamMembership */
|
||||
public function testUpdateTeamMembershipRoles($data): array
|
||||
{
|
||||
$teamUid = $data['teamUid'] ?? '';
|
||||
$membershipUid = $data['membershipUid'] ?? '';
|
||||
$session = $data['session'] ?? '';
|
||||
|
||||
/**
|
||||
* Test for SUCCESS
|
||||
*/
|
||||
$roles = ['developer'];
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid, array_merge([
|
||||
'origin' => 'http://localhost',
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'roles' => $roles
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertNotEmpty($response['body']['$id']);
|
||||
$this->assertNotEmpty($response['body']['userId']);
|
||||
$this->assertNotEmpty($response['body']['teamId']);
|
||||
$this->assertCount(count($roles), $response['body']['roles']);
|
||||
$this->assertEquals($roles[0], $response['body']['roles'][0]);
|
||||
|
||||
/**
|
||||
* Test for unknown team
|
||||
*/
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/teams/' . 'abc' . '/memberships/' . $membershipUid, array_merge([
|
||||
'origin' => 'http://localhost',
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'roles' => $roles
|
||||
]);
|
||||
|
||||
$this->assertEquals(404, $response['headers']['status-code']);
|
||||
|
||||
/**
|
||||
* Test for unknown membership ID
|
||||
*/
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . 'abc', array_merge([
|
||||
'origin' => 'http://localhost',
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'roles' => $roles
|
||||
]);
|
||||
|
||||
$this->assertEquals(404, $response['headers']['status-code']);
|
||||
|
||||
|
||||
/**
|
||||
* Test for when a user other than the owner tries to update membership
|
||||
*/
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid, [
|
||||
'origin' => 'http://localhost',
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session,
|
||||
], [
|
||||
'roles' => $roles
|
||||
]);
|
||||
|
||||
$this->assertEquals(401, $response['headers']['status-code']);
|
||||
$this->assertEquals('User is not allowed to modify roles', $response['body']['message']);
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue