diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index a42eb8a885..9e884e8753 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -6,7 +6,6 @@ use Utopia\Exception; use Utopia\Response; use Utopia\Validator\ArrayList; use Utopia\Validator\Boolean; -use Utopia\Validator\Domain as DomainValidator; use Utopia\Validator\Text; use Utopia\Validator\WhiteList; use Utopia\Validator\URL; @@ -19,6 +18,7 @@ use Appwrite\Database\Document; use Appwrite\Database\Validator\UID; use Appwrite\OpenSSL\OpenSSL; use Appwrite\Network\Validator\CNAME; +use Appwrite\Network\Validator\Domain as DomainValidator; use Cron\CronExpression; $scopes = include __DIR__.'/../../../app/config/scopes.php'; diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index e0cf3f8d2a..8981695aa3 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -51,7 +51,7 @@ $utopia->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 ($mode !== APP_MODE_ADMIN && $user->getId()) { // Don't add user on app/server mode $membership = new Document([ '$collection' => Database::SYSTEM_COLLECTION_MEMBERSHIPS, '$permissions' => [ @@ -219,7 +219,7 @@ $utopia->post('/v1/teams/:teamId/memberships') ->param('roles', [], function () { return new ArrayList(new Text(128)); }, '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).') ->param('url', '', function () use ($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.') // TODO add our own built-in confirm page ->action( - function ($teamId, $email, $name, $roles, $url) use ($response, $mail, $project, $user, $audit, $projectDB, $mode) { + function ($teamId, $email, $name, $roles, $url) use ($response, $mail, $project, $user, $audit, $projectDB, &$mode) { $name = (empty($name)) ? $email : $name; $team = $projectDB->getDocument($teamId); @@ -288,7 +288,7 @@ $utopia->post('/v1/teams/:teamId/memberships') } } - if (!$isOwner && (APP_MODE_ADMIN !== $mode)) { + if (!$isOwner && APP_MODE_ADMIN !== $mode && $user->getId()) { // Not owner, not admin, not app (server) throw new Exception('User is not allowed to send invitations for this team', 401); } @@ -304,14 +304,28 @@ $utopia->post('/v1/teams/:teamId/memberships') 'teamId' => $team->getId(), 'roles' => $roles, 'invited' => \time(), - 'joined' => 0, - 'confirm' => (APP_MODE_ADMIN === $mode), + 'joined' => (APP_MODE_ADMIN === $mode || !$user->getId()) ? \time() : 0, + 'confirm' => (APP_MODE_ADMIN === $mode || !$user->getId()), 'secret' => Auth::hash($secret), ]); - if (APP_MODE_ADMIN === $mode) { // Allow admin to create membership + if (APP_MODE_ADMIN === $mode || !$user->getId()) { // Allow admin to create membership Authorization::disable(); $membership = $projectDB->createDocument($membership->getArrayCopy()); + + $team = $projectDB->updateDocument(\array_merge($team->getArrayCopy(), [ + 'sum' => $team->getAttribute('sum', 0) + 1, + ])); + + // Attach user to team + $invitee->setAttribute('memberships', $membership, Document::SET_TYPE_APPEND); + + $invitee = $projectDB->updateDocument($invitee->getArrayCopy()); + + if (false === $invitee) { + throw new Exception('Failed saving user to DB', 500); + } + Authorization::reset(); } else { $membership = $projectDB->createDocument($membership->getArrayCopy()); @@ -346,7 +360,7 @@ $utopia->post('/v1/teams/:teamId/memberships') ->setParam('{{text-cta}}', '#ffffff') ; - if (APP_MODE_ADMIN !== $mode) { // No need in comfirmation when in admin mode + if (APP_MODE_ADMIN !== $mode && $user->getId()) { // No need in comfirmation when in admin or app mode $mail ->setParam('event', 'teams.membership.create') ->setParam('recipient', $email) diff --git a/app/views/console/settings/index.phtml b/app/views/console/settings/index.phtml index a16812a63e..d4c2c359fe 100644 --- a/app/views/console/settings/index.phtml +++ b/app/views/console/settings/index.phtml @@ -361,7 +361,7 @@ $customDomainsTarget = $this->getParam('customDomainsTarget', false); - +
diff --git a/composer.json b/composer.json index 78b0fd76cc..bde9cb7a31 100644 --- a/composer.json +++ b/composer.json @@ -32,7 +32,7 @@ "appwrite/php-clamav": "1.0.*", - "utopia-php/framework": "0.4.0", + "utopia-php/framework": "0.4.1", "utopia-php/abuse": "0.2.*", "utopia-php/audit": "0.3.*", "utopia-php/cache": "0.2.*", diff --git a/src/Appwrite/Auth/OAuth2/PaypalSandbox.php b/src/Appwrite/Auth/OAuth2/PaypalSandbox.php index 7ca628f6bb..8c4baee6ba 100644 --- a/src/Appwrite/Auth/OAuth2/PaypalSandbox.php +++ b/src/Appwrite/Auth/OAuth2/PaypalSandbox.php @@ -7,7 +7,7 @@ use Appwrite\Auth\OAuth2\Paypal; class PaypalSandbox extends Paypal { - protected environment = 'sandbox'; + protected $environment = 'sandbox'; /** * @return string diff --git a/src/Appwrite/Network/Validator/Domain.php b/src/Appwrite/Network/Validator/Domain.php new file mode 100644 index 0000000000..848e338d60 --- /dev/null +++ b/src/Appwrite/Network/Validator/Domain.php @@ -0,0 +1,54 @@ +domain = new Domain(); + } + + public function tearDown() + { + $this->domain = null; + } + + public function testIsValid() + { + // Assertions + $this->assertEquals(true, $this->domain->isValid('example.com')); + $this->assertEquals(true, $this->domain->isValid('subdomain.example.com')); + $this->assertEquals(true, $this->domain->isValid('subdomain.example-app.com')); + $this->assertEquals(true, $this->domain->isValid('subdomain.example_app.com')); + $this->assertEquals(true, $this->domain->isValid('subdomain-new.example.com')); + $this->assertEquals(true, $this->domain->isValid('subdomain_new.example.com')); + $this->assertEquals(true, $this->domain->isValid('localhost')); + $this->assertEquals(true, $this->domain->isValid('appwrite.io')); + $this->assertEquals(true, $this->domain->isValid('appwrite.org')); + $this->assertEquals(true, $this->domain->isValid('appwrite.org')); + $this->assertEquals(false, $this->domain->isValid(false)); + $this->assertEquals(false, $this->domain->isValid('.')); + $this->assertEquals(false, $this->domain->isValid('..')); + $this->assertEquals(false, $this->domain->isValid('')); + $this->assertEquals(false, $this->domain->isValid(['string', 'string'])); + $this->assertEquals(false, $this->domain->isValid(1)); + $this->assertEquals(false, $this->domain->isValid(1.2)); + } +} \ No newline at end of file