From bb9873be4f6f54d10764ea2a914e3913a146fa78 Mon Sep 17 00:00:00 2001 From: LautaroCesso Date: Mon, 3 Aug 2020 12:52:12 -0300 Subject: [PATCH 01/21] fix warning in checbox in form field. --- client/src/core-components/form-field.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/client/src/core-components/form-field.js b/client/src/core-components/form-field.js index 2be23fbe..c6ec13ef 100644 --- a/client/src/core-components/form-field.js +++ b/client/src/core-components/form-field.js @@ -194,8 +194,12 @@ class FormField extends React.Component { if(field === 'autocomplete') { props.values = value; } - - props.value = value; + + if(field === 'checkbox') { + props.value = !!value; + } else { + props.value = value; + } return props; } From 96990c8c04cc69bff4c51bdd19358d678daccd99 Mon Sep 17 00:00:00 2001 From: LautaroCesso Date: Mon, 3 Aug 2020 12:54:15 -0300 Subject: [PATCH 02/21] Add remember me function for staffs. --- client/src/app/admin/admin-login-page.js | 46 +++++++++++++++++----- client/src/app/admin/admin-login-page.scss | 6 ++- server/controllers/user/login.php | 2 +- 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/client/src/app/admin/admin-login-page.js b/client/src/app/admin/admin-login-page.js index 3042b2ea..835b4e18 100644 --- a/client/src/app/admin/admin-login-page.js +++ b/client/src/app/admin/admin-login-page.js @@ -49,11 +49,32 @@ class AdminLoginPage extends React.Component {
OpenSupports Admin Panel
-
-
- - - {i18n('LOG_IN')} +
+ +
+ + + +
+
+ {i18n('LOG_IN')} +
{this.renderRecoverStatus()} @@ -68,7 +89,7 @@ class AdminLoginPage extends React.Component { renderPasswordRecovery() { return ( -
+
); @@ -105,7 +126,7 @@ class AdminLoginPage extends React.Component { getLoginFormProps() { return { loading: this.props.session.pending, - className: 'admin-login-page__form', + className: 'admin-login-page__login-form-container__login-form', ref: 'loginForm', onSubmit: this.onLoginFormSubmit.bind(this), errors: this.getLoginFormErrors(), @@ -114,12 +135,17 @@ class AdminLoginPage extends React.Component { } getRecoverFormProps() { + const { + loadingRecover, + recoverFormErrors + } = this.state; + return { - loading: this.state.loadingRecover, - className: 'admin-login-page__form', + loading: loadingRecover, + className: 'admin-login-page__recovery-form-container__recovery-form', ref: 'recoverForm', onSubmit: this.onForgotPasswordSubmit.bind(this), - errors: this.state.recoverFormErrors, + errors: recoverFormErrors, onValidateErrors: this.onRecoverFormErrorsValidation.bind(this) }; } diff --git a/client/src/app/admin/admin-login-page.scss b/client/src/app/admin/admin-login-page.scss index 4f9f6b14..efbbcd4c 100644 --- a/client/src/app/admin/admin-login-page.scss +++ b/client/src/app/admin/admin-login-page.scss @@ -19,9 +19,13 @@ margin-bottom: 30px; } - &__login-form { + &__login-form-container { margin: 0 auto; display: inline-block; + + &__login-form__fields { + padding: 10px 0; + } } &__error { diff --git a/server/controllers/user/login.php b/server/controllers/user/login.php index b6006749..72a4031e 100755 --- a/server/controllers/user/login.php +++ b/server/controllers/user/login.php @@ -140,7 +140,7 @@ class LoginController extends Controller { private function createRememberToken() { $remember = Controller::request('remember'); - if (!Controller::request('staff') && $remember) { + if($remember) { $this->rememberToken = Hashing::generateRandomToken(); $this->rememberExpiration = Date::getNextDate(30); From d72aec3976c6478cd4bfad0ccfb75ec5ca986ae6 Mon Sep 17 00:00:00 2001 From: LautaroCesso Date: Tue, 11 Aug 2020 23:35:10 -0300 Subject: [PATCH 03/21] Add staff instance in session cookie. --- client/src/actions/session-actions.js | 2 +- client/src/lib-app/session-store.js | 5 ++++- client/src/reducers/session-reducer.js | 2 +- server/controllers/user/login.php | 13 +++++++++---- server/models/SessionCookie.php | 14 ++++++++++++++ 5 files changed, 29 insertions(+), 7 deletions(-) diff --git a/client/src/actions/session-actions.js b/client/src/actions/session-actions.js index ee8cc561..3b1d77a0 100644 --- a/client/src/actions/session-actions.js +++ b/client/src/actions/session-actions.js @@ -54,8 +54,8 @@ export default { data: { userId: rememberData.userId, rememberToken: rememberData.token, + staff: rememberData.isStaff, remember: 1, - isAutomatic: 1 } }).then((result) => { store.dispatch(this.getUserData(result.data.userId, result.data.token)); diff --git a/client/src/lib-app/session-store.js b/client/src/lib-app/session-store.js index 642a0983..8b731b22 100644 --- a/client/src/lib-app/session-store.js +++ b/client/src/lib-app/session-store.js @@ -48,9 +48,10 @@ class SessionStore { return JSON.parse(this.getItem('departments')); } - storeRememberData({token, userId, expiration}) { + storeRememberData({token, userId, expiration, isStaff}) { this.setItem('rememberData-token', token); this.setItem('rememberData-userId', userId); + this.setItem('rememberData-isStaff', isStaff); this.setItem('rememberData-expiration', expiration); } @@ -106,6 +107,7 @@ class SessionStore { return { token: this.getItem('rememberData-token'), userId: this.getItem('rememberData-userId'), + isStaff: this.getItem('rememberData-isStaff'), expiration: this.getItem('rememberData-expiration') }; } @@ -113,6 +115,7 @@ class SessionStore { clearRememberData() { this.removeItem('rememberData-token'); this.removeItem('rememberData-userId'); + this.removeItem('rememberData-isStaff'); this.removeItem('rememberData-expiration'); } diff --git a/client/src/reducers/session-reducer.js b/client/src/reducers/session-reducer.js index a329cebc..552c828a 100644 --- a/client/src/reducers/session-reducer.js +++ b/client/src/reducers/session-reducer.js @@ -95,7 +95,7 @@ class SessionReducer extends Reducer { sessionStore.storeRememberData({ token: resultData.rememberToken, userId: resultData.userId, - staff: resultData.staff, + isStaff: resultData.staff, expiration: resultData.rememberExpiration }); } diff --git a/server/controllers/user/login.php b/server/controllers/user/login.php index 72a4031e..3cd24e9f 100755 --- a/server/controllers/user/login.php +++ b/server/controllers/user/login.php @@ -61,6 +61,7 @@ class LoginController extends Controller { $this->createUserSession(); $this->createRememberToken(); + if(Controller::request('staff')) { $this->userInstance->lastLogin = Date::getCurrentDate(); $this->userInstance->store(); @@ -116,12 +117,14 @@ class LoginController extends Controller { $rememberToken = Controller::request('rememberToken'); $userInstance = new NullDataStore(); - if ($rememberToken) { + if($rememberToken) { $sessionCookie = SessionCookie::getDataStore($rememberToken, 'token'); $userId = Controller::request('userId'); + $isStaff = Controller::request('staff'); + $loggedInstance = $isStaff ? $sessionCookie->staff : $sessionCookie->user; - if (!$sessionCookie->isNull() && $userId === $sessionCookie->user->id) { - $userInstance = $sessionCookie->user; + if ((!$sessionCookie->isNull()) && ($userId === $loggedInstance->id) && ($isStaff === $sessionCookie->isStaff)) { + $userInstance = $loggedInstance; $sessionCookie->delete(); } } @@ -146,7 +149,9 @@ class LoginController extends Controller { $sessionCookie = new SessionCookie(); $sessionCookie->setProperties(array( - 'user' => $this->userInstance, + 'isStaff' => Controller::request('staff'), + 'user' => $this->userInstance instanceof User ? $this->userInstance : null, + 'staff' => $this->userInstance instanceof Staff ? $this->userInstance : null, 'token' => $this->rememberToken, 'ip' => $_SERVER['REMOTE_ADDR'], 'creationDate' => Date::getCurrentDate(), diff --git a/server/models/SessionCookie.php b/server/models/SessionCookie.php index 94460333..b6dc9c82 100755 --- a/server/models/SessionCookie.php +++ b/server/models/SessionCookie.php @@ -1,10 +1,24 @@ Date: Tue, 11 Aug 2020 23:51:41 -0300 Subject: [PATCH 04/21] Add result data staff in get user data in auto login. --- client/src/actions/session-actions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/actions/session-actions.js b/client/src/actions/session-actions.js index 3b1d77a0..9bec3100 100644 --- a/client/src/actions/session-actions.js +++ b/client/src/actions/session-actions.js @@ -58,7 +58,7 @@ export default { remember: 1, } }).then((result) => { - store.dispatch(this.getUserData(result.data.userId, result.data.token)); + store.dispatch(this.getUserData(result.data.userId, result.data.token, result.data.staff)); return result; }) From bbbc845fe758fbd58cf4bbd8df38160e9a3556fc Mon Sep 17 00:00:00 2001 From: LautaroCesso Date: Wed, 12 Aug 2020 16:02:39 -0300 Subject: [PATCH 05/21] Fix remember me function for user. --- client/src/actions/session-actions.js | 2 +- server/controllers/user/login.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/actions/session-actions.js b/client/src/actions/session-actions.js index 9bec3100..2e552d58 100644 --- a/client/src/actions/session-actions.js +++ b/client/src/actions/session-actions.js @@ -54,7 +54,7 @@ export default { data: { userId: rememberData.userId, rememberToken: rememberData.token, - staff: rememberData.isStaff, + staff: (rememberData.isStaff === "true") ? 1 : 0, remember: 1, } }).then((result) => { diff --git a/server/controllers/user/login.php b/server/controllers/user/login.php index 3cd24e9f..9e77c5c2 100755 --- a/server/controllers/user/login.php +++ b/server/controllers/user/login.php @@ -149,7 +149,7 @@ class LoginController extends Controller { $sessionCookie = new SessionCookie(); $sessionCookie->setProperties(array( - 'isStaff' => Controller::request('staff'), + 'isStaff' => !!Controller::request('staff'), 'user' => $this->userInstance instanceof User ? $this->userInstance : null, 'staff' => $this->userInstance instanceof Staff ? $this->userInstance : null, 'token' => $this->rememberToken, From e4a9366b0744cb04a36249414694a951b8d0a37c Mon Sep 17 00:00:00 2001 From: LautaroCesso Date: Wed, 12 Aug 2020 20:32:17 -0300 Subject: [PATCH 06/21] Fix login test rb and add remember me function test in login rb. --- tests/user/ban.rb | 1 + tests/user/login.rb | 55 +++++++++++++++++++++++++++++++++++++++------ 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/tests/user/ban.rb b/tests/user/ban.rb index 6e971006..e5114ab4 100644 --- a/tests/user/ban.rb +++ b/tests/user/ban.rb @@ -6,6 +6,7 @@ describe '/user/ban' do password: 'staff', staff: true }) + (result['status']).should.equal('success') $csrf_userid = result['data']['userId'] $csrf_token = result['data']['token'] diff --git a/tests/user/login.rb b/tests/user/login.rb index 15d5e98b..b216a04c 100644 --- a/tests/user/login.rb +++ b/tests/user/login.rb @@ -9,7 +9,6 @@ describe '/user/login' do email: @loginEmail, password: 'some_incorrect_password' }) - (result['status']).should.equal('fail') end @@ -18,7 +17,6 @@ describe '/user/login' do email: @loginEmail, password: @loginPass }) - (result['status']).should.equal('success') end @@ -27,7 +25,6 @@ describe '/user/login' do email: @loginEmail, password: @loginPass }) - (result['status']).should.equal('success') end @@ -36,21 +33,20 @@ describe '/user/login' do result = request('/user/login', { email: $staff[:email], password: $staff[:password], - staff: true + staff: 1 }) - (result['status']).should.equal('success') (result['data']['staff']).should.equal(true) end - it 'should work with remember token' do + it 'should work autologin user with remember token' do request('/user/logout', {}) result = request('/user/login', { email: @loginEmail, password: @loginPass, + staff: 0, remember: 1 }) - (result['status']).should.equal('success') @rememberToken = result['data']['rememberToken'] @@ -60,12 +56,15 @@ describe '/user/login' do result = request('/user/login', { userId: @userId, rememberToken: '12abc', + staff: 0, remember: 1 }) (result['status']).should.equal('fail') + result = request('/user/login', { userId: 1, rememberToken: @rememberToken, + staff: 0, remember: 1 }) (result['status']).should.equal('fail') @@ -73,8 +72,50 @@ describe '/user/login' do result = request('/user/login', { userId: @userId, rememberToken: @rememberToken, + staff: 0, remember: 1 }) (result['status']).should.equal('success') end + + it 'should work autologin staff with remember token' do + request('/user/logout', {}) + result = request('/user/login', { + email: $staff[:email], + password: $staff[:password], + staff: 1, + remember: 1 + }) + (result['status']).should.equal('success') + + @rememberToken = result['data']['rememberToken'] + puts result['data'] + @staffId = result['data']['userId'] + + request('/user/logout', {}) + result = request('/user/login', { + userId: @staffId, + rememberToken: '12abc', + staff: 1, + remember: 1 + }) + (result['status']).should.equal('fail') + + result = request('/user/login', { + userId: 3, + rememberToken: @rememberToken, + staff: 1, + remember: 1 + }) + (result['status']).should.equal('fail') + + result = request('/user/login', { + userId: @staffId, + rememberToken: @rememberToken, + staff: 1, + remember: 1 + }) + (result['status']).should.equal('success') + end + end From e36b984b23dedc3a3a08e6cbdd498bf8214b6e3b Mon Sep 17 00:00:00 2001 From: LautaroCesso Date: Tue, 18 Aug 2020 23:48:06 -0300 Subject: [PATCH 07/21] Resolve github maxi comments. --- client/src/actions/session-actions.js | 2 +- client/src/reducers/session-reducer.js | 2 +- server/controllers/user/login.php | 13 ++++++++----- tests/user/login.rb | 1 - 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/client/src/actions/session-actions.js b/client/src/actions/session-actions.js index 2e552d58..9bec3100 100644 --- a/client/src/actions/session-actions.js +++ b/client/src/actions/session-actions.js @@ -54,7 +54,7 @@ export default { data: { userId: rememberData.userId, rememberToken: rememberData.token, - staff: (rememberData.isStaff === "true") ? 1 : 0, + staff: rememberData.isStaff, remember: 1, } }).then((result) => { diff --git a/client/src/reducers/session-reducer.js b/client/src/reducers/session-reducer.js index 552c828a..0b0be3d3 100644 --- a/client/src/reducers/session-reducer.js +++ b/client/src/reducers/session-reducer.js @@ -95,7 +95,7 @@ class SessionReducer extends Reducer { sessionStore.storeRememberData({ token: resultData.rememberToken, userId: resultData.userId, - isStaff: resultData.staff, + isStaff: resultData.staff ? 1 : 0, expiration: resultData.rememberExpiration }); } diff --git a/server/controllers/user/login.php b/server/controllers/user/login.php index 9e77c5c2..c5eba95d 100755 --- a/server/controllers/user/login.php +++ b/server/controllers/user/login.php @@ -120,12 +120,15 @@ class LoginController extends Controller { if($rememberToken) { $sessionCookie = SessionCookie::getDataStore($rememberToken, 'token'); $userId = Controller::request('userId'); - $isStaff = Controller::request('staff'); - $loggedInstance = $isStaff ? $sessionCookie->staff : $sessionCookie->user; + $isStaff = !!Controller::request('staff'); - if ((!$sessionCookie->isNull()) && ($userId === $loggedInstance->id) && ($isStaff === $sessionCookie->isStaff)) { - $userInstance = $loggedInstance; - $sessionCookie->delete(); + if(!$sessionCookie->isNull()) { + $loggedInstance = $isStaff ? $sessionCookie->staff : $sessionCookie->user; + + if(($userId == $loggedInstance->id) && ($isStaff == $sessionCookie->isStaff)) { + $userInstance = $loggedInstance; + $sessionCookie->delete(); + } } } diff --git a/tests/user/login.rb b/tests/user/login.rb index b216a04c..6dd3c492 100644 --- a/tests/user/login.rb +++ b/tests/user/login.rb @@ -89,7 +89,6 @@ describe '/user/login' do (result['status']).should.equal('success') @rememberToken = result['data']['rememberToken'] - puts result['data'] @staffId = result['data']['userId'] request('/user/logout', {}) From deb590ceee83bd854cd0825b53c0f62c412a4e9e Mon Sep 17 00:00:00 2001 From: Maxi Redigonda Date: Sun, 16 Aug 2020 17:02:12 -0300 Subject: [PATCH 08/21] Places Google Login button inside login widget --- .../main-home/main-home-page-login-widget.js | 20 +++++++++++++++++-- client/src/index.html | 1 + 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/client/src/app/main/main-home/main-home-page-login-widget.js b/client/src/app/main/main-home/main-home-page-login-widget.js index 3e5fd685..47460c2b 100644 --- a/client/src/app/main/main-home/main-home-page-login-widget.js +++ b/client/src/app/main/main-home/main-home-page-login-widget.js @@ -1,12 +1,10 @@ import React from 'react'; -import ReactDOM from 'react-dom'; import {connect} from 'react-redux'; import classNames from 'classnames'; import _ from 'lodash'; import SessionActions from 'actions/session-actions'; import API from 'lib-app/api-call'; -import focus from 'lib-core/focus'; import i18n from 'lib-app/i18n'; import PasswordRecovery from 'app-components/password-recovery'; @@ -45,9 +43,27 @@ class MainHomePageLoginWidget extends React.Component { } renderLogin() { + const defaultGoogleHandler = (response) => { + console.log(response); + } + + gapi.load('auth2', () => { + gapi.auth2.init({client_id: '50174278643-gtvjdpm5rmkv75lf3jsp95iv77a2usgu.apps.googleusercontent.com'}) + gapi.signin2.render('google-oauth-id', { + scope: 'email', + width: 200, + height: 30, + longtitle: true, + theme: 'dark', + onsuccess: defaultGoogleHandler, + onfailure: defaultGoogleHandler + }) + }) + return (
+
Loading Google Login ...
diff --git a/client/src/index.html b/client/src/index.html index 10403723..986cb3df 100755 --- a/client/src/index.html +++ b/client/src/index.html @@ -16,6 +16,7 @@ + From fad3dce6462751181fc338ddc38a5306ed83d824 Mon Sep 17 00:00:00 2001 From: Maxi Redigonda Date: Mon, 17 Aug 2020 09:36:53 -0300 Subject: [PATCH 09/21] Adds google/apiclient to composer json --- server/Makefile | 2 +- server/composer.json | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/server/Makefile b/server/Makefile index 79b1d16c..dd78e3f3 100644 --- a/server/Makefile +++ b/server/Makefile @@ -10,7 +10,7 @@ build: @docker network create os-net || true install: - @docker exec -it opensupports-srv bash -c "cd /var/www/html && composer install" || echo "${red}Please execute 'make run' first${reset}" + @docker exec -it opensupports-srv bash -c "cd /var/www/html && composer update && composer install" || echo "${red}Please execute 'make run' first${reset}" @docker exec -it opensupports-db bash -c "mysql -u root -e \"CREATE DATABASE IF NOT EXISTS development;\" " || echo "${red}Please execute 'make run' first${reset}" run: stop diff --git a/server/composer.json b/server/composer.json index 698d7607..7f07c16f 100755 --- a/server/composer.json +++ b/server/composer.json @@ -10,7 +10,8 @@ "codeguy/upload": "^1.3", "php-imap/php-imap": "^3.0", "willdurand/email-reply-parser": "^2.8", - "ext-fileinfo": "^1.0" + "ext-fileinfo": "^1.0", + "google/apiclient": "^2.7" }, "require-dev": { "phpunit/phpunit": "^5.7" From 56ca30a7c394dd92818e368ced1c0aa8bd81f531 Mon Sep 17 00:00:00 2001 From: Maxi Redigonda Date: Mon, 17 Aug 2020 09:38:05 -0300 Subject: [PATCH 10/21] WIP - validates google token and gets its data --- .../main-home/main-home-page-login-widget.js | 13 ++++++++- server/controllers/user/login.php | 27 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/client/src/app/main/main-home/main-home-page-login-widget.js b/client/src/app/main/main-home/main-home-page-login-widget.js index 47460c2b..16a59f2f 100644 --- a/client/src/app/main/main-home/main-home-page-login-widget.js +++ b/client/src/app/main/main-home/main-home-page-login-widget.js @@ -43,6 +43,17 @@ class MainHomePageLoginWidget extends React.Component { } renderLogin() { + const onGoogleLoginSuccess = (googleUser) => { + let id_token = googleUser.getAuthResponse().id_token; + + API.call({ + path: '/user/login', + data: { + 'googleId': id_token + } + }).then(() => {}).catch(() => {}); + } + const defaultGoogleHandler = (response) => { console.log(response); } @@ -55,7 +66,7 @@ class MainHomePageLoginWidget extends React.Component { height: 30, longtitle: true, theme: 'dark', - onsuccess: defaultGoogleHandler, + onsuccess: onGoogleLoginSuccess, onfailure: defaultGoogleHandler }) }) diff --git a/server/controllers/user/login.php b/server/controllers/user/login.php index c5eba95d..6fe99717 100755 --- a/server/controllers/user/login.php +++ b/server/controllers/user/login.php @@ -19,6 +19,7 @@ use RedBeanPHP\Facade as RedBean; * @apiParam {Boolean} remember Indicates if the session wants to be remembered. * @apiParam {Number} userId The id of the user to login. * @apiParam {String} rememberToken Token to login automatically. It replaces the password. + * @apiParam {String} googleId Token to log in with Google. * * @apiUse UNVERIFIED_USER * @apiUse INVALID_CREDENTIALS @@ -49,6 +50,28 @@ class LoginController extends Controller { public function handler() { $this->clearOldRememberTokens(); + + if ($this->checkGoogleLogin()) { + + $client = new Google_Client(['client_id' => '50174278643-gtvjdpm5rmkv75lf3jsp95iv77a2usgu.apps.googleusercontent.com']); // Specify the CLIENT_ID of the app that accesses the backend + $payload = $client->verifyIdToken(Controller::request('googleId')); + if ($payload) { + $userid = $payload['sub']; + ob_start(); + var_dump($payload); + $result = ob_get_clean(); + Response::respondSuccess(array('googleUserData' => $result)); + return; + } else { + echo "Invalid token" . PHP_EOL; + } + + + Response::respondSuccess(array( + 'userId' => -1, + )); + return; + } if ($this->checkInputCredentials() || $this->checkRememberToken()) { if($this->userInstance->verificationToken !== null) { @@ -73,6 +96,10 @@ class LoginController extends Controller { } } + private function checkGoogleLogin() { + return !!Controller::request('googleId'); + } + private function checkInputCredentials() { $this->userInstance = $this->getUserByInputCredentials(); From c4e211518ccb67e8c598de56bd8c529316ba3491 Mon Sep 17 00:00:00 2001 From: Maxi Redigonda Date: Wed, 19 Aug 2020 17:33:38 -0300 Subject: [PATCH 11/21] WIP - Stub to log in with Google --- .../main-home/main-home-page-login-widget.js | 26 +++++++++---------- server/controllers/user/login.php | 16 +++++++----- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/client/src/app/main/main-home/main-home-page-login-widget.js b/client/src/app/main/main-home/main-home-page-login-widget.js index 16a59f2f..99fbc698 100644 --- a/client/src/app/main/main-home/main-home-page-login-widget.js +++ b/client/src/app/main/main-home/main-home-page-login-widget.js @@ -24,7 +24,9 @@ class MainHomePageLoginWidget extends React.Component { recoverFormErrors: {}, recoverSent: false, loadingLogin: false, - loadingRecover: false + loadingRecover: false, + + sent: false }; componentDidUpdate(prevProps) { @@ -43,17 +45,6 @@ class MainHomePageLoginWidget extends React.Component { } renderLogin() { - const onGoogleLoginSuccess = (googleUser) => { - let id_token = googleUser.getAuthResponse().id_token; - - API.call({ - path: '/user/login', - data: { - 'googleId': id_token - } - }).then(() => {}).catch(() => {}); - } - const defaultGoogleHandler = (response) => { console.log(response); } @@ -66,7 +57,7 @@ class MainHomePageLoginWidget extends React.Component { height: 30, longtitle: true, theme: 'dark', - onsuccess: onGoogleLoginSuccess, + onsuccess: this.onGoogleLoginSuccess.bind(this), onfailure: defaultGoogleHandler }) }) @@ -153,6 +144,15 @@ class MainHomePageLoginWidget extends React.Component { this.props.dispatch(SessionActions.login(formState)); } + onGoogleLoginSuccess(googleUser) { + if (!this.state.sent) { + let id_token = googleUser.getAuthResponse().id_token; + console.log(id_token); + this.props.dispatch(SessionActions.login({'googleId': id_token, 'remember': 1})); + this.setState({sent: true}); + } + } + onForgotPasswordSubmit(formState) { this.setState({ loadingRecover: true, diff --git a/server/controllers/user/login.php b/server/controllers/user/login.php index 6fe99717..ea0bf513 100755 --- a/server/controllers/user/login.php +++ b/server/controllers/user/login.php @@ -52,20 +52,22 @@ class LoginController extends Controller { $this->clearOldRememberTokens(); if ($this->checkGoogleLogin()) { - $client = new Google_Client(['client_id' => '50174278643-gtvjdpm5rmkv75lf3jsp95iv77a2usgu.apps.googleusercontent.com']); // Specify the CLIENT_ID of the app that accesses the backend $payload = $client->verifyIdToken(Controller::request('googleId')); if ($payload) { - $userid = $payload['sub']; - ob_start(); - var_dump($payload); - $result = ob_get_clean(); - Response::respondSuccess(array('googleUserData' => $result)); + // $userid = $payload['sub']; + // ob_start(); + // var_dump($payload); + // $result = ob_get_clean(); + + $this->userInstance = User::getUser($payload['email'], 'email'); + + Session::getInstance()->createSession($this->userInstance->id, false); + Response::respondSuccess($this->getUserData()); return; } else { echo "Invalid token" . PHP_EOL; } - Response::respondSuccess(array( 'userId' => -1, From 0518b0ac17b286bcb363b4795f2c8668c3d8cabd Mon Sep 17 00:00:00 2001 From: Maxi Redigonda Date: Thu, 20 Aug 2020 16:23:30 -0300 Subject: [PATCH 12/21] Adds branching for when social login user wasn't created --- server/controllers/user/login.php | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/server/controllers/user/login.php b/server/controllers/user/login.php index ea0bf513..808a6599 100755 --- a/server/controllers/user/login.php +++ b/server/controllers/user/login.php @@ -54,25 +54,20 @@ class LoginController extends Controller { if ($this->checkGoogleLogin()) { $client = new Google_Client(['client_id' => '50174278643-gtvjdpm5rmkv75lf3jsp95iv77a2usgu.apps.googleusercontent.com']); // Specify the CLIENT_ID of the app that accesses the backend $payload = $client->verifyIdToken(Controller::request('googleId')); - if ($payload) { - // $userid = $payload['sub']; - // ob_start(); - // var_dump($payload); - // $result = ob_get_clean(); - + if ($payload) { $this->userInstance = User::getUser($payload['email'], 'email'); - Session::getInstance()->createSession($this->userInstance->id, false); - Response::respondSuccess($this->getUserData()); - return; + if ($this->userInstance->isNull()) { + // Here I should create a new user with this email... + throw new Exception("Creating of new user by Google login yet to be done"); + } else { + Session::getInstance()->createSession($this->userInstance->id, false); + Response::respondSuccess($this->getUserData()); + return; + } } else { - echo "Invalid token" . PHP_EOL; + throw new Exception("Invalid GoogleID token"); } - - Response::respondSuccess(array( - 'userId' => -1, - )); - return; } if ($this->checkInputCredentials() || $this->checkRememberToken()) { From da534e30187f90a6d2d40a9d0e5983a80ffb9c56 Mon Sep 17 00:00:00 2001 From: Maxi Redigonda Date: Thu, 20 Aug 2020 16:40:15 -0300 Subject: [PATCH 13/21] Adds Google close session functionality --- client/src/actions/session-actions.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/src/actions/session-actions.js b/client/src/actions/session-actions.js index 9bec3100..0b6db3e8 100644 --- a/client/src/actions/session-actions.js +++ b/client/src/actions/session-actions.js @@ -71,6 +71,8 @@ export default { payload: API.call({ path: '/user/logout', data: {} + }).then(() => { + gapi.auth2.getAuthInstance().signOut(); }) }; }, From 38136ade4de67e9df5fa67df44ed585371c5c94b Mon Sep 17 00:00:00 2001 From: Maxi Redigonda Date: Thu, 20 Aug 2020 18:27:43 -0300 Subject: [PATCH 14/21] Moves renderGoogleButton out of render --- .../main-home/main-home-page-login-widget.js | 37 ++++++++++--------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/client/src/app/main/main-home/main-home-page-login-widget.js b/client/src/app/main/main-home/main-home-page-login-widget.js index 99fbc698..d5a0d8bd 100644 --- a/client/src/app/main/main-home/main-home-page-login-widget.js +++ b/client/src/app/main/main-home/main-home-page-login-widget.js @@ -45,23 +45,7 @@ class MainHomePageLoginWidget extends React.Component { } renderLogin() { - const defaultGoogleHandler = (response) => { - console.log(response); - } - - gapi.load('auth2', () => { - gapi.auth2.init({client_id: '50174278643-gtvjdpm5rmkv75lf3jsp95iv77a2usgu.apps.googleusercontent.com'}) - gapi.signin2.render('google-oauth-id', { - scope: 'email', - width: 200, - height: 30, - longtitle: true, - theme: 'dark', - onsuccess: this.onGoogleLoginSuccess.bind(this), - onfailure: defaultGoogleHandler - }) - }) - + this.renderGoogleButton(); return ( @@ -82,6 +66,25 @@ class MainHomePageLoginWidget extends React.Component { ); } + renderGoogleButton() { + const defaultGoogleHandler = (response) => { + console.log(response); + } + + gapi.load('auth2', () => { + gapi.auth2.init({client_id: '50174278643-gtvjdpm5rmkv75lf3jsp95iv77a2usgu.apps.googleusercontent.com'}) + gapi.signin2.render('google-oauth-id', { + scope: 'email', + width: 200, + height: 30, + longtitle: true, + theme: 'dark', + onsuccess: this.onGoogleLoginSuccess.bind(this), + onfailure: defaultGoogleHandler + }) + }) + } + renderPasswordRecovery() { return ( From 47f92569effd3d1d1f5a0a7155be71be803f80f5 Mon Sep 17 00:00:00 2001 From: Maxi Redigonda Date: Thu, 20 Aug 2020 22:56:31 -0300 Subject: [PATCH 15/21] Fixes button not showing and re-login --- client/src/actions/session-actions.js | 14 +++++++------- .../main/main-home/main-home-page-login-widget.js | 13 +++++++------ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/client/src/actions/session-actions.js b/client/src/actions/session-actions.js index 0b6db3e8..b72f80a0 100644 --- a/client/src/actions/session-actions.js +++ b/client/src/actions/session-actions.js @@ -68,13 +68,13 @@ export default { logout() { return { type: 'LOGOUT', - payload: API.call({ - path: '/user/logout', - data: {} - }).then(() => { - gapi.auth2.getAuthInstance().signOut(); - }) - }; + payload: Promise.resolve() + .then(() => gapi.auth2.getAuthInstance().signOut()) + .then(() => API.call({ + path: '/user/logout', + data: {} + })) + } }, getUserData(userId, token, staff) { diff --git a/client/src/app/main/main-home/main-home-page-login-widget.js b/client/src/app/main/main-home/main-home-page-login-widget.js index d5a0d8bd..c300967f 100644 --- a/client/src/app/main/main-home/main-home-page-login-widget.js +++ b/client/src/app/main/main-home/main-home-page-login-widget.js @@ -35,6 +35,10 @@ class MainHomePageLoginWidget extends React.Component { } } + componentDidMount() { + this.renderGoogleButton(); + } + render() { return ( @@ -45,7 +49,6 @@ class MainHomePageLoginWidget extends React.Component { } renderLogin() { - this.renderGoogleButton(); return ( @@ -67,10 +70,6 @@ class MainHomePageLoginWidget extends React.Component { } renderGoogleButton() { - const defaultGoogleHandler = (response) => { - console.log(response); - } - gapi.load('auth2', () => { gapi.auth2.init({client_id: '50174278643-gtvjdpm5rmkv75lf3jsp95iv77a2usgu.apps.googleusercontent.com'}) gapi.signin2.render('google-oauth-id', { @@ -80,7 +79,9 @@ class MainHomePageLoginWidget extends React.Component { longtitle: true, theme: 'dark', onsuccess: this.onGoogleLoginSuccess.bind(this), - onfailure: defaultGoogleHandler + onfailure: (response) => { + console.log(response); + } }) }) } From 5021781d257a38bec9c0fcaf3c464d0691de5e9d Mon Sep 17 00:00:00 2001 From: Maxi Redigonda Date: Thu, 20 Aug 2020 23:45:09 -0300 Subject: [PATCH 16/21] Implements Google auto signup If the user doesn't have an account on the system, the first time they log in with Google, an account will be created. --- server/controllers/user/login.php | 39 +++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/server/controllers/user/login.php b/server/controllers/user/login.php index 808a6599..c77345ae 100755 --- a/server/controllers/user/login.php +++ b/server/controllers/user/login.php @@ -52,19 +52,18 @@ class LoginController extends Controller { $this->clearOldRememberTokens(); if ($this->checkGoogleLogin()) { - $client = new Google_Client(['client_id' => '50174278643-gtvjdpm5rmkv75lf3jsp95iv77a2usgu.apps.googleusercontent.com']); // Specify the CLIENT_ID of the app that accesses the backend + $client = new Google_Client(['client_id' => '50174278643-gtvjdpm5rmkv75lf3jsp95iv77a2usgu.apps.googleusercontent.com']); $payload = $client->verifyIdToken(Controller::request('googleId')); if ($payload) { $this->userInstance = User::getUser($payload['email'], 'email'); if ($this->userInstance->isNull()) { - // Here I should create a new user with this email... - throw new Exception("Creating of new user by Google login yet to be done"); - } else { - Session::getInstance()->createSession($this->userInstance->id, false); - Response::respondSuccess($this->getUserData()); - return; + $this->userInstance = $this->createGoogleUser($payload); } + + Session::getInstance()->createSession($this->userInstance->id, false); + Response::respondSuccess($this->getUserData()); + return; } else { throw new Exception("Invalid GoogleID token"); } @@ -97,6 +96,32 @@ class LoginController extends Controller { return !!Controller::request('googleId'); } + private function createGoogleUser($payload) { + Controller::setDataRequester(function ($key) use ($payload) { + switch ($key) { + case 'email': + return $payload['email']; + case 'password': + return Hashing::generateRandomToken(); + case 'name': + return $payload['name']; + } + + return null; + }); + + $signupController = new SignUpController(true); + + try { + $signupController->validate(); + $signupController->handler(); + } catch (\Exception $exception) { + throw new Exception("OpenSupports doesn't accept this Google account, failed validations: " . $exception); + } + + return User::getUser($payload['email'], 'email'); + } + private function checkInputCredentials() { $this->userInstance = $this->getUserByInputCredentials(); From 0fd23ac6b8efdbccac250ce4ebf481054367f25d Mon Sep 17 00:00:00 2001 From: Maxi Redigonda Date: Thu, 20 Aug 2020 23:53:44 -0300 Subject: [PATCH 17/21] Aligns Google login button --- client/src/app/main/main-home/main-home-page-login-widget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/app/main/main-home/main-home-page-login-widget.js b/client/src/app/main/main-home/main-home-page-login-widget.js index c300967f..1065f0ec 100644 --- a/client/src/app/main/main-home/main-home-page-login-widget.js +++ b/client/src/app/main/main-home/main-home-page-login-widget.js @@ -52,8 +52,8 @@ class MainHomePageLoginWidget extends React.Component { return ( -
Loading Google Login ...
+
Loading Google Login ...
From 9f915a3291dc8f7f9216c71ab775015bf062f1ab Mon Sep 17 00:00:00 2001 From: Maxi Redigonda Date: Fri, 21 Aug 2020 00:05:42 -0300 Subject: [PATCH 18/21] Removes workaround --- .../main/main-home/main-home-page-login-widget.js | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/client/src/app/main/main-home/main-home-page-login-widget.js b/client/src/app/main/main-home/main-home-page-login-widget.js index 1065f0ec..ce0df8ca 100644 --- a/client/src/app/main/main-home/main-home-page-login-widget.js +++ b/client/src/app/main/main-home/main-home-page-login-widget.js @@ -24,9 +24,7 @@ class MainHomePageLoginWidget extends React.Component { recoverFormErrors: {}, recoverSent: false, loadingLogin: false, - loadingRecover: false, - - sent: false + loadingRecover: false }; componentDidUpdate(prevProps) { @@ -149,12 +147,9 @@ class MainHomePageLoginWidget extends React.Component { } onGoogleLoginSuccess(googleUser) { - if (!this.state.sent) { - let id_token = googleUser.getAuthResponse().id_token; - console.log(id_token); - this.props.dispatch(SessionActions.login({'googleId': id_token, 'remember': 1})); - this.setState({sent: true}); - } + let id_token = googleUser.getAuthResponse().id_token; + console.log(id_token); + this.props.dispatch(SessionActions.login({'googleId': id_token, 'remember': 1})); } onForgotPasswordSubmit(formState) { From a89a465ac983dc2d2f4bff1f7f5832f81b6ee928 Mon Sep 17 00:00:00 2001 From: Maxi Redigonda Date: Sat, 22 Aug 2020 00:47:24 -0300 Subject: [PATCH 19/21] Adds check to see if email was verified --- server/controllers/user/login.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/controllers/user/login.php b/server/controllers/user/login.php index c77345ae..d4ecb30e 100755 --- a/server/controllers/user/login.php +++ b/server/controllers/user/login.php @@ -54,7 +54,7 @@ class LoginController extends Controller { if ($this->checkGoogleLogin()) { $client = new Google_Client(['client_id' => '50174278643-gtvjdpm5rmkv75lf3jsp95iv77a2usgu.apps.googleusercontent.com']); $payload = $client->verifyIdToken(Controller::request('googleId')); - if ($payload) { + if ($payload && $payload['email_verified']) { $this->userInstance = User::getUser($payload['email'], 'email'); if ($this->userInstance->isNull()) { @@ -65,7 +65,7 @@ class LoginController extends Controller { Response::respondSuccess($this->getUserData()); return; } else { - throw new Exception("Invalid GoogleID token"); + throw new Exception("Invalid GoogleID token or unverified Google account"); } } From bb89956e9a680479ef40bed69941a6bee09b29ae Mon Sep 17 00:00:00 2001 From: Maxi Redigonda Date: Sun, 23 Aug 2020 18:55:05 -0300 Subject: [PATCH 20/21] Fixes admin logout --- client/src/actions/session-actions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/actions/session-actions.js b/client/src/actions/session-actions.js index b72f80a0..0744e422 100644 --- a/client/src/actions/session-actions.js +++ b/client/src/actions/session-actions.js @@ -69,7 +69,7 @@ export default { return { type: 'LOGOUT', payload: Promise.resolve() - .then(() => gapi.auth2.getAuthInstance().signOut()) + .then(() => gapi && gapi.auth2 && gapi.auth2.getAuthInstance().signOut()) .then(() => API.call({ path: '/user/logout', data: {} From 371f11170621cb7be2c3ffddeca0e188409c6a2c Mon Sep 17 00:00:00 2001 From: Maxi Redigonda Date: Mon, 24 Aug 2020 07:50:07 -0300 Subject: [PATCH 21/21] Fixes frontend tests by mocking gapi object --- .../__tests__/main-home-page-login-widget-test.js | 10 ++++++++++ .../app/main/main-home/main-home-page-login-widget.js | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/client/src/app/main/main-home/__tests__/main-home-page-login-widget-test.js b/client/src/app/main/main-home/__tests__/main-home-page-login-widget-test.js index b428e61d..45ec83b7 100644 --- a/client/src/app/main/main-home/__tests__/main-home-page-login-widget-test.js +++ b/client/src/app/main/main-home/__tests__/main-home-page-login-widget-test.js @@ -35,6 +35,11 @@ describe('Login/Recover Widget', function () { let dispatch = stub(); function renderComponent(props = {session: {pending: false, failed: false}}) { + window.gapi = { + load() { + return null; + } + }; component = reRenderIntoDocument( ); @@ -116,6 +121,11 @@ describe('Login/Recover Widget', function () { let dispatch = stub(); beforeEach(function () { + window.gapi = { + load() { + return null; + } + }; component = TestUtils.renderIntoDocument( ); diff --git a/client/src/app/main/main-home/main-home-page-login-widget.js b/client/src/app/main/main-home/main-home-page-login-widget.js index ce0df8ca..9b439291 100644 --- a/client/src/app/main/main-home/main-home-page-login-widget.js +++ b/client/src/app/main/main-home/main-home-page-login-widget.js @@ -68,7 +68,7 @@ class MainHomePageLoginWidget extends React.Component { } renderGoogleButton() { - gapi.load('auth2', () => { + window.gapi.load('auth2', () => { gapi.auth2.init({client_id: '50174278643-gtvjdpm5rmkv75lf3jsp95iv77a2usgu.apps.googleusercontent.com'}) gapi.signin2.render('google-oauth-id', { scope: 'email',