2019-12-29 05:37:39 +13:00
|
|
|
<?php
|
|
|
|
|
2022-08-01 22:22:04 +12:00
|
|
|
namespace Tests\Unit\Auth;
|
2019-12-29 05:37:39 +13:00
|
|
|
|
2020-03-25 06:56:32 +13:00
|
|
|
use Appwrite\Auth\Auth;
|
2022-07-13 01:32:39 +12:00
|
|
|
use Utopia\Database\DateTime;
|
2021-10-08 08:19:58 +13:00
|
|
|
use Utopia\Database\Document;
|
2022-08-14 22:33:36 +12:00
|
|
|
use Utopia\Database\ID;
|
2022-08-19 16:04:33 +12:00
|
|
|
use Utopia\Database\Role;
|
2021-10-08 08:27:23 +13:00
|
|
|
use Utopia\Database\Validator\Authorization;
|
2019-12-29 05:37:39 +13:00
|
|
|
use PHPUnit\Framework\TestCase;
|
2022-07-06 04:57:19 +12:00
|
|
|
use Utopia\Database\Database;
|
2019-12-29 05:37:39 +13:00
|
|
|
|
|
|
|
class AuthTest extends TestCase
|
|
|
|
{
|
2021-10-08 09:24:09 +13:00
|
|
|
/**
|
|
|
|
* Reset Roles
|
|
|
|
*/
|
2020-10-01 10:08:58 +13:00
|
|
|
public function tearDown(): void
|
2019-12-29 05:37:39 +13:00
|
|
|
{
|
2021-10-08 09:24:09 +13:00
|
|
|
Authorization::cleanRoles();
|
2022-08-19 16:04:33 +12:00
|
|
|
Authorization::setRole(Role::any()->toString());
|
2019-12-29 05:37:39 +13:00
|
|
|
}
|
|
|
|
|
2022-08-01 22:22:04 +12:00
|
|
|
public function testCookieName(): void
|
2019-12-29 05:37:39 +13:00
|
|
|
{
|
|
|
|
$name = 'cookie-name';
|
|
|
|
|
|
|
|
$this->assertEquals(Auth::setCookieName($name), $name);
|
|
|
|
$this->assertEquals(Auth::$cookieName, $name);
|
|
|
|
}
|
|
|
|
|
2022-08-01 22:22:04 +12:00
|
|
|
public function testEncodeDecodeSession(): void
|
2019-12-29 05:37:39 +13:00
|
|
|
{
|
|
|
|
$id = 'id';
|
|
|
|
$secret = 'secret';
|
|
|
|
$session = 'eyJpZCI6ImlkIiwic2VjcmV0Ijoic2VjcmV0In0=';
|
|
|
|
|
|
|
|
$this->assertEquals(Auth::encodeSession($id, $secret), $session);
|
|
|
|
$this->assertEquals(Auth::decodeSession($session), ['id' => $id, 'secret' => $secret]);
|
|
|
|
}
|
2022-05-24 02:54:50 +12:00
|
|
|
|
2022-08-01 22:22:04 +12:00
|
|
|
public function testHash(): void
|
2019-12-29 05:37:39 +13:00
|
|
|
{
|
|
|
|
$secret = 'secret';
|
|
|
|
$this->assertEquals(Auth::hash($secret), '2bb80d537b1da3e38bd30361aa855686bde0eacd7162fef6a25fe97bf527a25b');
|
|
|
|
}
|
2022-05-24 02:54:50 +12:00
|
|
|
|
2022-08-01 22:22:04 +12:00
|
|
|
public function testPassword(): void
|
2019-12-29 05:37:39 +13:00
|
|
|
{
|
|
|
|
$secret = 'secret';
|
|
|
|
$static = '$2y$08$PDbMtV18J1KOBI9tIYabBuyUwBrtXPGhLxCy9pWP6xkldVOKLrLKy';
|
|
|
|
$dynamic = Auth::passwordHash($secret);
|
2022-05-24 02:54:50 +12:00
|
|
|
|
2019-12-29 05:37:39 +13:00
|
|
|
$this->assertEquals(Auth::passwordVerify($secret, $dynamic), true);
|
|
|
|
$this->assertEquals(Auth::passwordVerify($secret, $static), true);
|
|
|
|
}
|
2022-05-24 02:54:50 +12:00
|
|
|
|
2022-08-01 22:22:04 +12:00
|
|
|
public function testPasswordGenerator(): void
|
2019-12-29 05:37:39 +13:00
|
|
|
{
|
|
|
|
$this->assertEquals(\mb_strlen(Auth::passwordGenerator()), 40);
|
|
|
|
$this->assertEquals(\mb_strlen(Auth::passwordGenerator(5)), 10);
|
|
|
|
}
|
2022-05-24 02:54:50 +12:00
|
|
|
|
2022-08-01 22:22:04 +12:00
|
|
|
public function testTokenGenerator(): void
|
2019-12-29 05:37:39 +13:00
|
|
|
{
|
|
|
|
$this->assertEquals(\mb_strlen(Auth::tokenGenerator()), 256);
|
|
|
|
$this->assertEquals(\mb_strlen(Auth::tokenGenerator(5)), 10);
|
|
|
|
}
|
2022-05-24 02:54:50 +12:00
|
|
|
|
2022-08-01 22:22:04 +12:00
|
|
|
public function testSessionVerify(): void
|
2021-02-20 01:12:47 +13:00
|
|
|
{
|
|
|
|
$secret = 'secret1';
|
|
|
|
$hash = Auth::hash($secret);
|
|
|
|
$tokens1 = [
|
|
|
|
new Document([
|
2022-08-14 22:33:36 +12:00
|
|
|
'$id' => ID::custom('token1'),
|
2022-08-16 07:18:37 +12:00
|
|
|
'expire' => DateTime::formatTz(DateTime::addSeconds(new \DateTime(), 60 * 60 * 24)),
|
2021-02-20 01:12:47 +13:00
|
|
|
'secret' => $hash,
|
|
|
|
'provider' => Auth::SESSION_PROVIDER_EMAIL,
|
|
|
|
'providerUid' => 'test@example.com',
|
|
|
|
]),
|
|
|
|
new Document([
|
2022-08-14 22:33:36 +12:00
|
|
|
'$id' => ID::custom('token2'),
|
2022-08-16 07:18:37 +12:00
|
|
|
'expire' => DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -60 * 60 * 24)),
|
2021-02-20 01:12:47 +13:00
|
|
|
'secret' => 'secret2',
|
|
|
|
'provider' => Auth::SESSION_PROVIDER_EMAIL,
|
|
|
|
'providerUid' => 'test@example.com',
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
$tokens2 = [
|
|
|
|
new Document([ // Correct secret and type time, wrong expire time
|
2022-08-14 22:33:36 +12:00
|
|
|
'$id' => ID::custom('token1'),
|
2022-08-16 07:18:37 +12:00
|
|
|
'expire' => DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -60 * 60 * 24)),
|
2021-02-20 01:12:47 +13:00
|
|
|
'secret' => $hash,
|
|
|
|
'provider' => Auth::SESSION_PROVIDER_EMAIL,
|
|
|
|
'providerUid' => 'test@example.com',
|
|
|
|
]),
|
|
|
|
new Document([
|
2022-08-14 22:33:36 +12:00
|
|
|
'$id' => ID::custom('token2'),
|
2022-08-16 07:18:37 +12:00
|
|
|
'expire' => DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -60 * 60 * 24)),
|
2021-02-20 01:12:47 +13:00
|
|
|
'secret' => 'secret2',
|
|
|
|
'provider' => Auth::SESSION_PROVIDER_EMAIL,
|
|
|
|
'providerUid' => 'test@example.com',
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
$this->assertEquals(Auth::sessionVerify($tokens1, $secret), 'token1');
|
|
|
|
$this->assertEquals(Auth::sessionVerify($tokens1, 'false-secret'), false);
|
|
|
|
$this->assertEquals(Auth::sessionVerify($tokens2, $secret), false);
|
|
|
|
$this->assertEquals(Auth::sessionVerify($tokens2, 'false-secret'), false);
|
|
|
|
}
|
|
|
|
|
2022-08-01 22:22:04 +12:00
|
|
|
public function testTokenVerify(): void
|
2019-12-29 05:37:39 +13:00
|
|
|
{
|
|
|
|
$secret = 'secret1';
|
|
|
|
$hash = Auth::hash($secret);
|
|
|
|
$tokens1 = [
|
|
|
|
new Document([
|
2022-08-14 22:33:36 +12:00
|
|
|
'$id' => ID::custom('token1'),
|
2021-02-20 01:12:47 +13:00
|
|
|
'type' => Auth::TOKEN_TYPE_RECOVERY,
|
2022-08-16 07:18:37 +12:00
|
|
|
'expire' => DateTime::formatTz(DateTime::addSeconds(new \DateTime(), 60 * 60 * 24)),
|
2019-12-29 05:37:39 +13:00
|
|
|
'secret' => $hash,
|
|
|
|
]),
|
|
|
|
new Document([
|
2022-08-14 22:33:36 +12:00
|
|
|
'$id' => ID::custom('token2'),
|
2021-02-20 01:12:47 +13:00
|
|
|
'type' => Auth::TOKEN_TYPE_RECOVERY,
|
2022-08-16 07:18:37 +12:00
|
|
|
'expire' => DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -60 * 60 * 24)),
|
2019-12-29 05:37:39 +13:00
|
|
|
'secret' => 'secret2',
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
$tokens2 = [
|
|
|
|
new Document([ // Correct secret and type time, wrong expire time
|
2022-08-14 22:33:36 +12:00
|
|
|
'$id' => ID::custom('token1'),
|
2021-02-20 01:12:47 +13:00
|
|
|
'type' => Auth::TOKEN_TYPE_RECOVERY,
|
2022-08-16 07:18:37 +12:00
|
|
|
'expire' => DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -60 * 60 * 24)),
|
2019-12-29 05:37:39 +13:00
|
|
|
'secret' => $hash,
|
|
|
|
]),
|
|
|
|
new Document([
|
2022-08-14 22:33:36 +12:00
|
|
|
'$id' => ID::custom('token2'),
|
2021-02-20 01:12:47 +13:00
|
|
|
'type' => Auth::TOKEN_TYPE_RECOVERY,
|
2022-08-16 07:18:37 +12:00
|
|
|
'expire' => DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -60 * 60 * 24)),
|
2019-12-29 05:37:39 +13:00
|
|
|
'secret' => 'secret2',
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
|
|
|
$tokens3 = [ // Correct secret and expire time, wrong type
|
|
|
|
new Document([
|
2022-08-14 22:33:36 +12:00
|
|
|
'$id' => ID::custom('token1'),
|
2021-02-20 01:12:47 +13:00
|
|
|
'type' => Auth::TOKEN_TYPE_INVITE,
|
2022-08-16 07:18:37 +12:00
|
|
|
'expire' => DateTime::formatTz(DateTime::addSeconds(new \DateTime(), 60 * 60 * 24)),
|
2019-12-29 05:37:39 +13:00
|
|
|
'secret' => $hash,
|
|
|
|
]),
|
|
|
|
new Document([
|
2022-08-14 22:33:36 +12:00
|
|
|
'$id' => ID::custom('token2'),
|
2021-02-20 01:12:47 +13:00
|
|
|
'type' => Auth::TOKEN_TYPE_RECOVERY,
|
2022-08-16 07:18:37 +12:00
|
|
|
'expire' => DateTime::formatTz(DateTime::addSeconds(new \DateTime(), -60 * 60 * 24)),
|
2019-12-29 05:37:39 +13:00
|
|
|
'secret' => 'secret2',
|
|
|
|
]),
|
|
|
|
];
|
|
|
|
|
2021-02-20 01:12:47 +13:00
|
|
|
$this->assertEquals(Auth::tokenVerify($tokens1, Auth::TOKEN_TYPE_RECOVERY, $secret), 'token1');
|
|
|
|
$this->assertEquals(Auth::tokenVerify($tokens1, Auth::TOKEN_TYPE_RECOVERY, 'false-secret'), false);
|
|
|
|
$this->assertEquals(Auth::tokenVerify($tokens2, Auth::TOKEN_TYPE_RECOVERY, $secret), false);
|
|
|
|
$this->assertEquals(Auth::tokenVerify($tokens2, Auth::TOKEN_TYPE_RECOVERY, 'false-secret'), false);
|
|
|
|
$this->assertEquals(Auth::tokenVerify($tokens3, Auth::TOKEN_TYPE_RECOVERY, $secret), false);
|
|
|
|
$this->assertEquals(Auth::tokenVerify($tokens3, Auth::TOKEN_TYPE_RECOVERY, 'false-secret'), false);
|
2019-12-29 05:37:39 +13:00
|
|
|
}
|
2020-11-20 19:48:25 +13:00
|
|
|
|
2022-08-01 22:22:04 +12:00
|
|
|
public function testIsPrivilegedUser(): void
|
2020-11-20 19:48:25 +13:00
|
|
|
{
|
2021-03-02 10:04:53 +13:00
|
|
|
$this->assertEquals(false, Auth::isPrivilegedUser([]));
|
2022-08-19 16:04:33 +12:00
|
|
|
$this->assertEquals(false, Auth::isPrivilegedUser([Role::guests()->toString()]));
|
|
|
|
$this->assertEquals(false, Auth::isPrivilegedUser([Role::users()->toString()]));
|
2022-08-03 21:52:34 +12:00
|
|
|
$this->assertEquals(true, Auth::isPrivilegedUser([Auth::USER_ROLE_ADMIN]));
|
|
|
|
$this->assertEquals(true, Auth::isPrivilegedUser([Auth::USER_ROLE_DEVELOPER]));
|
|
|
|
$this->assertEquals(true, Auth::isPrivilegedUser([Auth::USER_ROLE_OWNER]));
|
2022-08-15 19:20:10 +12:00
|
|
|
$this->assertEquals(false, Auth::isPrivilegedUser([Auth::USER_ROLE_APPS]));
|
2022-08-03 21:52:34 +12:00
|
|
|
$this->assertEquals(false, Auth::isPrivilegedUser([Auth::USER_ROLE_SYSTEM]));
|
|
|
|
|
2022-08-15 19:20:10 +12:00
|
|
|
$this->assertEquals(false, Auth::isPrivilegedUser([Auth::USER_ROLE_APPS, Auth::USER_ROLE_APPS]));
|
2022-08-19 16:04:33 +12:00
|
|
|
$this->assertEquals(false, Auth::isPrivilegedUser([Auth::USER_ROLE_APPS, Role::guests()->toString()]));
|
|
|
|
$this->assertEquals(true, Auth::isPrivilegedUser([Auth::USER_ROLE_OWNER, Role::guests()->toString()]));
|
2022-08-03 21:52:34 +12:00
|
|
|
$this->assertEquals(true, Auth::isPrivilegedUser([Auth::USER_ROLE_OWNER, Auth::USER_ROLE_ADMIN, Auth::USER_ROLE_DEVELOPER]));
|
2020-11-20 19:48:25 +13:00
|
|
|
}
|
2022-05-24 02:54:50 +12:00
|
|
|
|
2022-08-01 22:22:04 +12:00
|
|
|
public function testIsAppUser(): void
|
2020-11-20 19:48:25 +13:00
|
|
|
{
|
|
|
|
$this->assertEquals(false, Auth::isAppUser([]));
|
2022-08-19 16:04:33 +12:00
|
|
|
$this->assertEquals(false, Auth::isAppUser([Role::guests()->toString()]));
|
|
|
|
$this->assertEquals(false, Auth::isAppUser([Role::users()->toString()]));
|
2022-08-03 21:52:34 +12:00
|
|
|
$this->assertEquals(false, Auth::isAppUser([Auth::USER_ROLE_ADMIN]));
|
|
|
|
$this->assertEquals(false, Auth::isAppUser([Auth::USER_ROLE_DEVELOPER]));
|
|
|
|
$this->assertEquals(false, Auth::isAppUser([Auth::USER_ROLE_OWNER]));
|
2022-08-15 19:20:10 +12:00
|
|
|
$this->assertEquals(true, Auth::isAppUser([Auth::USER_ROLE_APPS]));
|
2022-08-03 21:52:34 +12:00
|
|
|
$this->assertEquals(false, Auth::isAppUser([Auth::USER_ROLE_SYSTEM]));
|
|
|
|
|
2022-08-15 19:20:10 +12:00
|
|
|
$this->assertEquals(true, Auth::isAppUser([Auth::USER_ROLE_APPS, Auth::USER_ROLE_APPS]));
|
2022-08-19 16:04:33 +12:00
|
|
|
$this->assertEquals(true, Auth::isAppUser([Auth::USER_ROLE_APPS, Role::guests()->toString()]));
|
|
|
|
$this->assertEquals(false, Auth::isAppUser([Auth::USER_ROLE_OWNER, Role::guests()->toString()]));
|
2022-08-03 21:52:34 +12:00
|
|
|
$this->assertEquals(false, Auth::isAppUser([Auth::USER_ROLE_OWNER, Auth::USER_ROLE_ADMIN, Auth::USER_ROLE_DEVELOPER]));
|
2020-11-20 19:48:25 +13:00
|
|
|
}
|
2021-06-30 01:11:14 +12:00
|
|
|
|
2022-08-01 22:22:04 +12:00
|
|
|
public function testGuestRoles(): void
|
2021-06-30 01:11:14 +12:00
|
|
|
{
|
|
|
|
$user = new Document([
|
|
|
|
'$id' => ''
|
|
|
|
]);
|
|
|
|
|
|
|
|
$roles = Auth::getRoles($user);
|
2021-07-01 02:04:32 +12:00
|
|
|
$this->assertCount(1, $roles);
|
2022-08-19 16:04:33 +12:00
|
|
|
$this->assertContains(Role::guests()->toString(), $roles);
|
2021-06-30 01:11:14 +12:00
|
|
|
}
|
|
|
|
|
2022-08-01 22:22:04 +12:00
|
|
|
public function testUserRoles(): void
|
2021-06-30 01:11:14 +12:00
|
|
|
{
|
|
|
|
$user = new Document([
|
2022-08-14 22:33:36 +12:00
|
|
|
'$id' => ID::custom('123'),
|
2021-06-30 01:11:14 +12:00
|
|
|
'memberships' => [
|
|
|
|
[
|
2022-08-14 22:33:36 +12:00
|
|
|
'teamId' => ID::custom('abc'),
|
2021-06-30 01:11:14 +12:00
|
|
|
'roles' => [
|
|
|
|
'administrator',
|
|
|
|
'moderator'
|
|
|
|
]
|
|
|
|
],
|
|
|
|
[
|
2022-08-14 22:33:36 +12:00
|
|
|
'teamId' => ID::custom('def'),
|
2021-06-30 01:11:14 +12:00
|
|
|
'roles' => [
|
|
|
|
'guest'
|
|
|
|
]
|
|
|
|
]
|
|
|
|
]
|
|
|
|
]);
|
|
|
|
|
|
|
|
$roles = Auth::getRoles($user);
|
|
|
|
|
2021-07-01 19:19:48 +12:00
|
|
|
$this->assertCount(7, $roles);
|
2022-08-03 16:17:49 +12:00
|
|
|
$this->assertContains('users', $roles);
|
2021-06-30 01:11:14 +12:00
|
|
|
$this->assertContains('user:123', $roles);
|
|
|
|
$this->assertContains('team:abc', $roles);
|
|
|
|
$this->assertContains('team:abc/administrator', $roles);
|
|
|
|
$this->assertContains('team:abc/moderator', $roles);
|
|
|
|
$this->assertContains('team:def', $roles);
|
|
|
|
$this->assertContains('team:def/guest', $roles);
|
|
|
|
}
|
2021-09-04 03:59:02 +12:00
|
|
|
|
2022-08-01 22:22:04 +12:00
|
|
|
public function testPrivilegedUserRoles(): void
|
2021-09-04 04:05:50 +12:00
|
|
|
{
|
2022-08-03 21:52:34 +12:00
|
|
|
Authorization::setRole(Auth::USER_ROLE_OWNER);
|
2021-09-04 04:05:50 +12:00
|
|
|
$user = new Document([
|
2022-08-14 22:33:36 +12:00
|
|
|
'$id' => ID::custom('123'),
|
2021-09-04 04:05:50 +12:00
|
|
|
'memberships' => [
|
|
|
|
[
|
2022-08-14 22:33:36 +12:00
|
|
|
'teamId' => ID::custom('abc'),
|
2021-09-04 04:05:50 +12:00
|
|
|
'roles' => [
|
|
|
|
'administrator',
|
|
|
|
'moderator'
|
|
|
|
]
|
|
|
|
],
|
|
|
|
[
|
2022-08-14 22:33:36 +12:00
|
|
|
'teamId' => ID::custom('def'),
|
2021-09-04 04:05:50 +12:00
|
|
|
'roles' => [
|
|
|
|
'guest'
|
|
|
|
]
|
|
|
|
]
|
|
|
|
]
|
|
|
|
]);
|
|
|
|
|
|
|
|
$roles = Auth::getRoles($user);
|
|
|
|
|
|
|
|
$this->assertCount(5, $roles);
|
2022-08-03 16:17:49 +12:00
|
|
|
$this->assertNotContains('users', $roles);
|
2021-09-04 04:05:50 +12:00
|
|
|
$this->assertNotContains('user:123', $roles);
|
|
|
|
$this->assertContains('team:abc', $roles);
|
|
|
|
$this->assertContains('team:abc/administrator', $roles);
|
|
|
|
$this->assertContains('team:abc/moderator', $roles);
|
|
|
|
$this->assertContains('team:def', $roles);
|
|
|
|
$this->assertContains('team:def/guest', $roles);
|
|
|
|
}
|
|
|
|
|
2022-08-01 22:22:04 +12:00
|
|
|
public function testAppUserRoles(): void
|
2021-09-04 03:59:02 +12:00
|
|
|
{
|
2022-08-15 19:20:10 +12:00
|
|
|
Authorization::setRole(Auth::USER_ROLE_APPS);
|
2021-09-04 03:59:02 +12:00
|
|
|
$user = new Document([
|
2022-08-14 22:33:36 +12:00
|
|
|
'$id' => ID::custom('123'),
|
2021-09-04 03:59:02 +12:00
|
|
|
'memberships' => [
|
|
|
|
[
|
2022-08-14 22:33:36 +12:00
|
|
|
'teamId' => ID::custom('abc'),
|
2021-09-04 03:59:02 +12:00
|
|
|
'roles' => [
|
|
|
|
'administrator',
|
|
|
|
'moderator'
|
|
|
|
]
|
|
|
|
],
|
|
|
|
[
|
2022-08-14 22:33:36 +12:00
|
|
|
'teamId' => ID::custom('def'),
|
2021-09-04 03:59:02 +12:00
|
|
|
'roles' => [
|
|
|
|
'guest'
|
|
|
|
]
|
|
|
|
]
|
|
|
|
]
|
|
|
|
]);
|
|
|
|
|
|
|
|
$roles = Auth::getRoles($user);
|
|
|
|
|
|
|
|
$this->assertCount(5, $roles);
|
2022-08-03 16:17:49 +12:00
|
|
|
$this->assertNotContains('users', $roles);
|
2021-09-04 03:59:02 +12:00
|
|
|
$this->assertNotContains('user:123', $roles);
|
|
|
|
$this->assertContains('team:abc', $roles);
|
|
|
|
$this->assertContains('team:abc/administrator', $roles);
|
|
|
|
$this->assertContains('team:abc/moderator', $roles);
|
|
|
|
$this->assertContains('team:def', $roles);
|
|
|
|
$this->assertContains('team:def/guest', $roles);
|
|
|
|
}
|
2020-10-01 10:08:58 +13:00
|
|
|
}
|