-
Notifications
You must be signed in to change notification settings - Fork 988
/
SmtpOAuthController.php
171 lines (148 loc) · 5.71 KB
/
SmtpOAuthController.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
<?php
/**
* @class SmtpOAuthController
*/
class SmtpOAuthController extends LSBaseController
{
/**
* It's important to have the accessRules set (security issue).
* Only logged in users should have access to actions. All other permissions
* should be checked in the action itself.
*
* @return array
*/
public function accessRules()
{
return [
[
'allow',
'actions' => ['receiveOAuthResponse'],
'users' => ['*'], //everybody
],
[
'allow',
'actions' => ['prepareRefreshTokenRequest', 'launchRefreshTokenRequest'],
'users' => ['@'], //only login users
],
['deny'], //always deny all actions not mentioned above
];
}
/**
* Displays the view with Get Token button
* @param string $plugin
* @return void
*/
public function actionPrepareRefreshTokenRequest($plugin)
{
if (!Permission::model()->hasGlobalPermission('settings', 'update')) {
Yii::app()->user->setFlash('error', gT("Access denied"));
$this->redirect(Yii::app()->createUrl("/admin"));
}
$pluginModel = Plugin::model()->findByAttributes(['name' => $plugin]);
if (empty($pluginModel) || !$pluginModel->active) {
Yii::app()->user->setFlash('error', gT("Invalid plugin"));
$this->redirect(Yii::app()->createUrl("/admin"));
}
// Dispatch the plugin event to get details needed for the view,
// like the size of the auth window.
$event = new PluginEvent('beforePrepareRedirectToAuthPage', $this);
Yii::app()->getPluginManager()->dispatchEvent($event, $plugin);
$data['width'] = $event->get('width');
$data['height'] = $event->get('height');
$data['providerName'] = $event->get('providerName', $plugin);
$data['topbar']['title'] = gT('Get OAuth 2.0 token for SMTP authentication');
$data['providerUrl'] = $this->createUrl('smtpOAuth/launchRefreshTokenRequest', ['plugin' => $plugin]);
$pluginEventContent = $event->getContent($plugin);
$description = null;
if ($pluginEventContent->hasContent()) {
$description = CHtml::tag(
'div',
[
'id' => $pluginEventContent->getCssId(),
'class' => $pluginEventContent->getCssClass()
],
$pluginEventContent->getContent()
);
}
$data['description'] = $description;
$data['redirectUrl'] = $this->createUrl(
'/admin/pluginmanager',
[
'sa' => 'configure',
'id' => $pluginModel->id
]
);
$this->aData = $data;
$this->render('redirectToAuth', $data);
}
public function actionLaunchRefreshTokenRequest($plugin)
{
if (!Permission::model()->hasGlobalPermission('settings', 'update')) {
Yii::app()->user->setFlash('error', gT("Access denied"));
$this->redirect(Yii::app()->createUrl("/admin"));
}
// Dispatch the plugin event to get the redirect URL
$event = new PluginEvent('beforeRedirectToAuthPage', $this);
Yii::app()->getPluginManager()->dispatchEvent($event, $plugin);
$authUrl = $event->get('authUrl');
$this->setOAuthState($plugin, $event->get('state'));
header('Location: ' . $authUrl);
exit;
}
/**
* Receive the response from the OAuth provider
* @return void
*/
public function actionReceiveOAuthResponse()
{
// Make sure the request includes the required data
$code = Yii::app()->request->getParam('code');
$state = Yii::app()->request->getParam('state');
if (empty($code) || empty($state)) {
throw new CHttpException(400);
}
// Find the plugin class matching the given OAuth state
$plugin = $this->getPluginClassByOAuthState($state);
// If no plugin was found, the state is invalid
if (empty($plugin)) {
throw new CHttpException(400);
}
$event = new PluginEvent('afterReceiveOAuthResponse', $this);
$event->set('code', $code);
$event->set('state', $state);
Yii::app()->getPluginManager()->dispatchEvent($event, $plugin);
// Remove the state from the session
$this->clearOAuthState($plugin);
Yii::app()->user->setFlash('success', gT('The OAuth 2.0 token was successfully retrieved.'));
// Render the HTML that will be displayed in the popup window
// The HTML will close the window and cause the page to reload
$this->renderPartial('/smtpOAuth/responseReceived', []);
}
/**
* Find the plugin class matching the given OAuth state.
* @param string $state
* @return string|null
*/
protected function getPluginClassByOAuthState($state)
{
$pluginsWithOAuthState = Yii::app()->session['smtpOAuthStates'] ?? [];
return array_search($state, $pluginsWithOAuthState, true);
}
/**
* Set the OAuth state for the given plugin.
* @param string $plugin
* @param string $state
*/
protected function setOAuthState($plugin, $state)
{
$smtpOAuthStates = Yii::app()->session['smtpOAuthStates'] ?? [];
$smtpOAuthStates[$plugin] = $state;
Yii::app()->session['smtpOAuthStates'] = $smtpOAuthStates;
}
protected function clearOAuthState($plugin)
{
$smtpOAuthStates = Yii::app()->session['smtpOAuthStates'] ?? [];
unset($smtpOAuthStates[$plugin]);
Yii::app()->session['smtpOAuthStates'] = $smtpOAuthStates;
}
}