diff --git a/.flowconfig b/.flowconfig
deleted file mode 100644
index f0d79f28e..000000000
--- a/.flowconfig
+++ /dev/null
@@ -1,25 +0,0 @@
-
-[ignore]
-.*/node_modules/.*
-.*/vendors/.*
-.*/rainloop/.*
-.*/plugins/.*
-.*/build/.*
-.*/asserts/.*
-
-[include]
-
-[libs]
-./dev/
-
-[options]
-strip_root=true
-module.system=haste
-
-esproposal.class_static_fields=enable
-esproposal.class_instance_fields=enable
-esproposal.decorators=ignore
-
-experimental.strict_type_args=true
-
-unsafe.enable_getters_and_setters=true
diff --git a/asserts/android-icon.png b/assets/android-icon.png
similarity index 100%
rename from asserts/android-icon.png
rename to assets/android-icon.png
diff --git a/asserts/apple-touch-icon.png b/assets/apple-touch-icon.png
similarity index 100%
rename from asserts/apple-touch-icon.png
rename to assets/apple-touch-icon.png
diff --git a/asserts/browsers/chrome.gif b/assets/browsers/chrome.gif
similarity index 100%
rename from asserts/browsers/chrome.gif
rename to assets/browsers/chrome.gif
diff --git a/asserts/browsers/firefox.gif b/assets/browsers/firefox.gif
similarity index 100%
rename from asserts/browsers/firefox.gif
rename to assets/browsers/firefox.gif
diff --git a/asserts/browsers/opera.gif b/assets/browsers/opera.gif
similarity index 100%
rename from asserts/browsers/opera.gif
rename to assets/browsers/opera.gif
diff --git a/asserts/browsers/safari.gif b/assets/browsers/safari.gif
similarity index 100%
rename from asserts/browsers/safari.gif
rename to assets/browsers/safari.gif
diff --git a/asserts/css/default-skin.png b/assets/css/default-skin.png
similarity index 100%
rename from asserts/css/default-skin.png
rename to assets/css/default-skin.png
diff --git a/asserts/css/default-skin.svg b/assets/css/default-skin.svg
similarity index 100%
rename from asserts/css/default-skin.svg
rename to assets/css/default-skin.svg
diff --git a/asserts/css/flags.png b/assets/css/flags.png
similarity index 100%
rename from asserts/css/flags.png
rename to assets/css/flags.png
diff --git a/asserts/css/images/editor.png b/assets/css/images/editor.png
similarity index 100%
rename from asserts/css/images/editor.png
rename to assets/css/images/editor.png
diff --git a/asserts/css/images/empty-contact.png b/assets/css/images/empty-contact.png
similarity index 100%
rename from asserts/css/images/empty-contact.png
rename to assets/css/images/empty-contact.png
diff --git a/asserts/css/images/grey.png b/assets/css/images/grey.png
similarity index 100%
rename from asserts/css/images/grey.png
rename to assets/css/images/grey.png
diff --git a/asserts/css/images/icom-message-notification.png b/assets/css/images/icom-message-notification.png
similarity index 100%
rename from asserts/css/images/icom-message-notification.png
rename to assets/css/images/icom-message-notification.png
diff --git a/asserts/css/images/loading.gif b/assets/css/images/loading.gif
similarity index 100%
rename from asserts/css/images/loading.gif
rename to assets/css/images/loading.gif
diff --git a/asserts/css/images/rainloop-logo.png b/assets/css/images/rainloop-logo.png
similarity index 100%
rename from asserts/css/images/rainloop-logo.png
rename to assets/css/images/rainloop-logo.png
diff --git a/asserts/css/images/sync.gif b/assets/css/images/sync.gif
similarity index 100%
rename from asserts/css/images/sync.gif
rename to assets/css/images/sync.gif
diff --git a/asserts/css/images/sync.png b/assets/css/images/sync.png
similarity index 100%
rename from asserts/css/images/sync.png
rename to assets/css/images/sync.png
diff --git a/asserts/css/images/white.png b/assets/css/images/white.png
similarity index 100%
rename from asserts/css/images/white.png
rename to assets/css/images/white.png
diff --git a/asserts/css/img/loading.gif b/assets/css/img/loading.gif
similarity index 100%
rename from asserts/css/img/loading.gif
rename to assets/css/img/loading.gif
diff --git a/asserts/css/loading.gif b/assets/css/loading.gif
similarity index 100%
rename from asserts/css/loading.gif
rename to assets/css/loading.gif
diff --git a/asserts/css/preloader.gif b/assets/css/preloader.gif
similarity index 100%
rename from asserts/css/preloader.gif
rename to assets/css/preloader.gif
diff --git a/asserts/favicon.ico b/assets/favicon.ico
similarity index 100%
rename from asserts/favicon.ico
rename to assets/favicon.ico
diff --git a/asserts/favicon.png b/assets/favicon.png
similarity index 100%
rename from asserts/favicon.png
rename to assets/favicon.png
diff --git a/asserts/manifest.json b/assets/manifest.json
similarity index 100%
rename from asserts/manifest.json
rename to assets/manifest.json
diff --git a/asserts/sounds/new-mail.mp3 b/assets/sounds/new-mail.mp3
similarity index 100%
rename from asserts/sounds/new-mail.mp3
rename to assets/sounds/new-mail.mp3
diff --git a/asserts/sounds/new-mail.ogg b/assets/sounds/new-mail.ogg
similarity index 100%
rename from asserts/sounds/new-mail.ogg
rename to assets/sounds/new-mail.ogg
diff --git a/dev/admin.js b/dev/admin.js
index d551991ad..75b836765 100644
--- a/dev/admin.js
+++ b/dev/admin.js
@@ -1,4 +1,4 @@
-/* @flow */
+
import bootstrap from 'bootstrap';
import App from 'App/Admin';
diff --git a/dev/app.js b/dev/app.js
index 7c6b53d1c..08aa049d5 100644
--- a/dev/app.js
+++ b/dev/app.js
@@ -1,4 +1,4 @@
-/* @flow */
+
import bootstrap from 'bootstrap';
import App from 'App/User';
diff --git a/dev/bootstrap.js b/dev/bootstrap.js
index 5ded282af..1a7b99f79 100644
--- a/dev/bootstrap.js
+++ b/dev/bootstrap.js
@@ -1,4 +1,4 @@
-/* @flow */
+
import window from 'window';
import {killCtrlACtrlS, detectDropdownVisibility, createCommandLegacy, domReady} from 'Common/Utils';
import {$win, $html, data as GlobalsData, bMobileDevice} from 'Common/Globals';
diff --git a/gulpfile.js b/gulpfile.js
index 61f9acc54..3a5a19c01 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -167,8 +167,8 @@ cfg.paths.staticMinJS = 'rainloop/v/' + cfg.devVersion + '/static/js/min/';
cfg.paths.staticCSS = 'rainloop/v/' + cfg.devVersion + '/static/css/';
cfg.paths.momentLocales = 'rainloop/v/' + cfg.devVersion + '/app/localization/moment/';
-cfg.paths.asserts = {
- src: 'asserts/**/*.*'
+cfg.paths.assets = {
+ src: 'assets/**/*.*'
};
cfg.paths.less = {
@@ -269,12 +269,12 @@ cfg.paths.js = {
// assers
-gulp.task('asserts:clean', function() {
+gulp.task('assets:clean', function() {
return cleanDir(cfg.paths.static);
});
-gulp.task('asserts', function() {
- return gulp.src(cfg.paths.asserts.src)
+gulp.task('assets', function() {
+ return gulp.src(cfg.paths.assets.src)
.pipe(gulp.dest(cfg.paths.static));
});
@@ -284,7 +284,7 @@ gulp.task('css:clean', function() {
return cleanDir(cfg.paths.staticCSS + '/*.css');
});
-gulp.task('css:main', ['asserts'], function() {
+gulp.task('css:main', ['assets'], function() {
var autoprefixer = require('gulp-autoprefixer'),
less = require('gulp-less'),
lessFilter = filter('**/*.less', {restore: true}),
@@ -614,7 +614,7 @@ gulp.task('css', ['css:min']);
gulp.task('vendors', ['moment', 'ckeditor', 'fontastic', 'lightgallery']);
-gulp.task('clean', ['js:clean', 'css:clean', 'asserts:clean']);
+gulp.task('clean', ['js:clean', 'css:clean', 'assets:clean']);
gulp.task('rainloop:start', ['rainloop:copy', 'rainloop:setup']);
diff --git a/package.json b/package.json
index 5cad19312..11ede194a 100644
--- a/package.json
+++ b/package.json
@@ -52,7 +52,7 @@
"autolinker": "1.4.0",
"babel-core": "6.20.0",
"babel-eslint": "7.1.1",
- "babel-loader": "6.2.9",
+ "babel-loader": "6.2.10",
"babel-plugin-transform-decorators-legacy": "1.3.4",
"babel-plugin-transform-runtime": "6.15.0",
"babel-preset-es2015": "6.18.0",
diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php
index 01caf0a92..260e5ba46 100644
--- a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php
+++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php
@@ -2137,12 +2137,13 @@ NewThemeLink IncludeCss LoadingDescriptionEsc TemplatesLink LangLink IncludeBack
* @param string $sSignMeToken = ''
* @param string $sAdditionalCode = ''
* @param string $bAdditionalCodeSignMe = false
+ * @param string $bSkipTwoFactorAuth = false
*
* @return \RainLoop\Model\Account
* @throws \RainLoop\Exceptions\ClientException
*/
public function LoginProcess(&$sEmail, &$sPassword, $sSignMeToken = '',
- $sAdditionalCode = '', $bAdditionalCodeSignMe = false)
+ $sAdditionalCode = '', $bAdditionalCodeSignMe = false, $bSkipTwoFactorAuth = false)
{
$sInputEmail = $sEmail;
@@ -2265,8 +2266,8 @@ NewThemeLink IncludeCss LoadingDescriptionEsc TemplatesLink LangLink IncludeBack
throw $oException;
}
- // Two factor auth
- if ($this->TwoFactorAuthProvider()->IsActive())
+ // 2FA
+ if (!$bSkipTwoFactorAuth && $this->TwoFactorAuthProvider()->IsActive())
{
$aData = $this->getTwoFactorInfo($oAccount);
if ($aData && isset($aData['IsSet'], $aData['Enable']) && !empty($aData['Secret']) && $aData['IsSet'] && $aData['Enable'])
@@ -2852,7 +2853,7 @@ NewThemeLink IncludeCss LoadingDescriptionEsc TemplatesLink LangLink IncludeBack
throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::AccountDoesNotExist);
}
- $oNewAccount = $this->LoginProcess($sEmail, $sPassword);
+ $oNewAccount = $this->LoginProcess($sEmail, $sPassword, '', '', false, true);
$oNewAccount->SetParentEmail($sParentEmail);
$aAccounts[$oNewAccount->Email()] = $oNewAccount->GetAuthToken();
diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Social.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Social.php
index 3515a6a1e..52c03c9fa 100644
--- a/rainloop/v/0.0.0/app/libraries/RainLoop/Social.php
+++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Social.php
@@ -1,807 +1,807 @@
-oHttp = $oHttp;
- $this->oActions = $oActions;
- }
-
- /**
- * @return bool
- */
- public function GoogleDisconnect($oAccount)
- {
- $oGoogle = $this->GoogleConnector();
- if ($oAccount && $oGoogle)
- {
- $oSettings = $this->oActions->SettingsProvider()->Load($oAccount);
- $sEncodedeData = $oSettings->GetConf('GoogleAccessToken', '');
-
- if (!empty($sEncodedeData))
- {
- $aData = \RainLoop\Utils::DecodeKeyValues($sEncodedeData);
- if (\is_array($aData) && !empty($aData['id']))
- {
- $this->oActions->StorageProvider()->Clear(null,
- \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
- $this->GoogleUserLoginStorageKey($oGoogle, $aData['id'])
- );
- }
- }
-
- $oSettings->SetConf('GoogleAccessToken', '');
- $oSettings->SetConf('GoogleSocialName', '');
-
- return $this->oActions->SettingsProvider()->Save($oAccount, $oSettings);
- }
-
- return false;
- }
-
- /**
- * @return bool
- */
- public function FacebookDisconnect($oAccount)
- {
- $oFacebook = $this->FacebookConnector($oAccount ? $oAccount : null);
- if ($oAccount && $oFacebook)
- {
- $oSettings = $this->oActions->SettingsProvider()->Load($oAccount);
-
- $sEncodedeData = $oSettings->GetConf('FacebookAccessToken', '');
-
- if (!empty($sEncodedeData))
- {
- $aData = \RainLoop\Utils::DecodeKeyValues($sEncodedeData);
- if (is_array($aData) && isset($aData['id']))
- {
- $this->oActions->StorageProvider()->Clear(null,
- \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
- $this->FacebookUserLoginStorageKey($oFacebook, $aData['id'])
- );
- }
- }
-
- $oSettings->SetConf('FacebookAccessToken', '');
- $oSettings->SetConf('FacebookSocialName', '');
-
- return $this->oActions->SettingsProvider()->Save($oAccount, $oSettings);
- }
-
- return false;
- }
-
- /**
- * @return bool
- */
- public function TwitterDisconnect($oAccount)
- {
- $oTwitter = $this->TwitterConnector();
- if ($oAccount && $oTwitter)
- {
- $oSettings = $this->oActions->SettingsProvider()->Load($oAccount);
- $sEncodedData = $oSettings->GetConf('TwitterAccessToken', '');
-
- if (!empty($sEncodedData))
- {
- $aData = \RainLoop\Utils::DecodeKeyValues($sEncodedData);
- if (is_array($aData) && isset($aData['id']))
- {
- $this->oActions->StorageProvider()->Clear(null,
- \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
- $this->TwitterUserLoginStorageKey($oTwitter, $aData['id'])
- );
- }
- }
-
- $oSettings->SetConf('TwitterAccessToken', '');
- $oSettings->SetConf('TwitterSocialName', '');
-
- return $this->oActions->SettingsProvider()->Save($oAccount, $oSettings);
- }
-
- return false;
- }
-
- /**
- * @return string
- */
- public function popupServiceResult($sTypeStr, $sLoginUrl, $bLogin, $iErrorCode)
- {
- $sResult = '';
- $bNiceSocialRedirect = $this->oActions->Config()->Get('labs', 'nice_social_redirect', true);
- $bAppCssDebug = !!$this->oActions->Config()->Get('labs', 'use_app_debug_css', false);
-
- $sIcon = $sTypeStr;
- if ('facebook' === $sIcon)
- {
- $sIcon = $sIcon.'-alt';
- }
-
- if ($sLoginUrl)
- {
- if (!$bNiceSocialRedirect)
- {
- $this->oActions->Location($sLoginUrl);
- }
- else
- {
- $this->oHttp->ServerNoCache();
- @\header('Content-Type: text/html; charset=utf-8');
-
- $sResult = \strtr(\file_get_contents(APP_VERSION_ROOT_PATH.'app/templates/Social.html'), array(
- '{{RefreshMeta}}' => '',
- '{{Stylesheet}}' => $this->oActions->StaticPath('css/social'.($bAppCssDebug ? '' : '.min').'.css'),
- '{{Icon}}' => $sIcon,
- '{{Script}}' => ''
- ));
- }
- }
- else
- {
- $this->oHttp->ServerNoCache();
- @\header('Content-Type: text/html; charset=utf-8');
-
- $sCallBackType = $bLogin ? '_login' : '';
- $sConnectionFunc = 'rl_'.\md5(\RainLoop\Utils::GetConnectionToken()).'_'.$sTypeStr.$sCallBackType.'_service';
-
- if (!$bNiceSocialRedirect)
- {
- $sResult = '';
- }
- else
- {
- $sResult = \strtr(\file_get_contents(APP_VERSION_ROOT_PATH.'app/templates/Social.html'), array(
- '{{RefreshMeta}}' => '',
- '{{Stylesheet}}' => $this->oActions->StaticPath('css/social'.($bAppCssDebug ? '' : '.min').'.css'),
- '{{Icon}}' => $sIcon,
- '{{Script}}' => ''
- ));
- }
- }
-
- return $sResult;
- }
-
- /**
- * @return string
- */
- public function GooglePopupService($bGmail = false)
- {
- $sLoginUrl = '';
- $oAccount = null;
-
- $bLogin = false;
- $iErrorCode = \RainLoop\Notifications::UnknownError;
-
- try
- {
- $oGoogle = $this->GoogleConnector();
- if ($this->oHttp->HasQuery('error'))
- {
- $iErrorCode = ('access_denied' === $this->oHttp->GetQuery('error')) ?
- \RainLoop\Notifications::SocialGoogleLoginAccessDisable : \RainLoop\Notifications::UnknownError;
- }
- else if ($oGoogle)
- {
- $oAccount = $this->oActions->GetAccount();
- $bLogin = !$oAccount;
-
- $sCheckToken = '';
- $sCheckAuth = '';
- $sState = $this->oHttp->GetQuery('state');
- if (!empty($sState))
- {
- $aParts = explode('|', $sState, 3);
-
- if (!$bGmail)
- {
- $bGmail = !empty($aParts[0]) ? '1' === (string) $aParts[0] : false;
- }
-
- $sCheckToken = !empty($aParts[1]) ? $aParts[1] : '';
- $sCheckAuth = !empty($aParts[2]) ? $aParts[2] : '';
- }
-
- $sRedirectUrl = $this->oHttp->GetFullUrl().'?SocialGoogle';
- if (!$this->oHttp->HasQuery('code'))
- {
- $aParams = array(
- 'scope' => \trim(\implode(' ', array(
- 'https://www.googleapis.com/auth/userinfo.email',
- 'https://www.googleapis.com/auth/userinfo.profile',
- $bGmail ? 'https://mail.google.com/' : ''
- ))),
- 'state' => ($bGmail ? '1' : '0').'|'.\RainLoop\Utils::GetConnectionToken().'|'.$this->oActions->GetSpecAuthToken(),
- 'response_type' => 'code'
- );
-
-// if ($bGmail)
-// {
-// $aParams['access_type'] = 'offline';
-// $aParams['approval_prompt'] = 'force';
-// }
-
- $sLoginUrl = $oGoogle->getAuthenticationUrl('https://accounts.google.com/o/oauth2/auth', $sRedirectUrl, $aParams);
- }
- else if (!empty($sState) && $sCheckToken === \RainLoop\Utils::GetConnectionToken())
- {
- if (!empty($sCheckAuth))
- {
- $this->oActions->SetSpecAuthToken($sCheckAuth);
- $oAccount = $this->oActions->GetAccount();
- $bLogin = !$oAccount;
- }
-
- $aParams = array('code' => $this->oHttp->GetQuery('code'), 'redirect_uri' => $sRedirectUrl);
- $aAuthorizationResponse = $oGoogle->getAccessToken('https://accounts.google.com/o/oauth2/token', 'authorization_code', $aParams);
-
- if (!empty($aAuthorizationResponse['result']['access_token']))
- {
- $oGoogle->setAccessToken($aAuthorizationResponse['result']['access_token']);
- $aUserInfoResponse = $oGoogle->fetch('https://www.googleapis.com/oauth2/v2/userinfo');
-
- if (!empty($aUserInfoResponse['result']['id']))
- {
- if ($bLogin)
- {
- $aUserData = null;
- if ($bGmail)
- {
- if (!empty($aUserInfoResponse['result']['email']))
- {
- $aUserData = array(
- 'Email' => $aUserInfoResponse['result']['email'],
- 'Password' => APP_GOOGLE_ACCESS_TOKEN_PREFIX.$aAuthorizationResponse['result']['access_token']
- );
- }
- }
- else
- {
- $sUserData = $this->oActions->StorageProvider()->Get(null,
- \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
- $this->GoogleUserLoginStorageKey($oGoogle, $aUserInfoResponse['result']['id'])
- );
-
- $aUserData = \RainLoop\Utils::DecodeKeyValues($sUserData);
- }
-
- if ($aUserData && \is_array($aUserData) &&
- !empty($aUserData['Email']) && isset($aUserData['Password']))
- {
- $iErrorCode = $this->loginProcess($oAccount, $aUserData['Email'], $aUserData['Password']);
- }
- else
- {
- $iErrorCode = \RainLoop\Notifications::SocialGoogleLoginAccessDisable;
- }
- }
-
- if ($oAccount && !$bGmail)
- {
- $aUserData = array(
- 'ID' => $aUserInfoResponse['result']['id'],
- 'Email' => $oAccount->Email(),
- 'Password' => $oAccount->Password()
- );
-
- $sSocialName = !empty($aUserInfoResponse['result']['name']) ? $aUserInfoResponse['result']['name'] : '';
- $sSocialName .= !empty($aUserInfoResponse['result']['email']) ? ' ('.$aUserInfoResponse['result']['email'].')' : '';
- $sSocialName = \trim($sSocialName);
-
- $oSettings = $this->oActions->SettingsProvider()->Load($oAccount);
-
- $oSettings->SetConf('GoogleAccessToken', \RainLoop\Utils::EncodeKeyValues(array(
- 'id' => $aUserInfoResponse['result']['id']
- )));
-
- $oSettings->SetConf('GoogleSocialName', $sSocialName);
-
- $this->oActions->SettingsProvider()->Save($oAccount, $oSettings);
-
- $this->oActions->StorageProvider()->Put(null,
- \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
- $this->GoogleUserLoginStorageKey($oGoogle, $aUserInfoResponse['result']['id']),
- \RainLoop\Utils::EncodeKeyValues($aUserData));
-
- $iErrorCode = 0;
- }
- }
- }
- }
- }
- }
- catch (\Exception $oException)
- {
- $this->oActions->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR);
- }
-
- return $this->popupServiceResult('google', $sLoginUrl, $bLogin, $iErrorCode);
- }
-
- /**
- * @return string
- */
- public function FacebookPopupService()
- {
- $sLoginUrl = '';
- $sSocialName = '';
-
- $mData = false;
- $sUserData = '';
- $aUserData = false;
- $oAccount = null;
-
- $bLogin = false;
- $iErrorCode = \RainLoop\Notifications::UnknownError;
-
- if (0 === \strlen($this->oActions->GetSpecAuthToken()) && $this->oHttp->HasQuery('rlah'))
- {
- $this->oActions->SetSpecAuthToken($this->oHttp->GetQuery('rlah', ''));
- }
-
- $oAccount = $this->oActions->GetAccount();
-
- $oFacebook = $this->FacebookConnector($oAccount);
- if ($oFacebook)
- {
- try
- {
- $oSession = $oFacebook->getSessionFromRedirect();
- if (!$oSession && !$this->oHttp->HasQuery('state'))
- {
- $sLoginUrl = $oFacebook->getLoginUrl().'&display=popup';
- }
- else if ($oSession)
- {
- $oRequest = new \Facebook\FacebookRequest($oSession, 'GET', '/me');
- $oResponse = $oRequest->execute();
- $oGraphObject = $oResponse->getGraphObject();
-
- $mData = $oGraphObject->getProperty('id');
- $sSocialName = $oGraphObject->getProperty('name');
-
- if ($oAccount)
- {
- if ($mData && 0 < \strlen($mData))
- {
- $aUserData = array(
- 'id' => $mData,
- 'Email' => $oAccount->Email(),
- 'Password' => $oAccount->Password()
- );
-
- $oSettings = $this->oActions->SettingsProvider()->Load($oAccount);
- $oSettings->SetConf('FacebookSocialName', $sSocialName);
- $oSettings->SetConf('FacebookAccessToken', \RainLoop\Utils::EncodeKeyValues(array('id' => $mData)));
-
- $this->oActions->SettingsProvider()->Save($oAccount, $oSettings);
-
- $this->oActions->StorageProvider()->Put(null,
- \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
- $this->FacebookUserLoginStorageKey($oFacebook, $mData),
- \RainLoop\Utils::EncodeKeyValues($aUserData));
-
- $iErrorCode = 0;
- }
- }
- else
- {
- $bLogin = true;
-
- if ($mData && 0 < \strlen($mData))
- {
- $sUserData = $this->oActions->StorageProvider()->Get(null,
- \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
- $this->FacebookUserLoginStorageKey($oFacebook, $mData));
-
- if ($sUserData)
- {
- $aUserData = \RainLoop\Utils::DecodeKeyValues($sUserData);
- }
- }
-
- if ($aUserData && \is_array($aUserData) &&
- !empty($aUserData['Email']) && isset($aUserData['Password']))
- {
- $iErrorCode = $this->loginProcess($oAccount, $aUserData['Email'], $aUserData['Password']);
- }
- else
- {
- $iErrorCode = \RainLoop\Notifications::SocialFacebookLoginAccessDisable;
- }
- }
- }
- }
- catch (\Exception $oException)
- {
- $this->oActions->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR);
- }
- }
-
- return $this->popupServiceResult('facebook', $sLoginUrl, $bLogin, $iErrorCode);
- }
-
- /**
- * @return string
- */
- public function TwitterPopupService()
- {
- $sLoginUrl = '';
-
- $sSocialName = '';
- $oAccount = null;
-
- $bLogin = false;
- $iErrorCode = \RainLoop\Notifications::UnknownError;
-
- $sRedirectUrl = $this->oHttp->GetFullUrl().'?SocialTwitter';
- if (0 < strlen($this->oActions->GetSpecAuthToken()))
- {
- $sRedirectUrl .= '&rlah='.$this->oActions->GetSpecAuthToken();
- }
- else if ($this->oHttp->HasQuery('rlah'))
- {
- $this->oActions->SetSpecAuthToken($this->oHttp->GetQuery('rlah', ''));
- $sRedirectUrl .= '&rlah='.$this->oActions->GetSpecAuthToken();
- }
-
- try
- {
- $oTwitter = $this->TwitterConnector();
- if ($oTwitter)
- {
- $sSessionKey = \implode('_', array('twitter',
- \md5($oTwitter->config['consumer_secret']), \md5(\RainLoop\Utils::GetConnectionToken()), 'AuthSessionData'));
-
- $oAccount = $this->oActions->GetAccount();
- if ($oAccount)
- {
- if (isset($_REQUEST['oauth_verifier']))
- {
- $sAuth = $this->oActions->Cacher()->Get($sSessionKey);
- $oAuth = $sAuth ? \json_decode($sAuth, true) : null;
-
- if ($oAuth && !empty($oAuth['oauth_token']) && !empty($oAuth['oauth_token_secret']))
- {
- $oTwitter->config['user_token'] = $oAuth['oauth_token'];
- $oTwitter->config['user_secret'] = $oAuth['oauth_token_secret'];
-
- $iCode = $oTwitter->request('POST', $oTwitter->url('oauth/access_token', ''), array(
- 'oauth_callback' => $sRedirectUrl,
- 'oauth_verifier' => $_REQUEST['oauth_verifier']
- ));
-
- if (200 === $iCode && isset($oTwitter->response['response']))
- {
- $aAccessToken = $oTwitter->extract_params($oTwitter->response['response']);
- if ($aAccessToken && isset($aAccessToken['oauth_token']) && !empty($aAccessToken['user_id']))
- {
- $aAccessToken['id'] = $aAccessToken['user_id'];
-
- $oTwitter->config['user_token'] = $aAccessToken['oauth_token'];
- $oTwitter->config['user_secret'] = $aAccessToken['oauth_token_secret'];
-
- $sSocialName = !empty($aAccessToken['screen_name']) ? '@'.$aAccessToken['screen_name'] : $aAccessToken['user_id'];
- $sSocialName = \trim($sSocialName);
-
- $aUserData = array(
- 'id' => $aAccessToken['id'],
- 'Email' => $oAccount->Email(),
- 'Password' => $oAccount->Password()
- );
-
- $oSettings = $this->oActions->SettingsProvider()->Load($oAccount);
- $oSettings->SetConf('TwitterAccessToken', \RainLoop\Utils::EncodeKeyValues($aAccessToken));
- $oSettings->SetConf('TwitterSocialName', $sSocialName);
- $this->oActions->SettingsProvider()->Save($oAccount, $oSettings);
-
- $this->oActions->StorageProvider()->Put(null,
- \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
- $this->TwitterUserLoginStorageKey($oTwitter, $aAccessToken['id']),
- \RainLoop\Utils::EncodeKeyValues($aUserData));
-
- $iErrorCode = 0;
- }
- }
- }
- }
- else
- {
- $aParams = array(
- 'oauth_callback' => $sRedirectUrl,
- 'x_auth_access_type' => 'read'
- );
-
- $iCode = $oTwitter->request('POST', $oTwitter->url('oauth/request_token', ''), $aParams);
- if (200 === $iCode && isset($oTwitter->response['response']))
- {
- $oAuth = $oTwitter->extract_params($oTwitter->response['response']);
- if (!empty($oAuth['oauth_token']))
- {
- $this->oActions->Cacher()->Set($sSessionKey, \json_encode($oAuth));
- $sLoginUrl = $oTwitter->url('oauth/authenticate', '').'?oauth_token='.$oAuth['oauth_token'];
- }
- }
- }
- }
- else
- {
- $bLogin = true;
-
- if (isset($_REQUEST['oauth_verifier']))
- {
- $sAuth = $this->oActions->Cacher()->Get($sSessionKey);
- $oAuth = $sAuth ? \json_decode($sAuth, true) : null;
- if ($oAuth && !empty($oAuth['oauth_token']) && !empty($oAuth['oauth_token_secret']))
- {
- $oTwitter->config['user_token'] = $oAuth['oauth_token'];
- $oTwitter->config['user_secret'] = $oAuth['oauth_token_secret'];
-
- $iCode = $oTwitter->request('POST', $oTwitter->url('oauth/access_token', ''), array(
- 'oauth_callback' => $sRedirectUrl,
- 'oauth_verifier' => $_REQUEST['oauth_verifier']
- ));
-
- if (200 === $iCode && isset($oTwitter->response['response']))
- {
- $aAccessToken = $oTwitter->extract_params($oTwitter->response['response']);
- if ($aAccessToken && isset($aAccessToken['oauth_token']) && !empty($aAccessToken['user_id']))
- {
- $sUserData = $this->oActions->StorageProvider()->Get(null,
- \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
- $this->TwitterUserLoginStorageKey($oTwitter, $aAccessToken['user_id'])
- );
-
- $aUserData = \RainLoop\Utils::DecodeKeyValues($sUserData);
-
- if ($aUserData && \is_array($aUserData) &&
- !empty($aUserData['Email']) && isset($aUserData['Password']))
- {
- $iErrorCode = $this->loginProcess($oAccount, $aUserData['Email'], $aUserData['Password']);
- }
- else
- {
- $iErrorCode = \RainLoop\Notifications::SocialTwitterLoginAccessDisable;
- }
-
- $this->oActions->Cacher()->Delete($sSessionKey);
- }
- }
- }
- }
- else
- {
- $aParams = array(
- 'oauth_callback' => $sRedirectUrl,
- 'x_auth_access_type' => 'read'
- );
-
- $iCode = $oTwitter->request('POST', $oTwitter->url('oauth/request_token', ''), $aParams);
- if (200 === $iCode && isset($oTwitter->response['response']))
- {
- $oAuth = $oTwitter->extract_params($oTwitter->response['response']);
- if (!empty($oAuth['oauth_token']))
- {
- $this->oActions->Cacher()->Set($sSessionKey, \json_encode($oAuth));
- $sLoginUrl = $oTwitter->url('oauth/authenticate', '').'?oauth_token='.$oAuth['oauth_token'];
- }
- }
- }
- }
- }
- }
- catch (\Exception $oException)
- {
- $this->oActions->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR);
- }
-
- return $this->popupServiceResult('twitter', $sLoginUrl, $bLogin, $iErrorCode);
- }
-
- /**
- * @return \OAuth2\Client|null
- */
- public function GoogleConnector()
- {
- $oGoogle = false;
- $oConfig = $this->oActions->Config();
- if ($oConfig->Get('social', 'google_enable', false) &&
- '' !== \trim($oConfig->Get('social', 'google_client_id', '')) &&
- '' !== \trim($oConfig->Get('social', 'google_client_secret', '')))
- {
- include_once APP_VERSION_ROOT_PATH.'app/libraries/PHP-OAuth2/Client.php';
- include_once APP_VERSION_ROOT_PATH.'app/libraries/PHP-OAuth2/GrantType/IGrantType.php';
- include_once APP_VERSION_ROOT_PATH.'app/libraries/PHP-OAuth2/GrantType/AuthorizationCode.php';
- include_once APP_VERSION_ROOT_PATH.'app/libraries/PHP-OAuth2/GrantType/RefreshToken.php';
-
- try
- {
- $oGoogle = new \OAuth2\Client(
- \trim($oConfig->Get('social', 'google_client_id', '')),
- \trim($oConfig->Get('social', 'google_client_secret', '')));
-
- $sProxy = $this->oActions->Config()->Get('labs', 'curl_proxy', '');
- if (0 < \strlen($sProxy))
- {
- $oGoogle->setCurlOption(CURLOPT_PROXY, $sProxy);
-
- $sProxyAuth = $this->oActions->Config()->Get('labs', 'curl_proxy_auth', '');
- if (0 < \strlen($sProxyAuth))
- {
- $oGoogle->setCurlOption(CURLOPT_PROXYUSERPWD, $sProxyAuth);
- }
- }
- }
- catch (\Exception $oException)
- {
- $this->oActions->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR);
- }
- }
-
- return false === $oGoogle ? null : $oGoogle;
- }
-
- /**
- * @return \tmhOAuth|null
- */
- public function TwitterConnector()
- {
- $oTwitter = false;
- $oConfig = $this->oActions->Config();
- if ($oConfig->Get('social', 'twitter_enable', false) &&
- '' !== \trim($oConfig->Get('social', 'twitter_consumer_key', '')) &&
- '' !== \trim($oConfig->Get('social', 'twitter_consumer_secret', '')))
- {
- include_once APP_VERSION_ROOT_PATH.'app/libraries/tmhOAuth/tmhOAuth.php';
- include_once APP_VERSION_ROOT_PATH.'app/libraries/tmhOAuth/tmhUtilities.php';
-
- $sProxy = $this->oActions->Config()->Get('labs', 'curl_proxy', '');
- $sProxyAuth = $this->oActions->Config()->Get('labs', 'curl_proxy_auth', '');
-
- $oTwitter = new \tmhOAuth(array(
- 'consumer_key' => \trim($oConfig->Get('social', 'twitter_consumer_key', '')),
- 'consumer_secret' => \trim($oConfig->Get('social', 'twitter_consumer_secret', '')),
- 'curl_proxy' => 0 < \strlen($sProxy) ? $sProxy : false,
- 'curl_proxyuserpwd' => 0 < \strlen($sProxyAuth) ? $sProxyAuth : false
- ));
- }
-
- return false === $oTwitter ? null : $oTwitter;
- }
-
- /**
- * @param \RainLoop\Model\Account|null $oAccount = null
- *
- * @return \RainLoop\Common\RainLoopFacebookRedirectLoginHelper|null
- */
- public function FacebookConnector($oAccount = null)
- {
- $oFacebook = false;
- $oConfig = $this->oActions->Config();
- $sAppID = \trim($oConfig->Get('social', 'fb_app_id', ''));
-
- if (\version_compare(PHP_VERSION, '5.4.0', '>=') &&
- $oConfig->Get('social', 'fb_enable', false) && '' !== $sAppID &&
- '' !== \trim($oConfig->Get('social', 'fb_app_secret', '')) &&
- \class_exists('Facebook\FacebookSession')
- )
- {
- \Facebook\FacebookSession::setDefaultApplication($sAppID,
- \trim($oConfig->Get('social', 'fb_app_secret', '')));
-
- $sRedirectUrl = $this->oHttp->GetFullUrl().'?SocialFacebook';
- if (0 < \strlen($this->oActions->GetSpecAuthToken()))
- {
- $sRedirectUrl .= '&rlah='.$this->oActions->GetSpecAuthToken();
- }
- else if ($this->oHttp->HasQuery('rlah'))
- {
- $this->oActions->SetSpecAuthToken($this->oHttp->GetQuery('rlah', ''));
- $sRedirectUrl .= '&rlah='.$this->oActions->GetSpecAuthToken();
- }
-
- try
- {
- $oAccount = $this->oActions->GetAccount();
-
- $oFacebook = new \RainLoop\Common\RainLoopFacebookRedirectLoginHelper($sRedirectUrl);
- $oFacebook->initRainLoopData(array(
- 'rlAppId' => $sAppID,
- 'rlAccount' => $oAccount,
- 'rlUserHash' => \RainLoop\Utils::GetConnectionToken(),
- 'rlStorageProvaider' => $this->oActions->StorageProvider()
- ));
- }
- catch (\Exception $oException)
- {
- $this->oActions->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR);
- }
- }
-
- return false === $oFacebook ? null : $oFacebook;
- }
-
- /**
- * @return string
- */
- public function GoogleUserLoginStorageKey($oGoogle, $sGoogleUserId)
- {
- return \implode('_', array('google', \md5($oGoogle->getClientId()), $sGoogleUserId, APP_SALT));
- }
-
- /**
- * @return string
- */
- public function FacebookUserLoginStorageKey($oFacebook, $sFacebookUserId)
- {
- return \implode('_', array('facebookNew', \md5($oFacebook->GetRLAppId()), $sFacebookUserId, APP_SALT));
- }
-
- /**
- * @return string
- */
- public function TwitterUserLoginStorageKey($oTwitter, $sTwitterUserId)
- {
- return \implode('_', array('twitter_2', \md5($oTwitter->config['consumer_secret']), $sTwitterUserId, APP_SALT));
- }
-
- /**
- * @param \RainLoop\Model\Account|null $oAccount
- * @param string $sEmail
- * @param string $sPassword
- *
- * @return int
- */
- private function loginProcess(&$oAccount, $sEmail, $sPassword)
- {
- $iErrorCode = \RainLoop\Notifications::UnknownError;
-
- try
- {
- $oAccount = $this->oActions->LoginProcess($sEmail, $sPassword);
- if ($oAccount instanceof \RainLoop\Model\Account)
- {
- $this->oActions->AuthToken($oAccount);
- $iErrorCode = 0;
- }
- else
- {
- $oAccount = null;
- $iErrorCode = \RainLoop\Notifications::AuthError;
- }
- }
- catch (\RainLoop\Exceptions\ClientException $oException)
- {
- $iErrorCode = $oException->getCode();
- }
- catch (\Exception $oException)
- {
- unset($oException);
- $iErrorCode = \RainLoop\Notifications::UnknownError;
- }
-
- return $iErrorCode;
- }
+oHttp = $oHttp;
+ $this->oActions = $oActions;
+ }
+
+ /**
+ * @return bool
+ */
+ public function GoogleDisconnect($oAccount)
+ {
+ $oGoogle = $this->GoogleConnector();
+ if ($oAccount && $oGoogle)
+ {
+ $oSettings = $this->oActions->SettingsProvider()->Load($oAccount);
+ $sEncodedeData = $oSettings->GetConf('GoogleAccessToken', '');
+
+ if (!empty($sEncodedeData))
+ {
+ $aData = \RainLoop\Utils::DecodeKeyValues($sEncodedeData);
+ if (\is_array($aData) && !empty($aData['id']))
+ {
+ $this->oActions->StorageProvider()->Clear(null,
+ \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
+ $this->GoogleUserLoginStorageKey($oGoogle, $aData['id'])
+ );
+ }
+ }
+
+ $oSettings->SetConf('GoogleAccessToken', '');
+ $oSettings->SetConf('GoogleSocialName', '');
+
+ return $this->oActions->SettingsProvider()->Save($oAccount, $oSettings);
+ }
+
+ return false;
+ }
+
+ /**
+ * @return bool
+ */
+ public function FacebookDisconnect($oAccount)
+ {
+ $oFacebook = $this->FacebookConnector($oAccount ? $oAccount : null);
+ if ($oAccount && $oFacebook)
+ {
+ $oSettings = $this->oActions->SettingsProvider()->Load($oAccount);
+
+ $sEncodedeData = $oSettings->GetConf('FacebookAccessToken', '');
+
+ if (!empty($sEncodedeData))
+ {
+ $aData = \RainLoop\Utils::DecodeKeyValues($sEncodedeData);
+ if (is_array($aData) && isset($aData['id']))
+ {
+ $this->oActions->StorageProvider()->Clear(null,
+ \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
+ $this->FacebookUserLoginStorageKey($oFacebook, $aData['id'])
+ );
+ }
+ }
+
+ $oSettings->SetConf('FacebookAccessToken', '');
+ $oSettings->SetConf('FacebookSocialName', '');
+
+ return $this->oActions->SettingsProvider()->Save($oAccount, $oSettings);
+ }
+
+ return false;
+ }
+
+ /**
+ * @return bool
+ */
+ public function TwitterDisconnect($oAccount)
+ {
+ $oTwitter = $this->TwitterConnector();
+ if ($oAccount && $oTwitter)
+ {
+ $oSettings = $this->oActions->SettingsProvider()->Load($oAccount);
+ $sEncodedData = $oSettings->GetConf('TwitterAccessToken', '');
+
+ if (!empty($sEncodedData))
+ {
+ $aData = \RainLoop\Utils::DecodeKeyValues($sEncodedData);
+ if (is_array($aData) && isset($aData['id']))
+ {
+ $this->oActions->StorageProvider()->Clear(null,
+ \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
+ $this->TwitterUserLoginStorageKey($oTwitter, $aData['id'])
+ );
+ }
+ }
+
+ $oSettings->SetConf('TwitterAccessToken', '');
+ $oSettings->SetConf('TwitterSocialName', '');
+
+ return $this->oActions->SettingsProvider()->Save($oAccount, $oSettings);
+ }
+
+ return false;
+ }
+
+ /**
+ * @return string
+ */
+ public function popupServiceResult($sTypeStr, $sLoginUrl, $bLogin, $iErrorCode)
+ {
+ $sResult = '';
+ $bNiceSocialRedirect = $this->oActions->Config()->Get('labs', 'nice_social_redirect', true);
+ $bAppCssDebug = !!$this->oActions->Config()->Get('labs', 'use_app_debug_css', false);
+
+ $sIcon = $sTypeStr;
+ if ('facebook' === $sIcon)
+ {
+ $sIcon = $sIcon.'-alt';
+ }
+
+ if ($sLoginUrl)
+ {
+ if (!$bNiceSocialRedirect)
+ {
+ $this->oActions->Location($sLoginUrl);
+ }
+ else
+ {
+ $this->oHttp->ServerNoCache();
+ @\header('Content-Type: text/html; charset=utf-8');
+
+ $sResult = \strtr(\file_get_contents(APP_VERSION_ROOT_PATH.'app/templates/Social.html'), array(
+ '{{RefreshMeta}}' => '',
+ '{{Stylesheet}}' => $this->oActions->StaticPath('css/social'.($bAppCssDebug ? '' : '.min').'.css'),
+ '{{Icon}}' => $sIcon,
+ '{{Script}}' => ''
+ ));
+ }
+ }
+ else
+ {
+ $this->oHttp->ServerNoCache();
+ @\header('Content-Type: text/html; charset=utf-8');
+
+ $sCallBackType = $bLogin ? '_login' : '';
+ $sConnectionFunc = 'rl_'.\md5(\RainLoop\Utils::GetConnectionToken()).'_'.$sTypeStr.$sCallBackType.'_service';
+
+ if (!$bNiceSocialRedirect)
+ {
+ $sResult = '';
+ }
+ else
+ {
+ $sResult = \strtr(\file_get_contents(APP_VERSION_ROOT_PATH.'app/templates/Social.html'), array(
+ '{{RefreshMeta}}' => '',
+ '{{Stylesheet}}' => $this->oActions->StaticPath('css/social'.($bAppCssDebug ? '' : '.min').'.css'),
+ '{{Icon}}' => $sIcon,
+ '{{Script}}' => ''
+ ));
+ }
+ }
+
+ return $sResult;
+ }
+
+ /**
+ * @return string
+ */
+ public function GooglePopupService($bGmail = false)
+ {
+ $sLoginUrl = '';
+ $oAccount = null;
+
+ $bLogin = false;
+ $iErrorCode = \RainLoop\Notifications::UnknownError;
+
+ try
+ {
+ $oGoogle = $this->GoogleConnector();
+ if ($this->oHttp->HasQuery('error'))
+ {
+ $iErrorCode = ('access_denied' === $this->oHttp->GetQuery('error')) ?
+ \RainLoop\Notifications::SocialGoogleLoginAccessDisable : \RainLoop\Notifications::UnknownError;
+ }
+ else if ($oGoogle)
+ {
+ $oAccount = $this->oActions->GetAccount();
+ $bLogin = !$oAccount;
+
+ $sCheckToken = '';
+ $sCheckAuth = '';
+ $sState = $this->oHttp->GetQuery('state');
+ if (!empty($sState))
+ {
+ $aParts = explode('|', $sState, 3);
+
+ if (!$bGmail)
+ {
+ $bGmail = !empty($aParts[0]) ? '1' === (string) $aParts[0] : false;
+ }
+
+ $sCheckToken = !empty($aParts[1]) ? $aParts[1] : '';
+ $sCheckAuth = !empty($aParts[2]) ? $aParts[2] : '';
+ }
+
+ $sRedirectUrl = $this->oHttp->GetFullUrl().'?SocialGoogle';
+ if (!$this->oHttp->HasQuery('code'))
+ {
+ $aParams = array(
+ 'scope' => \trim(\implode(' ', array(
+ 'https://www.googleapis.com/auth/userinfo.email',
+ 'https://www.googleapis.com/auth/userinfo.profile',
+ $bGmail ? 'https://mail.google.com/' : ''
+ ))),
+ 'state' => ($bGmail ? '1' : '0').'|'.\RainLoop\Utils::GetConnectionToken().'|'.$this->oActions->GetSpecAuthToken(),
+ 'response_type' => 'code'
+ );
+
+// if ($bGmail)
+// {
+// $aParams['access_type'] = 'offline';
+// $aParams['approval_prompt'] = 'force';
+// }
+
+ $sLoginUrl = $oGoogle->getAuthenticationUrl('https://accounts.google.com/o/oauth2/auth', $sRedirectUrl, $aParams);
+ }
+ else if (!empty($sState) && $sCheckToken === \RainLoop\Utils::GetConnectionToken())
+ {
+ if (!empty($sCheckAuth))
+ {
+ $this->oActions->SetSpecAuthToken($sCheckAuth);
+ $oAccount = $this->oActions->GetAccount();
+ $bLogin = !$oAccount;
+ }
+
+ $aParams = array('code' => $this->oHttp->GetQuery('code'), 'redirect_uri' => $sRedirectUrl);
+ $aAuthorizationResponse = $oGoogle->getAccessToken('https://accounts.google.com/o/oauth2/token', 'authorization_code', $aParams);
+
+ if (!empty($aAuthorizationResponse['result']['access_token']))
+ {
+ $oGoogle->setAccessToken($aAuthorizationResponse['result']['access_token']);
+ $aUserInfoResponse = $oGoogle->fetch('https://www.googleapis.com/oauth2/v2/userinfo');
+
+ if (!empty($aUserInfoResponse['result']['id']))
+ {
+ if ($bLogin)
+ {
+ $aUserData = null;
+ if ($bGmail)
+ {
+ if (!empty($aUserInfoResponse['result']['email']))
+ {
+ $aUserData = array(
+ 'Email' => $aUserInfoResponse['result']['email'],
+ 'Password' => APP_GOOGLE_ACCESS_TOKEN_PREFIX.$aAuthorizationResponse['result']['access_token']
+ );
+ }
+ }
+ else
+ {
+ $sUserData = $this->oActions->StorageProvider()->Get(null,
+ \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
+ $this->GoogleUserLoginStorageKey($oGoogle, $aUserInfoResponse['result']['id'])
+ );
+
+ $aUserData = \RainLoop\Utils::DecodeKeyValues($sUserData);
+ }
+
+ if ($aUserData && \is_array($aUserData) &&
+ !empty($aUserData['Email']) && isset($aUserData['Password']))
+ {
+ $iErrorCode = $this->loginProcess($oAccount, $aUserData['Email'], $aUserData['Password']);
+ }
+ else
+ {
+ $iErrorCode = \RainLoop\Notifications::SocialGoogleLoginAccessDisable;
+ }
+ }
+
+ if ($oAccount && !$bGmail)
+ {
+ $aUserData = array(
+ 'ID' => $aUserInfoResponse['result']['id'],
+ 'Email' => $oAccount->Email(),
+ 'Password' => $oAccount->Password()
+ );
+
+ $sSocialName = !empty($aUserInfoResponse['result']['name']) ? $aUserInfoResponse['result']['name'] : '';
+ $sSocialName .= !empty($aUserInfoResponse['result']['email']) ? ' ('.$aUserInfoResponse['result']['email'].')' : '';
+ $sSocialName = \trim($sSocialName);
+
+ $oSettings = $this->oActions->SettingsProvider()->Load($oAccount);
+
+ $oSettings->SetConf('GoogleAccessToken', \RainLoop\Utils::EncodeKeyValues(array(
+ 'id' => $aUserInfoResponse['result']['id']
+ )));
+
+ $oSettings->SetConf('GoogleSocialName', $sSocialName);
+
+ $this->oActions->SettingsProvider()->Save($oAccount, $oSettings);
+
+ $this->oActions->StorageProvider()->Put(null,
+ \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
+ $this->GoogleUserLoginStorageKey($oGoogle, $aUserInfoResponse['result']['id']),
+ \RainLoop\Utils::EncodeKeyValues($aUserData));
+
+ $iErrorCode = 0;
+ }
+ }
+ }
+ }
+ }
+ }
+ catch (\Exception $oException)
+ {
+ $this->oActions->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR);
+ }
+
+ return $this->popupServiceResult('google', $sLoginUrl, $bLogin, $iErrorCode);
+ }
+
+ /**
+ * @return string
+ */
+ public function FacebookPopupService()
+ {
+ $sLoginUrl = '';
+ $sSocialName = '';
+
+ $mData = false;
+ $sUserData = '';
+ $aUserData = false;
+ $oAccount = null;
+
+ $bLogin = false;
+ $iErrorCode = \RainLoop\Notifications::UnknownError;
+
+ if (0 === \strlen($this->oActions->GetSpecAuthToken()) && $this->oHttp->HasQuery('rlah'))
+ {
+ $this->oActions->SetSpecAuthToken($this->oHttp->GetQuery('rlah', ''));
+ }
+
+ $oAccount = $this->oActions->GetAccount();
+
+ $oFacebook = $this->FacebookConnector($oAccount);
+ if ($oFacebook)
+ {
+ try
+ {
+ $oSession = $oFacebook->getSessionFromRedirect();
+ if (!$oSession && !$this->oHttp->HasQuery('state'))
+ {
+ $sLoginUrl = $oFacebook->getLoginUrl().'&display=popup';
+ }
+ else if ($oSession)
+ {
+ $oRequest = new \Facebook\FacebookRequest($oSession, 'GET', '/me');
+ $oResponse = $oRequest->execute();
+ $oGraphObject = $oResponse->getGraphObject();
+
+ $mData = $oGraphObject->getProperty('id');
+ $sSocialName = $oGraphObject->getProperty('name');
+
+ if ($oAccount)
+ {
+ if ($mData && 0 < \strlen($mData))
+ {
+ $aUserData = array(
+ 'id' => $mData,
+ 'Email' => $oAccount->Email(),
+ 'Password' => $oAccount->Password()
+ );
+
+ $oSettings = $this->oActions->SettingsProvider()->Load($oAccount);
+ $oSettings->SetConf('FacebookSocialName', $sSocialName);
+ $oSettings->SetConf('FacebookAccessToken', \RainLoop\Utils::EncodeKeyValues(array('id' => $mData)));
+
+ $this->oActions->SettingsProvider()->Save($oAccount, $oSettings);
+
+ $this->oActions->StorageProvider()->Put(null,
+ \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
+ $this->FacebookUserLoginStorageKey($oFacebook, $mData),
+ \RainLoop\Utils::EncodeKeyValues($aUserData));
+
+ $iErrorCode = 0;
+ }
+ }
+ else
+ {
+ $bLogin = true;
+
+ if ($mData && 0 < \strlen($mData))
+ {
+ $sUserData = $this->oActions->StorageProvider()->Get(null,
+ \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
+ $this->FacebookUserLoginStorageKey($oFacebook, $mData));
+
+ if ($sUserData)
+ {
+ $aUserData = \RainLoop\Utils::DecodeKeyValues($sUserData);
+ }
+ }
+
+ if ($aUserData && \is_array($aUserData) &&
+ !empty($aUserData['Email']) && isset($aUserData['Password']))
+ {
+ $iErrorCode = $this->loginProcess($oAccount, $aUserData['Email'], $aUserData['Password']);
+ }
+ else
+ {
+ $iErrorCode = \RainLoop\Notifications::SocialFacebookLoginAccessDisable;
+ }
+ }
+ }
+ }
+ catch (\Exception $oException)
+ {
+ $this->oActions->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR);
+ }
+ }
+
+ return $this->popupServiceResult('facebook', $sLoginUrl, $bLogin, $iErrorCode);
+ }
+
+ /**
+ * @return string
+ */
+ public function TwitterPopupService()
+ {
+ $sLoginUrl = '';
+
+ $sSocialName = '';
+ $oAccount = null;
+
+ $bLogin = false;
+ $iErrorCode = \RainLoop\Notifications::UnknownError;
+
+ $sRedirectUrl = $this->oHttp->GetFullUrl().'?SocialTwitter';
+ if (0 < strlen($this->oActions->GetSpecAuthToken()))
+ {
+ $sRedirectUrl .= '&rlah='.$this->oActions->GetSpecAuthToken();
+ }
+ else if ($this->oHttp->HasQuery('rlah'))
+ {
+ $this->oActions->SetSpecAuthToken($this->oHttp->GetQuery('rlah', ''));
+ $sRedirectUrl .= '&rlah='.$this->oActions->GetSpecAuthToken();
+ }
+
+ try
+ {
+ $oTwitter = $this->TwitterConnector();
+ if ($oTwitter)
+ {
+ $sSessionKey = \implode('_', array('twitter',
+ \md5($oTwitter->config['consumer_secret']), \md5(\RainLoop\Utils::GetConnectionToken()), 'AuthSessionData'));
+
+ $oAccount = $this->oActions->GetAccount();
+ if ($oAccount)
+ {
+ if (isset($_REQUEST['oauth_verifier']))
+ {
+ $sAuth = $this->oActions->Cacher()->Get($sSessionKey);
+ $oAuth = $sAuth ? \json_decode($sAuth, true) : null;
+
+ if ($oAuth && !empty($oAuth['oauth_token']) && !empty($oAuth['oauth_token_secret']))
+ {
+ $oTwitter->config['user_token'] = $oAuth['oauth_token'];
+ $oTwitter->config['user_secret'] = $oAuth['oauth_token_secret'];
+
+ $iCode = $oTwitter->request('POST', $oTwitter->url('oauth/access_token', ''), array(
+ 'oauth_callback' => $sRedirectUrl,
+ 'oauth_verifier' => $_REQUEST['oauth_verifier']
+ ));
+
+ if (200 === $iCode && isset($oTwitter->response['response']))
+ {
+ $aAccessToken = $oTwitter->extract_params($oTwitter->response['response']);
+ if ($aAccessToken && isset($aAccessToken['oauth_token']) && !empty($aAccessToken['user_id']))
+ {
+ $aAccessToken['id'] = $aAccessToken['user_id'];
+
+ $oTwitter->config['user_token'] = $aAccessToken['oauth_token'];
+ $oTwitter->config['user_secret'] = $aAccessToken['oauth_token_secret'];
+
+ $sSocialName = !empty($aAccessToken['screen_name']) ? '@'.$aAccessToken['screen_name'] : $aAccessToken['user_id'];
+ $sSocialName = \trim($sSocialName);
+
+ $aUserData = array(
+ 'id' => $aAccessToken['id'],
+ 'Email' => $oAccount->Email(),
+ 'Password' => $oAccount->Password()
+ );
+
+ $oSettings = $this->oActions->SettingsProvider()->Load($oAccount);
+ $oSettings->SetConf('TwitterAccessToken', \RainLoop\Utils::EncodeKeyValues($aAccessToken));
+ $oSettings->SetConf('TwitterSocialName', $sSocialName);
+ $this->oActions->SettingsProvider()->Save($oAccount, $oSettings);
+
+ $this->oActions->StorageProvider()->Put(null,
+ \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
+ $this->TwitterUserLoginStorageKey($oTwitter, $aAccessToken['id']),
+ \RainLoop\Utils::EncodeKeyValues($aUserData));
+
+ $iErrorCode = 0;
+ }
+ }
+ }
+ }
+ else
+ {
+ $aParams = array(
+ 'oauth_callback' => $sRedirectUrl,
+ 'x_auth_access_type' => 'read'
+ );
+
+ $iCode = $oTwitter->request('POST', $oTwitter->url('oauth/request_token', ''), $aParams);
+ if (200 === $iCode && isset($oTwitter->response['response']))
+ {
+ $oAuth = $oTwitter->extract_params($oTwitter->response['response']);
+ if (!empty($oAuth['oauth_token']))
+ {
+ $this->oActions->Cacher()->Set($sSessionKey, \json_encode($oAuth));
+ $sLoginUrl = $oTwitter->url('oauth/authenticate', '').'?oauth_token='.$oAuth['oauth_token'];
+ }
+ }
+ }
+ }
+ else
+ {
+ $bLogin = true;
+
+ if (isset($_REQUEST['oauth_verifier']))
+ {
+ $sAuth = $this->oActions->Cacher()->Get($sSessionKey);
+ $oAuth = $sAuth ? \json_decode($sAuth, true) : null;
+ if ($oAuth && !empty($oAuth['oauth_token']) && !empty($oAuth['oauth_token_secret']))
+ {
+ $oTwitter->config['user_token'] = $oAuth['oauth_token'];
+ $oTwitter->config['user_secret'] = $oAuth['oauth_token_secret'];
+
+ $iCode = $oTwitter->request('POST', $oTwitter->url('oauth/access_token', ''), array(
+ 'oauth_callback' => $sRedirectUrl,
+ 'oauth_verifier' => $_REQUEST['oauth_verifier']
+ ));
+
+ if (200 === $iCode && isset($oTwitter->response['response']))
+ {
+ $aAccessToken = $oTwitter->extract_params($oTwitter->response['response']);
+ if ($aAccessToken && isset($aAccessToken['oauth_token']) && !empty($aAccessToken['user_id']))
+ {
+ $sUserData = $this->oActions->StorageProvider()->Get(null,
+ \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
+ $this->TwitterUserLoginStorageKey($oTwitter, $aAccessToken['user_id'])
+ );
+
+ $aUserData = \RainLoop\Utils::DecodeKeyValues($sUserData);
+
+ if ($aUserData && \is_array($aUserData) &&
+ !empty($aUserData['Email']) && isset($aUserData['Password']))
+ {
+ $iErrorCode = $this->loginProcess($oAccount, $aUserData['Email'], $aUserData['Password']);
+ }
+ else
+ {
+ $iErrorCode = \RainLoop\Notifications::SocialTwitterLoginAccessDisable;
+ }
+
+ $this->oActions->Cacher()->Delete($sSessionKey);
+ }
+ }
+ }
+ }
+ else
+ {
+ $aParams = array(
+ 'oauth_callback' => $sRedirectUrl,
+ 'x_auth_access_type' => 'read'
+ );
+
+ $iCode = $oTwitter->request('POST', $oTwitter->url('oauth/request_token', ''), $aParams);
+ if (200 === $iCode && isset($oTwitter->response['response']))
+ {
+ $oAuth = $oTwitter->extract_params($oTwitter->response['response']);
+ if (!empty($oAuth['oauth_token']))
+ {
+ $this->oActions->Cacher()->Set($sSessionKey, \json_encode($oAuth));
+ $sLoginUrl = $oTwitter->url('oauth/authenticate', '').'?oauth_token='.$oAuth['oauth_token'];
+ }
+ }
+ }
+ }
+ }
+ }
+ catch (\Exception $oException)
+ {
+ $this->oActions->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR);
+ }
+
+ return $this->popupServiceResult('twitter', $sLoginUrl, $bLogin, $iErrorCode);
+ }
+
+ /**
+ * @return \OAuth2\Client|null
+ */
+ public function GoogleConnector()
+ {
+ $oGoogle = false;
+ $oConfig = $this->oActions->Config();
+ if ($oConfig->Get('social', 'google_enable', false) &&
+ '' !== \trim($oConfig->Get('social', 'google_client_id', '')) &&
+ '' !== \trim($oConfig->Get('social', 'google_client_secret', '')))
+ {
+ include_once APP_VERSION_ROOT_PATH.'app/libraries/PHP-OAuth2/Client.php';
+ include_once APP_VERSION_ROOT_PATH.'app/libraries/PHP-OAuth2/GrantType/IGrantType.php';
+ include_once APP_VERSION_ROOT_PATH.'app/libraries/PHP-OAuth2/GrantType/AuthorizationCode.php';
+ include_once APP_VERSION_ROOT_PATH.'app/libraries/PHP-OAuth2/GrantType/RefreshToken.php';
+
+ try
+ {
+ $oGoogle = new \OAuth2\Client(
+ \trim($oConfig->Get('social', 'google_client_id', '')),
+ \trim($oConfig->Get('social', 'google_client_secret', '')));
+
+ $sProxy = $this->oActions->Config()->Get('labs', 'curl_proxy', '');
+ if (0 < \strlen($sProxy))
+ {
+ $oGoogle->setCurlOption(CURLOPT_PROXY, $sProxy);
+
+ $sProxyAuth = $this->oActions->Config()->Get('labs', 'curl_proxy_auth', '');
+ if (0 < \strlen($sProxyAuth))
+ {
+ $oGoogle->setCurlOption(CURLOPT_PROXYUSERPWD, $sProxyAuth);
+ }
+ }
+ }
+ catch (\Exception $oException)
+ {
+ $this->oActions->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR);
+ }
+ }
+
+ return false === $oGoogle ? null : $oGoogle;
+ }
+
+ /**
+ * @return \tmhOAuth|null
+ */
+ public function TwitterConnector()
+ {
+ $oTwitter = false;
+ $oConfig = $this->oActions->Config();
+ if ($oConfig->Get('social', 'twitter_enable', false) &&
+ '' !== \trim($oConfig->Get('social', 'twitter_consumer_key', '')) &&
+ '' !== \trim($oConfig->Get('social', 'twitter_consumer_secret', '')))
+ {
+ include_once APP_VERSION_ROOT_PATH.'app/libraries/tmhOAuth/tmhOAuth.php';
+ include_once APP_VERSION_ROOT_PATH.'app/libraries/tmhOAuth/tmhUtilities.php';
+
+ $sProxy = $this->oActions->Config()->Get('labs', 'curl_proxy', '');
+ $sProxyAuth = $this->oActions->Config()->Get('labs', 'curl_proxy_auth', '');
+
+ $oTwitter = new \tmhOAuth(array(
+ 'consumer_key' => \trim($oConfig->Get('social', 'twitter_consumer_key', '')),
+ 'consumer_secret' => \trim($oConfig->Get('social', 'twitter_consumer_secret', '')),
+ 'curl_proxy' => 0 < \strlen($sProxy) ? $sProxy : false,
+ 'curl_proxyuserpwd' => 0 < \strlen($sProxyAuth) ? $sProxyAuth : false
+ ));
+ }
+
+ return false === $oTwitter ? null : $oTwitter;
+ }
+
+ /**
+ * @param \RainLoop\Model\Account|null $oAccount = null
+ *
+ * @return \RainLoop\Common\RainLoopFacebookRedirectLoginHelper|null
+ */
+ public function FacebookConnector($oAccount = null)
+ {
+ $oFacebook = false;
+ $oConfig = $this->oActions->Config();
+ $sAppID = \trim($oConfig->Get('social', 'fb_app_id', ''));
+
+ if (\version_compare(PHP_VERSION, '5.4.0', '>=') &&
+ $oConfig->Get('social', 'fb_enable', false) && '' !== $sAppID &&
+ '' !== \trim($oConfig->Get('social', 'fb_app_secret', '')) &&
+ \class_exists('Facebook\FacebookSession')
+ )
+ {
+ \Facebook\FacebookSession::setDefaultApplication($sAppID,
+ \trim($oConfig->Get('social', 'fb_app_secret', '')));
+
+ $sRedirectUrl = $this->oHttp->GetFullUrl().'?SocialFacebook';
+ if (0 < \strlen($this->oActions->GetSpecAuthToken()))
+ {
+ $sRedirectUrl .= '&rlah='.$this->oActions->GetSpecAuthToken();
+ }
+ else if ($this->oHttp->HasQuery('rlah'))
+ {
+ $this->oActions->SetSpecAuthToken($this->oHttp->GetQuery('rlah', ''));
+ $sRedirectUrl .= '&rlah='.$this->oActions->GetSpecAuthToken();
+ }
+
+ try
+ {
+ $oAccount = $this->oActions->GetAccount();
+
+ $oFacebook = new \RainLoop\Common\RainLoopFacebookRedirectLoginHelper($sRedirectUrl);
+ $oFacebook->initRainLoopData(array(
+ 'rlAppId' => $sAppID,
+ 'rlAccount' => $oAccount,
+ 'rlUserHash' => \RainLoop\Utils::GetConnectionToken(),
+ 'rlStorageProvaider' => $this->oActions->StorageProvider()
+ ));
+ }
+ catch (\Exception $oException)
+ {
+ $this->oActions->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR);
+ }
+ }
+
+ return false === $oFacebook ? null : $oFacebook;
+ }
+
+ /**
+ * @return string
+ */
+ public function GoogleUserLoginStorageKey($oGoogle, $sGoogleUserId)
+ {
+ return \implode('_', array('google', \md5($oGoogle->getClientId()), $sGoogleUserId, APP_SALT));
+ }
+
+ /**
+ * @return string
+ */
+ public function FacebookUserLoginStorageKey($oFacebook, $sFacebookUserId)
+ {
+ return \implode('_', array('facebookNew', \md5($oFacebook->GetRLAppId()), $sFacebookUserId, APP_SALT));
+ }
+
+ /**
+ * @return string
+ */
+ public function TwitterUserLoginStorageKey($oTwitter, $sTwitterUserId)
+ {
+ return \implode('_', array('twitter_2', \md5($oTwitter->config['consumer_secret']), $sTwitterUserId, APP_SALT));
+ }
+
+ /**
+ * @param \RainLoop\Model\Account|null $oAccount
+ * @param string $sEmail
+ * @param string $sPassword
+ *
+ * @return int
+ */
+ private function loginProcess(&$oAccount, $sEmail, $sPassword)
+ {
+ $iErrorCode = \RainLoop\Notifications::UnknownError;
+
+ try
+ {
+ $oAccount = $this->oActions->LoginProcess($sEmail, $sPassword, '', '', false, true);
+ if ($oAccount instanceof \RainLoop\Model\Account)
+ {
+ $this->oActions->AuthToken($oAccount);
+ $iErrorCode = 0;
+ }
+ else
+ {
+ $oAccount = null;
+ $iErrorCode = \RainLoop\Notifications::AuthError;
+ }
+ }
+ catch (\RainLoop\Exceptions\ClientException $oException)
+ {
+ $iErrorCode = $oException->getCode();
+ }
+ catch (\Exception $oException)
+ {
+ unset($oException);
+ $iErrorCode = \RainLoop\Notifications::UnknownError;
+ }
+
+ return $iErrorCode;
+ }
}
\ No newline at end of file
diff --git a/yarn.lock b/yarn.lock
index 4edff796b..ebd654828 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -401,9 +401,9 @@ babel-helpers@^6.16.0:
babel-runtime "^6.0.0"
babel-template "^6.16.0"
-babel-loader@6.2.9:
- version "6.2.9"
- resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-6.2.9.tgz#2bce6a1c29b47afa90b937ba1fb1f87084d61c61"
+babel-loader@6.2.10:
+ version "6.2.10"
+ resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-6.2.10.tgz#adefc2b242320cd5d15e65b31cea0e8b1b02d4b0"
dependencies:
find-cache-dir "^0.1.1"
loader-utils "^0.2.11"