ApiAuthorizer.php 4.38 KB
Newer Older
1
2
3
4
5
6
<?php


namespace Source\Authorization;

use Illuminate\Contracts\Auth\Guard;
7
8
use Source\Gateways\Users\UsersRepository;
use Source\Gateways\Groups\GroupsRepository;
9
use Source\Exceptions\AuthorizationException;
Jacob Priddy's avatar
Jacob Priddy committed
10
use Source\Exceptions\EntityNotFoundException;
11
use Source\Gateways\GroupUser\GroupUserRepository;
12
13
14

class ApiAuthorizer implements Authorizer
{
15
16
17
    /**
     * @var \Illuminate\Contracts\Auth\Guard
     */
18
19
    protected Guard $guard;

20
21
22
23
24
    /**
     * @var \Source\Gateways\GroupUser\GroupUserRepository
     */
    protected GroupUserRepository $groupUserRepository;

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
    /**
     * @var \Source\Gateways\Groups\GroupsRepository
     */
    protected GroupsRepository $groups;

    /**
     * @var \Source\Gateways\Users\UsersRepository
     */
    protected UsersRepository $users;

    public function __construct(
        Guard $guard,
        UsersRepository $users,
        GroupsRepository $groups,
        GroupUserRepository $groupUserRepository
    ) {
        $this->users = $users;
42
        $this->guard = $guard;
43
        $this->groups = $groups;
44
        $this->groupUserRepository = $groupUserRepository;
45
46
47
    }

    /**
48
     * @inheritDoc
49
     */
50
    public function protectAll(array $permissions): void
51
    {
52
53
        if (!$this->allowsAll($permissions)) {
            throw new AuthorizationException();
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
        }
    }

    /**
     * @inheritDoc
     */
    public function allowsAll(array $permissions): bool
    {
        $groups = $this->getGroupsForCurrentUser();

        if (in_array(Permissions::ADMIN, $groups, true)) {
            return true;
        }

        foreach ($permissions as $permission) {
            if (!in_array($permission, $groups, true)) {
                return false;
            }
72
        }
73
74

        return true;
75
    }
76
77

    /**
78
79
     * @return string[]
     * @throws \Source\Exceptions\EntityNotFoundException
80
     */
81
    protected function getGroupsForCurrentUser(): array
82
    {
83
        $user = $this->guard->id();
84

85
86
        if (!$user) {
            return [];
87
88
        }

Jacob Priddy's avatar
Jacob Priddy committed
89
90
91
92
93
94
95
96
97
98
99
        return $this->getGroupsForUser($user);
    }

    /**
     * @param string $userId
     * @return string[]
     * @throws \Source\Exceptions\EntityNotFoundException
     */
    protected function getGroupsForUser(string $userId): array
    {
        return static::groupNames($this->groupUserRepository->getGroupsForUser($userId));
100
101
102
103
104
105
106
107
108
109
    }

    /**
     * @param \Source\Entities\Group[] $groups
     * @return string[]
     */
    protected static function groupNames(array $groups): array
    {
        $groupNames = [];

110
        foreach ($groups as $group) {
111
            $groupNames[] = $group->getTitle();
112
113
        }

114
        return $groupNames;
115
116
117
118
119
    }

    /**
     * @inheritDoc
     */
120
    public function protectOne(array $permissions): void
121
    {
122
        if (!$this->allowsOne($permissions)) {
123
124
125
126
127
128
129
            throw new AuthorizationException();
        }
    }

    /**
     * @inheritDoc
     */
130
    public function allowsOne(array $permissions): bool
131
    {
132
133
134
135
        $groups = $this->getGroupsForCurrentUser();

        if (in_array(Permissions::ADMIN, $groups, true)) {
            return true;
136
        }
137
138
139
140
141
142
143
144

        foreach ($groups as $group) {
            if (in_array($group, $permissions, true)) {
                return true;
            }
        }

        return false;
145
    }
Jacob Priddy's avatar
Jacob Priddy committed
146
147
148
149
150
151
152
153
154
155
156
157
158
159

    /**
     * @inheritDoc
     */
    public function protect(string $permission): void
    {
        $this->protectAll([$permission]);
    }

    /**
     * @inheritDoc
     */
    public function protectAdminRights(string $userId, ?string $groupId = null): void
    {
160
        $user = $this->users->get($userId);
Jacob Priddy's avatar
Jacob Priddy committed
161
162
163
164
165
166
167
168
169
170
171
172
173

        if (!$user) {
            throw new EntityNotFoundException('User not found.');
        }

        $groups = $this->getGroupsForUser($userId);

        // Only admins have access to other admins
        if (in_array(Permissions::ADMIN, $groups, true)) {
            $this->protect(Permissions::ADMIN);
        }

        if ($groupId) {
174
            $group = $this->groups->get($groupId);
Jacob Priddy's avatar
Jacob Priddy committed
175
176
177
178
179
180
181
182
183
184
185
186
187
            if (!$group) {
                throw new EntityNotFoundException('Group not found.');
            }
            // Only admins can create or remove other admins
            if ($group->hasTitleOf(Permissions::ADMIN)) {
                $this->protect(Permissions::ADMIN);
            }
        }

        if ($user->hasFirstNameOf('admin')) {
            throw new AuthorizationException('You cannot modify the admin user.');
        }
    }
188
}