Passed
Push — master ( 690dfa...8b5d92 )
by Marcel
08:38
created

UserCreator   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 142
Duplicated Lines 0 %

Test Coverage

Coverage 12.07%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 63
c 2
b 0
f 0
dl 0
loc 142
ccs 7
cts 58
cp 0.1207
rs 10
wmc 17

6 Methods

Rating   Name   Duplication   Size   Complexity  
B createUser() 0 50 7
A getTargetUserType() 0 10 2
A __construct() 0 8 1
A getGrade() 0 10 2
A canCreateUser() 0 3 1
A initialize() 0 14 4
1
<?php
2
3
namespace App\Security;
4
5
use App\ActiveDirectory\OptionResolver;
6
use App\Entity\ActiveDirectoryGradeSyncOption;
7
use App\Entity\ActiveDirectoryRoleSyncOption;
8
use App\Entity\ActiveDirectorySyncOption;
9
use App\Entity\ActiveDirectoryUser;
10
use App\Entity\UserType;
11
use App\Repository\ActiveDirectoryGradeSyncOptionRepositoryInterface;
12
use App\Repository\ActiveDirectoryRoleSyncOptionRepositoryInterface;
13
use App\Repository\ActiveDirectorySyncOptionRepositoryInterface;
14
use App\Repository\UserRepositoryInterface;
15
use Ramsey\Uuid\Uuid;
16
17
/**
18
 * Helper which creates users after successful Active Directory authentication.
19
 */
20
class UserCreator {
21
    /** @var ActiveDirectorySyncOption[] */
22
    private ?array $syncOptions = null;
23
24
    /** @var ActiveDirectoryGradeSyncOption[] */
25
    private ?array $gradeSyncOptions = null;
26
27
    /** @var ActiveDirectoryRoleSyncOption[] */
28
    private ?array $roleSyncOptions = null;
29
30
    private OptionResolver $optionsResolver;
31
32
    private ActiveDirectorySyncOptionRepositoryInterface $syncOptionRepository;
33
    private ActiveDirectoryGradeSyncOptionRepositoryInterface $gradeSyncOptionRepository;
34
    private ActiveDirectoryRoleSyncOptionRepositoryInterface $roleSyncOptionRepository;
35
    private UserRepositoryInterface $userRepository;
36
37
    public function __construct(ActiveDirectorySyncOptionRepositoryInterface $syncOptionRepository,
38
                                ActiveDirectoryGradeSyncOptionRepositoryInterface $gradeSyncOptionRepository,
39
                                ActiveDirectoryRoleSyncOptionRepositoryInterface $roleSyncOptionRepository, OptionResolver $optionResolver, UserRepositoryInterface $userRepository) {
40
        $this->syncOptionRepository = $syncOptionRepository;
41
        $this->gradeSyncOptionRepository = $gradeSyncOptionRepository;
42
        $this->roleSyncOptionRepository = $roleSyncOptionRepository;
43
        $this->optionsResolver = $optionResolver;
44
        $this->userRepository = $userRepository;
45 11
    }
46
47
    private function initialize(): void {
48 11
        if ($this->syncOptions === null) {
49 11
            $this->syncOptions = $this->syncOptionRepository
50 11
                ->findAll();
51 11
        }
52 11
53 11
        if ($this->gradeSyncOptions === null) {
54
            $this->gradeSyncOptions = $this->gradeSyncOptionRepository
55
                ->findAll();
56
        }
57
58
        if($this->roleSyncOptions === null) {
59
            $this->roleSyncOptions = $this->roleSyncOptionRepository
60
                ->findAll();
61
        }
62
    }
63
64
    /**
65
     * Determines whether the user can be imported from Active Directory.
66
     *
67
     * @param ActiveDirectoryUserInformation $response
68
     * @return bool
69
     */
70
    public function canCreateUser(ActiveDirectoryUserInformation $response): bool {
71
        $this->initialize();
72
        return $this->getTargetUserType($response) !== null;
73
    }
74
75
    /**
76
     * @param ActiveDirectoryUserInformation $response
77
     * @return UserType|null
78
     */
79
    private function getTargetUserType(ActiveDirectoryUserInformation $response): ?UserType {
80
        /** @var ActiveDirectorySyncOption|null $option */
81
        $option = $this->optionsResolver
82
            ->getOption($this->syncOptions, $response->getOu(), $response->getGroups());
0 ignored issues
show
Bug introduced by
It seems like $this->syncOptions can also be of type null; however, parameter $options of App\ActiveDirectory\OptionResolver::getOption() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

82
            ->getOption(/** @scrutinizer ignore-type */ $this->syncOptions, $response->getOu(), $response->getGroups());
Loading history...
83
84
        if ($option !== null) {
85
            return $option->getUserType();
86
        }
87
88
        return null;
89
    }
90
91
    /**
92
     * @param ActiveDirectoryUserInformation $response
93
     * @param ActiveDirectoryUser|null $user Already existing AD user
94
     * @return ActiveDirectoryUser
95
     */
96
    public function createUser(ActiveDirectoryUserInformation $response, ?ActiveDirectoryUser $user = null): ?ActiveDirectoryUser {
97
        $this->initialize();
98
99
        if ($user === null) {
100
            // Try to find already existing user by GUID (because username has changed)
101
            $user = $this->userRepository->findActiveDirectoryUserByObjectGuid($response->getGuid());
102
103
            if($user === null) {
104
                $user = new ActiveDirectoryUser();
105
                $user->setObjectGuid(Uuid::fromString($response->getGuid()));
106
            }
107
        }
108
109
        $user->setUsername(mb_strtolower($response->getUserPrincipalName()));
110
        $user->setFirstname($response->getFirstname());
111
        $user->setLastname($response->getLastname());
112
        $user->setGrade($this->getGrade($response));
113
        $user->setUserPrincipalName(mb_strtolower($response->getUserPrincipalName()));
114
        $user->setType($this->getTargetUserType($response));
0 ignored issues
show
Bug introduced by
It seems like $this->getTargetUserType($response) can also be of type null; however, parameter $userType of App\Entity\User::setType() does only seem to accept App\Entity\UserType, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

114
        $user->setType(/** @scrutinizer ignore-type */ $this->getTargetUserType($response));
Loading history...
115
        $user->setEmail($response->getEmail());
116
        $user->setExternalId($response->getUniqueId());
117
118
        $user->setOu($response->getOu());
119
        $user->setGroups($response->getGroups());
120
121
        // Set roles
122
123
        /** @var ActiveDirectoryRoleSyncOption[] $options */
124
        $options = $this->optionsResolver->getAllOptions(
125
            $this->roleSyncOptions,
0 ignored issues
show
Bug introduced by
It seems like $this->roleSyncOptions can also be of type null; however, parameter $options of App\ActiveDirectory\Opti...solver::getAllOptions() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

125
            /** @scrutinizer ignore-type */ $this->roleSyncOptions,
Loading history...
126
            $response->getOu(),
127
            $response->getGroups()
128
        );
129
130
        foreach($options as $option) {
131
            $role = $option->getUserRole();
132
133
            if($user->getUserRoles()->contains($role) !== true) {
134
                $user->addUserRole($role);
135
            }
136
        }
137
138
        $existingUser = $this->userRepository->findOneByUsername($user->getUserPrincipalName());
139
140
        // Convert user (if necessary)
141
        if($existingUser !== null && !$existingUser instanceof ActiveDirectoryUser) {
142
            $user = $this->userRepository->convertToActiveDirectory($existingUser, $user);
143
        }
144
145
        return $user;
146
    }
147
148
    /**
149
     * @param ActiveDirectoryUserInformation $response
150
     * @return string|null
151
     */
152
    private function getGrade(ActiveDirectoryUserInformation $response): ?string {
153
        /** @var ActiveDirectoryGradeSyncOption|null $option */
154
        $option = $this->optionsResolver
155
            ->getOption($this->gradeSyncOptions, $response->getOu(), $response->getGroups());
0 ignored issues
show
Bug introduced by
It seems like $this->gradeSyncOptions can also be of type null; however, parameter $options of App\ActiveDirectory\OptionResolver::getOption() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

155
            ->getOption(/** @scrutinizer ignore-type */ $this->gradeSyncOptions, $response->getOu(), $response->getGroups());
Loading history...
156
157
        if($option !== null) {
158
            return $option->getGrade();
159
        }
160
161
        return null;
162
    }
163
}