Completed
Push — master ( 197387...875417 )
by Damian
11s
created

LDAPMemberExtension   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 214
Duplicated Lines 11.68 %

Coupling/Cohesion

Components 1
Dependencies 9

Importance

Changes 0
Metric Value
wmc 27
lcom 1
cbo 9
dl 25
loc 214
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
B updateCMSFields() 0 56 8
A validate() 0 17 4
B onBeforeWrite() 0 13 5
A onAfterWrite() 13 13 4
A onAfterDelete() 12 12 4
A memberLoggedIn() 0 8 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace SilverStripe\ActiveDirectory\Extensions;
4
5
use SilverStripe\Core\Injector\Injector;
6
use SilverStripe\Forms\FieldList;
7
use SilverStripe\Forms\LiteralField;
8
use SilverStripe\Forms\ReadonlyField;
9
use SilverStripe\ORM\DataExtension;
10
use SilverStripe\ORM\ValidationResult;
11
use SilverStripe\ORM\ValidationException;
12
13
/**
14
 * Class LDAPMemberExtension.
15
 *
16
 * Adds mappings from AD attributes to SilverStripe {@link Member} fields.
17
 *
18
 * @package activedirectory
19
 */
20
class LDAPMemberExtension extends DataExtension
21
{
22
    /**
23
     * @var array
24
     */
25
    private static $db = [
0 ignored issues
show
Unused Code introduced by
The property $db is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
26
        // Unique user identifier, same field is used by SAMLMemberExtension
27
        'GUID' => 'Varchar(50)',
28
        'Username' => 'Varchar(64)',
29
        'IsExpired' => 'Boolean',
30
        'LastSynced' => 'DBDatetime',
31
    ];
32
33
    /**
34
     * These fields are used by {@link LDAPMemberSync} to map specific AD attributes
35
     * to {@link Member} fields.
36
     *
37
     * @var array
38
     * @config
39
     */
40
    private static $ldap_field_mappings = [
0 ignored issues
show
Unused Code introduced by
The property $ldap_field_mappings is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
41
        'givenname' => 'FirstName',
42
        'samaccountname' => 'Username',
43
        'sn' => 'Surname',
44
        'mail' => 'Email',
45
    ];
46
47
    /**
48
     * The location (relative to /assets) where to save thumbnailphoto data.
49
     *
50
     * @var string
51
     * @config
52
     */
53
    private static $ldap_thumbnail_path = 'Uploads';
0 ignored issues
show
Unused Code introduced by
The property $ldap_thumbnail_path is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
54
55
    /**
56
     * When enabled, LDAP managed Member records (GUID flag)
57
     * have their data written back to LDAP on write.
58
     *
59
     * This requires setting write permissions on the user configured in the LDAP
60
     * credentials, which is why this is disabled by default.
61
     *
62
     * @var bool
63
     * @config
64
     */
65
    private static $update_ldap_from_local = false;
0 ignored issues
show
Unused Code introduced by
The property $update_ldap_from_local is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
66
67
    /**
68
     * If enabled, Member records with a Username field have the user created in LDAP
69
     * on write.
70
     *
71
     * This requires setting write permissions on the user configured in the LDAP
72
     * credentials, which is why this is disabled by default.
73
     *
74
     * @var bool
75
     * @config
76
     */
77
    private static $create_users_in_ldap = false;
0 ignored issues
show
Unused Code introduced by
The property $create_users_in_ldap is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
78
79
    /**
80
     * If enabled, deleting Member records mapped to LDAP deletes the LDAP user.
81
     *
82
     * This requires setting write permissions on the user configured in the LDAP
83
     * credentials, which is why this is disabled by default.
84
     *
85
     * @var bool
86
     * @config
87
     */
88
    private static $delete_users_in_ldap = false;
0 ignored issues
show
Unused Code introduced by
The property $delete_users_in_ldap is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
89
90
    /**
91
     * @param FieldList $fields
92
     */
93
    public function updateCMSFields(FieldList $fields)
94
    {
95
        // Redo LDAP metadata fields as read-only and move to LDAP tab.
96
        $ldapMetadata = [];
97
        $fields->replaceField('GUID', $ldapMetadata[] = ReadonlyField::create('GUID'));
98
        $fields->replaceField(
99
            'IsExpired',
100
            $ldapMetadata[] = ReadonlyField::create(
101
                'IsExpired',
102
                _t('LDAPMemberExtension.ISEXPIRED', 'Has user\'s LDAP/AD login expired?')
103
            )
104
        );
105
        $fields->replaceField(
106
            'LastSynced',
107
            $ldapMetadata[] = ReadonlyField::create(
108
                'LastSynced',
109
                _t('LDAPMemberExtension.LASTSYNCED', 'Last synced')
110
            )
111
        );
112
        $fields->addFieldsToTab('Root.LDAP', $ldapMetadata);
113
114
        $message = '';
115
        if ($this->owner->GUID && $this->owner->config()->update_ldap_from_local) {
116
            $message = _t(
117
                'LDAPMemberExtension.CHANGEFIELDSUPDATELDAP',
118
                'Changing fields here will update them in LDAP.'
119
            );
120
        } elseif ($this->owner->GUID && !$this->owner->config()->update_ldap_from_local) {
121
            // Transform the automatically mapped fields into read-only. This doesn't
122
            // apply if updating LDAP from local is enabled, as changing data locally can be written back.
123
            foreach ($this->owner->config()->ldap_field_mappings as $name) {
124
                $field = $fields->dataFieldByName($name);
125
                if (!empty($field)) {
126
                    // Set to readonly, but not disabled so that the data is still sent to the
127
                    // server and doesn't break Member_Validator
128
                    $field->setReadonly(true);
129
                    $field->setTitle($field->Title()._t('LDAPMemberExtension.IMPORTEDFIELD', ' (imported)'));
130
                }
131
            }
132
            $message = _t(
133
                'LDAPMemberExtension.INFOIMPORTED',
134
                'This user is automatically imported from LDAP. '.
135
                    'Manual changes to imported fields will be removed upon sync.'
136
            );
137
        }
138
        if ($message) {
139
            $fields->addFieldToTab(
140
                'Root.Main',
141
                LiteralField::create(
142
                    'Info',
143
                    sprintf('<p class="message warning">%s</p>', $message)
144
                ),
145
                'FirstName'
146
            );
147
        }
148
    }
149
150
    /**
151
     * @param  ValidationResult
152
     * @throws ValidationException
153
     */
154
    public function validate(ValidationResult $validationResult)
155
    {
156
        // We allow empty Username for registration purposes, as we need to
157
        // create Member records with empty Username temporarily. Forms should explicitly
158
        // check for Username not being empty if they require it not to be.
159
        if (empty($this->owner->Username) || !$this->owner->config()->create_users_in_ldap) {
160
            return;
161
        }
162
163
        if (!preg_match('/^[a-z0-9\.]+$/', $this->owner->Username)) {
164
            $validationResult->addError(
165
                'Username must only contain lowercase alphanumeric characters and dots.',
166
                'bad'
167
            );
168
            throw new ValidationException($validationResult);
169
        }
170
    }
171
172
    /**
173
     * Create the user in LDAP, provided this configuration is enabled
174
     * and a username was passed to a new Member record.
175
     */
176
    public function onBeforeWrite()
177
    {
178
        $service = Injector::inst()->get('SilverStripe\\ActiveDirectory\\Services\\LDAPService');
179
        if (!$service->enabled()
180
            || !$this->owner->config()->create_users_in_ldap
181
            || !$this->owner->Username
182
            || $this->owner->GUID
183
        ) {
184
            return;
185
        }
186
187
        $service->createLDAPUser($this->owner);
188
    }
189
190
    /**
191
     * Update the local data with LDAP, and ensure local membership is also set in
192
     * LDAP too. This writes into LDAP, provided that feature is enabled.
193
     */
194 View Code Duplication
    public function onAfterWrite()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
195
    {
196
        $service = Injector::inst()->get('SilverStripe\\ActiveDirectory\\Services\\LDAPService');
197
        if (!$service->enabled()
198
            || !$this->owner->config()->update_ldap_from_local
199
            || !$this->owner->GUID
200
        ) {
201
            return;
202
        }
203
204
        $service->updateLDAPFromMember($this->owner);
205
        $service->updateLDAPGroupsForMember($this->owner);
206
    }
207
208 View Code Duplication
    public function onAfterDelete()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
209
    {
210
        $service = Injector::inst()->get('SilverStripe\\ActiveDirectory\\Services\\LDAPService');
211
        if (!$service->enabled()
212
            || !$this->owner->config()->delete_users_in_ldap
213
            || !$this->owner->GUID
214
        ) {
215
            return;
216
        }
217
218
        $service->deleteLDAPMember($this->owner);
219
    }
220
221
    /**
222
     * Triggered by {@link Member::logIn()} when successfully logged in,
223
     * this will update the Member record from AD data.
224
     */
225
    public function memberLoggedIn()
226
    {
227
        if ($this->owner->GUID) {
228
            Injector::inst()
229
                ->get('SilverStripe\\ActiveDirectory\\Services\\LDAPService')
230
                ->updateMemberFromLDAP($this->owner);
231
        }
232
    }
233
}
234