Failed Conditions
Pull Request — oauthcreation (#531)
by Simon
06:20
created
includes/Router/RequestRouter.php 1 patch
Indentation   +434 added lines, -434 removed lines patch added patch discarded remove patch
@@ -62,438 +62,438 @@
 block discarded – undo
62 62
  */
63 63
 class RequestRouter implements IRequestRouter
64 64
 {
65
-    /**
66
-     * This is the core routing table for the application. The basic idea is:
67
-     *
68
-     *      array(
69
-     *          "foo" =>
70
-     *              array(
71
-     *                  "class"   => PageFoo::class,
72
-     *                  "actions" => array("bar", "other")
73
-     *              ),
74
-     * );
75
-     *
76
-     * Things to note:
77
-     *     - If no page is requested, we go to PageMain. PageMain can't have actions defined.
78
-     *
79
-     *     - If a page is defined and requested, but no action is requested, go to that page's main() method
80
-     *     - If a page is defined and requested, and an action is defined and requested, go to that action's method.
81
-     *     - If a page is defined and requested, and an action NOT defined and requested, go to Page404 and it's main()
82
-     *       method.
83
-     *     - If a page is NOT defined and requested, go to Page404 and it's main() method.
84
-     *
85
-     *     - Query parameters are ignored.
86
-     *
87
-     * The key point here is request routing with validation that this is allowed, before we start hitting the
88
-     * filesystem through the AutoLoader, and opening random files. Also, so that we validate the action requested
89
-     * before we start calling random methods through the web UI.
90
-     *
91
-     * Examples:
92
-     * /internal.php                => returns instance of PageMain, routed to main()
93
-     * /internal.php?query          => returns instance of PageMain, routed to main()
94
-     * /internal.php/foo            => returns instance of PageFoo, routed to main()
95
-     * /internal.php/foo?query      => returns instance of PageFoo, routed to main()
96
-     * /internal.php/foo/bar        => returns instance of PageFoo, routed to bar()
97
-     * /internal.php/foo/bar?query  => returns instance of PageFoo, routed to bar()
98
-     * /internal.php/foo/baz        => returns instance of Page404, routed to main()
99
-     * /internal.php/foo/baz?query  => returns instance of Page404, routed to main()
100
-     * /internal.php/bar            => returns instance of Page404, routed to main()
101
-     * /internal.php/bar?query      => returns instance of Page404, routed to main()
102
-     * /internal.php/bar/baz        => returns instance of Page404, routed to main()
103
-     * /internal.php/bar/baz?query  => returns instance of Page404, routed to main()
104
-     *
105
-     * Take care when changing this - a lot of places rely on the array key for redirects and other links. If you need
106
-     * to change the key, then you'll likely have to update a lot of files.
107
-     *
108
-     * @var array
109
-     */
110
-    private $routeMap = array(
111
-
112
-        //////////////////////////////////////////////////////////////////////////////////////////////////
113
-        // Login and registration
114
-        'logout'                      =>
115
-            array(
116
-                'class'   => PageLogout::class,
117
-                'actions' => array(),
118
-            ),
119
-        'login'                       =>
120
-            array(
121
-                'class'   => PagePasswordLogin::class,
122
-                'actions' => array(),
123
-            ),
124
-        'login/otp'                   =>
125
-            array(
126
-                'class'   => PageOtpLogin::class,
127
-                'actions' => array(),
128
-            ),
129
-        'login/u2f'                   =>
130
-            array(
131
-                'class'   => PageU2FLogin::class,
132
-                'actions' => array(),
133
-            ),
134
-        'forgotPassword'              =>
135
-            array(
136
-                'class'   => PageForgotPassword::class,
137
-                'actions' => array('reset'),
138
-            ),
139
-        'register'                    =>
140
-            array(
141
-                'class'   => PageRegisterOption::class,
142
-                'actions' => array(),
143
-            ),
144
-        'register/standard'           =>
145
-            array(
146
-                'class'   => PageRegisterStandard::class,
147
-                'actions' => array('done'),
148
-            ),
149
-
150
-        //////////////////////////////////////////////////////////////////////////////////////////////////
151
-        // Discovery
152
-        'search'                      =>
153
-            array(
154
-                'class'   => PageSearch::class,
155
-                'actions' => array(),
156
-            ),
157
-        'logs'                        =>
158
-            array(
159
-                'class'   => PageLog::class,
160
-                'actions' => array(),
161
-            ),
162
-
163
-        //////////////////////////////////////////////////////////////////////////////////////////////////
164
-        // Administration
165
-        'bans'                        =>
166
-            array(
167
-                'class'   => PageBan::class,
168
-                'actions' => array('set', 'remove'),
169
-            ),
170
-        'userManagement'              =>
171
-            array(
172
-                'class'   => PageUserManagement::class,
173
-                'actions' => array(
174
-                    'approve',
175
-                    'decline',
176
-                    'rename',
177
-                    'editUser',
178
-                    'suspend',
179
-                    'editRoles',
180
-                ),
181
-            ),
182
-        'siteNotice'                  =>
183
-            array(
184
-                'class'   => PageSiteNotice::class,
185
-                'actions' => array(),
186
-            ),
187
-        'emailManagement'             =>
188
-            array(
189
-                'class'   => PageEmailManagement::class,
190
-                'actions' => array('create', 'edit', 'view'),
191
-            ),
192
-        'jobQueue'                    =>
193
-            array(
194
-                'class'   => PageJobQueue::class,
195
-                'actions' => array('acknowledge', 'requeue', 'view', 'all'),
196
-            ),
197
-
198
-        //////////////////////////////////////////////////////////////////////////////////////////////////
199
-        // Personal preferences
200
-        'preferences'                 =>
201
-            array(
202
-                'class'   => PagePreferences::class,
203
-                'actions' => array(),
204
-            ),
205
-        'changePassword'              =>
206
-            array(
207
-                'class'   => PageChangePassword::class,
208
-                'actions' => array(),
209
-            ),
210
-        'multiFactor'                 =>
211
-            array(
212
-                'class'   => PageMultiFactor::class,
213
-                'actions' => array(
214
-                    'scratch',
215
-                    'enableYubikeyOtp',
216
-                    'disableYubikeyOtp',
217
-                    'enableTotp',
218
-                    'disableTotp',
219
-                    'enableU2F',
220
-                    'disableU2F',
221
-                ),
222
-            ),
223
-        'oauth'                       =>
224
-            array(
225
-                'class'   => PageOAuth::class,
226
-                'actions' => array('detach', 'attach'),
227
-            ),
228
-        'oauth/callback'              =>
229
-            array(
230
-                'class'   => PageOAuthCallback::class,
231
-                'actions' => array('authorise', 'create'),
232
-            ),
233
-
234
-        //////////////////////////////////////////////////////////////////////////////////////////////////
235
-        // Welcomer configuration
236
-        'welcomeTemplates'            =>
237
-            array(
238
-                'class'   => PageWelcomeTemplateManagement::class,
239
-                'actions' => array('select', 'edit', 'delete', 'add', 'view'),
240
-            ),
241
-
242
-        //////////////////////////////////////////////////////////////////////////////////////////////////
243
-        // Statistics
244
-        'statistics'                  =>
245
-            array(
246
-                'class'   => StatsMain::class,
247
-                'actions' => array(),
248
-            ),
249
-        'statistics/fastCloses'       =>
250
-            array(
251
-                'class'   => StatsFastCloses::class,
252
-                'actions' => array(),
253
-            ),
254
-        'statistics/inactiveUsers'    =>
255
-            array(
256
-                'class'   => StatsInactiveUsers::class,
257
-                'actions' => array(),
258
-            ),
259
-        'statistics/monthlyStats'     =>
260
-            array(
261
-                'class'   => StatsMonthlyStats::class,
262
-                'actions' => array(),
263
-            ),
264
-        'statistics/reservedRequests' =>
265
-            array(
266
-                'class'   => StatsReservedRequests::class,
267
-                'actions' => array(),
268
-            ),
269
-        'statistics/templateStats'    =>
270
-            array(
271
-                'class'   => StatsTemplateStats::class,
272
-                'actions' => array(),
273
-            ),
274
-        'statistics/topCreators'      =>
275
-            array(
276
-                'class'   => StatsTopCreators::class,
277
-                'actions' => array(),
278
-            ),
279
-        'statistics/users'            =>
280
-            array(
281
-                'class'   => StatsUsers::class,
282
-                'actions' => array('detail'),
283
-            ),
284
-
285
-        //////////////////////////////////////////////////////////////////////////////////////////////////
286
-        // Zoom page
287
-        'viewRequest'                 =>
288
-            array(
289
-                'class'   => PageViewRequest::class,
290
-                'actions' => array(),
291
-            ),
292
-        'viewRequest/reserve'         =>
293
-            array(
294
-                'class'   => PageReservation::class,
295
-                'actions' => array(),
296
-            ),
297
-        'viewRequest/breakReserve'    =>
298
-            array(
299
-                'class'   => PageBreakReservation::class,
300
-                'actions' => array(),
301
-            ),
302
-        'viewRequest/defer'           =>
303
-            array(
304
-                'class'   => PageDeferRequest::class,
305
-                'actions' => array(),
306
-            ),
307
-        'viewRequest/comment'         =>
308
-            array(
309
-                'class'   => PageComment::class,
310
-                'actions' => array(),
311
-            ),
312
-        'viewRequest/sendToUser'      =>
313
-            array(
314
-                'class'   => PageSendToUser::class,
315
-                'actions' => array(),
316
-            ),
317
-        'viewRequest/close'           =>
318
-            array(
319
-                'class'   => PageCloseRequest::class,
320
-                'actions' => array(),
321
-            ),
322
-        'viewRequest/create'          =>
323
-            array(
324
-                'class'   => PageCreateRequest::class,
325
-                'actions' => array(),
326
-            ),
327
-        'viewRequest/drop'            =>
328
-            array(
329
-                'class'   => PageDropRequest::class,
330
-                'actions' => array(),
331
-            ),
332
-        'viewRequest/custom'          =>
333
-            array(
334
-                'class'   => PageCustomClose::class,
335
-                'actions' => array(),
336
-            ),
337
-        'editComment'                 =>
338
-            array(
339
-                'class'   => PageEditComment::class,
340
-                'actions' => array(),
341
-            ),
342
-
343
-        //////////////////////////////////////////////////////////////////////////////////////////////////
344
-        // Misc stuff
345
-        'team'                        =>
346
-            array(
347
-                'class'   => PageTeam::class,
348
-                'actions' => array(),
349
-            ),
350
-        'requestList'                 =>
351
-            array(
352
-                'class'   => PageExpandedRequestList::class,
353
-                'actions' => array(),
354
-            ),
355
-    );
356
-
357
-    /**
358
-     * @return IRoutedTask
359
-     * @throws Exception
360
-     */
361
-    final public function route()
362
-    {
363
-        $pathInfo = WebRequest::pathInfo();
364
-
365
-        list($pageClass, $action) = $this->getRouteFromPath($pathInfo);
366
-
367
-        /** @var IRoutedTask $page */
368
-        $page = new $pageClass();
369
-
370
-        // Dynamic creation, so we've got to be careful here. We can't use built-in language type protection, so
371
-        // let's use our own.
372
-        if (!($page instanceof IRoutedTask)) {
373
-            throw new Exception('Expected a page, but this is not a page.');
374
-        }
375
-
376
-        // OK, I'm happy at this point that we know we're running a page, and we know it's probably what we want if it
377
-        // inherits PageBase and has been created from the routing map.
378
-        $page->setRoute($action);
379
-
380
-        return $page;
381
-    }
382
-
383
-    /**
384
-     * @param $pathInfo
385
-     *
386
-     * @return array
387
-     */
388
-    protected function getRouteFromPath($pathInfo)
389
-    {
390
-        if (count($pathInfo) === 0) {
391
-            // No pathInfo, so no page to load. Load the main page.
392
-            return $this->getDefaultRoute();
393
-        }
394
-        elseif (count($pathInfo) === 1) {
395
-            // Exactly one path info segment, it's got to be a page.
396
-            $classSegment = $pathInfo[0];
397
-
398
-            return $this->routeSinglePathSegment($classSegment);
399
-        }
400
-
401
-        // OK, we have two or more segments now.
402
-        if (count($pathInfo) > 2) {
403
-            // Let's handle more than two, and collapse it down into two.
404
-            $requestedAction = array_pop($pathInfo);
405
-            $classSegment = implode('/', $pathInfo);
406
-        }
407
-        else {
408
-            // Two path info segments.
409
-            $classSegment = $pathInfo[0];
410
-            $requestedAction = $pathInfo[1];
411
-        }
412
-
413
-        $routeMap = $this->routePathSegments($classSegment, $requestedAction);
414
-
415
-        if ($routeMap[0] === Page404::class) {
416
-            $routeMap = $this->routeSinglePathSegment($classSegment . '/' . $requestedAction);
417
-        }
418
-
419
-        return $routeMap;
420
-    }
421
-
422
-    /**
423
-     * @param $classSegment
424
-     *
425
-     * @return array
426
-     */
427
-    final protected function routeSinglePathSegment($classSegment)
428
-    {
429
-        $routeMap = $this->getRouteMap();
430
-        if (array_key_exists($classSegment, $routeMap)) {
431
-            // Route exists, but we don't have an action in path info, so default to main.
432
-            $pageClass = $routeMap[$classSegment]['class'];
433
-            $action = 'main';
434
-
435
-            return array($pageClass, $action);
436
-        }
437
-        else {
438
-            // Doesn't exist in map. Fall back to 404
439
-            $pageClass = Page404::class;
440
-            $action = "main";
441
-
442
-            return array($pageClass, $action);
443
-        }
444
-    }
445
-
446
-    /**
447
-     * @param $classSegment
448
-     * @param $requestedAction
449
-     *
450
-     * @return array
451
-     */
452
-    final protected function routePathSegments($classSegment, $requestedAction)
453
-    {
454
-        $routeMap = $this->getRouteMap();
455
-        if (array_key_exists($classSegment, $routeMap)) {
456
-            // Route exists, but we don't have an action in path info, so default to main.
457
-
458
-            if (isset($routeMap[$classSegment]['actions'])
459
-                && array_search($requestedAction, $routeMap[$classSegment]['actions']) !== false
460
-            ) {
461
-                // Action exists in allowed action list. Allow both the page and the action
462
-                $pageClass = $routeMap[$classSegment]['class'];
463
-                $action = $requestedAction;
464
-
465
-                return array($pageClass, $action);
466
-            }
467
-            else {
468
-                // Valid page, invalid action. 404 our way out.
469
-                $pageClass = Page404::class;
470
-                $action = 'main';
471
-
472
-                return array($pageClass, $action);
473
-            }
474
-        }
475
-        else {
476
-            // Class doesn't exist in map. Fall back to 404
477
-            $pageClass = Page404::class;
478
-            $action = 'main';
479
-
480
-            return array($pageClass, $action);
481
-        }
482
-    }
483
-
484
-    /**
485
-     * @return array
486
-     */
487
-    protected function getRouteMap()
488
-    {
489
-        return $this->routeMap;
490
-    }
491
-
492
-    /**
493
-     * @return callable
494
-     */
495
-    protected function getDefaultRoute()
496
-    {
497
-        return array(PageMain::class, "main");
498
-    }
65
+	/**
66
+	 * This is the core routing table for the application. The basic idea is:
67
+	 *
68
+	 *      array(
69
+	 *          "foo" =>
70
+	 *              array(
71
+	 *                  "class"   => PageFoo::class,
72
+	 *                  "actions" => array("bar", "other")
73
+	 *              ),
74
+	 * );
75
+	 *
76
+	 * Things to note:
77
+	 *     - If no page is requested, we go to PageMain. PageMain can't have actions defined.
78
+	 *
79
+	 *     - If a page is defined and requested, but no action is requested, go to that page's main() method
80
+	 *     - If a page is defined and requested, and an action is defined and requested, go to that action's method.
81
+	 *     - If a page is defined and requested, and an action NOT defined and requested, go to Page404 and it's main()
82
+	 *       method.
83
+	 *     - If a page is NOT defined and requested, go to Page404 and it's main() method.
84
+	 *
85
+	 *     - Query parameters are ignored.
86
+	 *
87
+	 * The key point here is request routing with validation that this is allowed, before we start hitting the
88
+	 * filesystem through the AutoLoader, and opening random files. Also, so that we validate the action requested
89
+	 * before we start calling random methods through the web UI.
90
+	 *
91
+	 * Examples:
92
+	 * /internal.php                => returns instance of PageMain, routed to main()
93
+	 * /internal.php?query          => returns instance of PageMain, routed to main()
94
+	 * /internal.php/foo            => returns instance of PageFoo, routed to main()
95
+	 * /internal.php/foo?query      => returns instance of PageFoo, routed to main()
96
+	 * /internal.php/foo/bar        => returns instance of PageFoo, routed to bar()
97
+	 * /internal.php/foo/bar?query  => returns instance of PageFoo, routed to bar()
98
+	 * /internal.php/foo/baz        => returns instance of Page404, routed to main()
99
+	 * /internal.php/foo/baz?query  => returns instance of Page404, routed to main()
100
+	 * /internal.php/bar            => returns instance of Page404, routed to main()
101
+	 * /internal.php/bar?query      => returns instance of Page404, routed to main()
102
+	 * /internal.php/bar/baz        => returns instance of Page404, routed to main()
103
+	 * /internal.php/bar/baz?query  => returns instance of Page404, routed to main()
104
+	 *
105
+	 * Take care when changing this - a lot of places rely on the array key for redirects and other links. If you need
106
+	 * to change the key, then you'll likely have to update a lot of files.
107
+	 *
108
+	 * @var array
109
+	 */
110
+	private $routeMap = array(
111
+
112
+		//////////////////////////////////////////////////////////////////////////////////////////////////
113
+		// Login and registration
114
+		'logout'                      =>
115
+			array(
116
+				'class'   => PageLogout::class,
117
+				'actions' => array(),
118
+			),
119
+		'login'                       =>
120
+			array(
121
+				'class'   => PagePasswordLogin::class,
122
+				'actions' => array(),
123
+			),
124
+		'login/otp'                   =>
125
+			array(
126
+				'class'   => PageOtpLogin::class,
127
+				'actions' => array(),
128
+			),
129
+		'login/u2f'                   =>
130
+			array(
131
+				'class'   => PageU2FLogin::class,
132
+				'actions' => array(),
133
+			),
134
+		'forgotPassword'              =>
135
+			array(
136
+				'class'   => PageForgotPassword::class,
137
+				'actions' => array('reset'),
138
+			),
139
+		'register'                    =>
140
+			array(
141
+				'class'   => PageRegisterOption::class,
142
+				'actions' => array(),
143
+			),
144
+		'register/standard'           =>
145
+			array(
146
+				'class'   => PageRegisterStandard::class,
147
+				'actions' => array('done'),
148
+			),
149
+
150
+		//////////////////////////////////////////////////////////////////////////////////////////////////
151
+		// Discovery
152
+		'search'                      =>
153
+			array(
154
+				'class'   => PageSearch::class,
155
+				'actions' => array(),
156
+			),
157
+		'logs'                        =>
158
+			array(
159
+				'class'   => PageLog::class,
160
+				'actions' => array(),
161
+			),
162
+
163
+		//////////////////////////////////////////////////////////////////////////////////////////////////
164
+		// Administration
165
+		'bans'                        =>
166
+			array(
167
+				'class'   => PageBan::class,
168
+				'actions' => array('set', 'remove'),
169
+			),
170
+		'userManagement'              =>
171
+			array(
172
+				'class'   => PageUserManagement::class,
173
+				'actions' => array(
174
+					'approve',
175
+					'decline',
176
+					'rename',
177
+					'editUser',
178
+					'suspend',
179
+					'editRoles',
180
+				),
181
+			),
182
+		'siteNotice'                  =>
183
+			array(
184
+				'class'   => PageSiteNotice::class,
185
+				'actions' => array(),
186
+			),
187
+		'emailManagement'             =>
188
+			array(
189
+				'class'   => PageEmailManagement::class,
190
+				'actions' => array('create', 'edit', 'view'),
191
+			),
192
+		'jobQueue'                    =>
193
+			array(
194
+				'class'   => PageJobQueue::class,
195
+				'actions' => array('acknowledge', 'requeue', 'view', 'all'),
196
+			),
197
+
198
+		//////////////////////////////////////////////////////////////////////////////////////////////////
199
+		// Personal preferences
200
+		'preferences'                 =>
201
+			array(
202
+				'class'   => PagePreferences::class,
203
+				'actions' => array(),
204
+			),
205
+		'changePassword'              =>
206
+			array(
207
+				'class'   => PageChangePassword::class,
208
+				'actions' => array(),
209
+			),
210
+		'multiFactor'                 =>
211
+			array(
212
+				'class'   => PageMultiFactor::class,
213
+				'actions' => array(
214
+					'scratch',
215
+					'enableYubikeyOtp',
216
+					'disableYubikeyOtp',
217
+					'enableTotp',
218
+					'disableTotp',
219
+					'enableU2F',
220
+					'disableU2F',
221
+				),
222
+			),
223
+		'oauth'                       =>
224
+			array(
225
+				'class'   => PageOAuth::class,
226
+				'actions' => array('detach', 'attach'),
227
+			),
228
+		'oauth/callback'              =>
229
+			array(
230
+				'class'   => PageOAuthCallback::class,
231
+				'actions' => array('authorise', 'create'),
232
+			),
233
+
234
+		//////////////////////////////////////////////////////////////////////////////////////////////////
235
+		// Welcomer configuration
236
+		'welcomeTemplates'            =>
237
+			array(
238
+				'class'   => PageWelcomeTemplateManagement::class,
239
+				'actions' => array('select', 'edit', 'delete', 'add', 'view'),
240
+			),
241
+
242
+		//////////////////////////////////////////////////////////////////////////////////////////////////
243
+		// Statistics
244
+		'statistics'                  =>
245
+			array(
246
+				'class'   => StatsMain::class,
247
+				'actions' => array(),
248
+			),
249
+		'statistics/fastCloses'       =>
250
+			array(
251
+				'class'   => StatsFastCloses::class,
252
+				'actions' => array(),
253
+			),
254
+		'statistics/inactiveUsers'    =>
255
+			array(
256
+				'class'   => StatsInactiveUsers::class,
257
+				'actions' => array(),
258
+			),
259
+		'statistics/monthlyStats'     =>
260
+			array(
261
+				'class'   => StatsMonthlyStats::class,
262
+				'actions' => array(),
263
+			),
264
+		'statistics/reservedRequests' =>
265
+			array(
266
+				'class'   => StatsReservedRequests::class,
267
+				'actions' => array(),
268
+			),
269
+		'statistics/templateStats'    =>
270
+			array(
271
+				'class'   => StatsTemplateStats::class,
272
+				'actions' => array(),
273
+			),
274
+		'statistics/topCreators'      =>
275
+			array(
276
+				'class'   => StatsTopCreators::class,
277
+				'actions' => array(),
278
+			),
279
+		'statistics/users'            =>
280
+			array(
281
+				'class'   => StatsUsers::class,
282
+				'actions' => array('detail'),
283
+			),
284
+
285
+		//////////////////////////////////////////////////////////////////////////////////////////////////
286
+		// Zoom page
287
+		'viewRequest'                 =>
288
+			array(
289
+				'class'   => PageViewRequest::class,
290
+				'actions' => array(),
291
+			),
292
+		'viewRequest/reserve'         =>
293
+			array(
294
+				'class'   => PageReservation::class,
295
+				'actions' => array(),
296
+			),
297
+		'viewRequest/breakReserve'    =>
298
+			array(
299
+				'class'   => PageBreakReservation::class,
300
+				'actions' => array(),
301
+			),
302
+		'viewRequest/defer'           =>
303
+			array(
304
+				'class'   => PageDeferRequest::class,
305
+				'actions' => array(),
306
+			),
307
+		'viewRequest/comment'         =>
308
+			array(
309
+				'class'   => PageComment::class,
310
+				'actions' => array(),
311
+			),
312
+		'viewRequest/sendToUser'      =>
313
+			array(
314
+				'class'   => PageSendToUser::class,
315
+				'actions' => array(),
316
+			),
317
+		'viewRequest/close'           =>
318
+			array(
319
+				'class'   => PageCloseRequest::class,
320
+				'actions' => array(),
321
+			),
322
+		'viewRequest/create'          =>
323
+			array(
324
+				'class'   => PageCreateRequest::class,
325
+				'actions' => array(),
326
+			),
327
+		'viewRequest/drop'            =>
328
+			array(
329
+				'class'   => PageDropRequest::class,
330
+				'actions' => array(),
331
+			),
332
+		'viewRequest/custom'          =>
333
+			array(
334
+				'class'   => PageCustomClose::class,
335
+				'actions' => array(),
336
+			),
337
+		'editComment'                 =>
338
+			array(
339
+				'class'   => PageEditComment::class,
340
+				'actions' => array(),
341
+			),
342
+
343
+		//////////////////////////////////////////////////////////////////////////////////////////////////
344
+		// Misc stuff
345
+		'team'                        =>
346
+			array(
347
+				'class'   => PageTeam::class,
348
+				'actions' => array(),
349
+			),
350
+		'requestList'                 =>
351
+			array(
352
+				'class'   => PageExpandedRequestList::class,
353
+				'actions' => array(),
354
+			),
355
+	);
356
+
357
+	/**
358
+	 * @return IRoutedTask
359
+	 * @throws Exception
360
+	 */
361
+	final public function route()
362
+	{
363
+		$pathInfo = WebRequest::pathInfo();
364
+
365
+		list($pageClass, $action) = $this->getRouteFromPath($pathInfo);
366
+
367
+		/** @var IRoutedTask $page */
368
+		$page = new $pageClass();
369
+
370
+		// Dynamic creation, so we've got to be careful here. We can't use built-in language type protection, so
371
+		// let's use our own.
372
+		if (!($page instanceof IRoutedTask)) {
373
+			throw new Exception('Expected a page, but this is not a page.');
374
+		}
375
+
376
+		// OK, I'm happy at this point that we know we're running a page, and we know it's probably what we want if it
377
+		// inherits PageBase and has been created from the routing map.
378
+		$page->setRoute($action);
379
+
380
+		return $page;
381
+	}
382
+
383
+	/**
384
+	 * @param $pathInfo
385
+	 *
386
+	 * @return array
387
+	 */
388
+	protected function getRouteFromPath($pathInfo)
389
+	{
390
+		if (count($pathInfo) === 0) {
391
+			// No pathInfo, so no page to load. Load the main page.
392
+			return $this->getDefaultRoute();
393
+		}
394
+		elseif (count($pathInfo) === 1) {
395
+			// Exactly one path info segment, it's got to be a page.
396
+			$classSegment = $pathInfo[0];
397
+
398
+			return $this->routeSinglePathSegment($classSegment);
399
+		}
400
+
401
+		// OK, we have two or more segments now.
402
+		if (count($pathInfo) > 2) {
403
+			// Let's handle more than two, and collapse it down into two.
404
+			$requestedAction = array_pop($pathInfo);
405
+			$classSegment = implode('/', $pathInfo);
406
+		}
407
+		else {
408
+			// Two path info segments.
409
+			$classSegment = $pathInfo[0];
410
+			$requestedAction = $pathInfo[1];
411
+		}
412
+
413
+		$routeMap = $this->routePathSegments($classSegment, $requestedAction);
414
+
415
+		if ($routeMap[0] === Page404::class) {
416
+			$routeMap = $this->routeSinglePathSegment($classSegment . '/' . $requestedAction);
417
+		}
418
+
419
+		return $routeMap;
420
+	}
421
+
422
+	/**
423
+	 * @param $classSegment
424
+	 *
425
+	 * @return array
426
+	 */
427
+	final protected function routeSinglePathSegment($classSegment)
428
+	{
429
+		$routeMap = $this->getRouteMap();
430
+		if (array_key_exists($classSegment, $routeMap)) {
431
+			// Route exists, but we don't have an action in path info, so default to main.
432
+			$pageClass = $routeMap[$classSegment]['class'];
433
+			$action = 'main';
434
+
435
+			return array($pageClass, $action);
436
+		}
437
+		else {
438
+			// Doesn't exist in map. Fall back to 404
439
+			$pageClass = Page404::class;
440
+			$action = "main";
441
+
442
+			return array($pageClass, $action);
443
+		}
444
+	}
445
+
446
+	/**
447
+	 * @param $classSegment
448
+	 * @param $requestedAction
449
+	 *
450
+	 * @return array
451
+	 */
452
+	final protected function routePathSegments($classSegment, $requestedAction)
453
+	{
454
+		$routeMap = $this->getRouteMap();
455
+		if (array_key_exists($classSegment, $routeMap)) {
456
+			// Route exists, but we don't have an action in path info, so default to main.
457
+
458
+			if (isset($routeMap[$classSegment]['actions'])
459
+				&& array_search($requestedAction, $routeMap[$classSegment]['actions']) !== false
460
+			) {
461
+				// Action exists in allowed action list. Allow both the page and the action
462
+				$pageClass = $routeMap[$classSegment]['class'];
463
+				$action = $requestedAction;
464
+
465
+				return array($pageClass, $action);
466
+			}
467
+			else {
468
+				// Valid page, invalid action. 404 our way out.
469
+				$pageClass = Page404::class;
470
+				$action = 'main';
471
+
472
+				return array($pageClass, $action);
473
+			}
474
+		}
475
+		else {
476
+			// Class doesn't exist in map. Fall back to 404
477
+			$pageClass = Page404::class;
478
+			$action = 'main';
479
+
480
+			return array($pageClass, $action);
481
+		}
482
+	}
483
+
484
+	/**
485
+	 * @return array
486
+	 */
487
+	protected function getRouteMap()
488
+	{
489
+		return $this->routeMap;
490
+	}
491
+
492
+	/**
493
+	 * @return callable
494
+	 */
495
+	protected function getDefaultRoute()
496
+	{
497
+		return array(PageMain::class, "main");
498
+	}
499 499
 }
Please login to merge, or discard this patch.
includes/Security/CredentialProviders/YubikeyOtpCredentialProvider.php 1 patch
Indentation   +150 added lines, -150 removed lines patch added patch discarded remove patch
@@ -16,154 +16,154 @@
 block discarded – undo
16 16
 
17 17
 class YubikeyOtpCredentialProvider extends CredentialProviderBase
18 18
 {
19
-    /** @var HttpHelper */
20
-    private $httpHelper;
21
-    /**
22
-     * @var SiteConfiguration
23
-     */
24
-    private $configuration;
25
-
26
-    public function __construct(PdoDatabase $database, SiteConfiguration $configuration, HttpHelper $httpHelper)
27
-    {
28
-        parent::__construct($database, $configuration, 'yubikeyotp');
29
-        $this->httpHelper = $httpHelper;
30
-        $this->configuration = $configuration;
31
-    }
32
-
33
-    public function authenticate(User $user, $data)
34
-    {
35
-        if (is_array($data)) {
36
-            return false;
37
-        }
38
-
39
-        $credentialData = $this->getCredentialData($user->getId());
40
-
41
-        if ($credentialData === null) {
42
-            return false;
43
-        }
44
-
45
-        if ($credentialData->getData() !== $this->getYubikeyId($data)) {
46
-            // different device
47
-            return false;
48
-        }
49
-
50
-        return $this->verifyToken($data);
51
-    }
52
-
53
-    public function setCredential(User $user, $factor, $data)
54
-    {
55
-        $keyId = $this->getYubikeyId($data);
56
-        $valid = $this->verifyToken($data);
57
-
58
-        if (!$valid) {
59
-            throw new ApplicationLogicException("Provided token is not valid.");
60
-        }
61
-
62
-        $storedData = $this->getCredentialData($user->getId());
63
-
64
-        if ($storedData === null) {
65
-            $storedData = $this->createNewCredential($user);
66
-        }
67
-
68
-        $storedData->setData($keyId);
69
-        $storedData->setFactor($factor);
70
-        $storedData->setVersion(1);
71
-        $storedData->setPriority(8);
72
-
73
-        $storedData->save();
74
-    }
75
-
76
-    /**
77
-     * Get the Yubikey ID.
78
-     *
79
-     * This looks like it's just dumping the "password" that's stored in the database, but it's actually fine.
80
-     *
81
-     * We only store the "serial number" of the Yubikey - if we get a validated (by webservice) token prefixed with the
82
-     * serial number, that's a successful OTP authentication. Thus, retrieving the stored data is just retrieving the
83
-     * yubikey's serial number (in modhex format), since the actual security credentials are stored on the device.
84
-     *
85
-     * Note that the serial number is actually the credential serial number - it's possible to regenerate the keys on
86
-     * the device, and that will change the serial number too.
87
-     *
88
-     * More information about the structure of OTPs can be found here:
89
-     * https://developers.yubico.com/OTP/OTPs_Explained.html
90
-     *
91
-     * @param int $userId
92
-     *
93
-     * @return null|string
94
-     */
95
-    public function getYubikeyData($userId)
96
-    {
97
-        $credential = $this->getCredentialData($userId);
98
-
99
-        if ($credential === null) {
100
-            return null;
101
-        }
102
-
103
-        return $credential->getData();
104
-    }
105
-
106
-    /**
107
-     * @param $result
108
-     *
109
-     * @return array
110
-     */
111
-    private function parseYubicoApiResult($result)
112
-    {
113
-        $data = array();
114
-        foreach (explode("\r\n", $result) as $line) {
115
-            $pos = strpos($line, '=');
116
-            if ($pos === false) {
117
-                continue;
118
-            }
119
-
120
-            $data[substr($line, 0, $pos)] = substr($line, $pos + 1);
121
-        }
122
-
123
-        return $data;
124
-    }
125
-
126
-    private function getYubikeyId($data)
127
-    {
128
-        return substr($data, 0, -32);
129
-    }
130
-
131
-    private function verifyHmac($apiResponse, $apiKey)
132
-    {
133
-        ksort($apiResponse);
134
-        $signature = $apiResponse['h'];
135
-        unset($apiResponse['h']);
136
-
137
-        $data = array();
138
-        foreach ($apiResponse as $key => $value) {
139
-            $data[] = $key . "=" . $value;
140
-        }
141
-        $dataString = implode('&', $data);
142
-
143
-        $hmac = base64_encode(hash_hmac('sha1', $dataString, base64_decode($apiKey), true));
144
-
145
-        return $hmac === $signature;
146
-    }
147
-
148
-    /**
149
-     * @param $data
150
-     *
151
-     * @return bool
152
-     */
153
-    private function verifyToken($data)
154
-    {
155
-        $result = $this->httpHelper->get('https://api.yubico.com/wsapi/2.0/verify', array(
156
-            'id'    => $this->configuration->getYubicoApiId(),
157
-            'otp'   => $data,
158
-            'nonce' => md5(openssl_random_pseudo_bytes(64)),
159
-        ));
160
-
161
-        $apiResponse = $this->parseYubicoApiResult($result);
162
-
163
-        if (!$this->verifyHmac($apiResponse, $this->configuration->getYubicoApiKey())) {
164
-            return false;
165
-        }
166
-
167
-        return $apiResponse['status'] == 'OK';
168
-    }
19
+	/** @var HttpHelper */
20
+	private $httpHelper;
21
+	/**
22
+	 * @var SiteConfiguration
23
+	 */
24
+	private $configuration;
25
+
26
+	public function __construct(PdoDatabase $database, SiteConfiguration $configuration, HttpHelper $httpHelper)
27
+	{
28
+		parent::__construct($database, $configuration, 'yubikeyotp');
29
+		$this->httpHelper = $httpHelper;
30
+		$this->configuration = $configuration;
31
+	}
32
+
33
+	public function authenticate(User $user, $data)
34
+	{
35
+		if (is_array($data)) {
36
+			return false;
37
+		}
38
+
39
+		$credentialData = $this->getCredentialData($user->getId());
40
+
41
+		if ($credentialData === null) {
42
+			return false;
43
+		}
44
+
45
+		if ($credentialData->getData() !== $this->getYubikeyId($data)) {
46
+			// different device
47
+			return false;
48
+		}
49
+
50
+		return $this->verifyToken($data);
51
+	}
52
+
53
+	public function setCredential(User $user, $factor, $data)
54
+	{
55
+		$keyId = $this->getYubikeyId($data);
56
+		$valid = $this->verifyToken($data);
57
+
58
+		if (!$valid) {
59
+			throw new ApplicationLogicException("Provided token is not valid.");
60
+		}
61
+
62
+		$storedData = $this->getCredentialData($user->getId());
63
+
64
+		if ($storedData === null) {
65
+			$storedData = $this->createNewCredential($user);
66
+		}
67
+
68
+		$storedData->setData($keyId);
69
+		$storedData->setFactor($factor);
70
+		$storedData->setVersion(1);
71
+		$storedData->setPriority(8);
72
+
73
+		$storedData->save();
74
+	}
75
+
76
+	/**
77
+	 * Get the Yubikey ID.
78
+	 *
79
+	 * This looks like it's just dumping the "password" that's stored in the database, but it's actually fine.
80
+	 *
81
+	 * We only store the "serial number" of the Yubikey - if we get a validated (by webservice) token prefixed with the
82
+	 * serial number, that's a successful OTP authentication. Thus, retrieving the stored data is just retrieving the
83
+	 * yubikey's serial number (in modhex format), since the actual security credentials are stored on the device.
84
+	 *
85
+	 * Note that the serial number is actually the credential serial number - it's possible to regenerate the keys on
86
+	 * the device, and that will change the serial number too.
87
+	 *
88
+	 * More information about the structure of OTPs can be found here:
89
+	 * https://developers.yubico.com/OTP/OTPs_Explained.html
90
+	 *
91
+	 * @param int $userId
92
+	 *
93
+	 * @return null|string
94
+	 */
95
+	public function getYubikeyData($userId)
96
+	{
97
+		$credential = $this->getCredentialData($userId);
98
+
99
+		if ($credential === null) {
100
+			return null;
101
+		}
102
+
103
+		return $credential->getData();
104
+	}
105
+
106
+	/**
107
+	 * @param $result
108
+	 *
109
+	 * @return array
110
+	 */
111
+	private function parseYubicoApiResult($result)
112
+	{
113
+		$data = array();
114
+		foreach (explode("\r\n", $result) as $line) {
115
+			$pos = strpos($line, '=');
116
+			if ($pos === false) {
117
+				continue;
118
+			}
119
+
120
+			$data[substr($line, 0, $pos)] = substr($line, $pos + 1);
121
+		}
122
+
123
+		return $data;
124
+	}
125
+
126
+	private function getYubikeyId($data)
127
+	{
128
+		return substr($data, 0, -32);
129
+	}
130
+
131
+	private function verifyHmac($apiResponse, $apiKey)
132
+	{
133
+		ksort($apiResponse);
134
+		$signature = $apiResponse['h'];
135
+		unset($apiResponse['h']);
136
+
137
+		$data = array();
138
+		foreach ($apiResponse as $key => $value) {
139
+			$data[] = $key . "=" . $value;
140
+		}
141
+		$dataString = implode('&', $data);
142
+
143
+		$hmac = base64_encode(hash_hmac('sha1', $dataString, base64_decode($apiKey), true));
144
+
145
+		return $hmac === $signature;
146
+	}
147
+
148
+	/**
149
+	 * @param $data
150
+	 *
151
+	 * @return bool
152
+	 */
153
+	private function verifyToken($data)
154
+	{
155
+		$result = $this->httpHelper->get('https://api.yubico.com/wsapi/2.0/verify', array(
156
+			'id'    => $this->configuration->getYubicoApiId(),
157
+			'otp'   => $data,
158
+			'nonce' => md5(openssl_random_pseudo_bytes(64)),
159
+		));
160
+
161
+		$apiResponse = $this->parseYubicoApiResult($result);
162
+
163
+		if (!$this->verifyHmac($apiResponse, $this->configuration->getYubicoApiKey())) {
164
+			return false;
165
+		}
166
+
167
+		return $apiResponse['status'] == 'OK';
168
+	}
169 169
 }
Please login to merge, or discard this patch.
includes/Security/CredentialProviders/U2FCredentialProvider.php 1 patch
Indentation   +126 added lines, -126 removed lines patch added patch discarded remove patch
@@ -19,130 +19,130 @@
 block discarded – undo
19 19
 
20 20
 class U2FCredentialProvider extends CredentialProviderBase
21 21
 {
22
-    /** @var U2F */
23
-    private $u2f;
24
-
25
-    /**
26
-     * U2FCredentialProvider constructor.
27
-     *
28
-     * @param PdoDatabase       $database
29
-     * @param SiteConfiguration $configuration
30
-     */
31
-    public function __construct(PdoDatabase $database, SiteConfiguration $configuration)
32
-    {
33
-        parent::__construct($database, $configuration, 'u2f');
34
-
35
-        $appId = 'https://' . WebRequest::httpHost();
36
-        $this->u2f = new U2F($appId);
37
-    }
38
-
39
-    /**
40
-     * Validates a user-provided credential
41
-     *
42
-     * @param User   $user The user to test the authentication against
43
-     * @param string $data The raw credential data to be validated
44
-     *
45
-     * @return bool
46
-     */
47
-    public function authenticate(User $user, $data)
48
-    {
49
-        if (!is_array($data)) {
50
-            return false;
51
-        }
52
-
53
-        list($authenticate, $request, $isU2F) = $data;
54
-
55
-        if ($isU2F !== 'u2f') {
56
-            return false;
57
-        }
58
-
59
-        $storedData = $this->getCredentialData($user->getId(), false);
60
-        $registrations = json_decode($storedData->getData());
61
-
62
-        try {
63
-            $this->u2f->doAuthenticate($request, array($registrations), $authenticate);
64
-        }
65
-        catch (Error $ex) {
66
-            return false;
67
-        }
68
-
69
-        // TODO: counter?
70
-
71
-        return true;
72
-    }
73
-
74
-    public function enable(User $user, $request, $u2fData)
75
-    {
76
-        $registrationData = $this->u2f->doRegister($request, $u2fData);
77
-
78
-        $storedData = $this->getCredentialData($user->getId(), true);
79
-
80
-        if ($storedData === null) {
81
-            throw new ApplicationLogicException('Credential data not found');
82
-        }
83
-
84
-        if ($storedData->getTimeout() > new DateTimeImmutable()) {
85
-            $storedData->setData(json_encode($registrationData));
86
-            $storedData->setDisabled(0);
87
-            $storedData->setTimeout(null);
88
-            $storedData->save();
89
-        }
90
-    }
91
-
92
-    /**
93
-     * @param User   $user   The user the credential belongs to
94
-     * @param int    $factor The factor this credential provides
95
-     * @param string $data   Unused here, due to multi-stage enrollment
96
-     */
97
-    public function setCredential(User $user, $factor, $data)
98
-    {
99
-        $storedData = $this->getCredentialData($user->getId(), null);
100
-
101
-        if ($storedData !== null) {
102
-            $storedData->delete();
103
-        }
104
-
105
-        $storedData = $this->createNewCredential($user);
106
-
107
-        $storedData->setData(null);
108
-        $storedData->setFactor($factor);
109
-        $storedData->setTimeout(new DateTimeImmutable('+ 1 hour'));
110
-        $storedData->setDisabled(1);
111
-        $storedData->setPriority(4);
112
-        $storedData->setVersion(1);
113
-
114
-        $storedData->save();
115
-    }
116
-
117
-    public function isPartiallyEnrolled(User $user)
118
-    {
119
-        $storedData = $this->getCredentialData($user->getId(), true);
120
-
121
-        if ($storedData->getTimeout() < new DateTimeImmutable()) {
122
-            $storedData->delete();
123
-
124
-            return false;
125
-        }
126
-
127
-        if ($storedData === null) {
128
-            return false;
129
-        }
130
-
131
-        return true;
132
-    }
133
-
134
-    public function getRegistrationData()
135
-    {
136
-        return $this->u2f->getRegisterData();
137
-    }
138
-
139
-    public function getAuthenticationData(User $user)
140
-    {
141
-        $storedData = $this->getCredentialData($user->getId(), false);
142
-        $registrations = json_decode($storedData->getData());
143
-
144
-        $authenticateData = $this->u2f->getAuthenticateData(array($registrations));
145
-
146
-        return $authenticateData;
147
-    }
22
+	/** @var U2F */
23
+	private $u2f;
24
+
25
+	/**
26
+	 * U2FCredentialProvider constructor.
27
+	 *
28
+	 * @param PdoDatabase       $database
29
+	 * @param SiteConfiguration $configuration
30
+	 */
31
+	public function __construct(PdoDatabase $database, SiteConfiguration $configuration)
32
+	{
33
+		parent::__construct($database, $configuration, 'u2f');
34
+
35
+		$appId = 'https://' . WebRequest::httpHost();
36
+		$this->u2f = new U2F($appId);
37
+	}
38
+
39
+	/**
40
+	 * Validates a user-provided credential
41
+	 *
42
+	 * @param User   $user The user to test the authentication against
43
+	 * @param string $data The raw credential data to be validated
44
+	 *
45
+	 * @return bool
46
+	 */
47
+	public function authenticate(User $user, $data)
48
+	{
49
+		if (!is_array($data)) {
50
+			return false;
51
+		}
52
+
53
+		list($authenticate, $request, $isU2F) = $data;
54
+
55
+		if ($isU2F !== 'u2f') {
56
+			return false;
57
+		}
58
+
59
+		$storedData = $this->getCredentialData($user->getId(), false);
60
+		$registrations = json_decode($storedData->getData());
61
+
62
+		try {
63
+			$this->u2f->doAuthenticate($request, array($registrations), $authenticate);
64
+		}
65
+		catch (Error $ex) {
66
+			return false;
67
+		}
68
+
69
+		// TODO: counter?
70
+
71
+		return true;
72
+	}
73
+
74
+	public function enable(User $user, $request, $u2fData)
75
+	{
76
+		$registrationData = $this->u2f->doRegister($request, $u2fData);
77
+
78
+		$storedData = $this->getCredentialData($user->getId(), true);
79
+
80
+		if ($storedData === null) {
81
+			throw new ApplicationLogicException('Credential data not found');
82
+		}
83
+
84
+		if ($storedData->getTimeout() > new DateTimeImmutable()) {
85
+			$storedData->setData(json_encode($registrationData));
86
+			$storedData->setDisabled(0);
87
+			$storedData->setTimeout(null);
88
+			$storedData->save();
89
+		}
90
+	}
91
+
92
+	/**
93
+	 * @param User   $user   The user the credential belongs to
94
+	 * @param int    $factor The factor this credential provides
95
+	 * @param string $data   Unused here, due to multi-stage enrollment
96
+	 */
97
+	public function setCredential(User $user, $factor, $data)
98
+	{
99
+		$storedData = $this->getCredentialData($user->getId(), null);
100
+
101
+		if ($storedData !== null) {
102
+			$storedData->delete();
103
+		}
104
+
105
+		$storedData = $this->createNewCredential($user);
106
+
107
+		$storedData->setData(null);
108
+		$storedData->setFactor($factor);
109
+		$storedData->setTimeout(new DateTimeImmutable('+ 1 hour'));
110
+		$storedData->setDisabled(1);
111
+		$storedData->setPriority(4);
112
+		$storedData->setVersion(1);
113
+
114
+		$storedData->save();
115
+	}
116
+
117
+	public function isPartiallyEnrolled(User $user)
118
+	{
119
+		$storedData = $this->getCredentialData($user->getId(), true);
120
+
121
+		if ($storedData->getTimeout() < new DateTimeImmutable()) {
122
+			$storedData->delete();
123
+
124
+			return false;
125
+		}
126
+
127
+		if ($storedData === null) {
128
+			return false;
129
+		}
130
+
131
+		return true;
132
+	}
133
+
134
+	public function getRegistrationData()
135
+	{
136
+		return $this->u2f->getRegisterData();
137
+	}
138
+
139
+	public function getAuthenticationData(User $user)
140
+	{
141
+		$storedData = $this->getCredentialData($user->getId(), false);
142
+		$registrations = json_decode($storedData->getData());
143
+
144
+		$authenticateData = $this->u2f->getAuthenticateData(array($registrations));
145
+
146
+		return $authenticateData;
147
+	}
148 148
 }
149 149
\ No newline at end of file
Please login to merge, or discard this patch.
includes/Security/CredentialProviders/CredentialProviderBase.php 1 patch
Indentation   +133 added lines, -133 removed lines patch added patch discarded remove patch
@@ -15,137 +15,137 @@
 block discarded – undo
15 15
 
16 16
 abstract class CredentialProviderBase implements ICredentialProvider
17 17
 {
18
-    /**
19
-     * @var PdoDatabase
20
-     */
21
-    private $database;
22
-    /**
23
-     * @var SiteConfiguration
24
-     */
25
-    private $configuration;
26
-    /** @var string */
27
-    private $type;
28
-
29
-    /**
30
-     * CredentialProviderBase constructor.
31
-     *
32
-     * @param PdoDatabase       $database
33
-     * @param SiteConfiguration $configuration
34
-     * @param string            $type
35
-     */
36
-    public function __construct(PdoDatabase $database, SiteConfiguration $configuration, $type)
37
-    {
38
-        $this->database = $database;
39
-        $this->configuration = $configuration;
40
-        $this->type = $type;
41
-    }
42
-
43
-    /**
44
-     * @param int  $userId
45
-     *
46
-     * @param bool $disabled
47
-     *
48
-     * @return Credential
49
-     */
50
-    protected function getCredentialData($userId, $disabled = false)
51
-    {
52
-        $sql = 'SELECT * FROM credential WHERE type = :t AND user = :u';
53
-        $parameters = array(
54
-            ':u' => $userId,
55
-            ':t' => $this->type
56
-        );
57
-
58
-        if($disabled !== null) {
59
-            $sql .= ' AND disabled = :d';
60
-            $parameters[':d'] = $disabled ? 1 : 0;
61
-        }
62
-
63
-        $statement = $this->database->prepare($sql);
64
-        $statement->execute($parameters);
65
-
66
-        /** @var Credential $obj */
67
-        $obj = $statement->fetchObject(Credential::class);
68
-
69
-        if ($obj === false) {
70
-            return null;
71
-        }
72
-
73
-        $obj->setDatabase($this->database);
74
-
75
-        $statement->closeCursor();
76
-
77
-        return $obj;
78
-    }
79
-
80
-    /**
81
-     * @return PdoDatabase
82
-     */
83
-    public function getDatabase()
84
-    {
85
-        return $this->database;
86
-    }
87
-
88
-    /**
89
-     * @return SiteConfiguration
90
-     */
91
-    public function getConfiguration()
92
-    {
93
-        return $this->configuration;
94
-    }
95
-
96
-    public function deleteCredential(User $user) {
97
-        // get this factor
98
-        $statement = $this->database->prepare('SELECT * FROM credential WHERE user = :user AND type = :type');
99
-        $statement->execute(array(':user' => $user->getId(), ':type' => $this->type));
100
-        /** @var Credential $credential */
101
-        $credential = $statement->fetchObject(Credential::class);
102
-        $credential->setDatabase($this->database);
103
-        $statement->closeCursor();
104
-
105
-        $stage = $credential->getFactor();
106
-
107
-        $statement = $this->database->prepare('SELECT COUNT(*) FROM credential WHERE user = :user AND factor = :factor');
108
-        $statement->execute(array(':user' => $user->getId(), ':factor' => $stage));
109
-        $alternates = $statement->fetchColumn();
110
-        $statement->closeCursor();
111
-
112
-        if($alternates <= 1) {
113
-            // decrement the factor for every stage above this
114
-            $sql = 'UPDATE credential SET factor = factor - 1 WHERE user = :user AND factor > :factor';
115
-            $statement = $this->database->prepare($sql);
116
-            $statement->execute(array(':user' => $user->getId(), ':factor' => $stage));
117
-        }
118
-        else {
119
-            // There are other auth factors at this point. Don't renumber the factors just yet.
120
-        }
121
-
122
-        // delete this credential.
123
-        $credential->delete();
124
-    }
125
-
126
-    /**
127
-     * @param User $user
128
-     *
129
-     * @return Credential
130
-     */
131
-    protected function createNewCredential(User $user)
132
-    {
133
-        $credential = new Credential();
134
-        $credential->setDatabase($this->getDatabase());
135
-        $credential->setUserId($user->getId());
136
-        $credential->setType($this->type);
137
-
138
-        return $credential;
139
-    }
140
-
141
-    /**
142
-     * @param int $userId
143
-     *
144
-     * @return bool
145
-     */
146
-    public function userIsEnrolled($userId) {
147
-        $cred = $this->getCredentialData($userId);
148
-
149
-        return $cred !== null;
150
-    }
18
+	/**
19
+	 * @var PdoDatabase
20
+	 */
21
+	private $database;
22
+	/**
23
+	 * @var SiteConfiguration
24
+	 */
25
+	private $configuration;
26
+	/** @var string */
27
+	private $type;
28
+
29
+	/**
30
+	 * CredentialProviderBase constructor.
31
+	 *
32
+	 * @param PdoDatabase       $database
33
+	 * @param SiteConfiguration $configuration
34
+	 * @param string            $type
35
+	 */
36
+	public function __construct(PdoDatabase $database, SiteConfiguration $configuration, $type)
37
+	{
38
+		$this->database = $database;
39
+		$this->configuration = $configuration;
40
+		$this->type = $type;
41
+	}
42
+
43
+	/**
44
+	 * @param int  $userId
45
+	 *
46
+	 * @param bool $disabled
47
+	 *
48
+	 * @return Credential
49
+	 */
50
+	protected function getCredentialData($userId, $disabled = false)
51
+	{
52
+		$sql = 'SELECT * FROM credential WHERE type = :t AND user = :u';
53
+		$parameters = array(
54
+			':u' => $userId,
55
+			':t' => $this->type
56
+		);
57
+
58
+		if($disabled !== null) {
59
+			$sql .= ' AND disabled = :d';
60
+			$parameters[':d'] = $disabled ? 1 : 0;
61
+		}
62
+
63
+		$statement = $this->database->prepare($sql);
64
+		$statement->execute($parameters);
65
+
66
+		/** @var Credential $obj */
67
+		$obj = $statement->fetchObject(Credential::class);
68
+
69
+		if ($obj === false) {
70
+			return null;
71
+		}
72
+
73
+		$obj->setDatabase($this->database);
74
+
75
+		$statement->closeCursor();
76
+
77
+		return $obj;
78
+	}
79
+
80
+	/**
81
+	 * @return PdoDatabase
82
+	 */
83
+	public function getDatabase()
84
+	{
85
+		return $this->database;
86
+	}
87
+
88
+	/**
89
+	 * @return SiteConfiguration
90
+	 */
91
+	public function getConfiguration()
92
+	{
93
+		return $this->configuration;
94
+	}
95
+
96
+	public function deleteCredential(User $user) {
97
+		// get this factor
98
+		$statement = $this->database->prepare('SELECT * FROM credential WHERE user = :user AND type = :type');
99
+		$statement->execute(array(':user' => $user->getId(), ':type' => $this->type));
100
+		/** @var Credential $credential */
101
+		$credential = $statement->fetchObject(Credential::class);
102
+		$credential->setDatabase($this->database);
103
+		$statement->closeCursor();
104
+
105
+		$stage = $credential->getFactor();
106
+
107
+		$statement = $this->database->prepare('SELECT COUNT(*) FROM credential WHERE user = :user AND factor = :factor');
108
+		$statement->execute(array(':user' => $user->getId(), ':factor' => $stage));
109
+		$alternates = $statement->fetchColumn();
110
+		$statement->closeCursor();
111
+
112
+		if($alternates <= 1) {
113
+			// decrement the factor for every stage above this
114
+			$sql = 'UPDATE credential SET factor = factor - 1 WHERE user = :user AND factor > :factor';
115
+			$statement = $this->database->prepare($sql);
116
+			$statement->execute(array(':user' => $user->getId(), ':factor' => $stage));
117
+		}
118
+		else {
119
+			// There are other auth factors at this point. Don't renumber the factors just yet.
120
+		}
121
+
122
+		// delete this credential.
123
+		$credential->delete();
124
+	}
125
+
126
+	/**
127
+	 * @param User $user
128
+	 *
129
+	 * @return Credential
130
+	 */
131
+	protected function createNewCredential(User $user)
132
+	{
133
+		$credential = new Credential();
134
+		$credential->setDatabase($this->getDatabase());
135
+		$credential->setUserId($user->getId());
136
+		$credential->setType($this->type);
137
+
138
+		return $credential;
139
+	}
140
+
141
+	/**
142
+	 * @param int $userId
143
+	 *
144
+	 * @return bool
145
+	 */
146
+	public function userIsEnrolled($userId) {
147
+		$cred = $this->getCredentialData($userId);
148
+
149
+		return $cred !== null;
150
+	}
151 151
 }
152 152
\ No newline at end of file
Please login to merge, or discard this patch.
includes/Security/CredentialProviders/TotpCredentialProvider.php 1 patch
Indentation   +129 added lines, -129 removed lines patch added patch discarded remove patch
@@ -19,136 +19,136 @@
 block discarded – undo
19 19
 
20 20
 class TotpCredentialProvider extends CredentialProviderBase
21 21
 {
22
-    /** @var EncryptionHelper */
23
-    private $encryptionHelper;
24
-
25
-    /**
26
-     * TotpCredentialProvider constructor.
27
-     *
28
-     * @param PdoDatabase       $database
29
-     * @param SiteConfiguration $configuration
30
-     */
31
-    public function __construct(PdoDatabase $database, SiteConfiguration $configuration)
32
-    {
33
-        parent::__construct($database, $configuration, 'totp');
34
-        $this->encryptionHelper = new EncryptionHelper($configuration);
35
-    }
36
-
37
-    /**
38
-     * Validates a user-provided credential
39
-     *
40
-     * @param User   $user The user to test the authentication against
41
-     * @param string $data The raw credential data to be validated
42
-     *
43
-     * @return bool
44
-     * @throws ApplicationLogicException
45
-     */
46
-    public function authenticate(User $user, $data)
47
-    {
48
-        if (is_array($data)) {
49
-            return false;
50
-        }
51
-
52
-        $storedData = $this->getCredentialData($user->getId());
53
-
54
-        if ($storedData === null) {
55
-            throw new ApplicationLogicException('Credential data not found');
56
-        }
57
-
58
-        $provisioningUrl = $this->encryptionHelper->decryptData($storedData->getData());
59
-        $totp = Factory::loadFromProvisioningUri($provisioningUrl);
60
-
61
-        return $totp->verify($data, null, 2);
62
-    }
63
-
64
-    public function verifyEnable(User $user, $data)
65
-    {
66
-        $storedData = $this->getCredentialData($user->getId(), true);
67
-
68
-        if ($storedData === null) {
69
-            throw new ApplicationLogicException('Credential data not found');
70
-        }
71
-
72
-        $provisioningUrl = $this->encryptionHelper->decryptData($storedData->getData());
73
-        $totp = Factory::loadFromProvisioningUri($provisioningUrl);
74
-
75
-        $result = $totp->verify($data, null, 2);
76
-
77
-        if ($result && $storedData->getTimeout() > new DateTimeImmutable()) {
78
-            $storedData->setDisabled(0);
79
-            $storedData->setPriority(5);
80
-            $storedData->setTimeout(null);
81
-            $storedData->save();
82
-        }
83
-
84
-        return $result;
85
-    }
86
-
87
-    /**
88
-     * @param User   $user   The user the credential belongs to
89
-     * @param int    $factor The factor this credential provides
90
-     * @param string $data   Unused here, due to there being no user-provided data. We provide the user with the secret.
91
-     */
92
-    public function setCredential(User $user, $factor, $data)
93
-    {
94
-        $issuer = 'ACC - ' . $this->getConfiguration()->getIrcNotificationsInstance();
95
-        $totp = new TOTP($user->getUsername());
96
-        $totp->setIssuer($issuer);
97
-
98
-        $storedData = $this->getCredentialData($user->getId(), null);
99
-
100
-        if ($storedData !== null) {
101
-            $storedData->delete();
102
-        }
103
-
104
-        $storedData = $this->createNewCredential($user);
105
-
106
-        $storedData->setData($this->encryptionHelper->encryptData($totp->getProvisioningUri()));
107
-        $storedData->setFactor($factor);
108
-        $storedData->setTimeout(new DateTimeImmutable('+ 1 hour'));
109
-        $storedData->setDisabled(1);
110
-        $storedData->setVersion(1);
111
-
112
-        $storedData->save();
113
-    }
114
-
115
-    public function getProvisioningUrl(User $user)
116
-    {
117
-        $storedData = $this->getCredentialData($user->getId(), true);
118
-
119
-        if ($storedData->getTimeout() < new DateTimeImmutable()) {
120
-            $storedData->delete();
121
-            $storedData = null;
122
-        }
123
-
124
-        if ($storedData === null) {
125
-            throw new ApplicationLogicException('Credential data not found');
126
-        }
127
-
128
-        return $this->encryptionHelper->decryptData($storedData->getData());
129
-    }
130
-
131
-    public function isPartiallyEnrolled(User $user)
132
-    {
133
-        $storedData = $this->getCredentialData($user->getId(), true);
134
-
135
-        if ($storedData->getTimeout() < new DateTimeImmutable()) {
136
-            $storedData->delete();
137
-
138
-            return false;
139
-        }
140
-
141
-        if ($storedData === null) {
142
-            return false;
143
-        }
22
+	/** @var EncryptionHelper */
23
+	private $encryptionHelper;
24
+
25
+	/**
26
+	 * TotpCredentialProvider constructor.
27
+	 *
28
+	 * @param PdoDatabase       $database
29
+	 * @param SiteConfiguration $configuration
30
+	 */
31
+	public function __construct(PdoDatabase $database, SiteConfiguration $configuration)
32
+	{
33
+		parent::__construct($database, $configuration, 'totp');
34
+		$this->encryptionHelper = new EncryptionHelper($configuration);
35
+	}
36
+
37
+	/**
38
+	 * Validates a user-provided credential
39
+	 *
40
+	 * @param User   $user The user to test the authentication against
41
+	 * @param string $data The raw credential data to be validated
42
+	 *
43
+	 * @return bool
44
+	 * @throws ApplicationLogicException
45
+	 */
46
+	public function authenticate(User $user, $data)
47
+	{
48
+		if (is_array($data)) {
49
+			return false;
50
+		}
51
+
52
+		$storedData = $this->getCredentialData($user->getId());
53
+
54
+		if ($storedData === null) {
55
+			throw new ApplicationLogicException('Credential data not found');
56
+		}
57
+
58
+		$provisioningUrl = $this->encryptionHelper->decryptData($storedData->getData());
59
+		$totp = Factory::loadFromProvisioningUri($provisioningUrl);
60
+
61
+		return $totp->verify($data, null, 2);
62
+	}
63
+
64
+	public function verifyEnable(User $user, $data)
65
+	{
66
+		$storedData = $this->getCredentialData($user->getId(), true);
67
+
68
+		if ($storedData === null) {
69
+			throw new ApplicationLogicException('Credential data not found');
70
+		}
71
+
72
+		$provisioningUrl = $this->encryptionHelper->decryptData($storedData->getData());
73
+		$totp = Factory::loadFromProvisioningUri($provisioningUrl);
74
+
75
+		$result = $totp->verify($data, null, 2);
76
+
77
+		if ($result && $storedData->getTimeout() > new DateTimeImmutable()) {
78
+			$storedData->setDisabled(0);
79
+			$storedData->setPriority(5);
80
+			$storedData->setTimeout(null);
81
+			$storedData->save();
82
+		}
83
+
84
+		return $result;
85
+	}
86
+
87
+	/**
88
+	 * @param User   $user   The user the credential belongs to
89
+	 * @param int    $factor The factor this credential provides
90
+	 * @param string $data   Unused here, due to there being no user-provided data. We provide the user with the secret.
91
+	 */
92
+	public function setCredential(User $user, $factor, $data)
93
+	{
94
+		$issuer = 'ACC - ' . $this->getConfiguration()->getIrcNotificationsInstance();
95
+		$totp = new TOTP($user->getUsername());
96
+		$totp->setIssuer($issuer);
97
+
98
+		$storedData = $this->getCredentialData($user->getId(), null);
99
+
100
+		if ($storedData !== null) {
101
+			$storedData->delete();
102
+		}
103
+
104
+		$storedData = $this->createNewCredential($user);
105
+
106
+		$storedData->setData($this->encryptionHelper->encryptData($totp->getProvisioningUri()));
107
+		$storedData->setFactor($factor);
108
+		$storedData->setTimeout(new DateTimeImmutable('+ 1 hour'));
109
+		$storedData->setDisabled(1);
110
+		$storedData->setVersion(1);
111
+
112
+		$storedData->save();
113
+	}
114
+
115
+	public function getProvisioningUrl(User $user)
116
+	{
117
+		$storedData = $this->getCredentialData($user->getId(), true);
118
+
119
+		if ($storedData->getTimeout() < new DateTimeImmutable()) {
120
+			$storedData->delete();
121
+			$storedData = null;
122
+		}
123
+
124
+		if ($storedData === null) {
125
+			throw new ApplicationLogicException('Credential data not found');
126
+		}
127
+
128
+		return $this->encryptionHelper->decryptData($storedData->getData());
129
+	}
130
+
131
+	public function isPartiallyEnrolled(User $user)
132
+	{
133
+		$storedData = $this->getCredentialData($user->getId(), true);
134
+
135
+		if ($storedData->getTimeout() < new DateTimeImmutable()) {
136
+			$storedData->delete();
137
+
138
+			return false;
139
+		}
140
+
141
+		if ($storedData === null) {
142
+			return false;
143
+		}
144 144
 
145
-        return true;
146
-    }
145
+		return true;
146
+	}
147 147
 
148
-    public function getSecret(User $user)
149
-    {
150
-        $totp = Factory::loadFromProvisioningUri($this->getProvisioningUrl($user));
148
+	public function getSecret(User $user)
149
+	{
150
+		$totp = Factory::loadFromProvisioningUri($this->getProvisioningUrl($user));
151 151
 
152
-        return $totp->getSecret();
153
-    }
152
+		return $totp->getSecret();
153
+	}
154 154
 }
155 155
\ No newline at end of file
Please login to merge, or discard this patch.
includes/Security/CredentialProviders/ScratchTokenCredentialProvider.php 1 patch
Indentation   +117 added lines, -117 removed lines patch added patch discarded remove patch
@@ -17,121 +17,121 @@
 block discarded – undo
17 17
 
18 18
 class ScratchTokenCredentialProvider extends CredentialProviderBase
19 19
 {
20
-    /** @var EncryptionHelper */
21
-    private $encryptionHelper;
22
-
23
-    /**
24
-     * ScratchTokenCredentialProvider constructor.
25
-     *
26
-     * @param PdoDatabase       $database
27
-     * @param SiteConfiguration $configuration
28
-     */
29
-    public function __construct(PdoDatabase $database, SiteConfiguration $configuration)
30
-    {
31
-        parent::__construct($database, $configuration, 'scratch');
32
-        $this->encryptionHelper = new EncryptionHelper($configuration);
33
-    }
34
-
35
-    /**
36
-     * Validates a user-provided credential
37
-     *
38
-     * @param User   $user The user to test the authentication against
39
-     * @param string $data The raw credential data to be validated
40
-     *
41
-     * @return bool
42
-     * @throws ApplicationLogicException
43
-     */
44
-    public function authenticate(User $user, $data)
45
-    {
46
-        if (is_array($data)) {
47
-            return false;
48
-        }
49
-
50
-        $storedData = $this->getCredentialData($user->getId());
51
-
52
-        if ($storedData === null) {
53
-            throw new ApplicationLogicException('Credential data not found');
54
-        }
55
-
56
-        $scratchTokens = unserialize($this->encryptionHelper->decryptData($storedData->getData()));
57
-
58
-        $i = array_search($data, $scratchTokens);
59
-
60
-        if($i === false) {
61
-            return false;
62
-        }
63
-
64
-        unset($scratchTokens[$i]);
65
-
66
-        $storedData->setData($this->encryptionHelper->encryptData(serialize($scratchTokens)));
67
-        $storedData->save();
68
-
69
-        return true;
70
-    }
71
-
72
-    /**
73
-     * @param User   $user   The user the credential belongs to
74
-     * @param int    $factor The factor this credential provides
75
-     * @param string $data   Unused.
76
-     */
77
-    public function setCredential(User $user, $factor, $data)
78
-    {
79
-        $scratch = array();
80
-        for ($i = 0; $i < 5; $i++) {
81
-            $scratch[] = Base32::encode(openssl_random_pseudo_bytes(10));
82
-        }
83
-
84
-        $storedData = $this->getCredentialData($user->getId(), null);
85
-
86
-        if ($storedData !== null) {
87
-            $storedData->delete();
88
-        }
89
-
90
-        $storedData = $this->createNewCredential($user);
91
-
92
-        $storedData->setData($this->encryptionHelper->encryptData(serialize($scratch)));
93
-        $storedData->setFactor($factor);
94
-        $storedData->setVersion(1);
95
-        $storedData->setPriority(9);
96
-
97
-        $storedData->save();
98
-    }
99
-
100
-    /**
101
-     * @param int $userId
102
-     *
103
-     * @return int
104
-     * @throws ApplicationLogicException
105
-     */
106
-    public function getRemaining($userId)
107
-    {
108
-        $storedData = $this->getCredentialData($userId);
109
-
110
-        if ($storedData === null) {
111
-            return 0;
112
-        }
113
-
114
-        $scratchTokens = unserialize($this->encryptionHelper->decryptData($storedData->getData()));
115
-
116
-        return count($scratchTokens);
117
-    }
118
-
119
-    /**
120
-     * @param int $userId
121
-     *
122
-     * @return int
123
-     * @throws ApplicationLogicException
124
-     */
125
-    public function getTokens($userId)
126
-    {
127
-        $storedData = $this->getCredentialData($userId);
128
-
129
-        if ($storedData === null) {
130
-            return 0;
131
-        }
132
-
133
-        $scratchTokens = unserialize($this->encryptionHelper->decryptData($storedData->getData()));
134
-
135
-        return $scratchTokens;
136
-    }
20
+	/** @var EncryptionHelper */
21
+	private $encryptionHelper;
22
+
23
+	/**
24
+	 * ScratchTokenCredentialProvider constructor.
25
+	 *
26
+	 * @param PdoDatabase       $database
27
+	 * @param SiteConfiguration $configuration
28
+	 */
29
+	public function __construct(PdoDatabase $database, SiteConfiguration $configuration)
30
+	{
31
+		parent::__construct($database, $configuration, 'scratch');
32
+		$this->encryptionHelper = new EncryptionHelper($configuration);
33
+	}
34
+
35
+	/**
36
+	 * Validates a user-provided credential
37
+	 *
38
+	 * @param User   $user The user to test the authentication against
39
+	 * @param string $data The raw credential data to be validated
40
+	 *
41
+	 * @return bool
42
+	 * @throws ApplicationLogicException
43
+	 */
44
+	public function authenticate(User $user, $data)
45
+	{
46
+		if (is_array($data)) {
47
+			return false;
48
+		}
49
+
50
+		$storedData = $this->getCredentialData($user->getId());
51
+
52
+		if ($storedData === null) {
53
+			throw new ApplicationLogicException('Credential data not found');
54
+		}
55
+
56
+		$scratchTokens = unserialize($this->encryptionHelper->decryptData($storedData->getData()));
57
+
58
+		$i = array_search($data, $scratchTokens);
59
+
60
+		if($i === false) {
61
+			return false;
62
+		}
63
+
64
+		unset($scratchTokens[$i]);
65
+
66
+		$storedData->setData($this->encryptionHelper->encryptData(serialize($scratchTokens)));
67
+		$storedData->save();
68
+
69
+		return true;
70
+	}
71
+
72
+	/**
73
+	 * @param User   $user   The user the credential belongs to
74
+	 * @param int    $factor The factor this credential provides
75
+	 * @param string $data   Unused.
76
+	 */
77
+	public function setCredential(User $user, $factor, $data)
78
+	{
79
+		$scratch = array();
80
+		for ($i = 0; $i < 5; $i++) {
81
+			$scratch[] = Base32::encode(openssl_random_pseudo_bytes(10));
82
+		}
83
+
84
+		$storedData = $this->getCredentialData($user->getId(), null);
85
+
86
+		if ($storedData !== null) {
87
+			$storedData->delete();
88
+		}
89
+
90
+		$storedData = $this->createNewCredential($user);
91
+
92
+		$storedData->setData($this->encryptionHelper->encryptData(serialize($scratch)));
93
+		$storedData->setFactor($factor);
94
+		$storedData->setVersion(1);
95
+		$storedData->setPriority(9);
96
+
97
+		$storedData->save();
98
+	}
99
+
100
+	/**
101
+	 * @param int $userId
102
+	 *
103
+	 * @return int
104
+	 * @throws ApplicationLogicException
105
+	 */
106
+	public function getRemaining($userId)
107
+	{
108
+		$storedData = $this->getCredentialData($userId);
109
+
110
+		if ($storedData === null) {
111
+			return 0;
112
+		}
113
+
114
+		$scratchTokens = unserialize($this->encryptionHelper->decryptData($storedData->getData()));
115
+
116
+		return count($scratchTokens);
117
+	}
118
+
119
+	/**
120
+	 * @param int $userId
121
+	 *
122
+	 * @return int
123
+	 * @throws ApplicationLogicException
124
+	 */
125
+	public function getTokens($userId)
126
+	{
127
+		$storedData = $this->getCredentialData($userId);
128
+
129
+		if ($storedData === null) {
130
+			return 0;
131
+		}
132
+
133
+		$scratchTokens = unserialize($this->encryptionHelper->decryptData($storedData->getData()));
134
+
135
+		return $scratchTokens;
136
+	}
137 137
 }
138 138
\ No newline at end of file
Please login to merge, or discard this patch.
includes/Security/CredentialProviders/PasswordCredentialProvider.php 1 patch
Indentation   +40 added lines, -40 removed lines patch added patch discarded remove patch
@@ -15,55 +15,55 @@
 block discarded – undo
15 15
 
16 16
 class PasswordCredentialProvider extends CredentialProviderBase
17 17
 {
18
-    const PASSWORD_COST = 10;
18
+	const PASSWORD_COST = 10;
19 19
 
20
-    public function __construct(PdoDatabase $database, SiteConfiguration $configuration)
21
-    {
22
-        parent::__construct($database, $configuration, 'password');
23
-    }
20
+	public function __construct(PdoDatabase $database, SiteConfiguration $configuration)
21
+	{
22
+		parent::__construct($database, $configuration, 'password');
23
+	}
24 24
 
25
-    public function authenticate(User $user, $data)
26
-    {
27
-        $storedData = $this->getCredentialData($user->getId());
28
-        if($storedData === null)
29
-        {
30
-            // No available credential matching these parameters
31
-            return false;
32
-        }
25
+	public function authenticate(User $user, $data)
26
+	{
27
+		$storedData = $this->getCredentialData($user->getId());
28
+		if($storedData === null)
29
+		{
30
+			// No available credential matching these parameters
31
+			return false;
32
+		}
33 33
 
34
-        if($storedData->getVersion() !== 2) {
35
-            // Non-2 versions are not supported.
36
-            return false;
37
-        }
34
+		if($storedData->getVersion() !== 2) {
35
+			// Non-2 versions are not supported.
36
+			return false;
37
+		}
38 38
 
39
-        if(password_verify($data, $storedData->getData())) {
40
-            if(password_needs_rehash($storedData->getData(), PASSWORD_BCRYPT, array('cost' => self::PASSWORD_COST))){
41
-                $this->setCredential($user, $storedData->getFactor(), $data);
42
-            }
39
+		if(password_verify($data, $storedData->getData())) {
40
+			if(password_needs_rehash($storedData->getData(), PASSWORD_BCRYPT, array('cost' => self::PASSWORD_COST))){
41
+				$this->setCredential($user, $storedData->getFactor(), $data);
42
+			}
43 43
 
44
-            return true;
45
-        }
44
+			return true;
45
+		}
46 46
 
47
-        return false;
48
-    }
47
+		return false;
48
+	}
49 49
 
50
-    public function setCredential(User $user, $factor, $password)
51
-    {
52
-        $storedData = $this->getCredentialData($user->getId());
50
+	public function setCredential(User $user, $factor, $password)
51
+	{
52
+		$storedData = $this->getCredentialData($user->getId());
53 53
 
54
-        if($storedData === null){
55
-            $storedData = $this->createNewCredential($user);
56
-        }
54
+		if($storedData === null){
55
+			$storedData = $this->createNewCredential($user);
56
+		}
57 57
 
58
-        $storedData->setData(password_hash($password, PASSWORD_BCRYPT, array('cost' => self::PASSWORD_COST)));
59
-        $storedData->setFactor($factor);
60
-        $storedData->setVersion(2);
58
+		$storedData->setData(password_hash($password, PASSWORD_BCRYPT, array('cost' => self::PASSWORD_COST)));
59
+		$storedData->setFactor($factor);
60
+		$storedData->setVersion(2);
61 61
 
62
-        $storedData->save();
63
-    }
62
+		$storedData->save();
63
+	}
64 64
 
65
-    public function deleteCredential(User $user)
66
-    {
67
-        throw new ApplicationLogicException('Deletion of password credential is not allowed.');
68
-    }
65
+	public function deleteCredential(User $user)
66
+	{
67
+		throw new ApplicationLogicException('Deletion of password credential is not allowed.');
68
+	}
69 69
 }
70 70
\ No newline at end of file
Please login to merge, or discard this patch.
includes/Security/CredentialProviders/ICredentialProvider.php 1 patch
Indentation   +25 added lines, -25 removed lines patch added patch discarded remove patch
@@ -12,32 +12,32 @@
 block discarded – undo
12 12
 
13 13
 interface ICredentialProvider
14 14
 {
15
-    /**
16
-     * Validates a user-provided credential
17
-     *
18
-     * @param User $user The user to test the authentication against
19
-     * @param string $data The raw credential data to be validated
20
-     *
21
-     * @return bool
22
-     */
23
-    public function authenticate(User $user, $data);
15
+	/**
16
+	 * Validates a user-provided credential
17
+	 *
18
+	 * @param User $user The user to test the authentication against
19
+	 * @param string $data The raw credential data to be validated
20
+	 *
21
+	 * @return bool
22
+	 */
23
+	public function authenticate(User $user, $data);
24 24
 
25
-    /**
26
-     * @param User $user The user the credential belongs to
27
-     * @param int $factor The factor this credential provides
28
-     * @param string $data
29
-     */
30
-    public function setCredential(User $user, $factor, $data);
25
+	/**
26
+	 * @param User $user The user the credential belongs to
27
+	 * @param int $factor The factor this credential provides
28
+	 * @param string $data
29
+	 */
30
+	public function setCredential(User $user, $factor, $data);
31 31
 
32
-    /**
33
-     * @param User $user
34
-     */
35
-    public function deleteCredential(User $user);
32
+	/**
33
+	 * @param User $user
34
+	 */
35
+	public function deleteCredential(User $user);
36 36
 
37
-    /**
38
-     * @param int $userId
39
-     *
40
-     * @return bool
41
-     */
42
-    public function userIsEnrolled($userId);
37
+	/**
38
+	 * @param int $userId
39
+	 *
40
+	 * @return bool
41
+	 */
42
+	public function userIsEnrolled($userId);
43 43
 }
44 44
\ No newline at end of file
Please login to merge, or discard this patch.
includes/Security/EncryptionHelper.php 1 patch
Indentation   +44 added lines, -44 removed lines patch added patch discarded remove patch
@@ -12,48 +12,48 @@
 block discarded – undo
12 12
 
13 13
 class EncryptionHelper
14 14
 {
15
-    /**
16
-     * @var SiteConfiguration
17
-     */
18
-    private $configuration;
19
-
20
-    /**
21
-     * EncryptionHelper constructor.
22
-     *
23
-     * @param SiteConfiguration $configuration
24
-     */
25
-    public function __construct(SiteConfiguration $configuration)
26
-    {
27
-        $this->configuration = $configuration;
28
-    }
29
-
30
-    public function encryptData($secret)
31
-    {
32
-        $iv = openssl_random_pseudo_bytes(16);
33
-        $password = $this->getEncryptionKey();
34
-        $encryptedKey = openssl_encrypt($secret, 'aes-256-ctr', $password, OPENSSL_RAW_DATA, $iv);
35
-
36
-        $data = base64_encode($iv) . '|' . base64_encode($encryptedKey);
37
-
38
-        return $data;
39
-    }
40
-
41
-    public function decryptData($data)
42
-    {
43
-        list($iv, $encryptedKey) = array_map('base64_decode', explode('|', $data));
44
-
45
-        $password = $this->getEncryptionKey();
46
-
47
-        $secret = openssl_decrypt($encryptedKey, 'aes-256-ctr', $password, OPENSSL_RAW_DATA, $iv);
48
-
49
-        return $secret;
50
-    }
51
-
52
-    /**
53
-     * @return string
54
-     */
55
-    private function getEncryptionKey()
56
-    {
57
-        return openssl_digest($this->configuration->getTotpEncryptionKey(), 'sha256');
58
-    }
15
+	/**
16
+	 * @var SiteConfiguration
17
+	 */
18
+	private $configuration;
19
+
20
+	/**
21
+	 * EncryptionHelper constructor.
22
+	 *
23
+	 * @param SiteConfiguration $configuration
24
+	 */
25
+	public function __construct(SiteConfiguration $configuration)
26
+	{
27
+		$this->configuration = $configuration;
28
+	}
29
+
30
+	public function encryptData($secret)
31
+	{
32
+		$iv = openssl_random_pseudo_bytes(16);
33
+		$password = $this->getEncryptionKey();
34
+		$encryptedKey = openssl_encrypt($secret, 'aes-256-ctr', $password, OPENSSL_RAW_DATA, $iv);
35
+
36
+		$data = base64_encode($iv) . '|' . base64_encode($encryptedKey);
37
+
38
+		return $data;
39
+	}
40
+
41
+	public function decryptData($data)
42
+	{
43
+		list($iv, $encryptedKey) = array_map('base64_decode', explode('|', $data));
44
+
45
+		$password = $this->getEncryptionKey();
46
+
47
+		$secret = openssl_decrypt($encryptedKey, 'aes-256-ctr', $password, OPENSSL_RAW_DATA, $iv);
48
+
49
+		return $secret;
50
+	}
51
+
52
+	/**
53
+	 * @return string
54
+	 */
55
+	private function getEncryptionKey()
56
+	{
57
+		return openssl_digest($this->configuration->getTotpEncryptionKey(), 'sha256');
58
+	}
59 59
 }
60 60
\ No newline at end of file
Please login to merge, or discard this patch.