PluginProbe
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress / 11.1.0
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress v11.1.0
11.1.1 11.1.0 11.0.5 11.0.4 11.0.3 11.0.2 11.0.1 11.0.0 10.11.1 10.11.0 10.10.2 10.10.1 10.10.0 10.9.1 trunk 10.0.0 10.0.1 10.1.0 10.1.1 10.1.2 10.1.3 10.1.4 10.2.0 10.2.1 10.2.2 All 62 releases
← All changes | back/Controllers/ToggleController.php +53 -2 10.11.1 → 11.1.0 View file →
@@ -2,8 +2,9 @@
2 2
3 3 namespace AcyMailing\Controllers;
4 4
5 5 use AcyMailing\Classes\ListClass;
6 +use AcyMailing\Classes\MailClass;
6 7 use AcyMailing\Classes\UserClass;
7 8 use AcyMailing\Core\AcymController;
8 9
9 10 class ToggleController extends AcymController
@@ -20,13 +21,15 @@
20 21 $this->defaulttask = 'toggle';
21 22
22 23 $this->defineToggles();
23 24
25 + // Avoid caching issue in Internet Explorer
24 26 acym_noCache();
25 27 }
26 28
27 29 protected function defineToggles(): void
28 30 {
31 + // $this->toggleableColumns[TABLE NAME WITHOUT PREFIX] = array(COLUMN NAME => PRIMARY KEY);
29 32 $this->toggleableColumns['automation'] = ['active' => 'id'];
30 33 $this->toggleableColumns['field'] = [
31 34 'active' => 'id',
32 35 'required' => 'id',
@@ -45,8 +48,9 @@
45 48 $this->toggleableColumns['mail_override'] = ['active' => 'id'];
46 49 $this->toggleableColumns['mailbox_action'] = ['active' => 'id'];
47 50 $this->toggleableColumns['scenario'] = ['active' => 'id'];
48 51
52 + // $this->icons[TABLE NAME WITHOUT PREFIX][COLUMN NAME][VALUE] = ICON CLASS;
49 53 $this->icons['automation']['active'][1] = 'acymicon-check-circle acym__color__green';
50 54 $this->icons['automation']['active'][0] = 'acymicon-times-circle acym__color__red';
51 55 $this->icons['field']['active'][1] = 'acymicon-check-circle acym__color__green';
52 56 $this->icons['field']['active'][0] = 'acymicon-times-circle acym__color__red';
@@ -97,8 +101,9 @@
97 101 $this->tooltips['campaign']['visible'][1] = 'ACYM_VISIBLE';
98 102 $this->tooltips['mail_override']['active'][0] = 'ACYM_INACTIVE';
99 103 $this->tooltips['mail_override']['active'][1] = 'ACYM_ACTIVE';
100 104
105 + // $this->deletableRows[] = TABLE NAME WITHOUT PREFIX;
101 106 $this->deletableRows[] = 'mail';
102 107 $this->deletableRows[] = 'queue';
103 108 }
104 109
@@ -103,9 +108,9 @@
103 108 }
104 109
105 110 public function toggle(): void
106 111 {
107 - acym_checkToken();
112 + wp_verify_nonce(acym_getVar('cmd', '_wpnonce'), 'acymnonce') || die('Invalid Token');
108 113
109 114 $table = acym_getVar('word', 'table', '');
110 115 $field = acym_getVar('cmd', 'field', '');
111 116 $id = acym_getVar('int', 'id', 0);
@@ -117,8 +122,11 @@
117 122 if (empty($table) || empty($field) || empty($id) || empty($this->toggleableColumns[$table][$field])) {
118 123 exit;
119 124 }
120 125
126 + // Security (ACL): per-table check — the 'toggle' exception opens this controller to ~10 roles regardless of table.
127 + $this->checkToggleAcl($table);
128 +
121 129 $preciseMethod = $table.ucfirst($field);
122 130 $globalMethod = $table.'Global';
123 131 if (method_exists($this, $preciseMethod)) {
124 132 $this->$preciseMethod($id, $table, $field, $newValue);
@@ -129,8 +137,9 @@
129 137 }
130 138
131 139 acym_trigger('onAcymToggle'.ucfirst($table).ucfirst($field), [&$id, &$newValue]);
132 140
141 + // Return the replacement icon
133 142 if (empty($this->icons[$table][$field][$newValue])) {
134 143 acym_sendAjaxResponse(acym_translation('ACYM_UNAUTHORIZED_ACCESS'), [], false);
135 144 }
136 145
@@ -144,8 +153,31 @@
144 153
145 154 acym_sendAjaxResponse('', $data);
146 155 }
147 156
157 + // Each toggle icon is only rendered on the page whose ACL the user already holds, so this per-table check blocks only forged cross-feature requests (the 'toggle' exception opens the controller to ~10 roles); overridden as a no-op by FronttoggleController.
158 + protected function checkToggleAcl(string $table): void
159 + {
160 + $tableAcl = [
161 + 'user' => 'users',
162 + 'list' => 'lists',
163 + 'campaign' => 'campaigns',
164 + 'followup' => 'campaigns',
165 + 'automation' => 'automation',
166 + 'segment' => 'segments',
167 + 'scenario' => 'scenarios',
168 + 'form' => 'forms',
169 + 'field' => 'fields',
170 + 'mailbox_action' => 'bounces',
171 + 'rule' => 'bounces',
172 + 'mail_override' => 'override',
173 + ];
174 +
175 + if (empty($tableAcl[$table]) || !acym_isAllowed($tableAcl[$table])) {
176 + acym_sendAjaxResponse(acym_translation('ACYM_ACCESS_DENIED'), [], false);
177 + }
178 + }
179 +
148 180 protected function userActive(int $id, string $table, string $field, int $newValue): void
149 181 {
150 182 $userClass = new UserClass();
151 183 if ($newValue === 0) {
@@ -166,9 +198,9 @@
166 198
167 199 public function delete(): void
168 200 {
169 201 if (!acym_isAdmin()) exit;
170 - acym_checkToken();
202 + wp_verify_nonce(acym_getVar('cmd', '_wpnonce'), 'acymnonce') || die('Invalid Token');
171 203
172 204 $table = acym_getVar('word', 'table', '');
173 205 $id = acym_getVar('int', 'id', 0);
174 206
@@ -175,8 +207,19 @@
175 207 if (empty($table) || !in_array($table, $this->deletableRows) || empty($id)) {
176 208 exit;
177 209 }
178 210
211 + if ($table === 'queue') {
212 + $allowed = acym_isAllowed('queue');
213 + } else {
214 + $mailClass = new MailClass();
215 + $allowed = $mailClass->hasUserAccess($id, true);
216 + }
217 +
218 + if (!$allowed) {
219 + acym_sendAjaxResponse(acym_translation('ACYM_ACCESS_DENIED'), [], false);
220 + }
221 +
179 222 $method = $table === 'queue' ? 'deleteQueuedByUserIds' : 'delete';
180 223
181 224 $namespaceClass = 'AcyMailing\\Classes\\'.ucfirst($table).'Class';
182 225 $elementClass = new $namespaceClass();
@@ -206,8 +249,12 @@
206 249 }
207 250
208 251 public function subscribeOnClick(): void
209 252 {
253 + wp_verify_nonce(acym_getVar('cmd', '_wpnonce'), 'acymnonce') || die('Invalid Token');
254 + // Security (ACL): subscription management is restricted to the 'users' role (backend); no-op on front (ownership).
255 + $this->checkToggleAcl('user');
256 +
210 257 $userIds = acym_getVar('array', 'userid', []);
211 258 $listIds = acym_getVar('array', 'listid', []);
212 259
213 260 $userClass = new UserClass();
@@ -227,8 +274,12 @@
227 274 }
228 275
229 276 public function unsubscribeOnClick(): void
230 277 {
278 + wp_verify_nonce(acym_getVar('cmd', '_wpnonce'), 'acymnonce') || die('Invalid Token');
279 + // Security (ACL): subscription management is restricted to the 'users' role (backend); no-op on front (ownership).
280 + $this->checkToggleAcl('user');
281 +
231 282 $userIds = acym_getVar('array', 'userid', []);
232 283 $listIds = acym_getVar('array', 'listid', []);
233 284
234 285 $userClass = new UserClass();