Completed
Branch release/5.5.0 (ca3c12)
by Schlaefer
04:35
created

Permissions   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 99
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 39
c 1
b 0
f 0
dl 0
loc 99
rs 10
wmc 9

4 Methods

Rating   Name   Duplication   Size   Complexity  
A getRoles() 0 3 1
A bootstrapCategories() 0 24 4
A __construct() 0 22 2
A check() 0 5 2
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * Saito - The Threaded Web Forum
7
 *
8
 * @copyright Copyright (c) the Saito Project Developers
9
 * @link https://github.com/Schlaefer/Saito
10
 * @license http://opensource.org/licenses/MIT
11
 */
12
13
namespace Saito\User\Permission;
14
15
use App\Model\Table\CategoriesTable;
16
use Cake\Cache\Cache;
17
use Saito\RememberTrait;
18
use Saito\User\Permission\Resource;
19
use Saito\User\Permission\ResourceAC;
20
use Saito\User\Permission\Resources;
21
use Saito\User\Permission\Roles;
22
use Stopwatch\Lib\Stopwatch;
23
24
/**
25
 * Class Permission
26
 *
27
 * Implements simple access control scheme.
28
 *
29
 * @package Saito\User
30
 */
31
class Permissions
32
{
33
    use RememberTrait;
34
35
    /** @var Roles */
36
    protected $roles;
37
38
    /** @var Resources */
39
    protected $resources;
40
41
    /** @var CategoriesTable */
42
    protected $categories;
43
44
    /**
45
     * Constructor
46
     *
47
     * @param Roles $roles The roles
48
     * @param Resources $resources The resources collection
49
     * @param CategoriesTable $categories Categories for accession permissions
50
     */
51
    public function __construct(Roles $roles, Resources $resources, CategoriesTable $categories)
52
    {
53
        Stopwatch::start('Permission::__construct()');
54
        $this->roles = $roles;
55
        $this->resources = $resources;
56
        $this->categories = $categories;
57
58
        $categories = Cache::remember(
59
            'saito.core.permission.categories',
60
            function () {
61
                return $this->bootstrapCategories();
62
            }
63
        );
64
        foreach ($categories as $category) {
65
            $this->resources->add(
66
                (new Resource($category['resource']))
67
                ->allow((new ResourceAC())
68
                    ->asRole($category['role']))
69
            );
70
        }
71
72
        Stopwatch::stop('Permission::__construct()');
73
    }
74
75
    /**
76
     * Check if access to resource is allowed.
77
     *
78
     * @param string $resource Resource to check
79
     * @param ResourceAI $identifier Identifier to provide
80
     * @return bool
81
     */
82
    public function check(string $resource, ResourceAI $identifier): bool
83
    {
84
        $resource = $this->resources->get($resource);
85
86
        return $resource === null ? false : $resource->check($identifier);
87
    }
88
89
    /**
90
     * Gets the roles object
91
     *
92
     * @return Roles
93
     */
94
    public function getRoles(): Roles
95
    {
96
        return $this->roles;
97
    }
98
99
    /**
100
     * convert category-accessions and insert them as resources
101
     *
102
     * Resource: `saito.core.category.<category-ID>.<action>`
103
     *
104
     * @return array [['resource' => <Resource>, 'role' => <role-type>]]
105
     */
106
    protected function bootstrapCategories(): array
107
    {
108
        $resources = [];
109
        $categories = $this->categories->getAllCategories();
110
        $roles = $this->roles->getAvailable(true);
111
        $accessions = array_combine(array_column($roles, 'id'), array_column($roles, 'type'));
112
        $actions = [
113
            'read' => 'accession',
114
            'thread' => 'accession_new_thread',
115
            'answer' => 'accession_new_posting'
116
        ];
117
        foreach ($categories as $category) {
118
            foreach ($actions as $action => $field) {
119
                if (empty($accessions[$category->get($field)])) {
120
                    continue;
121
                }
122
                $role = $accessions[$category->get($field)];
123
                $categoryId = $category->get('id');
124
                $resource = "saito.core.category.{$categoryId}.{$action}";
125
                $resources[] = ['resource' => $resource, 'role' => $role];
126
            }
127
        }
128
129
        return $resources;
130
    }
131
}
132