1: <?php
2: /**
3: * This code is licensed under AGPLv3 license or Afterlogic Software License
4: * if commercial version of the product was purchased.
5: * For full statements of the licenses see LICENSE-AFTERLOGIC and LICENSE-AGPL3 files.
6: */
7:
8: namespace Aurora\Modules\GMailConnector;
9:
10: /**
11: * Adds ability to work with GMail inside Mail module.
12: *
13: * @license https://www.gnu.org/licenses/agpl-3.0.html AGPL-3.0
14: * @license https://afterlogic.com/products/common-licensing Afterlogic Software License
15: * @copyright Copyright (c) 2023, Afterlogic Corp.
16: *
17: * @property Settings $oModuleSettings
18: *
19: * @package Modules
20: */
21: class Module extends \Aurora\System\Module\AbstractModule
22: {
23: protected $sService = 'gmail';
24:
25: protected $aRequireModules = array(
26: 'OAuthIntegratorWebclient',
27: 'GoogleAuthWebclient'
28: );
29:
30: /**
31: * @return Module
32: */
33: public static function getInstance()
34: {
35: return parent::getInstance();
36: }
37:
38: /**
39: * @return Module
40: */
41: public static function Decorator()
42: {
43: return parent::Decorator();
44: }
45:
46: /**
47: * @return Settings
48: */
49: public function getModuleSettings()
50: {
51: return $this->oModuleSettings;
52: }
53:
54: public function init()
55: {
56: $this->subscribeEvent('PopulateScopes', array($this, 'onPopulateScopes'));
57:
58: $this->subscribeEvent('Mail::BeforeDeleteAccount', array($this, 'onBeforeDeleteAccount'));
59: $this->subscribeEvent('OAuthIntegratorAction', array($this, 'onOAuthIntegratorAction'));
60: $this->subscribeEvent('ResetAccessToken', array($this, 'onResetAccessToken'));
61: $this->subscribeEvent('GetAccessToken', array($this, 'onGetAccessToken'));
62: }
63:
64: /**
65: * Deletes cPanel account, its aliases, forward, autoresponder and filters.
66: * @param array $aArgs
67: * @param mixed $mResult
68: */
69: public function onBeforeDeleteAccount($aArgs, &$mResult)
70: {
71: $oAccount = $aArgs['Account'];
72: if ($oAccount instanceof \Aurora\Modules\Mail\Models\MailAccount) {
73: \Aurora\Modules\OAuthIntegratorWebclient\Module::Decorator()->DeleteAccount(
74: $oAccount->XOAuth,
75: $oAccount->Email
76: );
77: }
78: }
79:
80:
81: public function onPopulateScopes($sScope, &$aResult)
82: {
83: $aScopes = \explode('|', $sScope);
84: foreach ($aScopes as $sScope) {
85: if ($sScope === 'mail') {
86: $aResult[] = 'https://mail.google.com/';
87: }
88: }
89: }
90:
91: /**
92: * Passes data to connect to service.
93: *
94: * @ignore
95: * @param string $aArgs Service type to verify if data should be passed.
96: * @param boolean|array $mResult variable passed by reference to take the result.
97: */
98: public function onOAuthIntegratorAction($aArgs, &$mResult)
99: {
100: if ($aArgs['Service'] === $this->sService) {
101: $sOAuthScopes = isset($_COOKIE['oauth-scopes']) ? $_COOKIE['oauth-scopes'] : '';
102: $aGoogleScopes = [
103: 'https://www.googleapis.com/auth/userinfo.email',
104: 'https://www.googleapis.com/auth/userinfo.profile'
105: ];
106: $this->broadcastEvent('PopulateScopes', $sOAuthScopes, $aGoogleScopes);
107:
108: $mResult = false;
109: $oConnector = new Classes\Connector($this);
110: if ($oConnector) {
111: $oGoogleModule = \Aurora\Modules\Google\Module::getInstance();
112: if ($oGoogleModule) {
113: $sId = $oGoogleModule->oModuleSettings->Id;
114: $sSecret = $oGoogleModule->oModuleSettings->Secret;
115:
116: $mResult = $oConnector->Init(
117: $sId,
118: $sSecret,
119: [$sOAuthScopes, \implode(' ', $aGoogleScopes)]
120: );
121: if (isset($mResult['type'])) {
122: $mResult['type'] = $this->sService;
123:
124: $oAccount = \Aurora\Modules\OAuthIntegratorWebclient\Module::Decorator()->GetAccount($mResult['type'], $mResult['email']);
125: if ($oAccount instanceof \Aurora\Modules\OAuthIntegratorWebclient\Models\OauthAccount) {
126: $mResult = false;
127: }
128: }
129: }
130: }
131: return true;
132: }
133: }
134:
135: public function onResetAccessToken($aArgs)
136: {
137: if ($aArgs['Service'] === $this->sService) {
138: $oConnector = new Classes\Connector($this);
139: if ($oConnector) {
140: $oGoogleModule = \Aurora\Modules\Google\Module::getInstance();
141: if ($oGoogleModule && $oGoogleModule->oModuleSettings->EnableModule) {
142: $oConnector->ResetAccessToken(
143: $oGoogleModule->oModuleSettings->Id,
144: $oGoogleModule->oModuleSettings->Secret
145: );
146: }
147: }
148: }
149: }
150:
151: public function onGetAccessToken($aArgs, &$mResult)
152: {
153: if ($aArgs['Service'] === $this->sService && isset($aArgs['Account'])) {
154: $mResult = false;
155: /** @var \Aurora\Modules\OAuthIntegratorWebclient\Models\OauthAccount $oAccount */
156: $oAccount = $aArgs['Account'];
157: $oTokenData = \json_decode($oAccount->AccessToken);
158: if ($oTokenData) {
159: $iCreated = (int) $oTokenData->created;
160: $iExpiresIn = (int) $oTokenData->expires_in;
161: if (time() > ($iCreated + $iExpiresIn) && isset($oAccount->RefreshToken)) {
162: $oGoogleModule = \Aurora\Modules\Google\Module::getInstance();
163: if ($oGoogleModule) {
164: $oConnector = new Classes\Connector($this);
165: $aResult = $oConnector->RefreshAccessToken(
166: $oGoogleModule->oModuleSettings->Id,
167: $oGoogleModule->oModuleSettings->Secret,
168: $oAccount->RefreshToken
169: );
170: if (isset($aResult['access_token'])) {
171: $oTokenData->access_token = $aResult['access_token'];
172: $oTokenData->created = time();
173: $oTokenData->expires_in = $aResult['expires_in'];
174:
175: $mResult = $oTokenData->access_token;
176:
177: $oAccount->AccessToken = \json_encode($oTokenData);
178: $oAccount->save();
179: }
180: }
181: } else {
182: $mResult = $oTokenData->access_token;
183: }
184: }
185:
186: return true;
187: }
188: }
189: }
190: