Issues (257)

Services/UserSystem/PermissionSchemaUpdater.php (2 issues)

Severity
1
<?php
2
/*
3
 * This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
4
 *
5
 *  Copyright (C) 2019 - 2023 Jan Böhmer (https://github.com/jbtronics)
6
 *
7
 *  This program is free software: you can redistribute it and/or modify
8
 *  it under the terms of the GNU Affero General Public License as published
9
 *  by the Free Software Foundation, either version 3 of the License, or
10
 *  (at your option) any later version.
11
 *
12
 *  This program is distributed in the hope that it will be useful,
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 *  GNU Affero General Public License for more details.
16
 *
17
 *  You should have received a copy of the GNU Affero General Public License
18
 *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
19
 */
20
21
namespace App\Services\UserSystem;
22
23
use App\Entity\UserSystem\Group;
24
use App\Entity\UserSystem\PermissionData;
25
use App\Entity\UserSystem\User;
26
use App\Security\Interfaces\HasPermissionsInterface;
27
28
class PermissionSchemaUpdater
29
{
30
    /**
31
     * Check if the given user/group needs an update of its permission schema.
32
     * @param  HasPermissionsInterface  $holder
33
     * @return bool True if the permission schema needs an update, false otherwise.
34
     */
35
    public function isSchemaUpdateNeeded(HasPermissionsInterface $holder): bool
36
    {
37
        $perm_data = $holder->getPermissions();
38
39
        if ($perm_data->getSchemaVersion() < PermissionData::CURRENT_SCHEMA_VERSION) {
40
            return true;
41
        }
42
43
        return false;
44
    }
45
46
    /**
47
     * Upgrades the permission schema of the given user/group to the chosen version.
48
     * Please note that this function does not flush the changes to DB!
49
     * @param  HasPermissionsInterface  $holder
50
     * @param  int  $target_version
51
     * @return bool True, if an upgrade was done, false if it was not needed.
52
     */
53
    public function upgradeSchema(HasPermissionsInterface $holder, int $target_version = PermissionData::CURRENT_SCHEMA_VERSION): bool
54
    {
55
        if ($target_version > PermissionData::CURRENT_SCHEMA_VERSION) {
56
            throw new \InvalidArgumentException('The target version is higher than the maximum possible schema version!');
57
        }
58
59
        //Check if we need to do an update, if not, return false
60
        if ($target_version <= $holder->getPermissions()->getSchemaVersion()) {
61
            return false;
62
        }
63
64
        //Do the update
65
        for ($n = $holder->getPermissions()->getSchemaVersion(); $n < $target_version; ++$n) {
66
            $reflectionClass = new \ReflectionClass(self::class);
67
            try {
68
                $method = $reflectionClass->getMethod('upgradeSchemaToVersion'.($n + 1));
69
                //Set the method accessible, so we can call it (needed for PHP < 8.1)
70
                $method->setAccessible(true);
71
                $method->invoke($this, $holder);
72
            } catch (\ReflectionException $e) {
73
                throw new \RuntimeException('Could not find update method for schema version '.($n + 1));
74
            }
75
76
            //Bump the schema version
77
            $holder->getPermissions()->setSchemaVersion($n + 1);
78
        }
79
80
        //When we end up here, we have done an upgrade and we can return true
81
        return true;
82
    }
83
84
    /**
85
     * Upgrades the permission schema of the given group and all of its parent groups to the chosen version.
86
     * Please note that this function does not flush the changes to DB!
87
     * @param  Group  $group
88
     * @param  int  $target_version
89
     * @return bool True if an upgrade was done, false if it was not needed.
90
     */
91
    public function groupUpgradeSchemaRecursively(Group $group, int $target_version = PermissionData::CURRENT_SCHEMA_VERSION): bool
92
    {
93
        $updated = $this->upgradeSchema($group, $target_version);
94
95
        /** @var Group $parent */
96
        $parent = $group->getParent();
97
        while ($parent) {
98
            $updated = $this->upgradeSchema($parent, $target_version) || $updated;
99
            $parent = $parent->getParent();
100
        }
101
102
        return $updated;
103
    }
104
105
    /**
106
     * Upgrades the permissions schema of the given users and its parent (including parent groups) to the chosen version.
107
     * Please note that this function does not flush the changes to DB!
108
     * @param  User  $user
109
     * @param  int  $target_version
110
     * @return bool True if an upgrade was done, false if it was not needed.
111
     */
112
    public function userUpgradeSchemaRecursively(User $user, int $target_version = PermissionData::CURRENT_SCHEMA_VERSION): bool
113
    {
114
        $updated = $this->upgradeSchema($user, $target_version);
115
        if ($user->getGroup()) {
116
            $updated = $this->groupUpgradeSchemaRecursively($user->getGroup(), $target_version) || $updated;
117
        }
118
119
        return $updated;
120
    }
121
122
    private function upgradeSchemaToVersion1(HasPermissionsInterface $holder): void
0 ignored issues
show
The method upgradeSchemaToVersion1() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
123
    {
124
        //Use the part edit permission to set the preset value for the new part stock permission
125
        if (
126
            !$holder->getPermissions()->isPermissionSet('parts_stock', 'withdraw')
127
            && !$holder->getPermissions()->isPermissionSet('parts_stock', 'add')
128
            && !$holder->getPermissions()->isPermissionSet('parts_stock', 'move')
129
        ) { //Only do migration if the permission was not set already
130
131
            $new_value = $holder->getPermissions()->getPermissionValue('parts', 'edit');
132
133
            $holder->getPermissions()->setPermissionValue('parts_stock', 'withdraw', $new_value);
134
            $holder->getPermissions()->setPermissionValue('parts_stock', 'add', $new_value);
135
            $holder->getPermissions()->setPermissionValue('parts_stock', 'move', $new_value);
136
        }
137
    }
138
139
    private function upgradeSchemaToVersion2(HasPermissionsInterface $holder): void
0 ignored issues
show
The method upgradeSchemaToVersion2() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
140
    {
141
        //If the projects permissions are not defined yet, rename devices permission to projects (just copy its data over)
142
        if (!$holder->getPermissions()->isAnyOperationOfPermissionSet('projects')) {
143
            $operations_value = $holder->getPermissions()->getAllDefinedOperationsOfPermission('devices');
144
            $holder->getPermissions()->setAllOperationsOfPermission('projects', $operations_value);
145
            $holder->getPermissions()->removePermission('devices');
146
        }
147
    }
148
}