From 47ebf77ff041234b82c44b4146b2d9b43cc8b9b3 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Tue, 8 Aug 2023 20:28:38 +0100 Subject: [PATCH] Continue work on OAuth Firebase last stage --- app/config/collections.php | 11 ++++ app/controllers/api/migrations.php | 76 ++++++++++++++++---------- composer.lock | 8 +-- src/Appwrite/Auth/OAuth2/Exception.php | 12 +++- src/Appwrite/Auth/OAuth2/Firebase.php | 33 ++++++++--- 5 files changed, 96 insertions(+), 44 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index 69a9a4777..080919efe 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -275,6 +275,17 @@ $commonCollections = [ 'default' => null, 'array' => false, 'filters' => ['encrypt'], + ], + [ + '$id' => ID::custom('migrationsFirebaseServiceAccount'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['encrypt'], ] ], 'indexes' => [ diff --git a/app/controllers/api/migrations.php b/app/controllers/api/migrations.php index 5eb4e6db8..4104aa121 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -186,35 +186,44 @@ App::post('/v1/migrations/firebase/oauth') $dbForConsole->updateDocument('users', $user->getId(), $user); } - $serviceAccount = $firebase->createServiceAccount($accessToken, $projectId); + if ($user->getAttribute('migrationsFirebaseServiceAccount')) { + $serviceAccount = json_decode($user->getAttribute('migrationsFirebaseServiceAccount'), true); + } else { + $serviceAccount = $firebase->createServiceAccount($accessToken, $projectId); + $user = $user + ->setAttribute('migrationsFirebaseServiceAccount', json_encode($serviceAccount)); - // $migration = $dbForProject->createDocument('migrations', new Document([ - // '$id' => ID::unique(), - // 'status' => 'pending', - // 'stage' => 'init', - // 'source' => Firebase::getName(), - // 'credentials' => [ - // 'serviceAccount' => $serviceAccount, - // ], - // 'resources' => $resources, - // 'statusCounters' => '{}', - // 'resourceData' => '{}', - // 'errors' => [] - // ])); + $dbForConsole->updateDocument('users', $user->getId(), $user); + } - // $events->setParam('migrationId', $migration->getId()); + $migration = $dbForProject->createDocument('migrations', new Document([ + '$id' => ID::unique(), + 'status' => 'pending', + 'stage' => 'init', + 'source' => Firebase::getName(), + 'credentials' => [ + 'serviceAccount' => $serviceAccount, + ], + 'resources' => $resources, + 'statusCounters' => '{}', + 'resourceData' => '{}', + 'errors' => [] + ])); - // // Trigger Transfer - // $event = new Migration(); - // $event - // ->setMigration($migration) - // ->setProject($project) - // ->setUser($user) - // ->trigger(); + $events->setParam('migrationId', $migration->getId()); - // $response - // ->setStatusCode(Response::STATUS_CODE_ACCEPTED) - // ->dynamic($migration, Response::MODEL_MIGRATION); + // Trigger Transfer + var_dump($project); + $event = new Migration(); + $event + ->setMigration($migration) + ->setProject($project) + ->setUser($user) + ->trigger(); + + $response + ->setStatusCode(Response::STATUS_CODE_ACCEPTED) + ->dynamic($migration, Response::MODEL_MIGRATION); }); App::post('/v1/migrations/supabase') @@ -515,13 +524,24 @@ App::get('/v1/migrations/firebase/report/oauth') $dbForConsole->updateDocument('users', $user->getId(), $user); } - $serviceAccount = $firebase->createServiceAccount($accessToken, $projectId); + // Get Service Account + if ($user->getAttribute('migrationsFirebaseServiceAccount')) { + $serviceAccount = json_decode($user->getAttribute('migrationsFirebaseServiceAccount'), true); + } else { + $serviceAccount = $firebase->createServiceAccount($accessToken, $projectId); + $user = $user + ->setAttribute('migrationsFirebaseServiceAccount', json_encode($serviceAccount)); - $firebase = new Firebase(json_decode($serviceAccount, true)); + $dbForConsole->updateDocument('users', $user->getId(), $user); + } + + $firebase = new Firebase(array_merge($serviceAccount, ['project_id' => $projectId])); + + $report = $firebase->report($resources); $response ->setStatusCode(Response::STATUS_CODE_OK) - ->dynamic(new Document($firebase->report($resources)), Response::MODEL_MIGRATION_REPORT); + ->dynamic(new Document($report), Response::MODEL_MIGRATION_REPORT); } catch (\Exception $e) { throw new Exception(Exception::GENERAL_SERVER_ERROR, $e->getMessage()); } diff --git a/composer.lock b/composer.lock index 57f960615..5c8be9aa9 100644 --- a/composer.lock +++ b/composer.lock @@ -2504,12 +2504,12 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/transfer.git", - "reference": "49578adbe4c103f56ecb78d6b83ff7af6ac56bab" + "reference": "034c2dcacd4aa2595bfff84f11776dce66cf9153" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/transfer/zipball/49578adbe4c103f56ecb78d6b83ff7af6ac56bab", - "reference": "49578adbe4c103f56ecb78d6b83ff7af6ac56bab", + "url": "https://api.github.com/repos/utopia-php/transfer/zipball/034c2dcacd4aa2595bfff84f11776dce66cf9153", + "reference": "034c2dcacd4aa2595bfff84f11776dce66cf9153", "shasum": "" }, "require": { @@ -2566,7 +2566,7 @@ "source": "https://github.com/utopia-php/transfer/tree/feat-improve-features", "issues": "https://github.com/utopia-php/transfer/issues" }, - "time": "2023-08-07T15:10:32+00:00" + "time": "2023-08-08T14:38:06+00:00" }, { "name": "utopia-php/websocket", diff --git a/src/Appwrite/Auth/OAuth2/Exception.php b/src/Appwrite/Auth/OAuth2/Exception.php index af98fa5e9..3d5b79d3b 100644 --- a/src/Appwrite/Auth/OAuth2/Exception.php +++ b/src/Appwrite/Auth/OAuth2/Exception.php @@ -16,9 +16,15 @@ class Exception extends AppwriteException $this->message = $response; $decoded = json_decode($response, true); if (\is_array($decoded)) { - $this->error = $decoded['error']; - $this->errorDescription = $decoded['error_description']; - $this->message = $this->error . ': ' . $this->errorDescription; + if (\is_array($decoded['error'])) { + $this->error = $decoded['error']['status']; + $this->errorDescription = $decoded['error']['message']; + $this->message = $this->error . ': ' . $this->errorDescription; + } else { + $this->error = $decoded['error']; + $this->errorDescription = $decoded['error_description']; + $this->message = $this->error . ': ' . $this->errorDescription; + } } $type = match ($code) { 400 => AppwriteException::USER_OAUTH2_BAD_REQUEST, diff --git a/src/Appwrite/Auth/OAuth2/Firebase.php b/src/Appwrite/Auth/OAuth2/Firebase.php index 892a9c095..95acf0e0b 100644 --- a/src/Appwrite/Auth/OAuth2/Firebase.php +++ b/src/Appwrite/Auth/OAuth2/Firebase.php @@ -21,8 +21,8 @@ class Firebase extends OAuth2 */ protected array $scopes = [ 'https://www.googleapis.com/auth/firebase', - 'https://www.googleapis.com/auth/datastore', - 'https://www.googleapis.com/auth/cloud-platform', + 'https://www.googleapis.com/auth/datastore', + 'https://www.googleapis.com/auth/cloud-platform', 'https://www.googleapis.com/auth/identitytoolkit', 'https://www.googleapis.com/auth/userinfo.profile' ]; @@ -51,7 +51,7 @@ class Firebase extends OAuth2 ]); } - /** + /** * @param string $code * * @return array @@ -176,8 +176,8 @@ class Firebase extends OAuth2 if (empty($this->user)) { $response = $this->request( 'GET', - 'https://www.googleapis.com/oauth2/v1/userinfo', - ['Authorization: Bearer ' . \urlencode($accessToken)] + 'https://www.googleapis.com/oauth2/v1/userinfo?access_token=' . \urlencode($accessToken), + [], ); $this->user = \json_decode($response, true); @@ -195,11 +195,12 @@ class Firebase extends OAuth2 return $projects['results']; } - public function createServiceAccount(string $accessToken, string $projectID): string + public function createServiceAccount(string $accessToken, string $projectID): array { + // Create Service Account $response = $this->request( 'POST', - "https://iam.googleapis.com/v1/projects/{$projectID}/serviceAccounts", + 'https://iam.googleapis.com/v1/projects/' . $projectID . '/serviceAccounts', [ 'Authorization: Bearer ' . \urlencode($accessToken), 'Content-Type: application/json' @@ -212,6 +213,20 @@ class Firebase extends OAuth2 ]) ); - return $response; + $response = json_decode($response, true); + + // Create Service Account Key + $responseKey = $this->request( + 'POST', + 'https://iam.googleapis.com/v1/projects/' . $projectID . '/serviceAccounts/' . $response['email'] . '/keys', + [ + 'Authorization: Bearer ' . \urlencode($accessToken), + 'Content-Type: application/json' + ] + ); + + $responseKey = json_decode($responseKey, true); + + return json_decode(base64_decode($responseKey['privateKeyData']), true); } -} \ No newline at end of file +}