UserCreator::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 0
c 2
b 0
f 0
nc 1
nop 5
dl 0
loc 2
ccs 0
cts 0
cp 0
crap 2
rs 10
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
    public function __construct(private ActiveDirectorySyncOptionRepositoryInterface $syncOptionRepository, private ActiveDirectoryGradeSyncOptionRepositoryInterface $gradeSyncOptionRepository, private ActiveDirectoryRoleSyncOptionRepositoryInterface $roleSyncOptionRepository, private OptionResolver $optionsResolver, private UserRepositoryInterface $userRepository)
31
    {
32
    }
33
34
    private function initialize(): void {
35
        if ($this->syncOptions === null) {
36
            $this->syncOptions = $this->syncOptionRepository
37
                ->findAll();
38
        }
39
40
        if ($this->gradeSyncOptions === null) {
41
            $this->gradeSyncOptions = $this->gradeSyncOptionRepository
42
                ->findAll();
43
        }
44
45 11
        if($this->roleSyncOptions === null) {
46
            $this->roleSyncOptions = $this->roleSyncOptionRepository
47
                ->findAll();
48 11
        }
49 11
    }
50 11
51 11
    /**
52 11
     * Determines whether the user can be imported from Active Directory.
53 11
     */
54
    public function canCreateUser(ActiveDirectoryUserInformation $response): bool {
55
        $this->initialize();
56
        return $this->getTargetUserType($response) !== null;
57
    }
58
59
    private function getTargetUserType(ActiveDirectoryUserInformation $response): ?UserType {
60
        /** @var ActiveDirectorySyncOption|null $option */
61
        $option = $this->optionsResolver
62
            ->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

62
            ->getOption(/** @scrutinizer ignore-type */ $this->syncOptions, $response->getOu(), $response->getGroups());
Loading history...
63
64
        if ($option !== null) {
65
            return $option->getUserType();
66
        }
67
68
        return null;
69
    }
70
71
    /**
72
     * @param ActiveDirectoryUser|null $user Already existing AD user
73
     * @return ActiveDirectoryUser
74
     */
75
    public function createUser(ActiveDirectoryUserInformation $response, ?ActiveDirectoryUser $user = null): ?ActiveDirectoryUser {
76
        $this->initialize();
77
78
        if ($user === null) {
79
            // Try to find already existing user by GUID (because username has changed)
80
            $user = $this->userRepository->findActiveDirectoryUserByObjectGuid($response->getGuid());
81
82
            if($user === null) {
83
                $user = new ActiveDirectoryUser();
84
                $user->setObjectGuid(Uuid::fromString($response->getGuid()));
85
            }
86
        }
87
88
        $user->setUsername(mb_strtolower($response->getUserPrincipalName()));
89
        $user->setFirstname($response->getFirstname());
90
        $user->setLastname($response->getLastname());
91
        $user->setGrade($this->getGrade($response));
92
        $user->setUserPrincipalName(mb_strtolower($response->getUserPrincipalName()));
93
        $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

93
        $user->setType(/** @scrutinizer ignore-type */ $this->getTargetUserType($response));
Loading history...
94
        $user->setEmail($response->getEmail());
95
        $user->setExternalId($response->getUniqueId());
96
97
        $user->setOu($response->getOu());
98
        $user->setGroups($response->getGroups());
99
100
        // Set roles
101
102
        /** @var ActiveDirectoryRoleSyncOption[] $options */
103
        $options = $this->optionsResolver->getAllOptions(
104
            $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

104
            /** @scrutinizer ignore-type */ $this->roleSyncOptions,
Loading history...
105
            $response->getOu(),
106
            $response->getGroups()
107
        );
108
109
        foreach($options as $option) {
110
            $role = $option->getUserRole();
111
112
            if($user->getUserRoles()->contains($role) !== true) {
113
                $user->addUserRole($role);
114
            }
115
        }
116
117
        $existingUser = $this->userRepository->findOneByUsername($user->getUserPrincipalName());
118
119
        // Convert user (if necessary)
120
        if($existingUser !== null && !$existingUser instanceof ActiveDirectoryUser) {
121
            $user = $this->userRepository->convertToActiveDirectory($existingUser, $user);
122
        }
123
124
        return $user;
125
    }
126
127
    private function getGrade(ActiveDirectoryUserInformation $response): ?string {
128
        /** @var ActiveDirectoryGradeSyncOption|null $option */
129
        $option = $this->optionsResolver
130
            ->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

130
            ->getOption(/** @scrutinizer ignore-type */ $this->gradeSyncOptions, $response->getOu(), $response->getGroups());
Loading history...
131
132
        if($option !== null) {
133
            return $option->getGrade();
134
        }
135
136
        return null;
137
    }
138
}