diff --git a/app/config/locale/templates/email-mfa-challenge.tpl b/app/config/locale/templates/email-mfa-challenge.tpl index cf09448ca5..e3cb6b444d 100644 --- a/app/config/locale/templates/email-mfa-challenge.tpl +++ b/app/config/locale/templates/email-mfa-challenge.tpl @@ -5,7 +5,7 @@
-

{{otp}}

+

{{otp}}

diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 90a35ede78..f379dd3023 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -1069,17 +1069,15 @@ App::get('/v1/account/sessions/oauth2/callback/:provider/:projectId') $domain = $request->getHostname(); $protocol = $request->getProtocol(); + $params = $request->getParams(); + $params['project'] = $projectId; + unset($params['projectId']); + $response ->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0') ->addHeader('Pragma', 'no-cache') ->redirect($protocol . '://' . $domain . '/v1/account/sessions/oauth2/' . $provider . '/redirect?' - . \http_build_query([ - 'project' => $projectId, - 'code' => $code, - 'state' => $state, - 'error' => $error, - 'error_description' => $error_description - ])); + . \http_build_query($params)); }); App::post('/v1/account/sessions/oauth2/callback/:provider/:projectId') @@ -1102,17 +1100,15 @@ App::post('/v1/account/sessions/oauth2/callback/:provider/:projectId') $domain = $request->getHostname(); $protocol = $request->getProtocol(); + $params = $request->getParams(); + $params['project'] = $projectId; + unset($params['projectId']); + $response ->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0') ->addHeader('Pragma', 'no-cache') ->redirect($protocol . '://' . $domain . '/v1/account/sessions/oauth2/' . $provider . '/redirect?' - . \http_build_query([ - 'project' => $projectId, - 'code' => $code, - 'state' => $state, - 'error' => $error, - 'error_description' => $error_description - ])); + . \http_build_query($params)); }); App::get('/v1/account/sessions/oauth2/:provider/redirect') @@ -1239,7 +1235,17 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $failureRedirect(Exception::USER_MISSING_ID); } - $name = $oauth2->getUserName($accessToken); + $name = ''; + $nameOAuth = $oauth2->getUserName($accessToken); + $userParam = \json_decode($request->getParam('user'), true); + if (!empty($nameOAuth)) { + $name = $nameOAuth; + } elseif (is_array($userParam)) { + $nameParam = $userParam['name']; + if (is_array($nameParam) && isset($nameParam['firstName']) && isset($nameParam['lastName'])) { + $name = $nameParam['firstName'] . ' ' . $nameParam['lastName']; + } + } $email = $oauth2->getUserEmail($accessToken); // Check if this identity is connected to a different user @@ -3495,14 +3501,33 @@ App::patch('/v1/account/mfa') ->inject('requestTimestamp') ->inject('response') ->inject('user') + ->inject('session') ->inject('dbForProject') ->inject('queueForEvents') - ->action(function (bool $mfa, ?\DateTime $requestTimestamp, Response $response, Document $user, Database $dbForProject, Event $queueForEvents) { + ->action(function (bool $mfa, ?\DateTime $requestTimestamp, Response $response, Document $user, Document $session, Database $dbForProject, Event $queueForEvents) { $user->setAttribute('mfa', $mfa); $user = $dbForProject->withRequestTimestamp($requestTimestamp, fn () => $dbForProject->updateDocument('users', $user->getId(), $user)); + if ($mfa) { + $factors = $session->getAttribute('factors', []); + $totp = TOTP::getAuthenticatorFromUser($user); + if ($totp !== null && $totp->getAttribute('verified', false)) { + $factors[] = Type::TOTP; + } + if ($user->getAttribute('email', false) && $user->getAttribute('emailVerification', false)) { + $factors[] = Type::EMAIL; + } + if ($user->getAttribute('phone', false) && $user->getAttribute('phoneVerification', false)) { + $factors[] = Type::PHONE; + } + $factors = \array_unique($factors); + + $session->setAttribute('factors', $factors); + $dbForProject->updateDocument('sessions', $session->getId(), $session); + } + $queueForEvents->setParam('userId', $user->getId()); $response->dynamic($user, Response::MODEL_ACCOUNT); @@ -3633,10 +3658,10 @@ App::put('/v1/account/mfa/authenticators/:type') ->param('otp', '', new Text(256), 'Valid verification token.') ->inject('response') ->inject('user') - ->inject('project') + ->inject('session') ->inject('dbForProject') ->inject('queueForEvents') - ->action(function (string $type, string $otp, Response $response, Document $user, Document $project, Database $dbForProject, Event $queueForEvents) { + ->action(function (string $type, string $otp, Response $response, Document $user, Document $session, Database $dbForProject, Event $queueForEvents) { $authenticator = (match ($type) { Type::TOTP => TOTP::getAuthenticatorFromUser($user), @@ -3665,10 +3690,12 @@ App::put('/v1/account/mfa/authenticators/:type') $dbForProject->updateDocument('authenticators', $authenticator->getId(), $authenticator); $dbForProject->purgeCachedDocument('users', $user->getId()); - $authDuration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG; - $sessionId = Auth::sessionVerify($user->getAttribute('sessions', []), Auth::$secret, $authDuration); - $session = $dbForProject->getDocument('sessions', $sessionId); - $dbForProject->updateDocument('sessions', $sessionId, $session->setAttribute('factors', $type, Document::SET_TYPE_APPEND)); + $factors = $session->getAttribute('factors', []); + $factors[] = $type; + $factors = \array_unique($factors); + + $session->setAttribute('factors', $factors); + $dbForProject->updateDocument('sessions', $session->getId(), $session); $queueForEvents->setParam('userId', $user->getId()); @@ -4057,9 +4084,10 @@ App::put('/v1/account/mfa/challenge') ->inject('project') ->inject('response') ->inject('user') + ->inject('session') ->inject('dbForProject') ->inject('queueForEvents') - ->action(function (string $challengeId, string $otp, Document $project, Response $response, Document $user, Database $dbForProject, Event $queueForEvents) { + ->action(function (string $challengeId, string $otp, Document $project, Response $response, Document $user, Document $session, Database $dbForProject, Event $queueForEvents) { $challenge = $dbForProject->getDocument('challenges', $challengeId); @@ -4105,15 +4133,15 @@ App::put('/v1/account/mfa/challenge') $dbForProject->deleteDocument('challenges', $challengeId); $dbForProject->purgeCachedDocument('users', $user->getId()); - $authDuration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG; - $sessionId = Auth::sessionVerify($user->getAttribute('sessions', []), Auth::$secret, $authDuration); - $session = $dbForProject->getDocument('sessions', $sessionId); + $factors = $session->getAttribute('factors', []); + $factors[] = $type; + $factors = \array_unique($factors); - $session = $session - ->setAttribute('factors', $type, Document::SET_TYPE_APPEND) + $session + ->setAttribute('factors', $factors) ->setAttribute('mfaUpdatedAt', DateTime::now()); - $dbForProject->updateDocument('sessions', $sessionId, $session); + $dbForProject->updateDocument('sessions', $session->getId(), $session); $queueForEvents ->setParam('userId', $user->getId()) diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index 208e288614..a3e07927d6 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -70,7 +70,7 @@ App::get('/v1/project/usage') '1d' => 'Y-m-d\T00:00:00.000P', }; - Authorization::skip(function () use ($dbForProject, $firstDay, $lastDay, $period, $metrics, &$total, &$stats) { + Authorization::skip(function () use ($dbForProject, $firstDay, $lastDay, $period, $metrics, $limit, &$total, &$stats) { foreach ($metrics['total'] as $metric) { $result = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), @@ -85,6 +85,7 @@ App::get('/v1/project/usage') Query::equal('period', [$period]), Query::greaterThanEqual('time', $firstDay), Query::lessThan('time', $lastDay), + Query::limit($limit), Query::orderDesc('time'), ]); diff --git a/app/controllers/general.php b/app/controllers/general.php index 85c76bd820..618f0b465c 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -750,12 +750,12 @@ App::error() 'file' => $file, 'line' => $line, 'trace' => \json_encode($trace, JSON_UNESCAPED_UNICODE) === false ? [] : $trace, // check for failing encode - 'version' => $version, + 'version' => APP_VERSION_STABLE, 'type' => $type, ] : [ 'message' => $message, 'code' => $code, - 'version' => $version, + 'version' => APP_VERSION_STABLE, 'type' => $type, ]; diff --git a/app/init.php b/app/init.php index 5165f64d7f..8bf5d682cd 100644 --- a/app/init.php +++ b/app/init.php @@ -1239,14 +1239,13 @@ App::setResource('project', function ($dbForConsole, $request, $console) { return $project; }, ['dbForConsole', 'request', 'console']); -App::setResource('session', function (Document $user, Document $project) { +App::setResource('session', function (Document $user) { if ($user->isEmpty()) { return; } $sessions = $user->getAttribute('sessions', []); - $authDuration = $project->getAttribute('auths', [])['duration'] ?? Auth::TOKEN_EXPIRATION_LOGIN_LONG; - $sessionId = Auth::sessionVerify($user->getAttribute('sessions'), Auth::$secret, $authDuration); + $sessionId = Auth::sessionVerify($user->getAttribute('sessions'), Auth::$secret); if (!$sessionId) { return; @@ -1259,7 +1258,7 @@ App::setResource('session', function (Document $user, Document $project) { } return; -}, ['user', 'project']); +}, ['user']); App::setResource('console', function () { return new Document([ diff --git a/src/Appwrite/Auth/OAuth2/Apple.php b/src/Appwrite/Auth/OAuth2/Apple.php index 2abf61c947..0b4ec50881 100644 --- a/src/Appwrite/Auth/OAuth2/Apple.php +++ b/src/Appwrite/Auth/OAuth2/Apple.php @@ -160,15 +160,6 @@ class Apple extends OAuth2 */ public function getUserName(string $accessToken): string { - if ( - isset($this->claims['email']) && - !empty($this->claims['email']) && - isset($this->claims['email_verified']) && - $this->claims['email_verified'] === 'true' - ) { - return $this->claims['email']; - } - return ''; }