GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

FlatAuthorization   D
last analyzed

Complexity

Total Complexity 91

Size/Duplication

Total Lines 757
Duplicated Lines 26.68 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
dl 202
loc 757
rs 4.4444
c 0
b 0
f 0
wmc 91
lcom 1
cbo 3

24 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 3
A error() 0 4 1
A useModel() 0 6 1
D inGroup() 0 42 9
C hasPermission() 0 29 8
D addUserToGroup() 36 36 9
D removeUserFromGroup() 36 36 9
B addPermissionToGroup() 27 27 4
B removePermissionFromGroup() 27 27 4
B addPermissionToUser() 0 42 6
B removePermissionFromUser() 0 38 6
B doesUserHavePermission() 0 30 5
A group() 0 9 2
A groups() 0 4 1
A createGroup() 18 18 2
A deleteGroup() 0 11 2
A updateGroup() 20 20 3
A getGroupID() 0 18 3
A permission() 0 9 2
A permissions() 0 4 1
A createPermission() 18 18 2
A deletePermission() 0 14 2
A updatePermission() 20 20 3
A getPermissionID() 0 20 3

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like FlatAuthorization often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use FlatAuthorization, and based on these observations, apply Extract Interface, too.

1
<?php namespace Myth\Auth;
2
/**
3
 * Sprint
4
 *
5
 * A set of power tools to enhance the CodeIgniter framework and provide consistent workflow.
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8
 * of this software and associated documentation files (the "Software"), to deal
9
 * in the Software without restriction, including without limitation the rights
10
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
 * copies of the Software, and to permit persons to whom the Software is
12
 * furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be included in
15
 * all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
 * THE SOFTWARE.
24
 *
25
 * @package     Sprint
26
 * @author      Lonnie Ezell
27
 * @copyright   Copyright 2014-2015, New Myth Media, LLC (http://newmythmedia.com)
28
 * @license     http://opensource.org/licenses/MIT  (MIT)
29
 * @link        http://sprintphp.com
30
 * @since       Version 1.0
31
 */
32
33
use Myth\Auth\Flat\FlatGroupsModel;
34
use Myth\Auth\Flat\FlatPermissionsModel;
35
use Myth\Events\Events;
36
37
class FlatAuthorization implements AuthorizeInterface {
38
39
	protected $groupModel;
40
41
	protected $permissionModel;
42
43
	protected $error = NULL;
44
45
	protected $user_model = null;
46
47
	//--------------------------------------------------------------------
48
49
	public function __construct($groupModel = null, $permModel = null)
50
	{
51
		$this->groupModel      = ! empty($groupModel) ? $groupModel : new FlatGroupsModel();
52
		$this->permissionModel = ! empty($permModel)  ? $permModel  : new FlatPermissionsModel();
53
54
		get_instance()->load->language('auth/auth');
55
	}
56
57
	//--------------------------------------------------------------------
58
59
	public function error()
60
	{
61
		return $this->error;
62
	}
63
64
	//--------------------------------------------------------------------
65
66
	/**
67
	 * Allows the consuming application to pass in a reference to the
68
	 * model that should be used.
69
	 *
70
	 * @param $model
71
	 * @return mixed
72
	 */
73
	public function useModel($model)
74
	{
75
		$this->user_model =& $model;
76
77
		return $this;
78
	}
79
80
	//--------------------------------------------------------------------
81
82
	//--------------------------------------------------------------------
83
	// Actions
84
	//--------------------------------------------------------------------
85
86
	/**
87
	 * Checks to see if a user is in a group.
88
	 *
89
	 * Groups can be either a string, with the name of the group, an INT
90
	 * with the ID of the group, or an array of strings/ids that the
91
	 * user must belong to ONE of. (It's an OR check not an AND check)
92
	 *
93
	 * @param $groups
94
	 *
95
	 * @return bool
96
	 */
97
	public function inGroup( $groups, $user_id )
98
	{
99
		if ( ! is_array( $groups ) )
100
		{
101
			$groups = [ $groups ];
102
		}
103
104
		if (empty($user_id))
105
		{
106
			return null;
107
		}
108
109
		$user_groups = $this->groupModel->getGroupsForUser( (int) $user_id );
110
111
		if ( ! $user_groups )
112
		{
113
			return false;
114
		}
115
116
		foreach ( $groups as $group )
117
		{
118
			if (is_numeric($group))
119
			{
120
				$ids = array_column($user_groups, 'id');
121
				if (in_array($group, $ids))
122
				{
123
					return true;
124
				}
125
			}
126
127
			else if (is_string($group))
128
			{
129
				$ids = array_column($user_groups, 'name');
130
				if (in_array($group, $ids))
131
				{
132
					return true;
133
				}
134
			}
135
		}
136
137
		return false;
138
	}
139
140
	//--------------------------------------------------------------------
141
142
	/**
143
	 * Checks a user's groups to see if they have the specified permission.
144
	 *
145
	 * @param int|string $permission
146
	 * @param int|string $user_id
147
	 *
148
	 * @return mixed
149
	 */
150
	public function hasPermission( $permission, $user_id )
151
	{
152
		if (empty($permission) || (! is_string($permission) && ! is_numeric($permission)) )
153
		{
154
			return null;
155
		}
156
157
		if (empty($user_id) || ! is_numeric($user_id))
158
		{
159
			return null;
160
		}
161
162
		// Get the Permission ID
163
		$permission_id = $this->getPermissionID($permission);
164
165
		if ( ! is_numeric( $permission_id ) )
166
		{
167
			return false;
168
		}
169
170
		// First check the permission model. If that exists, then we're golden.
171
		if ($this->permissionModel->doesUserHavePermission( (int)$user_id, (int)$permission_id ) )
172
		{
173
			return true;
174
		}
175
176
		// Still here? Then we have one last check to make - any user private permissions.
177
		return $this->doesUserHavePermission( (int)$user_id, (int)$permission_id);
178
	}
179
180
	//--------------------------------------------------------------------
181
182
	/**
183
	 * Makes a member a part of a group.
184
	 *
185
	 * @param $user_id
186
	 * @param $group // Either ID or name
187
	 *
188
	 * @return bool
189
	 */
190 View Code Duplication
	public function addUserToGroup( $user_id, $group )
191
	{
192
		if (empty($user_id) || ! is_numeric($user_id))
193
		{
194
			return null;
195
		}
196
197
		if (empty($group) || (! is_numeric($group) && ! is_string($group) ) )
198
		{
199
			return null;
200
		}
201
202
		if (! Events::trigger('beforeAddUserToGroup', [$user_id, $group]))
203
		{
204
			return false;
205
		}
206
207
		$group_id = $this->getGroupID($group);
208
209
		// Group ID
210
		if ( ! is_numeric( $group_id ) )
211
		{
212
			return null;
213
		}
214
215
		if ( ! $this->groupModel->addUserToGroup( (int)$user_id, (int)$group_id ) )
216
		{
217
			$this->error = $this->groupModel->error();
218
219
			return FALSE;
220
		}
221
222
		Events::trigger('didAddUserToGroup', [$user_id, $group]);
223
224
		return TRUE;
225
	}
226
227
	//--------------------------------------------------------------------
228
229
	/**
230
	 * Removes a single user from a group.
231
	 *
232
	 * @param $user_id
233
	 * @param $group
234
	 *
235
	 * @return mixed
236
	 */
237 View Code Duplication
	public function removeUserFromGroup( $user_id, $group )
238
	{
239
		if (empty($user_id) || ! is_numeric($user_id))
240
		{
241
			return null;
242
		}
243
244
		if (empty($group) || (! is_numeric($group) && ! is_string($group) ) )
245
		{
246
			return null;
247
		}
248
249
		if (! Events::trigger('beforeRemoveUserFromGroup', [$user_id, $group]))
250
		{
251
			return false;
252
		}
253
254
		$group_id = $this->getGroupID($group);
255
256
		// Group ID
257
		if ( ! is_numeric( $group_id ) )
258
		{
259
			return false;
260
		}
261
262
		if ( ! $this->groupModel->removeUserFromGroup( $user_id, $group_id ) )
263
		{
264
			$this->error = $this->groupModel->error();
265
266
			return FALSE;
267
		}
268
269
		Events::trigger('didRemoveUserFromGroup', [$user_id, $group]);
270
271
		return TRUE;
272
	}
273
274
	//--------------------------------------------------------------------
275
276
	/**
277
	 * Adds a single permission to a single group.
278
	 *
279
	 * @param int|string $permission
280
	 * @param int|string $group
281
	 *
282
	 * @return mixed
283
	 */
284 View Code Duplication
	public function addPermissionToGroup( $permission, $group )
285
	{
286
		$permission_id = $this->getPermissionID($permission);
287
		$group_id      = $this->getGroupID($group);
288
289
		// Permission ID
290
		if ( ! is_numeric( $permission_id ) )
291
		{
292
			return false;
293
		}
294
295
		// Group ID
296
		if ( ! is_numeric( $group_id ) )
297
		{
298
			return false;
299
		}
300
301
		// Remove it!
302
		if ( ! $this->groupModel->addPermissionToGroup( $permission_id, $group_id ) )
303
		{
304
			$this->error = $this->groupModel->error();
305
306
			return FALSE;
307
		}
308
309
		return TRUE;
310
	}
311
312
	//--------------------------------------------------------------------
313
314
	/**
315
	 * Removes a single permission from a group.
316
	 *
317
	 * @param int|string $permission
318
	 * @param int|string $group
319
	 *
320
	 * @return mixed
321
	 */
322 View Code Duplication
	public function removePermissionFromGroup( $permission, $group )
323
	{
324
		$permission_id = $this->getPermissionID($permission);
325
		$group_id      = $this->getGroupID($group);
326
327
		// Permission ID
328
		if ( ! is_numeric( $permission_id ) )
329
		{
330
			return false;
331
		}
332
333
		// Group ID
334
		if ( ! is_numeric( $group_id ) )
335
		{
336
			return false;
337
		}
338
339
		// Remove it!
340
		if ( ! $this->groupModel->removePermissionFromGroup( $permission_id, $group_id ) )
341
		{
342
			$this->error = $this->groupModel->error();
343
344
			return FALSE;
345
		}
346
347
		return TRUE;
348
	}
349
350
	//--------------------------------------------------------------------
351
352
	/**
353
	 * Assigns a single permission to a user, irregardless of permissions
354
	 * assigned by roles. This is saved to the user's meta information.
355
	 *
356
	 * @param int|string $permission
357
	 * @param int $user_id
358
	 *
359
	 * @return int|bool
360
	 */
361
	public function addPermissionToUser( $permission, $user_id )
362
	{
363
		$permission_id = $this->getPermissionID($permission);
364
365
		if (! is_numeric($permission_id) )
366
		{
367
			return null;
368
		}
369
370
		if (empty($user_id) || ! is_numeric($user_id))
371
		{
372
			return null;
373
		}
374
375
		$user_id = (int)$user_id;
376
377
		if (! Events::trigger('beforeAddPermissionToUser', [$user_id, $permission]))
378
		{
379
			return false;
380
		}
381
382
		$ci =& get_instance();
383
		$ci->load->model('User_model');
384
385
		$permissions = $ci->user_model->getMetaItem($user_id, 'RBAC_permissions');
386
387
		// If we already have permissions, unserialize them and add
388
		// the new permission to it.
389
		if (! empty($permissions))
390
		{
391
			$permissions = unserialize($permissions);
392
		}
393
		else
394
		{
395
			$permissions = [];
396
		}
397
398
		$permissions[] = $permission_id;
399
400
		// Save the updated permissions
401
		return $ci->user_model->saveMetaToUser($user_id, 'RBAC_permissions', serialize($permissions));
402
	}
403
404
	//--------------------------------------------------------------------
405
406
	/**
407
	 * Removes a single permission from a user. Only applies to permissions
408
	 * that have been assigned with addPermissionToUser, not to permissions
409
	 * inherited based on groups they belong to.
410
	 *
411
	 * @param int/string $permission
412
	 * @param int        $user_id
413
	 */
414
	public function removePermissionFromUser( $permission, $user_id )
415
	{
416
		$permission_id = $this->getPermissionID($permission);
417
418
		if (! is_numeric($permission_id) )
419
		{
420
			return false;
421
		}
422
423
		if (empty($user_id) || ! is_numeric($user_id))
424
		{
425
			return null;
426
		}
427
428
		$user_id = (int)$user_id;
429
430
		if (! Events::trigger('beforeRemovePermissionFromUser', [$user_id, $permission]))
431
		{
432
			return false;
433
		}
434
435
		// Grab the existing permissions for this user, and remove
436
		// the permission id from the list.
437
		$ci =& get_instance();
438
		$ci->load->model('User_model');
439
440
		$permissions = $ci->user_model->getMetaItem($user_id, 'RBAC_permissions');
441
442
		if (! is_array($permissions))
443
		{
444
			$permissions = [];
445
		}
446
447
		unset($permissions[ array_search($permission_id, $permissions) ]);
448
449
		// Save the updated permissions
450
		return $ci->user_model->saveMetaToUser($user_id, 'RBAC_permissions', serialize($permissions));
451
	}
452
453
	//--------------------------------------------------------------------
454
455
	/**
456
	 * Checks to see if a user has private permission assigned to it.
457
	 *
458
	 * @param $user_id
459
	 * @param $permission
460
	 *
461
	 * @return bool|null
462
	 */
463
	public function doesUserHavePermission($user_id, $permission)
464
	{
465
		$permission_id = $this->getPermissionID($permission);
466
467
		if (! is_numeric($permission_id) )
468
		{
469
			return false;
470
		}
471
472
		if (empty($user_id) || ! is_numeric($user_id))
473
		{
474
			return null;
475
		}
476
477
		$user_id = (int)$user_id;
478
479
		$model = $this->user_model;
480
481
		if (empty($model))
482
		{
483
			$ci =& get_instance();
484
			$ci->load->model( 'User_model' );
485
486
			$model = $ci->user_model;
487
		}
488
489
		$permissions = $model->getMetaItem($user_id, 'RBAC_permissions');
490
491
		return in_array($permission_id, $permissions);
492
	}
493
494
	//--------------------------------------------------------------------
495
496
497
498
	//--------------------------------------------------------------------
499
	// Groups
500
	//--------------------------------------------------------------------
501
502
	/**
503
	 * Grabs the details about a single group.
504
	 *
505
	 * @param $group
506
	 *
507
	 * @return object|null
508
	 */
509
	public function group( $group )
510
	{
511
		if ( is_numeric( $group ) )
512
		{
513
			return $this->groupModel->find( (int) $group );
514
		}
515
516
		return $this->groupModel->find_by( 'name', $group );
517
	}
518
519
	//--------------------------------------------------------------------
520
521
	/**
522
	 * Grabs an array of all groups.
523
	 *
524
	 * @return array of objects
525
	 */
526
	public function groups()
527
	{
528
		return $this->groupModel->find_all();
529
	}
530
531
	//--------------------------------------------------------------------
532
533
	/**
534
	 * @param $name
535
	 * @param string $description
536
	 *
537
	 * @return mixed
538
	 */
539 View Code Duplication
	public function createGroup( $name, $description = '' )
540
	{
541
		$data = [
542
			'name'        => $name,
543
			'description' => $description
544
		];
545
546
		$id = $this->groupModel->insert( $data );
547
548
		if ( is_numeric( $id ) )
549
		{
550
			return (int) $id;
551
		}
552
553
		$this->error = $this->groupModel->error();
554
555
		return FALSE;
556
	}
557
558
	//--------------------------------------------------------------------
559
560
	/**
561
	 * Deletes a single group.
562
	 *
563
	 * @param int $group_id
564
	 *
565
	 * @return bool
566
	 */
567
	public function deleteGroup( $group_id )
568
	{
569
		if ( ! $this->groupModel->delete( $group_id ) )
570
		{
571
			$this->error = $this->groupModel->error();
572
573
			return FALSE;
574
		}
575
576
		return TRUE;
577
	}
578
579
	//--------------------------------------------------------------------
580
581
	/**
582
	 * Updates a single group's information.
583
	 *
584
	 * @param $id
585
	 * @param $name
586
	 * @param string $description
587
	 *
588
	 * @return mixed
589
	 */
590 View Code Duplication
	public function updateGroup( $id, $name, $description = '' )
591
	{
592
		$data = [
593
			'name' => $name
594
		];
595
596
		if ( ! empty( $description ) )
597
		{
598
			$data['description'] = $description;
599
		}
600
601
		if ( ! $this->groupModel->update( (int) $id, $data ) )
602
		{
603
			$this->error = $this->groupModel->error();
604
605
			return FALSE;
606
		}
607
608
		return TRUE;
609
	}
610
611
	//--------------------------------------------------------------------
612
613
	/**
614
	 * Given a group, will return the group ID. The group can be either
615
	 * the ID or the name of the group.
616
	 *
617
	 * @param int|string $group
618
	 *
619
	 * @return int|false
620
	 */
621
	protected function getGroupID( $group )
622
	{
623
		if (is_numeric($group))
624
		{
625
			return (int)$group;
626
		}
627
628
		$g = $this->groupModel->find_by( 'name', $group );
629
630
		if ( ! $g )
631
		{
632
			$this->error = lang('auth.group_not_found');
633
634
			return FALSE;
635
		}
636
637
		return (int)$g->id;
638
	}
639
640
	//--------------------------------------------------------------------
641
642
	//--------------------------------------------------------------------
643
	// Permissions
644
	//--------------------------------------------------------------------
645
646
	/**
647
	 * Returns the details about a single permission.
648
	 *
649
	 * @param int|string $permission
650
	 *
651
	 * @return object|null
652
	 */
653
	public function permission( $permission )
654
	{
655
		if ( is_numeric( $permission ) )
656
		{
657
			return $this->permissionModel->find( (int) $permission );
658
		}
659
660
		return $this->permissionModel->find_by( 'LOWER(name)', strtolower( $permission ) );
661
	}
662
663
	//--------------------------------------------------------------------
664
665
	/**
666
	 * Returns an array of all permissions in the system.
667
	 *
668
	 * @return mixed
669
	 */
670
	public function permissions()
671
	{
672
		return $this->permissionModel->find_all();
673
	}
674
675
	//--------------------------------------------------------------------
676
677
	/**
678
	 * Creates a single permission.
679
	 *
680
	 * @param $name
681
	 * @param string $description
682
	 *
683
	 * @return mixed
684
	 */
685 View Code Duplication
	public function createPermission( $name, $description = '' )
686
	{
687
		$data = [
688
			'name'        => $name,
689
			'description' => $description
690
		];
691
692
		$id = $this->permissionModel->insert( $data );
693
694
		if ( is_numeric( $id ) )
695
		{
696
			return (int) $id;
697
		}
698
699
		$this->error = $this->permissionModel->error();
700
701
		return FALSE;
702
	}
703
704
	//--------------------------------------------------------------------
705
706
	/**
707
	 * Deletes a single permission and removes that permission from all groups.
708
	 *
709
	 * @param $permission
710
	 *
711
	 * @return mixed
712
	 */
713
	public function deletePermission( $permission_id )
714
	{
715
		if ( ! $this->permissionModel->delete( $permission_id ) )
716
		{
717
			$this->error = $this->permissionModel->error();
718
719
			return FALSE;
720
		}
721
722
		// Remove the permission from all groups
723
		$this->groupModel->removePermissionFromAllGroups( $permission_id );
724
725
		return TRUE;
726
	}
727
728
	//--------------------------------------------------------------------
729
730
	/**
731
	 * Updates the details for a single permission.
732
	 *
733
	 * @param int $id
734
	 * @param string $name
735
	 * @param string $description
736
	 *
737
	 * @return bool
738
	 */
739 View Code Duplication
	public function updatePermission( $id, $name, $description = '' )
740
	{
741
		$data = [
742
			'name' => $name
743
		];
744
745
		if ( ! empty( $description ) )
746
		{
747
			$data['description'] = $description;
748
		}
749
750
		if ( ! $this->permissionModel->update( (int) $id, $data ) )
751
		{
752
			$this->error = $this->permissionModel->error();
753
754
			return FALSE;
755
		}
756
757
		return TRUE;
758
	}
759
760
	//--------------------------------------------------------------------
761
762
	/**
763
	 * Verifies that a permission (either ID or the name) exists and returns
764
	 * the permission ID.
765
	 *
766
	 * @param int|string $permission
767
	 *
768
	 * @return int|null
769
	 */
770
	protected function getPermissionID( $permission )
771
	{
772
		// If it's a number, we're done here.
773
		if (is_numeric($permission))
774
		{
775
			return (int)$permission;
776
		}
777
778
		// Otherwise, pull it from the database.
779
		$p = $this->permissionModel->find_by( 'name', $permission );
780
781
		if ( ! $p )
782
		{
783
			$this->error = lang('auth.permission_not_found');
784
785
			return FALSE;
786
		}
787
788
		return (int)$p->id;
789
	}
790
791
	//--------------------------------------------------------------------
792
793
}
794