Passed
Push — master ( 5cdc85...37718d )
by Morris
38:53 queued 21:57
created

Configuration::saveConfiguration()   D

Complexity

Conditions 19
Paths 49

Size

Total Lines 36
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 19
eloc 30
nc 49
nop 0
dl 0
loc 36
rs 4.5166
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Alex Weirig <[email protected]>
6
 * @author Alexander Bergolth <[email protected]>
7
 * @author Arthur Schiwon <[email protected]>
8
 * @author Joas Schilling <[email protected]>
9
 * @author Jörn Friedrich Dreyer <[email protected]>
10
 * @author Lennart Rosam <[email protected]>
11
 * @author Lukas Reschke <[email protected]>
12
 * @author Morris Jobke <[email protected]>
13
 * @author Robin McCorkell <[email protected]>
14
 * @author Roger Szabo <[email protected]>
15
 * @author Victor Dubiniuk <[email protected]>
16
 * @author Xuanwo <[email protected]>
17
 *
18
 * @license AGPL-3.0
19
 *
20
 * This code is free software: you can redistribute it and/or modify
21
 * it under the terms of the GNU Affero General Public License, version 3,
22
 * as published by the Free Software Foundation.
23
 *
24
 * This program is distributed in the hope that it will be useful,
25
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27
 * GNU Affero General Public License for more details.
28
 *
29
 * You should have received a copy of the GNU Affero General Public License, version 3,
30
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
31
 *
32
 */
33
34
namespace OCA\User_LDAP;
35
36
/**
37
 * @property int ldapPagingSize holds an integer
38
 * @property string ldapUserAvatarRule
39
 */
40
class Configuration {
41
	const AVATAR_PREFIX_DEFAULT = 'default';
42
	const AVATAR_PREFIX_NONE = 'none';
43
	const AVATAR_PREFIX_DATA_ATTRIBUTE = 'data:';
44
45
	protected $configPrefix = null;
46
	protected $configRead = false;
47
	/**
48
	 * @var string[] pre-filled with one reference key so that at least one entry is written on save request and
49
	 *               the config ID is registered
50
	 */
51
	protected $unsavedChanges = ['ldapConfigurationActive' => 'ldapConfigurationActive'];
52
53
	//settings
54
	protected $config = array(
55
		'ldapHost' => null,
56
		'ldapPort' => null,
57
		'ldapBackupHost' => null,
58
		'ldapBackupPort' => null,
59
		'ldapBase' => null,
60
		'ldapBaseUsers' => null,
61
		'ldapBaseGroups' => null,
62
		'ldapAgentName' => null,
63
		'ldapAgentPassword' => null,
64
		'ldapTLS' => null,
65
		'turnOffCertCheck' => null,
66
		'ldapIgnoreNamingRules' => null,
67
		'ldapUserDisplayName' => null,
68
		'ldapUserDisplayName2' => null,
69
		'ldapUserAvatarRule' => null,
70
		'ldapGidNumber' => null,
71
		'ldapUserFilterObjectclass' => null,
72
		'ldapUserFilterGroups' => null,
73
		'ldapUserFilter' => null,
74
		'ldapUserFilterMode' => null,
75
		'ldapGroupFilter' => null,
76
		'ldapGroupFilterMode' => null,
77
		'ldapGroupFilterObjectclass' => null,
78
		'ldapGroupFilterGroups' => null,
79
		'ldapGroupDisplayName' => null,
80
		'ldapGroupMemberAssocAttr' => null,
81
		'ldapLoginFilter' => null,
82
		'ldapLoginFilterMode' => null,
83
		'ldapLoginFilterEmail' => null,
84
		'ldapLoginFilterUsername' => null,
85
		'ldapLoginFilterAttributes' => null,
86
		'ldapQuotaAttribute' => null,
87
		'ldapQuotaDefault' => null,
88
		'ldapEmailAttribute' => null,
89
		'ldapCacheTTL' => null,
90
		'ldapUuidUserAttribute' => 'auto',
91
		'ldapUuidGroupAttribute' => 'auto',
92
		'ldapOverrideMainServer' => false,
93
		'ldapConfigurationActive' => false,
94
		'ldapAttributesForUserSearch' => null,
95
		'ldapAttributesForGroupSearch' => null,
96
		'ldapExperiencedAdmin' => false,
97
		'homeFolderNamingRule' => null,
98
		'hasPagedResultSupport' => false,
99
		'hasMemberOfFilterSupport' => false,
100
		'useMemberOfToDetectMembership' => true,
101
		'ldapExpertUsernameAttr' => null,
102
		'ldapExpertUUIDUserAttr' => null,
103
		'ldapExpertUUIDGroupAttr' => null,
104
		'lastJpegPhotoLookup' => null,
105
		'ldapNestedGroups' => false,
106
		'ldapPagingSize' => null,
107
		'turnOnPasswordChange' => false,
108
		'ldapDynamicGroupMemberURL' => null,
109
		'ldapDefaultPPolicyDN' => null,
110
	);
111
112
	/**
113
	 * @param string $configPrefix
114
	 * @param bool $autoRead
115
	 */
116
	public function __construct($configPrefix, $autoRead = true) {
117
		$this->configPrefix = $configPrefix;
118
		if($autoRead) {
119
			$this->readConfiguration();
120
		}
121
	}
122
123
	/**
124
	 * @param string $name
125
	 * @return mixed|null
126
	 */
127
	public function __get($name) {
128
		if(isset($this->config[$name])) {
129
			return $this->config[$name];
130
		}
131
		return null;
132
	}
133
134
	/**
135
	 * @param string $name
136
	 * @param mixed $value
137
	 */
138
	public function __set($name, $value) {
139
		$this->setConfiguration(array($name => $value));
140
	}
141
142
	/**
143
	 * @return array
144
	 */
145
	public function getConfiguration() {
146
		return $this->config;
147
	}
148
149
	/**
150
	 * set LDAP configuration with values delivered by an array, not read
151
	 * from configuration. It does not save the configuration! To do so, you
152
	 * must call saveConfiguration afterwards.
153
	 * @param array $config array that holds the config parameters in an associated
154
	 * array
155
	 * @param array &$applied optional; array where the set fields will be given to
156
	 * @return false|null
157
	 */
158
	public function setConfiguration($config, &$applied = null) {
159
		if(!is_array($config)) {
0 ignored issues
show
introduced by
The condition is_array($config) is always true.
Loading history...
160
			return false;
161
		}
162
163
		$cta = $this->getConfigTranslationArray();
164
		foreach($config as $inputKey => $val) {
165
			if(strpos($inputKey, '_') !== false && array_key_exists($inputKey, $cta)) {
166
				$key = $cta[$inputKey];
167
			} elseif(array_key_exists($inputKey, $this->config)) {
168
				$key = $inputKey;
169
			} else {
170
				continue;
171
			}
172
173
			$setMethod = 'setValue';
174
			switch($key) {
175
				case 'ldapAgentPassword':
176
					$setMethod = 'setRawValue';
177
					break;
178
				case 'homeFolderNamingRule':
179
					$trimmedVal = trim($val);
180
					if ($trimmedVal !== '' && strpos($val, 'attr:') === false) {
181
						$val = 'attr:'.$trimmedVal;
182
					}
183
					break;
184
				case 'ldapBase':
185
				case 'ldapBaseUsers':
186
				case 'ldapBaseGroups':
187
				case 'ldapAttributesForUserSearch':
188
				case 'ldapAttributesForGroupSearch':
189
				case 'ldapUserFilterObjectclass':
190
				case 'ldapUserFilterGroups':
191
				case 'ldapGroupFilterObjectclass':
192
				case 'ldapGroupFilterGroups':
193
				case 'ldapLoginFilterAttributes':
194
					$setMethod = 'setMultiLine';
195
					break;
196
			}
197
			$this->$setMethod($key, $val);
198
			if(is_array($applied)) {
199
				$applied[] = $inputKey;
200
				// storing key as index avoids duplication, and as value for simplicity
201
			}
202
			$this->unsavedChanges[$key] = $key;
203
		}
204
		return null;
205
	}
206
207
	public function readConfiguration() {
208
		if(!$this->configRead && !is_null($this->configPrefix)) {
209
			$cta = array_flip($this->getConfigTranslationArray());
210
			foreach($this->config as $key => $val) {
211
				if(!isset($cta[$key])) {
212
					//some are determined
213
					continue;
214
				}
215
				$dbKey = $cta[$key];
216
				switch($key) {
217
					case 'ldapBase':
218
					case 'ldapBaseUsers':
219
					case 'ldapBaseGroups':
220
					case 'ldapAttributesForUserSearch':
221
					case 'ldapAttributesForGroupSearch':
222
					case 'ldapUserFilterObjectclass':
223
					case 'ldapUserFilterGroups':
224
					case 'ldapGroupFilterObjectclass':
225
					case 'ldapGroupFilterGroups':
226
					case 'ldapLoginFilterAttributes':
227
						$readMethod = 'getMultiLine';
228
						break;
229
					case 'ldapIgnoreNamingRules':
230
						$readMethod = 'getSystemValue';
231
						$dbKey = $key;
232
						break;
233
					case 'ldapAgentPassword':
234
						$readMethod = 'getPwd';
235
						break;
236
					case 'ldapUserDisplayName2':
237
					case 'ldapGroupDisplayName':
238
						$readMethod = 'getLcValue';
239
						break;
240
					case 'ldapUserDisplayName':
241
					default:
242
						// user display name does not lower case because
243
						// we rely on an upper case N as indicator whether to
244
						// auto-detect it or not. FIXME
245
						$readMethod = 'getValue';
246
						break;
247
				}
248
				$this->config[$key] = $this->$readMethod($dbKey);
249
			}
250
			$this->configRead = true;
251
		}
252
	}
253
254
	/**
255
	 * saves the current config changes in the database
256
	 */
257
	public function saveConfiguration() {
258
		$cta = array_flip($this->getConfigTranslationArray());
259
		foreach($this->unsavedChanges as $key) {
260
			$value = $this->config[$key];
261
			switch ($key) {
262
				case 'ldapAgentPassword':
263
					$value = base64_encode($value);
264
					break;
265
				case 'ldapBase':
266
				case 'ldapBaseUsers':
267
				case 'ldapBaseGroups':
268
				case 'ldapAttributesForUserSearch':
269
				case 'ldapAttributesForGroupSearch':
270
				case 'ldapUserFilterObjectclass':
271
				case 'ldapUserFilterGroups':
272
				case 'ldapGroupFilterObjectclass':
273
				case 'ldapGroupFilterGroups':
274
				case 'ldapLoginFilterAttributes':
275
					if(is_array($value)) {
276
						$value = implode("\n", $value);
277
					}
278
					break;
279
				//following options are not stored but detected, skip them
280
				case 'ldapIgnoreNamingRules':
281
				case 'hasPagedResultSupport':
282
				case 'ldapUuidUserAttribute':
283
				case 'ldapUuidGroupAttribute':
284
					continue 2;
285
			}
286
			if(is_null($value)) {
287
				$value = '';
288
			}
289
			$this->saveValue($cta[$key], $value);
290
		}
291
		$this->saveValue('_lastChange', time());
292
		$this->unsavedChanges = [];
293
	}
294
295
	/**
296
	 * @param string $varName
297
	 * @return array|string
298
	 */
299
	protected function getMultiLine($varName) {
300
		$value = $this->getValue($varName);
301
		if(empty($value)) {
302
			$value = '';
303
		} else {
304
			$value = preg_split('/\r\n|\r|\n/', $value);
305
		}
306
307
		return $value;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $value could also return false which is incompatible with the documented return type array|string. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
308
	}
309
310
	/**
311
	 * Sets multi-line values as arrays
312
	 * 
313
	 * @param string $varName name of config-key
314
	 * @param array|string $value to set
315
	 */
316
	protected function setMultiLine($varName, $value) {
317
		if(empty($value)) {
318
			$value = '';
319
		} else if (!is_array($value)) {
320
			$value = preg_split('/\r\n|\r|\n|;/', $value);
321
			if($value === false) {
322
				$value = '';
323
			}
324
		}
325
326
		if(!is_array($value)) {
327
			$finalValue = trim($value);
328
		} else {
329
			$finalValue = [];
330
			foreach($value as $key => $val) {
331
				if(is_string($val)) {
332
					$val = trim($val);
333
					if ($val !== '') {
334
						//accidental line breaks are not wanted and can cause
335
						// odd behaviour. Thus, away with them.
336
						$finalValue[] = $val;
337
					}
338
				} else {
339
					$finalValue[] = $val;
340
				}
341
			}
342
		}
343
344
		$this->setRawValue($varName, $finalValue);
345
	}
346
347
	/**
348
	 * @param string $varName
349
	 * @return string
350
	 */
351
	protected function getPwd($varName) {
352
		return base64_decode($this->getValue($varName));
353
	}
354
355
	/**
356
	 * @param string $varName
357
	 * @return string
358
	 */
359
	protected function getLcValue($varName) {
360
		return mb_strtolower($this->getValue($varName), 'UTF-8');
361
	}
362
363
	/**
364
	 * @param string $varName
365
	 * @return string
366
	 */
367
	protected function getSystemValue($varName) {
368
		//FIXME: if another system value is added, softcode the default value
369
		return \OC::$server->getConfig()->getSystemValue($varName, false);
370
	}
371
372
	/**
373
	 * @param string $varName
374
	 * @return string
375
	 */
376
	protected function getValue($varName) {
377
		static $defaults;
378
		if(is_null($defaults)) {
379
			$defaults = $this->getDefaults();
380
		}
381
		return \OC::$server->getConfig()->getAppValue('user_ldap',
382
										$this->configPrefix.$varName,
383
										$defaults[$varName]);
384
	}
385
386
	/**
387
	 * Sets a scalar value.
388
	 * 
389
	 * @param string $varName name of config key
390
	 * @param mixed $value to set
391
	 */
392
	protected function setValue($varName, $value) {
393
		if(is_string($value)) {
394
			$value = trim($value);
395
		}
396
		$this->config[$varName] = $value;
397
	}
398
399
	/**
400
	 * Sets a scalar value without trimming.
401
	 *
402
	 * @param string $varName name of config key
403
	 * @param mixed $value to set
404
	 */
405
	protected function setRawValue($varName, $value) {
406
		$this->config[$varName] = $value;
407
	}
408
409
	/**
410
	 * @param string $varName
411
	 * @param string $value
412
	 * @return bool
413
	 */
414
	protected function saveValue($varName, $value) {
415
		\OC::$server->getConfig()->setAppValue(
416
			'user_ldap',
417
			$this->configPrefix.$varName,
418
			$value
419
		);
420
		return true;
421
	}
422
423
	/**
424
	 * @return array an associative array with the default values. Keys are correspond
425
	 * to config-value entries in the database table
426
	 */
427
	public function getDefaults() {
428
		return array(
429
			'ldap_host'                         => '',
430
			'ldap_port'                         => '',
431
			'ldap_backup_host'                  => '',
432
			'ldap_backup_port'                  => '',
433
			'ldap_override_main_server'         => '',
434
			'ldap_dn'                           => '',
435
			'ldap_agent_password'               => '',
436
			'ldap_base'                         => '',
437
			'ldap_base_users'                   => '',
438
			'ldap_base_groups'                  => '',
439
			'ldap_userlist_filter'              => '',
440
			'ldap_user_filter_mode'             => 0,
441
			'ldap_userfilter_objectclass'       => '',
442
			'ldap_userfilter_groups'            => '',
443
			'ldap_login_filter'                 => '',
444
			'ldap_login_filter_mode'            => 0,
445
			'ldap_loginfilter_email'            => 0,
446
			'ldap_loginfilter_username'         => 1,
447
			'ldap_loginfilter_attributes'       => '',
448
			'ldap_group_filter'                 => '',
449
			'ldap_group_filter_mode'            => 0,
450
			'ldap_groupfilter_objectclass'      => '',
451
			'ldap_groupfilter_groups'           => '',
452
			'ldap_gid_number'                   => 'gidNumber',
453
			'ldap_display_name'                 => 'displayName',
454
			'ldap_user_display_name_2'			=> '',
455
			'ldap_group_display_name'           => 'cn',
456
			'ldap_tls'                          => 0,
457
			'ldap_quota_def'                    => '',
458
			'ldap_quota_attr'                   => '',
459
			'ldap_email_attr'                   => '',
460
			'ldap_group_member_assoc_attribute' => 'uniqueMember',
461
			'ldap_cache_ttl'                    => 600,
462
			'ldap_uuid_user_attribute'          => 'auto',
463
			'ldap_uuid_group_attribute'         => 'auto',
464
			'home_folder_naming_rule'           => '',
465
			'ldap_turn_off_cert_check'          => 0,
466
			'ldap_configuration_active'         => 0,
467
			'ldap_attributes_for_user_search'   => '',
468
			'ldap_attributes_for_group_search'  => '',
469
			'ldap_expert_username_attr'         => '',
470
			'ldap_expert_uuid_user_attr'        => '',
471
			'ldap_expert_uuid_group_attr'       => '',
472
			'has_memberof_filter_support'       => 0,
473
			'use_memberof_to_detect_membership' => 1,
474
			'last_jpegPhoto_lookup'             => 0,
475
			'ldap_nested_groups'                => 0,
476
			'ldap_paging_size'                  => 500,
477
			'ldap_turn_on_pwd_change'           => 0,
478
			'ldap_experienced_admin'            => 0,
479
			'ldap_dynamic_group_member_url'     => '',
480
			'ldap_default_ppolicy_dn'           => '',
481
			'ldap_user_avatar_rule'             => 'default',
482
		);
483
	}
484
485
	/**
486
	 * @return array that maps internal variable names to database fields
487
	 */
488
	public function getConfigTranslationArray() {
489
		//TODO: merge them into one representation
490
		static $array = array(
491
			'ldap_host'                         => 'ldapHost',
492
			'ldap_port'                         => 'ldapPort',
493
			'ldap_backup_host'                  => 'ldapBackupHost',
494
			'ldap_backup_port'                  => 'ldapBackupPort',
495
			'ldap_override_main_server'         => 'ldapOverrideMainServer',
496
			'ldap_dn'                           => 'ldapAgentName',
497
			'ldap_agent_password'               => 'ldapAgentPassword',
498
			'ldap_base'                         => 'ldapBase',
499
			'ldap_base_users'                   => 'ldapBaseUsers',
500
			'ldap_base_groups'                  => 'ldapBaseGroups',
501
			'ldap_userfilter_objectclass'       => 'ldapUserFilterObjectclass',
502
			'ldap_userfilter_groups'            => 'ldapUserFilterGroups',
503
			'ldap_userlist_filter'              => 'ldapUserFilter',
504
			'ldap_user_filter_mode'             => 'ldapUserFilterMode',
505
			'ldap_user_avatar_rule'             => 'ldapUserAvatarRule',
506
			'ldap_login_filter'                 => 'ldapLoginFilter',
507
			'ldap_login_filter_mode'            => 'ldapLoginFilterMode',
508
			'ldap_loginfilter_email'            => 'ldapLoginFilterEmail',
509
			'ldap_loginfilter_username'         => 'ldapLoginFilterUsername',
510
			'ldap_loginfilter_attributes'       => 'ldapLoginFilterAttributes',
511
			'ldap_group_filter'                 => 'ldapGroupFilter',
512
			'ldap_group_filter_mode'            => 'ldapGroupFilterMode',
513
			'ldap_groupfilter_objectclass'      => 'ldapGroupFilterObjectclass',
514
			'ldap_groupfilter_groups'           => 'ldapGroupFilterGroups',
515
			'ldap_gid_number'                   => 'ldapGidNumber',
516
			'ldap_display_name'                 => 'ldapUserDisplayName',
517
			'ldap_user_display_name_2'			=> 'ldapUserDisplayName2',
518
			'ldap_group_display_name'           => 'ldapGroupDisplayName',
519
			'ldap_tls'                          => 'ldapTLS',
520
			'ldap_quota_def'                    => 'ldapQuotaDefault',
521
			'ldap_quota_attr'                   => 'ldapQuotaAttribute',
522
			'ldap_email_attr'                   => 'ldapEmailAttribute',
523
			'ldap_group_member_assoc_attribute' => 'ldapGroupMemberAssocAttr',
524
			'ldap_cache_ttl'                    => 'ldapCacheTTL',
525
			'home_folder_naming_rule'           => 'homeFolderNamingRule',
526
			'ldap_turn_off_cert_check'          => 'turnOffCertCheck',
527
			'ldap_configuration_active'         => 'ldapConfigurationActive',
528
			'ldap_attributes_for_user_search'   => 'ldapAttributesForUserSearch',
529
			'ldap_attributes_for_group_search'  => 'ldapAttributesForGroupSearch',
530
			'ldap_expert_username_attr'         => 'ldapExpertUsernameAttr',
531
			'ldap_expert_uuid_user_attr'        => 'ldapExpertUUIDUserAttr',
532
			'ldap_expert_uuid_group_attr'       => 'ldapExpertUUIDGroupAttr',
533
			'has_memberof_filter_support'       => 'hasMemberOfFilterSupport',
534
			'use_memberof_to_detect_membership' => 'useMemberOfToDetectMembership',
535
			'last_jpegPhoto_lookup'             => 'lastJpegPhotoLookup',
536
			'ldap_nested_groups'                => 'ldapNestedGroups',
537
			'ldap_paging_size'                  => 'ldapPagingSize',
538
			'ldap_turn_on_pwd_change'           => 'turnOnPasswordChange',
539
			'ldap_experienced_admin'            => 'ldapExperiencedAdmin',
540
			'ldap_dynamic_group_member_url'     => 'ldapDynamicGroupMemberURL',
541
			'ldap_default_ppolicy_dn'           => 'ldapDefaultPPolicyDN',
542
			'ldapIgnoreNamingRules'             => 'ldapIgnoreNamingRules',	// sysconfig
543
		);
544
		return $array;
545
	}
546
547
	/**
548
	 * @param string $rule
549
	 * @return array
550
	 * @throws \RuntimeException
551
	 */
552
	public function resolveRule($rule) {
553
		if($rule === 'avatar') {
554
			return $this->getAvatarAttributes();
555
		}
556
		throw new \RuntimeException('Invalid rule');
557
	}
558
559
	public function getAvatarAttributes() {
560
		$value = $this->ldapUserAvatarRule ?: self::AVATAR_PREFIX_DEFAULT;
561
		$defaultAttributes = ['jpegphoto', 'thumbnailphoto'];
562
563
		if($value === self::AVATAR_PREFIX_NONE) {
564
			return [];
565
		}
566
		if(strpos($value, self::AVATAR_PREFIX_DATA_ATTRIBUTE) === 0) {
567
			$attribute = trim(substr($value, strlen(self::AVATAR_PREFIX_DATA_ATTRIBUTE)));
568
			if($attribute === '') {
569
				return $defaultAttributes;
570
			}
571
			return [strtolower($attribute)];
572
		}
573
		if($value !== self::AVATAR_PREFIX_DEFAULT) {
574
			\OC::$server->getLogger()->warning('Invalid config value to ldapUserAvatarRule; falling back to default.');
575
		}
576
		return $defaultAttributes;
577
	}
578
579
}
580