diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index bdf05bd54..32d77e5e1 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -33,14 +33,16 @@ App::post('/v1/teams') ->label('sdk.response.model', Response::MODEL_TEAM) ->param('name', null, new Text(128), 'Team name. Max length: 128 chars.') ->param('roles', ['owner'], new ArrayList(new Key()), 'Array of strings. Use this param to set the roles in the team for the user who created it. The default role is **owner**. A role can be any string. Learn more about [roles and permissions](/docs/permissions). Max length for each role is 32 chars.', true) - ->action(function ($name, $roles, $response, $user, $projectDB, $mode) { + ->action(function ($name, $roles, $response, $user, $projectDB) { /** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Database\Document $user */ /** @var Appwrite\Database\Database $projectDB */ - /** @var bool $mode */ Authorization::disable(); + $isPreviliggedUser = Auth::isPreviliggedUser(Authorization::$roles); + $isAppUser = Auth::isAppUser(Authorization::$roles); + $team = $projectDB->createDocument([ '$collection' => Database::SYSTEM_COLLECTION_TEAMS, '$permissions' => [ @@ -48,7 +50,7 @@ App::post('/v1/teams') 'write' => ['team:{self}/owner'], ], 'name' => $name, - 'sum' => ($mode !== APP_MODE_ADMIN && $user->getId()) ? 1 : 0, + 'sum' => ($isPreviliggedUser || $isAppUser) ? 0 : 1, 'dateCreated' => \time(), ]); @@ -58,7 +60,7 @@ App::post('/v1/teams') throw new Exception('Failed saving team to DB', 500); } - if ($mode !== APP_MODE_ADMIN && $user->getId()) { // Don't add user on server mode + if (!$isPreviliggedUser && !$isAppUser) { // Don't add user on server mode $membership = new Document([ '$collection' => Database::SYSTEM_COLLECTION_MEMBERSHIPS, '$permissions' => [ @@ -88,7 +90,7 @@ App::post('/v1/teams') ->setStatusCode(Response::STATUS_CODE_CREATED) ->dynamic($team, Response::MODEL_TEAM) ; - }, ['response', 'user', 'projectDB', 'mode']); + }, ['response', 'user', 'projectDB']); App::get('/v1/teams') ->desc('List Teams') @@ -246,14 +248,16 @@ App::post('/v1/teams/:teamId/memberships') ->param('name', '', new Text(128), 'New team member name. Max length: 128 chars.', true) ->param('roles', [], new ArrayList(new Key()), '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](/docs/permissions). Max length for each role is 32 chars.') ->param('url', '', function ($clients) { return new Host($clients); }, 'URL to redirect the user back to your app from the invitation email. 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.', false, ['clients']) // TODO add our own built-in confirm page - ->action(function ($teamId, $email, $name, $roles, $url, $response, $project, $user, $projectDB, $locale, $audits, $mails, $mode) { + ->action(function ($teamId, $email, $name, $roles, $url, $response, $project, $user, $projectDB, $locale, $audits, $mails) { /** @var Appwrite\Utopia\Response $response */ /** @var Appwrite\Database\Document $project */ /** @var Appwrite\Database\Document $user */ /** @var Appwrite\Database\Database $projectDB */ /** @var Appwrite\Event\Event $audits */ /** @var Appwrite\Event\Event $mails */ - /** @var bool $mode */ + + $isPreviliggedUser = Auth::isPreviliggedUser(Authorization::$roles); + $isAppUser = Auth::isAppUser(Authorization::$roles); $name = (empty($name)) ? $email : $name; $team = $projectDB->getDocument($teamId); @@ -323,7 +327,7 @@ App::post('/v1/teams/:teamId/memberships') } } - if (!$isOwner && APP_MODE_ADMIN !== $mode && $user->getId()) { // Not owner, not admin, not app (server) + if (!$isOwner && !$isPreviliggedUser && !$isAppUser) { // Not owner, not admin, not app (server) throw new Exception('User is not allowed to send invitations for this team', 401); } @@ -339,12 +343,12 @@ App::post('/v1/teams/:teamId/memberships') 'teamId' => $team->getId(), 'roles' => $roles, 'invited' => \time(), - 'joined' => (APP_MODE_ADMIN === $mode || !$user->getId()) ? \time() : 0, - 'confirm' => (APP_MODE_ADMIN === $mode || !$user->getId()), + 'joined' => ($isPreviliggedUser || $isAppUser) ? \time() : 0, + 'confirm' => ($isPreviliggedUser || $isAppUser), 'secret' => Auth::hash($secret), ]); - if (APP_MODE_ADMIN === $mode || !$user->getId()) { // Allow admin to create membership + if ($isPreviliggedUser || $isAppUser) { // Allow admin to create membership Authorization::disable(); $membership = $projectDB->createDocument($membership->getArrayCopy()); @@ -395,7 +399,7 @@ App::post('/v1/teams/:teamId/memberships') ->setParam('{{text-cta}}', '#ffffff') ; - if (APP_MODE_ADMIN !== $mode && $user->getId()) { // No need in comfirmation when in admin or app mode + if (!$isPreviliggedUser && !$isAppUser) { // No need in comfirmation when in admin or app mode $mails ->setParam('event', 'teams.membership.create') ->setParam('from', ($project->getId() === 'console') ? '' : \sprintf($locale->getText('account.emails.team'), $project->getAttribute('name'))) @@ -420,7 +424,7 @@ App::post('/v1/teams/:teamId/memberships') 'name' => $name, ])), Response::MODEL_MEMBERSHIP) ; - }, ['response', 'project', 'user', 'projectDB', 'locale', 'audits', 'mails', 'mode']); + }, ['response', 'project', 'user', 'projectDB', 'locale', 'audits', 'mails']); App::get('/v1/teams/:teamId/memberships') ->desc('Get Team Memberships') diff --git a/app/init.php b/app/init.php index 7f31739bd..3e64c8756 100644 --- a/app/init.php +++ b/app/init.php @@ -382,8 +382,7 @@ App::setResource('user', function($mode, $project, $console, $request, $response $session = Auth::decodeSession( $request->getCookie(Auth::$cookieName, // Get sessions - $request->getCookie(Auth::$cookieName.'_legacy', // Get fallback session from old clients (no SameSite support) - $request->getHeader('x-appwrite-key', '')))); // Get API Key + $request->getCookie(Auth::$cookieName.'_legacy', '')));// Get fallback session from old clients (no SameSite support) // Get fallback session from clients who block 3rd-party cookies $response->addHeader('X-Debug-Fallback', 'false'); diff --git a/src/Appwrite/Auth/Auth.php b/src/Appwrite/Auth/Auth.php index 89a0e9075..88eb11299 100644 --- a/src/Appwrite/Auth/Auth.php +++ b/src/Appwrite/Auth/Auth.php @@ -23,7 +23,6 @@ class Auth const USER_ROLE_OWNER = 4; const USER_ROLE_APP = 5; const USER_ROLE_SYSTEM = 6; - const USER_ROLE_ALL = '*'; /** * Token Types. @@ -206,4 +205,40 @@ class Auth return false; } + + /** + * Is Previligged User? + * + * @param array $roles + * + * @return bool + */ + public static function isPreviliggedUser(array $roles): bool + { + if( + array_key_exists('role:'.self::USER_ROLE_OWNER, $roles) || + array_key_exists('role:'.self::USER_ROLE_DEVELOPER, $roles) || + array_key_exists('role:'.self::USER_ROLE_ADMIN, $roles) + ) { + return true; + } + + return false; + } + + /** + * Is App User? + * + * @param array $roles + * + * @return bool + */ + public static function isAppUser(array $roles): bool + { + if(array_key_exists('role:'.self::USER_ROLE_APP, $roles)) { + return true; + } + + return false; + } }