Completed
Push — develop ( 841446...f3e111 )
by Schlaefer
04:07
created

Permissions::buildCategories()   A

Complexity

Conditions 5
Paths 2

Size

Total Lines 37
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 25
nc 2
nop 1
dl 0
loc 37
rs 9.2088
c 0
b 0
f 0
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
    /**
42
     * Constructor
43
     *
44
     * @param Roles $roles The roles
45
     * @param Resources $resources The resources collection
46
     */
47
    public function __construct(Roles $roles, Resources $resources)
48
    {
49
        Stopwatch::start('Permission::__construct()');
50
        $this->roles = $roles;
51
        $this->resources = $resources;
52
53
        Stopwatch::stop('Permission::__construct()');
54
    }
55
56
    /**
57
     * Check if access to resource is allowed.
58
     *
59
     * @param string $resource Resource to check
60
     * @param ResourceAI $identifier Identifier to provide
61
     * @return bool
62
     */
63
    public function check(string $resource, ResourceAI $identifier): bool
64
    {
65
        $resource = $this->resources->get($resource);
66
67
        return $resource === null ? false : $resource->check($identifier);
68
    }
69
70
    /**
71
     * Gets the roles object
72
     *
73
     * @return Roles
74
     */
75
    public function getRoles(): Roles
76
    {
77
        return $this->roles;
78
    }
79
80
    /**
81
     * Build category permissions
82
     *
83
     * @param CategoriesTable $categories Categories for accession permissions
84
     * @return void
85
     */
86
    public function buildCategories(CategoriesTable $categories): void
87
    {
88
        $categories = Cache::remember(
89
            'saito.core.permission.categories',
90
            function () use ($categories): array {
91
                $resources = [];
92
                $categories = $categories->getAllCategories();
93
                $roles = $this->roles->getAvailable(true);
94
                $accessions = array_combine(array_column($roles, 'id'), array_column($roles, 'type'));
95
                $actions = [
96
                    'read' => 'accession',
97
                    'thread' => 'accession_new_thread',
98
                    'answer' => 'accession_new_posting'
99
                ];
100
                foreach ($categories as $category) {
101
                    foreach ($actions as $action => $field) {
102
                        if (empty($accessions[$category->get($field)])) {
103
                            continue;
104
                        }
105
                        $role = $accessions[$category->get($field)];
106
                        $categoryId = $category->get('id');
107
                        $resource = "saito.core.category.{$categoryId}.{$action}";
108
                        $resources[] = ['resource' => $resource, 'role' => $role];
109
                    }
110
                }
111
112
                // array [['resource' => <Resource>, 'role' => <role-type>]]
113
                // Resource: `saito.core.category.<category-ID>.<action>`
114
                return $resources;
115
            }
116
        );
117
118
        foreach ($categories as $category) {
119
            $this->resources->add(
120
                (new Resource($category['resource']))
121
                ->allow((new ResourceAC())
122
                    ->asRole($category['role']))
123
            );
124
        }
125
    }
126
}
127