1
0
Fork 0
mirror of synced 2024-06-27 18:50:47 +12:00

Start work on identities implementation

This commit is contained in:
Bradley Schofield 2023-08-09 16:18:17 +01:00
parent 7d60e4272d
commit 1135060681
No known key found for this signature in database
GPG key ID: CDDF1217D7D66C9D
4 changed files with 108 additions and 80 deletions

View file

@ -243,39 +243,6 @@ $commonCollections = [
'array' => false,
'filters' => ['datetime'],
],
[
'$id' => ID::custom('migrationsFirebaseAccessToken'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => 16384,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => ['encrypt'],
],
[
'$id' => ID::custom('migrationsFirebaseAccessTokenExpiry'),
'type' => Database::VAR_DATETIME,
'format' => '',
'size' => 0,
'signed' => false,
'required' => false,
'default' => null,
'array' => false,
'filters' => ['datetime'],
],
[
'$id' => ID::custom('migrationsFirebaseRefreshToken'),
'type' => Database::VAR_STRING,
'format' => '',
'size' => 16384,
'signed' => true,
'required' => false,
'default' => null,
'array' => false,
'filters' => ['encrypt'],
],
[
'$id' => ID::custom('migrationsFirebaseServiceAccount'),
'type' => Database::VAR_STRING,

View file

@ -5,6 +5,8 @@ use Appwrite\Event\Delete;
use Appwrite\Event\Event;
use Appwrite\Event\Migration;
use Appwrite\Extend\Exception;
use Appwrite\Permission;
use Appwrite\Role;
use Appwrite\Utopia\Database\Validator\Queries\Migrations;
use Appwrite\Utopia\Request;
use Appwrite\Utopia\Response;
@ -161,9 +163,18 @@ App::post('/v1/migrations/firebase/oauth')
$request->getProtocol() . '://' . $request->getHostname() . '/v1/migrations/firebase/redirect'
);
$accessToken = $user->getAttribute('migrationsFirebaseAccessToken');
$refreshToken = $user->getAttribute('migrationsFirebaseRefreshToken');
$accessTokenExpiry = $user->getAttribute('migrationsFirebaseAccessTokenExpiry');
$identity = $dbForConsole->findOne('identities', [
Query::equal('provider', ['firebase']),
Query::equal('userInternalId', [$user->getInternalId()]),
]);
if ($identity === false || $identity->isEmpty()) {
throw new Exception(Exception::GENERAL_SERVER_ERROR); //TODO: REMOVE
// throw new Exception(Exception::USER_IDENTITY_NOT_FOUND);
}
$accessToken = $identity->getAttribute('providerAccessToken');
$refreshToken = $identity->getAttribute('providerRefreshToken');
$accessTokenExpiry = $identity->getAttribute('providerAccessTokenExpiry');
$isExpired = new \DateTime($accessTokenExpiry) < new \DateTime('now');
if ($isExpired) {
@ -178,12 +189,12 @@ App::post('/v1/migrations/firebase/oauth')
throw new Exception(Exception::GENERAL_RATE_LIMIT_EXCEEDED, 'Another request is currently refreshing OAuth token. Please try again.');
}
$user = $user
->setAttribute('migrationsFirebaseAccessToken', $accessToken)
->setAttribute('migrationsFirebaseRefreshToken', $refreshToken)
->setAttribute('migrationsFirebaseAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int) $firebase->getAccessTokenExpiry('')));
$identity = $identity
->setAttribute('providerAccessToken', $accessToken)
->setAttribute('providerRefreshToken', $refreshToken)
->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$firebase->getAccessTokenExpiry('')));
$dbForConsole->updateDocument('users', $user->getId(), $user);
$dbForConsole->updateDocument('identities', $identity->getId(), $identity);
}
if ($user->getAttribute('migrationsFirebaseServiceAccount')) {
@ -499,9 +510,18 @@ App::get('/v1/migrations/firebase/report/oauth')
$request->getProtocol() . '://' . $request->getHostname() . '/v1/migrations/firebase/redirect'
);
$accessToken = $user->getAttribute('migrationsFirebaseAccessToken');
$refreshToken = $user->getAttribute('migrationsFirebaseRefreshToken');
$accessTokenExpiry = $user->getAttribute('migrationsFirebaseAccessTokenExpiry');
$identity = $dbForConsole->findOne('identities', [
Query::equal('provider', ['firebase']),
Query::equal('userInternalId', [$user->getInternalId()]),
]);
if ($identity === false || $identity->isEmpty()) {
throw new Exception(Exception::GENERAL_SERVER_ERROR); //TODO: REMOVE
// throw new Exception(Exception::USER_IDENTITY_NOT_FOUND);
}
$accessToken = $identity->getAttribute('providerAccessToken');
$refreshToken = $identity->getAttribute('providerRefreshToken');
$accessTokenExpiry = $identity->getAttribute('providerAccessTokenExpiry');
$isExpired = new \DateTime($accessTokenExpiry) < new \DateTime('now');
if ($isExpired) {
@ -516,12 +536,12 @@ App::get('/v1/migrations/firebase/report/oauth')
throw new Exception(Exception::GENERAL_RATE_LIMIT_EXCEEDED, 'Another request is currently refreshing OAuth token. Please try again.');
}
$user = $user
->setAttribute('migrationsFirebaseAccessToken', $accessToken)
->setAttribute('migrationsFirebaseRefreshToken', $refreshToken)
->setAttribute('migrationsFirebaseAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int) $firebase->getAccessTokenExpiry('')));
$identity = $identity
->setAttribute('providerAccessToken', $accessToken)
->setAttribute('providerRefreshToken', $refreshToken)
->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$firebase->getAccessTokenExpiry('')));
$dbForConsole->updateDocument('users', $user->getId(), $user);
$dbForConsole->updateDocument('identities', $identity->getId(), $identity);
}
// Get Service Account
@ -641,6 +661,8 @@ App::get('/v1/migrations/firebase/redirect')
$accessToken = $oauth2->getAccessToken($code);
$refreshToken = $oauth2->getRefreshToken($code);
$accessTokenExpiry = $oauth2->getAccessTokenExpiry($code);
$email = $oauth2->getUserEmail($accessToken);
$oauth2ID = $oauth2->getUserID($accessToken);
if (empty($accessToken)) {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to get access token.');
@ -654,12 +676,42 @@ App::get('/v1/migrations/firebase/redirect')
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to get access token expiry.');
}
$user = $user
->setAttribute('migrationsFirebaseAccessToken', $accessToken)
->setAttribute('migrationsFirebaseRefreshToken', $refreshToken)
->setAttribute('migrationsFirebaseAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int) $accessTokenExpiry));
// Makes sure this email is not already used in another identity
$identity = $dbForConsole->findOne('identities', [
Query::equal('providerEmail', [$email]),
]);
$dbForConsole->updateDocument('users', $user->getId(), $user);
if ($identity !== false && !$identity->isEmpty()) {
if ($identity->getAttribute('userInternalId', '') !== $user->getInternalId()) {
throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS);
}
}
if ($identity !== false && !$identity->isEmpty()) {
$identity = $identity
->setAttribute('providerAccessToken', $accessToken)
->setAttribute('providerRefreshToken', $refreshToken)
->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$accessTokenExpiry));
$dbForConsole->updateDocument('identities', $identity->getId(), $identity);
} else {
$identity = $dbForConsole->createDocument('identities', new Document([
'$id' => ID::unique(),
'$permissions' => [
Permission::read(Role::any()),
Permission::update(Role::user($user->getId())),
Permission::delete(Role::user($user->getId())),
],
'userInternalId' => $user->getInternalId(),
'userId' => $user->getId(),
'provider' => 'firebase',
'providerUid' => $oauth2ID,
'providerEmail' => $email,
'providerAccessToken' => $accessToken,
'providerRefreshToken' => $refreshToken,
'providerAccessTokenExpiry' => DateTime::addSeconds(new \DateTime(), (int)$accessTokenExpiry),
]));
}
} else {
throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Missing OAuth2 code.');
}
@ -686,23 +738,31 @@ App::get('/v1/migrations/firebase/projects')
->inject('dbForConsole')
->inject('request')
->action(function (Document $user, Response $response, Document $project, Database $dbForConsole, Request $request) {
if (empty($user->getAttribute('migrationsFirebaseAccessToken')) || empty($user->getAttribute('migrationsFirebaseRefreshToken')) || empty($user->getAttribute('migrationsFirebaseAccessTokenExpiry'))) {
throw new Exception(Exception::GENERAL_ACCESS_FORBIDDEN, 'Not authenticated with Firebase');
}
if (App::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_ID', '') === '' || App::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET', '') === '') {
throw new Exception(Exception::GENERAL_ACCESS_FORBIDDEN, 'Missing Google OAuth credentials');
}
$firebase = new OAuth2Firebase(
App::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_ID', ''),
App::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET', ''),
$request->getProtocol() . '://' . $request->getHostname() . '/v1/migrations/firebase/redirect'
);
$accessToken = $user->getAttribute('migrationsFirebaseAccessToken');
$refreshToken = $user->getAttribute('migrationsFirebaseRefreshToken');
$accessTokenExpiry = $user->getAttribute('migrationsFirebaseAccessTokenExpiry');
$identity = $dbForConsole->findOne('identities', [
Query::equal('provider', ['firebase']),
Query::equal('userInternalId', [$user->getInternalId()]),
]);
if ($identity === false || $identity->isEmpty()) {
throw new Exception(Exception::GENERAL_ACCESS_FORBIDDEN, 'Not authenticated with Firebase'); //TODO: Replace with USER_IDENTITY_NOT_FOUND
}
$accessToken = $identity->getAttribute('providerAccessToken');
$refreshToken = $identity->getAttribute('providerRefreshToken');
$accessTokenExpiry = $identity->getAttribute('providerAccessTokenExpiry');
if (empty($accessToken) || empty($refreshToken) || empty($accessTokenExpiry)) {
throw new Exception(Exception::GENERAL_ACCESS_FORBIDDEN, 'Not authenticated with Firebase');
}
if (App::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_ID', '') === '' || App::getEnv('_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET', '') === '') {
throw new Exception(Exception::GENERAL_ACCESS_FORBIDDEN, 'Missing Google OAuth credentials');
}
$isExpired = new \DateTime($accessTokenExpiry) < new \DateTime('now');
if ($isExpired) {
@ -717,12 +777,12 @@ App::get('/v1/migrations/firebase/projects')
throw new Exception(Exception::GENERAL_RATE_LIMIT_EXCEEDED, 'Another request is currently refreshing OAuth token. Please try again.');
}
$user = $user
->setAttribute('migrationsFirebaseAccessToken', $accessToken)
->setAttribute('migrationsFirebaseRefreshToken', $refreshToken)
->setAttribute('migrationsFirebaseAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int) $firebase->getAccessTokenExpiry('')));
$identity = $identity
->setAttribute('providerAccessToken', $accessToken)
->setAttribute('providerRefreshToken', $refreshToken)
->setAttribute('providerAccessTokenExpiry', DateTime::addSeconds(new \DateTime(), (int)$firebase->getAccessTokenExpiry('')));
$dbForConsole->updateDocument('users', $user->getId(), $user);
$dbForConsole->updateDocument('identities', $identity->getId(), $identity);
}
$projects = $firebase->getProjects($accessToken);
@ -754,12 +814,16 @@ App::get('/v1/migrations/firebase/deauthorize')
->inject('response')
->inject('dbForConsole')
->action(function (Document $user, Response $response, Database $dbForConsole) {
$user = $user
->setAttribute('migrationsFirebaseAccessToken', '')
->setAttribute('migrationsFirebaseRefreshToken', '')
->setAttribute('migrationsFirebaseAccessTokenExpiry', '');
$identity = $dbForConsole->findOne('identities', [
Query::equal('provider', ['firebase']),
Query::equal('userInternalId', [$user->getInternalId()]),
]);
$dbForConsole->updateDocument('users', $user->getId(), $user);
if ($identity === false || $identity->isEmpty()) {
throw new Exception(Exception::GENERAL_ACCESS_FORBIDDEN, 'Not authenticated with Firebase'); //TODO: Replace with USER_IDENTITY_NOT_FOUND
}
$dbForConsole->deleteDocument('identities', $identity->getId());
$response->noContent();
});

View file

@ -1,5 +1,6 @@
<?php
$development = $this->getParam('development', false);
$type = $this->getParam('type', 'general_server_error');
$code = $this->getParam('code', 500);
$errorID = $this->getParam('errorID', 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
$message = $this->getParam('message', '');

View file

@ -66,7 +66,7 @@
"utopia-php/storage": "0.14.*",
"utopia-php/swoole": "0.8.*",
"utopia-php/websocket": "0.1.*",
"utopia-php/transfer": "dev-feat-improve-features",
"utopia-php/transfer": "0.2.*",
"resque/php-resque": "1.3.6",
"matomo/device-detector": "6.1.*",
"dragonmantank/cron-expression": "3.3.2",
@ -81,10 +81,6 @@
{
"url": "https://github.com/appwrite/runtimes.git",
"type": "git"
},
{
"url": "https://github.com/utopia-php/transfer.git",
"type": "vcs"
}
],
"require-dev": {