From e9e83d14c308d0e7645f4cbc847d0762974ab68a Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 31 Aug 2021 15:07:48 +0545 Subject: [PATCH] updates and fixes, default handler for magic login --- app/config/auth.php | 7 ++ app/controllers/api/account.php | 11 +- app/controllers/web/home.php | 29 +++++ app/views/home/auth/magicURL.phtml | 35 ++++++ public/dist/scripts/app-all.js | 2 +- public/dist/scripts/app.js | 2 +- public/images/users/magic-url.png | Bin 0 -> 2328 bytes public/scripts/routes.js | 4 + tests/e2e/Services/Account/AccountBase.php | 126 +++++++++++++++++++++ 9 files changed, 213 insertions(+), 3 deletions(-) create mode 100644 app/views/home/auth/magicURL.phtml create mode 100644 public/images/users/magic-url.png diff --git a/app/config/auth.php b/app/config/auth.php index 11b89dd9e..170b87344 100644 --- a/app/config/auth.php +++ b/app/config/auth.php @@ -10,6 +10,13 @@ return [ 'docs' => 'https://appwrite.io/docs/client/account?sdk=web#accountCreateSession', 'enabled' => true, ], + 'magic-url' => [ + 'name' => 'Magic URL', + 'key' => 'usersAuthMagicURL', + 'icon' => '/images/users/magic-url.png', + 'docs' => 'https://appwrite.io/docs/client/account?sdk=web#accountCreateMagicURLSession', + 'enabled' => true, + ], 'anonymous' => [ 'name' => 'Anonymous', 'key' => 'usersAuthAnonymous', diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 9649c5e2f..a18d85105 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -616,6 +616,7 @@ App::post('/v1/account/sessions/magic-url') ->desc('Create Magic URL session') ->groups(['api', 'account']) ->label('scope', 'public') + ->label('auth.type', 'magic-url') ->label('sdk.auth', []) ->label('sdk.namespace', 'account') ->label('sdk.method', 'createMagicURLSession') @@ -730,8 +731,12 @@ App::post('/v1/account/sessions/magic-url') throw new Exception('Failed to save user to DB', 500); } + if(empty($url)) { + $url = $request->getProtocol().'://'.$request->getHostname().'/auth/magic-url/success'; + } + $url = Template::parseURL($url); - $url['query'] = Template::mergeQuery(((isset($url['query'])) ? $url['query'] : ''), ['userId' => $user->getId(), 'secret' => $loginSecret, 'expire' => $expire]); + $url['query'] = Template::mergeQuery(((isset($url['query'])) ? $url['query'] : ''), ['userId' => $user->getId(), 'secret' => $loginSecret, 'expire' => $expire, 'project' => $project->getId()]); $url = Template::unParseURL($url); $mails @@ -849,6 +854,10 @@ App::put('/v1/account/sessions/magic-url') if (false === $user) { throw new Exception('Failed saving user to DB', 500); } + + if (!$projectDB->deleteDocument($token)) { + throw new Exception('Failed to remove login token from DB', 500); + } $audits ->setParam('userId', $user->getId()) diff --git a/app/controllers/web/home.php b/app/controllers/web/home.php index f3eeb71c9..5805473b9 100644 --- a/app/controllers/web/home.php +++ b/app/controllers/web/home.php @@ -197,6 +197,35 @@ App::get('/auth/oauth2/success') ; }); +App::get('/auth/magic-url') + ->groups(['web', 'home']) + ->label('permission', 'public') + ->label('scope', 'home') + ->inject('request') + // ->inject('response') + ->inject('layout') + ->action(function ($request, $layout) { + /** @var Utopia\Swoole\Request $request */ + /** @var Utopia\Swoole\Response $response */ + + $page = new View(__DIR__.'/../../views/home/auth/magicURL.phtml'); + + $userId = $request->getQuery('userId'); + $secret = $request->getQuery('secret'); + $project = $request->getQuery('project'); + $page + ->setParam('userId', $userId) + ->setParam('secret', $secret) + ->setParam('project', $project); + + $layout + ->setParam('title', APP_NAME) + ->setParam('body', $page) + ->setParam('header', []) + ->setParam('footer', []) + ; + }); + App::get('/auth/oauth2/failure') ->groups(['web', 'home']) ->label('permission', 'public') diff --git a/app/views/home/auth/magicURL.phtml b/app/views/home/auth/magicURL.phtml new file mode 100644 index 000000000..1b07a2951 --- /dev/null +++ b/app/views/home/auth/magicURL.phtml @@ -0,0 +1,35 @@ + + + +
\ No newline at end of file diff --git a/public/dist/scripts/app-all.js b/public/dist/scripts/app-all.js index e4db3f821..b9e75f8b8 100644 --- a/public/dist/scripts/app-all.js +++ b/public/dist/scripts/app-all.js @@ -2239,7 +2239,7 @@ return slf.renderToken(tokens,idx,opts);} md.renderer.rules.strong_open=renderEm;md.renderer.rules.strong_close=renderEm;return md;},true);})(window);(function(window){"use strict";window.ls.container.set('rtl',function(){var rtlStock="^ا^ب^ت^ث^ج^ح^خ^د^ذ^ر^ز^س^ش^ص^ض^ط^ظ^ع^غ^ف^ق^ك^ل^م^ن^ه^و^ي^א^ב^ג^ד^ה^ו^ז^ח^ט^י^כ^ך^ל^מ^ם^נ^ן^ס^ע^פ^ף^צ^ץ^ק^ר^ש^ת^";var special=["\n"," "," ","״",'"',"_","'","!","@","#","$","^","&","%","*","(",")","+","=","-","[","]","\\","/","{","}","|",":","<",">","?",",",".","0","1","2","3","4","5","6","7","8","9"];var isRTL=function(value){for(var i=0;i","?",",",".","0","1","2","3","4","5","6","7","8","9"];var isRTL=function(value){for(var i=0;iclient->call(Client::METHOD_POST, '/account/sessions/magic-url', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ]), [ + 'email' => $email, + // 'url' => 'http://localhost/magiclogin', + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + $this->assertNotEmpty($response['body']['$id']); + $this->assertEmpty($response['body']['secret']); + $this->assertIsNumeric($response['body']['expire']); + + $userId = $response['body']['userId']; + + $lastEmail = $this->getLastEmail(); + $this->assertEquals($email, $lastEmail['to'][0]['address']); + $this->assertEquals('Login', $lastEmail['subject']); + + $token = substr($lastEmail['text'], strpos($lastEmail['text'], '&secret=', 0) + 8, 256); + + $expireTime = strpos($lastEmail['text'], 'expire='.$response['body']['expire'], 0); + + $this->assertNotFalse($expireTime); + + $secretTest = strpos($lastEmail['text'], 'secret='.$response['body']['secret'], 0); + + $this->assertNotFalse($secretTest); + + $userIDTest = strpos($lastEmail['text'], 'userId='.$response['body']['userId'], 0); + + $this->assertNotFalse($userIDTest); + + /** + * Test for FAILURE + */ + $response = $this->client->call(Client::METHOD_POST, '/account/sessions/magic-url', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ]), [ + 'email' => $email, + 'url' => 'localhost/magiclogin', + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_POST, '/account/sessions/magic-url', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ]), [ + 'email' => $email, + 'url' => 'http://remotehost/magiclogin', + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + $data['token'] = $token; + $data['id'] = $userId; + + return $data; + } + + /** + * @depends testCreateMagicUrl + */ + public function testCreateSessionWithMagicUrl($data):array + { + $id = $data['id'] ?? ''; + $token = $data['token'] ?? ''; + + /** + * Test for SUCCESS + */ + $response = $this->client->call(Client::METHOD_PUT, '/account/sessions/magic-url', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ]), [ + 'userId' => $id, + 'secret' => $token, + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + $this->assertIsArray($response['body']); + $this->assertNotEmpty($response['body']); + $this->assertNotEmpty($response['body']['$id']); + $this->assertNotEmpty($response['body']['userId']); + + /** + * Test for FAILURE + */ + $response = $this->client->call(Client::METHOD_PUT, '/account/sessions/magic-url', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ]), [ + 'userId' => 'ewewe', + 'secret' => $token, + ]); + + $this->assertEquals(404, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_PUT, '/account/sessions/magic-url', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ]), [ + 'userId' => $id, + 'secret' => 'sdasdasdasd', + ]); + + $this->assertEquals(401, $response['headers']['status-code']); + + return $data; + } } \ No newline at end of file