PermissionsTrait   A
last analyzed

Complexity

Total Complexity 12

Size/Duplication

Total Lines 125
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 41
dl 0
loc 125
rs 10
c 1
b 0
f 0
wmc 12

7 Methods

Rating   Name   Duplication   Size   Complexity  
A addPermissions() 0 6 2
A savePermissions() 0 16 2
A removePermissions() 0 3 1
A rolesByIds() 0 9 2
A rolesByNames() 0 9 2
A objectPermissionsIds() 0 12 2
A roles() 0 7 1
1
<?php
2
declare(strict_types=1);
3
4
/**
5
 * BEdita, API-first content management framework
6
 * Copyright 2023 Atlas Srl, Chialab Srl
7
 *
8
 * This file is part of BEdita: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published
10
 * by the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * See LICENSE.LGPL or <http://gnu.org/licenses/lgpl-3.0.html> for more details.
14
 */
15
namespace App\Utility;
16
17
use App\Controller\Admin\RolesController;
18
use BEdita\WebTools\ApiClientProvider;
19
use Cake\Cache\Cache;
20
use Cake\Utility\Hash;
21
22
/**
23
 * Save and delete permissions via API
24
 */
25
trait PermissionsTrait
26
{
27
    /**
28
     * Save permissions for single object.
29
     *
30
     * @param array $response The object response
31
     * @param array $schema The object type schema
32
     * @param array $newPermissions The permissions to save
33
     * @return bool
34
     */
35
    public function savePermissions(array $response, array $schema, array $newPermissions): bool
36
    {
37
        if (!in_array('Permissions', (array)Hash::get($schema, 'associations'))) {
38
            return false;
39
        }
40
        $objectId = (string)Hash::get($response, 'data.id');
41
        $oldPermissions = (array)Hash::get($response, 'data.meta.perms.roles');
42
        $oldPermissions = $this->rolesByNames($oldPermissions);
43
        $newPermissions = $this->rolesByIds($newPermissions);
44
        $toRemove = array_keys(array_diff($oldPermissions, $newPermissions));
45
        $toAdd = array_keys(array_diff($newPermissions, $oldPermissions));
46
        $toRemove = $this->objectPermissionsIds($objectId, $toRemove);
47
        $this->removePermissions($toRemove);
48
        $this->addPermissions($objectId, $toAdd);
49
50
        return true;
51
    }
52
53
    /**
54
     * Add permissions per object by ID
55
     *
56
     * @param string $objectId The object ID
57
     * @param array $roleIds The role IDs
58
     * @return void
59
     */
60
    public function addPermissions(string $objectId, array $roleIds): void
61
    {
62
        foreach ($roleIds as $roleId) {
63
            ApiClientProvider::getApiClient()->save(
64
                'object_permissions',
65
                ['object_id' => $objectId, 'role_id' => $roleId]
66
            );
67
        }
68
    }
69
70
    /**
71
     * Remove permissions by object permission IDs
72
     *
73
     * @param array $objectPermissionIds The object permission IDs
74
     * @return void
75
     */
76
    public function removePermissions(array $objectPermissionIds): void
77
    {
78
        ApiClientProvider::getApiClient()->deleteObjects($objectPermissionIds, 'object_permissions');
79
    }
80
81
    /**
82
     * Object permissions IDs per role IDs.
83
     *
84
     * @param string $objectId The object ID
85
     * @param array $roleIds The role IDs
86
     * @return array
87
     */
88
    public function objectPermissionsIds(string $objectId, array $roleIds): array
89
    {
90
        if (empty($roleIds)) {
91
            return [];
92
        }
93
        $query = ['filter' => ['object_id' => $objectId], 'page_size' => 100];
94
        $objectPermissions = (array)ApiClientProvider::getApiClient()->getObjects('object_permissions', $query);
95
        $objectPermissions = Hash::combine($objectPermissions, 'data.{n}.attributes.role_id', 'data.{n}.id');
96
97
        return array_map(function ($roleId) use ($objectPermissions) {
98
            return $objectPermissions[$roleId];
99
        }, $roleIds);
100
    }
101
102
    /**
103
     * Return roles data (<id>:<name), using cache.
104
     *
105
     * @return array
106
     */
107
    public function roles(): array
108
    {
109
        return Cache::remember(RolesController::CACHE_KEY_ROLES, function () {
110
            return Hash::combine(
111
                (array)ApiClientProvider::getApiClient()->get('/roles'),
112
                'data.{n}.id',
113
                'data.{n}.attributes.name'
114
            );
115
        });
116
    }
117
118
    /**
119
     * Return roles data (<id>:<name) from role names
120
     *
121
     * @param array $names Role names
122
     * @return array Roles IDs and names
123
     */
124
    public function rolesByNames(array $names): array
125
    {
126
        $result = [];
127
        $flipped = array_flip($this->roles());
128
        foreach ($names as $name) {
129
            $result[(string)Hash::get($flipped, $name)] = $name;
130
        }
131
132
        return $result;
133
    }
134
135
    /**
136
     * Return roles data (<id>:<name) from role ids
137
     *
138
     * @param array $ids Roles IDs
139
     * @return array Roles IDs and names
140
     */
141
    public function rolesByIds(array $ids): array
142
    {
143
        $roles = $this->roles();
144
        $result = [];
145
        foreach ($ids as $id) {
146
            $result[$id] = (string)Hash::get($roles, $id);
147
        }
148
149
        return $result;
150
    }
151
}
152