';
16 |
17 | private function __construct()
18 | {
19 | }
20 |
21 | private function __clone()
22 | {
23 | }
24 |
25 | /**
26 | * Escape harmful HTML tags from a string or an array with strings
27 | *
28 | * @param $element array|string
29 | * @return array|string|null
30 | */
31 | public static function escapeHarmfulHtml($element)
32 | {
33 | if (is_string($element)) {
34 | return strip_tags($element, self::HARMLESS_HTML_TAGS);
35 | }
36 |
37 | if (is_array($element)) {
38 | foreach ($element as $key => $value) {
39 | $element[$key] = self::escapeHarmfulHtml($value);
40 | }
41 | return $element;
42 | }
43 |
44 | return null;
45 | }
46 | }
--------------------------------------------------------------------------------
/views/user-profile-option.twig:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ i18n.userDisabled }}
4 |
5 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/shared/WordPress/Multisite/Option/Attribute.php:
--------------------------------------------------------------------------------
1 |
8 | * @access public
9 | */
10 | class Attribute
11 | {
12 | const TITLE = 'title';
13 | const TYPE = 'type';
14 | const DESCRIPTION = 'description';
15 | const DETAIL = 'detail';
16 | const ANGULAR_ATTRIBUTES = 'angular_attributes';
17 | const ANGULAR_BUTTON_ATTRIBUTES = 'angular_button_attributes';
18 | const SHOW_PERMISSION = 'show_permission';
19 | const TRANSIENT = 'transient';
20 |
21 | const ELEMENTS = 'elements';
22 | const INLINE = 'inline';
23 |
24 | const TAB_TITLE = 'tabTitle';
25 | const GROUP_TITLE = 'groupTitle';
26 |
27 | const DEFAULT_VALUE = 'defaultValue';
28 | const PERSIST_DEFAULT_VALUE = 'persistDefaultValue';
29 |
30 | const DISABLED = 'disabled';
31 | const DISABLED_MESSAGE = 'disabled_message';
32 |
33 | const SANITIZER = 'sanitizer';
34 |
35 | const TYPE_STRUCTURE = 'type_structure';
36 | }
--------------------------------------------------------------------------------
/src/plug-in/Ui/Validator/Rule/SelectValueValid.php:
--------------------------------------------------------------------------------
1 |
10 | * @author Sebastian Weinert
11 | * @author Danny Meißner
12 | *
13 | * @access
14 | */
15 | class SelectValueValid extends RuleAdapter
16 | {
17 | /**
18 | * @var array
19 | */
20 | private $validValues = array();
21 |
22 | /**
23 | * @param string $msg
24 | * @param array $validValues
25 | */
26 | public function __construct($msg, array $validValues)
27 | {
28 | parent::__construct($msg);
29 |
30 | $this->validValues = $validValues;
31 | }
32 |
33 | /**
34 | * Validate the given data.
35 | *
36 | * @param string $value
37 | * @param array $data
38 | *
39 | * @return mixed
40 | */
41 | public function validate($value, $data)
42 | {
43 | if (!in_array($value, $this->validValues)) {
44 | return $this->getMsg();
45 | }
46 |
47 | return true;
48 | }
49 | }
--------------------------------------------------------------------------------
/src/plug-in/Ui/Validator/Rule/Port.php:
--------------------------------------------------------------------------------
1 |
12 | * @author Sebastian Weinert
13 | * @author Danny Meißner
14 | *
15 | * @access
16 | */
17 | class Port extends Numeric
18 | {
19 |
20 | /**
21 | * Validate the given data.
22 | *
23 | * @param string $value
24 | * @param array $data
25 | *
26 | * @return mixed
27 | */
28 | public function validate($value, $data)
29 | {
30 | if (!is_numeric($value) || !$this->isInPortRange($value)) {
31 | return $this->getMsg();
32 | }
33 |
34 | return true;
35 | }
36 |
37 | /**
38 | * Check if the given number is inside the port range.
39 | *
40 | * @param $value
41 | *
42 | * @return bool
43 | */
44 | public function isInPortRange($value)
45 | {
46 | if ($value >= 0 && $value <= 65535) {
47 | return true;
48 | }
49 |
50 | return false;
51 | }
52 | }
--------------------------------------------------------------------------------
/src/shared/WordPress/Multisite/Util.php:
--------------------------------------------------------------------------------
1 |
7 | * @author Sebastian Weinert
8 | * @author Danny Meißner
9 | *
10 | * @access
11 | */
12 | class Util
13 | {
14 | private function __construct()
15 | {
16 |
17 | }
18 |
19 | private function __clone()
20 | {
21 |
22 | }
23 |
24 | /**
25 | * Check if the user is currently on the network Dashboard.
26 | *
27 | * @return bool
28 | */
29 | public static function isOnNetworkDashboard()
30 | {
31 | $referer = $_SERVER['HTTP_REFERER'] ?? '';
32 |
33 | // network admin + ajax requests
34 | // see: https://core.trac.wordpress.org/ticket/22589
35 | if (defined('DOING_AJAX') && DOING_AJAX && is_multisite()
36 | && preg_match('#^' . network_admin_url() . '#i', $referer)
37 | ) {
38 | return true;
39 | }
40 |
41 | // it is a multisite installation, the user is network administrator and the current page is the network dashboard
42 | return (is_multisite() && is_super_admin() && is_network_admin());
43 | }
44 | }
--------------------------------------------------------------------------------
/src/plug-in/Authentication/SingleSignOn/Ui/ShowSingleSignOnLink.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * @access
11 | */
12 | class ShowSingleSignOnLink
13 | {
14 | /**
15 | * @var bool
16 | */
17 | private $isRegistered = false;
18 |
19 | /**
20 | * Register our action to add the SSO link to the login page.
21 | */
22 | public function register()
23 | {
24 | // don't allow multiple registrations of the same LoginService instance
25 | if ($this->isRegistered) {
26 | return;
27 | }
28 |
29 | add_action('login_form', array($this, 'generateLoginFooter'), 1);
30 | }
31 |
32 | /**
33 | * Render the link to re-authenticate using SSO for the login page.
34 | */
35 | public function generateLoginFooter()
36 | {
37 | $message = __('Log in using SSO', 'next-active-directory-integration');
38 | $url = esc_url(add_query_arg('reauth', 'sso'));
39 | echo '';
40 | }
41 | }
--------------------------------------------------------------------------------
/js/model/profile-configuration-model.js:
--------------------------------------------------------------------------------
1 | document['next_ad_int'] = document['next_ad_int'] || {};
2 | document['next_ad_int']['model'] = document['next_ad_int']['model'] || {};
3 | document['next_ad_int']['model']['configuration'] = document['next_ad_int']['model']['configuration'] || {};
4 |
5 | document['next_ad_int']['model']['configuration']['SinglePropertyValue'] = (function () {
6 | function SinglePropertyValue() {
7 | this.option_value = '';
8 | this.option_permission = '';
9 | }
10 |
11 | return SinglePropertyValue;
12 | })();
13 |
14 | document['next_ad_int']['model']['configuration']['General'] = (function (SinglePropertyValue) {
15 | function General() {
16 | this.profile_name = new SinglePropertyValue();
17 | this.profile_is_active = new SinglePropertyValue();
18 | this.is_active = new SinglePropertyValue();
19 | this.show_menu_test_authentication = new SinglePropertyValue();
20 | this.show_menu_sync_to_ad = new SinglePropertyValue();
21 | this.show_menu_sync_to_wordpress = new SinglePropertyValue();
22 | }
23 |
24 | return General;
25 | })(document['next_ad_int']['model']['configuration']['SinglePropertyValue']);
--------------------------------------------------------------------------------
/js/app/shared/services/notification.service.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | app.service('NotificationService', NotificationService);
3 |
4 | NotificationService.$inject = ['ngNotify'];
5 |
6 | function NotificationService(ngNotify) {
7 | return {
8 | isMessage: isMessage,
9 | showMessage: showMessage
10 | };
11 |
12 | /**
13 | * Check if the given data contains the isMessage flag.
14 | *
15 | * @param data
16 | *
17 | * @returns {boolean}
18 | */
19 | function isMessage(data) {
20 | return (typeof data['isMessage'] != 'undefined');
21 | }
22 |
23 | /**
24 | * Check if the given data is a message. If so, trigger the ngNotify messages
25 | *
26 | * @param data
27 | */
28 | function showMessage(data) {
29 | // if the given data is no message, do not notify anything
30 | if (!this.isMessage(data)) {
31 | return;
32 | }
33 |
34 | var message = data['message'];
35 | var type = data['type'];
36 |
37 | ngNotify.set(message, type)
38 | }
39 | }
40 | })();
--------------------------------------------------------------------------------
/src/plug-in/Ui/Validator/Rule/AdAttributeConflict.php:
--------------------------------------------------------------------------------
1 |
12 | * @author Sebastian Weinert
13 | * @author Danny Meißner
14 | *
15 | * @access
16 | */
17 | class AdAttributeConflict extends RuleAdapter
18 | {
19 | /**
20 | * Validate the given data.
21 | *
22 | * @param string $value
23 | * @param array $data
24 | *
25 | * @return mixed
26 | */
27 | public function validate($value, $data)
28 | {
29 | $conflict = $this->checkAttributeNamesForConflict($value);
30 |
31 | if ($conflict) {
32 | return $this->getMsg();
33 | }
34 |
35 | return true;
36 | }
37 |
38 | /**
39 | * Simple delegation to {@see Repository::checkAttributeMapping}.
40 | *
41 | * @param $attributeString
42 | *
43 | * @return bool
44 | */
45 | protected function checkAttributeNamesForConflict($attributeString)
46 | {
47 | return Repository::checkAttributeNamesForConflict($attributeString);
48 | }
49 | }
--------------------------------------------------------------------------------
/views/option/element/label.twig:
--------------------------------------------------------------------------------
1 | {% macro create(optionName, permission, inputId) %}
2 |
3 | {% set inline = getMetadata(optionName, 'INLINE')|join(' ') %}
4 | {% set description = getMetadata(optionName, 'DESCRIPTION') %}
5 | {% set angularAttributes = getMetadata(optionName, 'ANGULAR_ATTRIBUTES') %}
6 | {% set newNetwork = isOnNetworkDashboard() %}
7 |
8 | {% if newNetwork %}
9 | {% if not angularAttributes is empty %}
10 | {% set angularAttributes = angularAttributes ~ ' && (0))"' %}
11 | {% endif %}
12 | {% else %}
13 |
14 | {% if permission == 2 or permission == 1 %}
15 | {% set disabled = "disabled" %}
16 | {% else %}
17 | {% set disabled = "" %}
18 | {% endif %}
19 |
20 | {% if not angularAttributes is empty %}
21 | {% set angularAttributes = angularAttributes ~ '&& (1))"' %}
22 | {% endif %}
23 | {% endif %}
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | {% import "option/element/description.twig" as descriptionElement %}
32 | {{ descriptionElement.create(description) }}
33 |
34 | {% endmacro %}
--------------------------------------------------------------------------------
/js/app/shared/services/list.service.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | app.service('ListService', ListService);
3 |
4 | ListService.$inject = [];
5 |
6 | function ListService() {
7 | var vm = this;
8 |
9 | vm.removeListItem = function (index, listArray) {
10 | listArray.splice(index, 1);
11 | return listArray;
12 | };
13 |
14 | vm.addListItem = function (newItem, listArray) {
15 | if (newItem) {
16 | listArray.push(newItem);
17 | return listArray;
18 | }
19 |
20 | return listArray;
21 | };
22 |
23 | vm.parseListArrayToString = function (listArray) {
24 | var stringBuffer = "";
25 | var arrayLength = listArray.length;
26 |
27 | for (var i = 0; i < arrayLength; i++) {
28 | var value = listArray[i];
29 |
30 | if (value != '') {
31 | if (i + 1 < arrayLength) {
32 | stringBuffer += value + ";";
33 | continue;
34 | }
35 |
36 | stringBuffer += value;
37 | }
38 | }
39 |
40 | return stringBuffer;
41 | };
42 |
43 | return vm;
44 | }
45 | })();
--------------------------------------------------------------------------------
/src/shared/WordPress/Multisite/Configuration/Persistence/DefaultProfileRepository.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * @access public
11 | */
12 | class DefaultProfileRepository
13 | {
14 | const SUFFIX_DEFAULT = 'default';
15 |
16 | /**
17 | * Find the default profile from the configuration.
18 | *
19 | * @return int -1 if no profile was found.
20 | */
21 | public function findProfileId()
22 | {
23 | $name = $this->getProfileOptionName();
24 | $profileId = get_site_option($name, false);
25 |
26 | return (false === $profileId) ? -1 : (int)$profileId;
27 | }
28 |
29 | /**
30 | * Save the new $profileId as the default profile.
31 | *
32 | * @param $profileId
33 | */
34 | public function saveProfileId($profileId)
35 | {
36 | $name = $this->getProfileOptionName();
37 | update_site_option($name, $profileId);
38 | }
39 |
40 | /**
41 | * Return the configuration name for the default profile.
42 | *
43 | * @return string
44 | */
45 | protected function getProfileOptionName()
46 | {
47 | return NEXT_ACTIVE_DIRECTORY_INTEGRATION_PREFIX . ProfileRepository::PREFIX . self::SUFFIX_DEFAULT;
48 | }
49 | }
--------------------------------------------------------------------------------
/src/plug-in/Ui/Validator/Rule/AccountSuffix.php:
--------------------------------------------------------------------------------
1 |
11 | * @author Sebastian Weinert
12 | * @author Danny Meißner
13 | *
14 | * @access
15 | */
16 | class AccountSuffix extends HasSuffix
17 | {
18 | /**
19 | * Validate the given data.
20 | *
21 | * @param string $value
22 | * @param array $data
23 | *
24 | * @return bool|mixed
25 | */
26 | public function validate($value, $data)
27 | {
28 | if ($this->isList($value)) {
29 | $emails = explode(';', $value);
30 |
31 | foreach ($emails as $email) {
32 |
33 | if ($this->isInvalid($email)) {
34 | return $this->getMsg();
35 | }
36 |
37 | continue;
38 | }
39 |
40 | return true;
41 | }
42 |
43 | if ($this->isInvalid($value)) {
44 | return $this->getMsg();
45 | }
46 |
47 | return true;
48 | }
49 |
50 | /**
51 | * Check if the given value is invalid.
52 | *
53 | * @param $entry
54 | *
55 | * @return bool
56 | */
57 | private function isInvalid($entry)
58 | {
59 | return ($entry != "" && strpos($entry, '@') === false || $entry != "" && $entry[0] != '@');
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/shared/WordPress/WordPressErrorException.php:
--------------------------------------------------------------------------------
1 |
12 | * @access
13 | */
14 | class WordPressErrorException extends Exception
15 | {
16 | /** @var \WP_Error */
17 | private $wordPressError;
18 |
19 | public function __construct(\WP_Error $wordPressError)
20 | {
21 | parent::__construct('', 0, null);
22 |
23 | $this->wordPressError = $wordPressError;
24 | }
25 |
26 | /**
27 | * @return \WP_Error
28 | */
29 | public function getWordPressError()
30 | {
31 | return $this->wordPressError;
32 | }
33 |
34 | /**
35 | * Throw a new {@see WordPressErrorException} using the given $error. If the given value
36 | * is not an instance of {@see WP_Error}, false will be returned.
37 | *
38 | * @param \WP_Error|mixed $error
39 | *
40 | * @return bool
41 | *
42 | * @throws WordPressErrorException
43 | */
44 | public static function processWordPressError($error)
45 | {
46 | if (!is_wp_error($error)) {
47 | return false;
48 | }
49 |
50 | LogFacade::error($error->get_error_messages());
51 |
52 | throw new WordPressErrorException($error);
53 | }
54 | }
--------------------------------------------------------------------------------
/src/shared/Util/Logger/Handlers/FrontendLogHandler.php:
--------------------------------------------------------------------------------
1 |
12 | */
13 | class FrontendLogHandler extends AbstractProcessingHandler
14 | {
15 |
16 | private $log;
17 |
18 | private $enabled = false;
19 |
20 | /**
21 | * @param integer $level The minimum logging level at which this handler will be triggered
22 | * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
23 | */
24 | public function __construct($level = Logger::DEBUG, $bubble = true)
25 | {
26 | parent::__construct($level, $bubble);
27 | }
28 |
29 | public function enable()
30 | {
31 | $this->enabled = true;
32 | }
33 |
34 | public function disable()
35 | {
36 | $this->enabled = false;
37 | }
38 |
39 | protected function write(array $record): void
40 | {
41 | if (!$this->enabled) {
42 | return;
43 | }
44 |
45 | $this->log[] = $record;
46 | }
47 |
48 | public function getBufferedLog()
49 | {
50 | $log = $this->log;
51 |
52 | // Clean Log
53 | $this->log = [];
54 |
55 | return $log;
56 | }
57 | }
--------------------------------------------------------------------------------
/views/option/element/checkbox.twig:
--------------------------------------------------------------------------------
1 | {% macro create(optionName, permission, inputId) %}
2 |
3 | {% set inline = getMetadata(optionName, 'INLINE')|join(' ') %}
4 | {% set description = getMetadata(optionName, 'DESCRIPTION') %}
5 | {% set angularAttributes = getMetadata(optionName, 'ANGULAR_ATTRIBUTES') %}
6 | {% set newNetwork = isOnNetworkDashboard() %}
7 |
8 | {% if permission == 2 or permission == 1 %}
9 | {% set disabled = "disabled" %}
10 | {% else %}
11 | {% set disabled = "" %}
12 | {% endif %}
13 |
14 | {% if not angularAttributes is empty %}
15 | {% if newNetwork %}
16 | {% set angularAttributes = angularAttributes ~ ' && (0))"' %}
17 | {% else %}
18 | {% set angularAttributes = angularAttributes ~ '&& (1))"' %}
19 | {% endif %}
20 | {% endif %}
21 |
22 |
30 |
31 | {% endmacro %}
--------------------------------------------------------------------------------
/src/plug-in/Ui/Validator/Rule/AdminEmail.php:
--------------------------------------------------------------------------------
1 |
11 | * @author Sebastian Weinert
12 | * @author Danny Meißner
13 | *
14 | * @access
15 | */
16 | class AdminEmail extends HasSuffix
17 | {
18 |
19 | /**
20 | * Validate the given data.
21 | *
22 | * @param string $value
23 | * @param array $data
24 | *
25 | * @return bool|mixed
26 | */
27 | public function validate($value, $data)
28 | {
29 | if ($this->isList($value)) {
30 | $emails = explode(';', $value);
31 |
32 | foreach ($emails as $email) {
33 | if ($this->isInvalid($email)) {
34 | return $this->getMsg();
35 | }
36 |
37 | continue;
38 | }
39 |
40 | return true;
41 | }
42 |
43 | if ($this->isInvalid($value)) {
44 | return $this->getMsg();
45 | }
46 |
47 | return true;
48 | }
49 |
50 | /**
51 | * Check if the given value is invalid.
52 | *
53 | * @param $email
54 | *
55 | * @return bool
56 | */
57 | private function isInvalid($email)
58 | {
59 | return ($email != "" && strpos($email, '@') === false)
60 | || ($email != "" && $email[0] == '@')
61 | || ($email != "" && $email[strlen($email) - 1] == '@');
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/shared/Util/Validator/Rule/HasSuffix.php:
--------------------------------------------------------------------------------
1 |
10 | * @author Sebastian Weinert
11 | * @author Danny Meißner
12 | *
13 | * @access
14 | */
15 | class HasSuffix extends RuleAdapter
16 | {
17 | /**
18 | * The suffix to check for.
19 | *
20 | * @var string
21 | */
22 | private $suffix;
23 |
24 | /**
25 | * Adi_Validation_Rule_SuffixRule constructor.
26 | *
27 | * @param string $msg
28 | * @param string $suffix
29 | */
30 | public function __construct($msg, $suffix)
31 | {
32 | parent::__construct($msg);
33 | $this->suffix = $suffix;
34 | }
35 |
36 | /**
37 | * Validate the given data.
38 | *
39 | * @param string $value
40 | * @param array $data
41 | *
42 | * @return bool|mixed
43 | */
44 | public function validate($value, $data)
45 | {
46 | if ($value != "" && strpos($value, $this->suffix) == false) {
47 | return $this->getMsg();
48 | }
49 |
50 | return true;
51 | }
52 |
53 | /**
54 | * Check if the given value is a frontend list.
55 | *
56 | * @param $value
57 | *
58 | * @return bool
59 | */
60 | public function isList($value)
61 | {
62 | if (strpos($value, ";") !== false) {
63 | return true;
64 | }
65 |
66 | return false;
67 | }
68 | }
--------------------------------------------------------------------------------
/views/option/line.twig:
--------------------------------------------------------------------------------
1 | {% macro create(optionName, network, isProfile, i18n) %}
2 |
3 | {% if network %}
4 | {% set preparedId = 'profile' ~ isProfile ~ '__' ~ optionName %}
5 | {% else %}
6 | {% set preparedId = optionName %}
7 | {% endif %}
8 |
9 | {% set inputId = preparedId ~ '__value' %}
10 | {% set permissionSelectionId = preparedId ~ '__permission' %}
11 |
12 | {% set title = getMetadata(optionName, 'TITLE') %}
13 | {% set type = getMetadata(optionName, 'TYPE') %}
14 |
15 | {# render options input #}
16 | {% if optionName != "additional_user_attributes"%}
17 |
18 | {# write comment #}
19 | {{ title }}
20 |
21 | {# write comment #}
22 |
23 |
24 | {% import "option/element.twig" as element %}
25 | {{ element.create(optionName, isProfile, inputId, permissionSelectionId, network, i18n) }}
26 |
27 |
28 | {% else %}
29 |
30 | {% set permission = getPermissionForOptionAndBlog(optionName) %}
31 |
32 | {% import "option/attributes.twig" as attributes %}
33 | {{ attributes.create(optionName, permission, inputId, permissionSelectionId, network, i18n) }}
34 |
35 | {% endif %}
36 |
37 | {% endmacro %}
38 |
--------------------------------------------------------------------------------
/src/shared/Util/Validator/Result.php:
--------------------------------------------------------------------------------
1 |
10 | * @author Sebastian Weinert
11 | * @author Danny Meißner
12 | */
13 | class Result
14 | {
15 | /**
16 | * @var array
17 | */
18 | private $validationResult = array();
19 |
20 | /**
21 | * @param string $name
22 | * @param string $msg
23 | */
24 | public function addValidationResult($name, $msg)
25 | {
26 | if (!isset($this->validationResult[$name])) {
27 | $this->validationResult[$name] = array();
28 | }
29 |
30 | $this->validationResult[$name] = $msg;
31 | }
32 |
33 | /**
34 | * @return bool
35 | */
36 | public function isValid()
37 | {
38 | return (sizeof($this->validationResult) == 0);
39 | }
40 |
41 | /**
42 | * This method will check the current validationResult object and find the first occurrence of an error.
43 | * If a validation error is found, return true;
44 | *
45 | * @return bool
46 | */
47 | public function containsErrors()
48 | {
49 | foreach ($this->validationResult as $result) {
50 | if (array_key_exists(Type::ERROR, $result)) {
51 | return true;
52 | }
53 | }
54 |
55 | return false;
56 | }
57 |
58 | /**
59 | * @return array
60 | */
61 | public function getValidationResult()
62 | {
63 | return $this->validationResult;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/views/option/element/domainsid.twig:
--------------------------------------------------------------------------------
1 | {% macro create(optionName, permission, inputId) %}
2 |
3 | {% set inline = getMetadata(optionName, 'INLINE')|join(' ') %}
4 | {% set description = getMetadata(optionName, 'DESCRIPTION') %}
5 | {% set angularAttributes = getMetadata(optionName, 'ANGULAR_ATTRIBUTES') %}
6 | {% set verificationStatus = '{{ verificationStatus }}' %}
7 | {% set newNetwork = isOnNetworkDashboard() %}
8 | {% set disabled = "" %}
9 |
10 | {% if newNetwork %}
11 | {% if not angularAttributes is empty %}
12 | {% set angularAttributes = angularAttributes ~ ' && (0))"' %}
13 | {% endif %}
14 | {% else %}
15 |
16 | {% if permission == 2 or permission == 1 %}
17 | {% set disabled = "disabled" %}
18 | {% else %}
19 | {% set disabled = "" %}
20 | {% endif %}
21 |
22 | {% if not angularAttributes is empty %}
23 | {% set angularAttributes = angularAttributes ~ '&& (1))"' %}
24 | {% endif %}
25 | {% endif %}
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | {% import "option/element/description.twig" as descriptionElement %}
34 | {{ descriptionElement.create(description) }}
35 |
36 | {% endmacro %}
--------------------------------------------------------------------------------
/views/option/element/textarea.twig:
--------------------------------------------------------------------------------
1 | {% macro create(optionName, permission, inputId, network) %}
2 |
3 | {% set inline = getMetadata(optionName, 'INLINE')|join(' ') %}
4 | {% set description = getMetadata(optionName, 'DESCRIPTION') %}
5 | {% set type = getMetadata(optionName, 'TYPE') %}
6 | {% set angularAttributes = getMetadata(optionName, 'ANGULAR_ATTRIBUTES') %}
7 | {% set newNetwork = isOnNetworkDashboard() %}
8 |
9 | {% if permission < 3 %}
10 | {% set disabled = "disabled" %}
11 | {% else %}
12 | {% set disabled = "" %}
13 | {% endif %}
14 |
15 | {% if not angularAttributes is empty %}
16 | {% if newNetwork %}
17 | {% set angularAttributes = angularAttributes ~ ' && (0))"' %}
18 | {% else %}
19 | {% set angularAttributes = angularAttributes ~ ' && (1))"' %}
20 | {% endif %}
21 | {% else %}
22 | {% set angularAttributes = '' %}
23 | {% endif %}
24 |
25 |
26 |
27 |
28 |
29 | {% import "option/element/error-msg.twig" as errorElement %}
30 | {{ errorElement.create(optionName) }}
31 |
32 |
33 | {% import "option/element/description.twig" as descriptionElement %}
34 | {{ descriptionElement.create(description) }}
35 |
36 | {% endmacro %}
--------------------------------------------------------------------------------
/js/app/blog-options/services/persistence.service.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | app.service('PersistService', PersistService);
3 |
4 | PersistService.$inject = ['$http', '$result', 'ngNotify'];
5 |
6 | function PersistService($http, $result, ngNotify) {
7 | var vm = this;
8 |
9 | vm.persistData = function (data) {
10 |
11 | // exclude domain_sid from persist
12 | data.verification_username = "";
13 | data.verification_password = "";
14 | delete data.verification_status;
15 | delete data.verification_status_message;
16 |
17 | return $http.post('admin-ajax.php', {
18 | action: 'next_ad_int_blog_options',
19 | security: document.next_ad_int.security,
20 | subAction: 'persistOptionsValues',
21 | data: data
22 | }).then($result);
23 | };
24 |
25 | vm.persist = function ($scope, _data) {
26 | var data = _data || JSON.parse(angular.toJson($scope.option));
27 |
28 | vm.persistData(data).then(function (response) {
29 | if (typeof response != 'undefined') {
30 | $scope.messages = response.data;
31 | ngNotify.set('Something went wrong!', 'error')
32 | } else {
33 | $scope.messages = {};
34 | ngNotify.set('Save successful!', 'success');
35 | }
36 | });
37 | };
38 |
39 | return vm;
40 | }
41 | })();
--------------------------------------------------------------------------------
/src/shared/Util/Uninstaller.php:
--------------------------------------------------------------------------------
1 | options);
16 | }
17 |
18 | $sites = WordPressSiteRepository::getSites();
19 | $firstOptionTable = $wpdb->base_prefix . 'options';
20 | $tables = array($firstOptionTable);
21 |
22 | for ($i = 2; $i <= sizeof($sites); $i++) {
23 | $optionTable = $wpdb->base_prefix . $i . '_options';
24 | array_push($tables, $optionTable);
25 | }
26 |
27 | return $tables;
28 | }
29 |
30 | public function deleteAllEntriesFromTable($table, $keyName) {
31 | global $wpdb;
32 | $prefix =NEXT_ACTIVE_DIRECTORY_INTEGRATION_PREFIX;
33 |
34 | $sql = "DELETE FROM $table WHERE $keyName LIKE '$prefix%';";
35 | $wpdb->query($sql);
36 | }
37 |
38 | public function removePluginSettings() {
39 | global $wpdb;
40 |
41 | $tables = $this->getAllOptionTables();
42 | foreach($tables as $table) {
43 | $this->deleteAllEntriesFromTable($table, 'option_name');
44 | }
45 |
46 | if (is_multisite()) {
47 | $this->deleteAllEntriesFromTable($wpdb->sitemeta, 'meta_key');
48 | }
49 |
50 | $this->deleteAllEntriesFromTable($wpdb->usermeta, 'meta_key');
51 | }
52 | }
--------------------------------------------------------------------------------
/src/shared/Util/Util.php:
--------------------------------------------------------------------------------
1 |
13 | * @access public
14 | */
15 | class Util
16 | {
17 | private function __construct()
18 | {
19 | }
20 |
21 | /**
22 | * @var Native
23 | */
24 | private static $native = null;
25 |
26 | /**
27 | * Gain access to PHP's native functions which could be disabled in certain environments
28 | *
29 | * @param none|null|Native {0}
30 | * if no parameter is provided the current Adi_Util_Internal_Native instance is returned.
31 | * if the parameter is explicitly null, the current instance is resetted and replaced with a fresh instance
32 | * if the parameter is not null it is set as $native object. This must be used inside the test environment
33 | *
34 | * @return Native not null
35 | */
36 | public static function native()
37 | {
38 | $args = func_get_args();
39 | $instance = self::$native;
40 |
41 | // (re)set native PHP functions?
42 | if (sizeof($args) > 0) {
43 | $instance = $args[0];
44 | }
45 |
46 | if ($instance == null) {
47 | // create new instance
48 | self::$native = new Native();
49 | } else {
50 | // get instance from parameter
51 | self::$native = $instance;
52 | }
53 |
54 | return self::$native;
55 | }
56 | }
--------------------------------------------------------------------------------
/src/shared/WordPress/WordPressSiteRepository.php:
--------------------------------------------------------------------------------
1 |
10 | *
11 | * @access public
12 | */
13 | class WordPressSiteRepository
14 | {
15 | private function __clone()
16 | {
17 | }
18 |
19 | /**
20 | * Delegate to either get_sites (for >= 4.6) or wp_get_sites (for < 4.6).
21 | *
22 | * @return mixed
23 | * @see wp_get_sites, get_sites
24 | *
25 | */
26 | public static function getSites($param = array())
27 | {
28 | global $wp_version;
29 |
30 | if (version_compare($wp_version, '4.6', '>=')) {
31 | $sites = get_sites($param);
32 | $oldStyle = array();
33 |
34 | // convert WP_Site to the old array style
35 | foreach ($sites as $site) {
36 | array_push($oldStyle, $site->to_array());
37 | }
38 |
39 | return $oldStyle;
40 | }
41 |
42 | return wp_get_sites($param);
43 | }
44 |
45 | /**
46 | * Delegate to either get_site (for >= 4.7) or get_blog_details (for < 4.7).
47 | *
48 | * @param null|int $blogId
49 | * @return WP_Site
50 | * @see get_site, get_blog_details
51 | * @issue ADI-419
52 | */
53 | public static function getSite($blogId = null)
54 | {
55 | global $wp_version;
56 |
57 | if (version_compare($wp_version, '4.7', '>=')) {
58 | return get_site($blogId);
59 | }
60 |
61 | return get_blog_details($blogId);
62 | }
63 | }
--------------------------------------------------------------------------------
/src/plug-in/Ui/Validator/Rule/WordPressMetakeyConflict.php:
--------------------------------------------------------------------------------
1 |
13 | * @author Sebastian Weinert
14 | * @author Danny Meißner
15 | *
16 | * @access
17 | */
18 | class WordPressMetakeyConflict extends RuleAdapter
19 | {
20 | /**
21 | * Validate the given data.
22 | *
23 | * @param string $value
24 | * @param array $data
25 | *
26 | * @return mixed
27 | */
28 | public function validate($value, $data)
29 | {
30 | $attributeMapping = $this->convertAttributeMapping($value);
31 |
32 | $metakeyBuffer = array();
33 |
34 | foreach ($attributeMapping as $attribute) {
35 |
36 | if (sizeof($metakeyBuffer) <= 0) {
37 | $metakeyBuffer[$attribute["wordpress_attribute"]] = true;
38 | continue;
39 | }
40 |
41 | if (isset($metakeyBuffer[$attribute["wordpress_attribute"]])) {
42 | return $this->getMsg();
43 | }
44 |
45 | $metakeyBuffer[$attribute["wordpress_attribute"]] = true;
46 | }
47 |
48 | return true;
49 | }
50 |
51 | /**
52 | * Simple delegation to {@see Repository::convertAttributeMapping}.
53 | *
54 | * @param $attributeString
55 | *
56 | * @return array
57 | */
58 | protected function convertAttributeMapping($attributeString)
59 | {
60 | return Repository::convertAttributeMapping($attributeString);
61 | }
62 | }
--------------------------------------------------------------------------------
/views/option/element/authcode.twig:
--------------------------------------------------------------------------------
1 | {% macro create(optionName, permission, inputId, i18n) %}
2 |
3 | {% set inline = getMetadata(optionName, 'INLINE')|join(' ') %}
4 | {% set description = getMetadata(optionName, 'DESCRIPTION') %}
5 | {% set angularAttributes = getMetadata(optionName, 'ANGULAR_ATTRIBUTES') %}
6 | {% set authCode = '{{ authCode }}' %}
7 | {% set newNetwork = isOnNetworkDashboard() %}
8 |
9 | {% if not angularAttributes is empty %}
10 | {% if newNetwork %}
11 | {% set angularAttributes = angularAttributes ~ ' && (0))"' %}
12 | {% else %}
13 |
14 | {% if permission == 2 or permission == 1 %}
15 | {% set disabled = "disabled" %}
16 | {% else %}
17 | {% set disabled = "" %}
18 | {% endif %}
19 |
20 | {% set angularAttributes = angularAttributes ~ '&& (1))"' %}
21 | {% endif %}
22 | {% endif %}
23 |
24 |
25 |
26 |
27 |  
28 |
29 |
31 |
32 |
33 | {% import "option/element/error-msg.twig" as errorElement %}
34 | {{ errorElement.create(optionName) }}
35 |
36 |
37 |
38 | {% import "option/element/description.twig" as descriptionElement %}
39 | {{ descriptionElement.create(description) }}
40 |
41 |
42 | {% endmacro %}
--------------------------------------------------------------------------------
/src/shared/WordPress/Multisite/Configuration/Persistence/ConfigurationRepository.php:
--------------------------------------------------------------------------------
1 |
6 | * @author Danny Meißner
7 | */
8 | interface ConfigurationRepository
9 | {
10 | /**
11 | * Find the value of the given option
12 | *
13 | * @param int $id
14 | * @param string $optionName
15 | *
16 | * @return mixed
17 | */
18 | public function findSanitizedValue($id, $optionName);
19 |
20 | /**
21 | * Find the raw value of the given option.
22 | * This method is necessary for the migration of the encrypted passwords.
23 | *
24 | *
25 | * @param $siteId
26 | * @param $optionName
27 | *
28 | * @return mixed
29 | */
30 | public function findRawValue($siteId, $optionName);
31 |
32 | /**
33 | * Persist the given configuration option
34 | *
35 | * @param int $siteId
36 | * @param string $optionName
37 | * @param mixed $optionValue
38 | */
39 | public function persistSanitizedValue($siteId, $optionName, $optionValue);
40 |
41 | /**
42 | * Get the option permission for the profile and the option.
43 | *
44 | * @param int $profileId
45 | * @param string $optionName
46 | *
47 | * @return array|bool|null|object|void
48 | */
49 | public function findSanitizedPermission($profileId, $optionName);
50 |
51 | /**
52 | * @param int $profileId
53 | * @param string $optionName
54 | * @param int $optionPermission between [0,3]
55 | *
56 | * @return bool
57 | */
58 | public function persistSanitizedPermission($profileId, $optionName, $optionPermission);
59 | }
--------------------------------------------------------------------------------
/src/compat-v2/stubs.php:
--------------------------------------------------------------------------------
1 |
10 | * @access public
11 | */
12 | class LoginState
13 | {
14 | /**
15 | * Indicate that the user has been logged in by NADI
16 | * @var bool
17 | */
18 | private $authenticated = false;
19 |
20 | /**
21 | * null indicates that no authorization has been done
22 | * @var bool|null
23 | */
24 | private $authorized = null;
25 |
26 | /**
27 | * Return if user has been authenticated by NADI
28 | * @return bool
29 | */
30 | public function isAuthenticated()
31 | {
32 | return $this->authenticated;
33 | }
34 |
35 | /**
36 | * Return true if user has been authorized by NADI
37 | * @return bool
38 | */
39 | public function isAuthorized()
40 | {
41 | return $this->authorized;
42 | }
43 |
44 | /**
45 | * Set the NADI authentication has succeeded
46 | */
47 | public function setAuthenticationSucceeded()
48 | {
49 | $this->authenticated = true;
50 | }
51 |
52 | /**
53 | * Set the NADI authorization has succeeded
54 | */
55 | public function setAuthorizationSucceeded()
56 | {
57 | $this->authorized = true;
58 | }
59 |
60 | public function setAuthorizationFailed()
61 | {
62 | $this->authorized = false;
63 | }
64 |
65 | /**
66 | * Return true if authentication is valid and authorization is valid or not done
67 | */
68 | public function isAuthenticatedAndAuthorized()
69 | {
70 | return $this->isAuthenticated() && ($this->isAuthorized() !== false);
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/plug-in/Ui/Validator/Rule/AttributeMappingNull.php:
--------------------------------------------------------------------------------
1 |
13 | * @author Sebastian Weinert
14 | * @author Danny Meißner
15 | *
16 | * @access
17 | */
18 | class AttributeMappingNull extends RuleAdapter
19 | {
20 | /**
21 | * Validate the given data.
22 | *
23 | * @param string $value
24 | * @param array $data
25 | *
26 | * @return mixed
27 | */
28 | public function validate($value, $data)
29 | {
30 | $attributeMapping = $this->convertAttributeMapping($value);
31 |
32 | $isAdAttributeUndefinedOrEmpty = isset($attributeMapping[""]) || isset($attributeMapping["undefined"]);
33 |
34 | if ($isAdAttributeUndefinedOrEmpty) {
35 | return $this->getMsg();
36 | }
37 |
38 | foreach ($attributeMapping as $attribute) {
39 | $isEmpty = $attribute["type"] === ""
40 | || $attribute["type"] === "undefined"
41 | || $attribute["wordpress_attribute"] === ""
42 | || $attribute["wordpress_attribute"] === "undefined"
43 | || $attribute["wordpress_attribute"] === "next_ad_int_";
44 |
45 | if ($isEmpty) {
46 | return $this->getMsg();
47 | }
48 | }
49 |
50 | return true;
51 | }
52 |
53 | /**
54 | * Simple delegation to {@see Repository::convertAttributeMapping}.
55 | *
56 | * @param $attributeString
57 | *
58 | * @return array
59 | */
60 | protected function convertAttributeMapping($attributeString)
61 | {
62 | return Repository::convertAttributeMapping($attributeString);
63 | }
64 | }
--------------------------------------------------------------------------------
/src/plug-in/Ui/Validator/Rule/BaseDn.php:
--------------------------------------------------------------------------------
1 |
13 | *
14 | * @access
15 | */
16 | class BaseDn extends RuleAdapter
17 | {
18 |
19 | /**
20 | * Validate the given base DN.
21 | *
22 | * @param string $value
23 | * @param array $data
24 | *
25 | * @return bool|mixed
26 | */
27 | public function validate($value, $data)
28 | {
29 |
30 | // DME: ADI-563 | Github Issue #49 If baseDN is empty there is no need to continue format validation. We return true in order to allow an empty BaseDN
31 | if ($value == '') {
32 | return true;
33 | }
34 |
35 | // check if baseDN starts with a special character
36 | $re = '/[\W]+/';
37 | preg_match_all($re, $value[0], $matches);
38 |
39 | if ($matches[0]) {
40 | return $this->getMsg();
41 | }
42 |
43 | // general format is incorrect
44 | $dns = ldap_explode_dn($value, 0);
45 |
46 | if (!$dns) {
47 | return $this->getMsg();
48 | }
49 |
50 | // last part of DN must be a domain controller object
51 | $lastObject = end($dns);
52 |
53 | // make lowercase for further comparison
54 | $lastObject = strtolower($lastObject);
55 |
56 | // check if first 3 characters are equal to 'dc='
57 | if (substr($lastObject, 0, 3) !== "dc=") {
58 | return $this->getMsg();
59 | }
60 |
61 | // check if at least one domain controller is present
62 | $occurrences = ArrayUtil::countOccurencesStartsWith($dns, 'dc=');
63 |
64 | if ($occurrences == 0) {
65 | return $this->getMsg();
66 | }
67 |
68 | return true;
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/src/shared/Util/Validator/Rule/Numeric.php:
--------------------------------------------------------------------------------
1 |
10 | * @author Sebastian Weinert
11 | * @author Danny Meißner
12 | *
13 | * @access
14 | */
15 | class Numeric extends RuleAdapter
16 | {
17 | /**
18 | * Validate the given data.
19 | *
20 | * @param string $value
21 | * @param array $data
22 | *
23 | * @return mixed
24 | */
25 | public function validate($value, $data)
26 | {
27 | if (!is_numeric($value)) {
28 | return $this->getMsg();
29 | }
30 |
31 | return true;
32 | }
33 |
34 | /**
35 | * Check if the given value is a negative number.
36 | *
37 | * @param $value
38 | *
39 | * @return bool
40 | */
41 | public function isNegative($value)
42 | {
43 | if ($value < 0) {
44 | return true;
45 | }
46 |
47 | return false;
48 | }
49 |
50 | /**
51 | * Check if the given value is a positive number.
52 | *
53 | * @param $value
54 | *
55 | * @return bool
56 | */
57 | public function isPositive($value)
58 | {
59 | if ($value > 0) {
60 | return true;
61 | }
62 |
63 | return false;
64 | }
65 |
66 | /**
67 | * Check if the given value is a float.
68 | *
69 | * @param $value
70 | *
71 | * @return bool
72 | */
73 | public function isFloat($value)
74 | {
75 | if (is_float($value)) {
76 | return true;
77 | }
78 |
79 | return false;
80 | }
81 |
82 | /**
83 | * Check if the given value is a zero.
84 | *
85 | * @param $value
86 | *
87 | * @return bool
88 | */
89 | public function isZero($value)
90 | {
91 | if ($value === 0) {
92 | return true;
93 | }
94 |
95 | return false;
96 | }
97 | }
--------------------------------------------------------------------------------
/src/shared/Ldap/Attributes.php:
--------------------------------------------------------------------------------
1 |
8 | * @access public
9 | */
10 | class Attributes
11 | {
12 | /**
13 | * @var array
14 | */
15 | private $raw = array();
16 |
17 | /**
18 | * @var array
19 | */
20 | private $filtered = array();
21 |
22 | /**
23 | * Ldap_Attributes constructor.
24 | * @param array $raw
25 | * @param array $filtered
26 | */
27 | public function __construct($raw = array(), $filtered = array())
28 | {
29 | $this->raw = $raw;
30 | $this->filtered = $filtered;
31 | }
32 |
33 | /**
34 | * @return array
35 | */
36 | public function getFiltered()
37 | {
38 | return $this->filtered;
39 | }
40 |
41 | /**
42 | * @param array $filtered
43 | */
44 | public function setFiltered($filtered)
45 | {
46 | $this->filtered = $filtered;
47 | }
48 |
49 | /**
50 | * Return a filtered attribute or $default
51 | * @param string $attributeName
52 | * @param null $default
53 | * @return null
54 | */
55 | public function getFilteredValue($attributeName, $default = null) {
56 | if (isset($this->filtered)) {
57 | if (isset($this->filtered[$attributeName])) {
58 | return $this->filtered[$attributeName];
59 | }
60 | }
61 |
62 | return $default;
63 | }
64 |
65 | /**
66 | * @return array
67 | */
68 | public function getRaw()
69 | {
70 | return $this->raw;
71 | }
72 |
73 | /**
74 | * @param array $raw
75 | */
76 | public function setRaw($raw)
77 | {
78 | $this->raw = $raw;
79 | }
80 |
81 | /**
82 | * @param string $domainSid
83 | */
84 | public function setDomainSid($domainSid) {
85 | if (isset($this->filtered)) {
86 | $this->filtered["domainsid"] = $domainSid;
87 | }
88 | }
89 | }
--------------------------------------------------------------------------------
/src/plug-in/Ui/Validator/Rule/NoDefaultAttributeName.php:
--------------------------------------------------------------------------------
1 |
14 | * @author Sebastian Weinert
15 | * @author Danny Meißner
16 | *
17 | * @access
18 | */
19 | class NoDefaultAttributeName extends RuleAdapter
20 | {
21 | /**
22 | * Validate the given data.
23 | *
24 | * @param string $value
25 | * @param array $data
26 | *
27 | * @return mixed
28 | */
29 | public function validate($value, $data)
30 | {
31 | $attributeMapping = $this->convertAttributeMapping($value);
32 | $attributeMappingMetaKeys = array_map(function ($mapping) {
33 | return $mapping['wordpress_attribute'];
34 | }, $attributeMapping);
35 |
36 | $intersect = array_intersect($attributeMappingMetaKeys, $this->getForbiddenAttributeNames());
37 |
38 | if (sizeof($intersect) > 0) {
39 | return $this->getMsg();
40 | }
41 |
42 | return true;
43 | }
44 |
45 | /**
46 | * Simple delegation to {@see Repository::convertAttributeMapping}.
47 | *
48 | * @param $attributeString
49 | *
50 | * @return array
51 | */
52 | protected function convertAttributeMapping($attributeString)
53 | {
54 | return Repository::convertAttributeMapping($attributeString);
55 | }
56 |
57 | /**
58 | * Get an array with all default attribute meta keys to prevent that the user overrides any of this.
59 | *
60 | * @return array
61 | */
62 | protected function getForbiddenAttributeNames()
63 | {
64 | return Repository::getDefaultAttributeMetaKeys();
65 | }
66 | }
--------------------------------------------------------------------------------
/js/blog-profile-relationship.js:
--------------------------------------------------------------------------------
1 | /**
2 | * UI utility class for assigning a profile to a to a site
3 | */
4 | document['next_ad_int'] = document['next_ad_int'] || {};
5 | document['next_ad_int']['profile_of_blog'] = {};
6 |
7 | jQuery(document).ready(function () {
8 |
9 | jQuery('#assignProfile').on('click', function (event) {
10 | event.preventDefault();
11 |
12 | var form = jQuery(this).closest('form');
13 | var data = {
14 | profile: form.find('[name="profile"]').val(),
15 | allblogs: form.find('[name="allblogs[]"]:checked').map(function () {
16 | return jQuery(this).val();
17 | }).get()
18 | };
19 |
20 | jQuery.post(ajaxurl, {
21 | 'action': 'next_ad_int_blog_profile_relationship',
22 | 'data': data,
23 | 'security': document['next_ad_int']['security']
24 | }, function (response) {
25 | if (response == 0) {
26 | location.reload();
27 | } else {
28 | alert(response);
29 | }
30 | });
31 | });
32 |
33 | jQuery('#assignDefaultProfile').on('click', function (event) {
34 | event.preventDefault();
35 |
36 | var form = jQuery(this).closest('form');
37 | var data = {
38 | 'default-profile': form.find('[name="profile"]').val()
39 | };
40 |
41 | jQuery.post(ajaxurl, {
42 | 'action': 'next_ad_int_blog_profile_relationship',
43 | 'data': data,
44 | 'security': document['next_ad_int']['security']
45 | }, function (response) {
46 | if (response == 0) {
47 | location.reload();
48 | } else {
49 | alert(response);
50 | }
51 | });
52 | });
53 | });
54 |
--------------------------------------------------------------------------------
/js/app/shared/utils/value.util.js:
--------------------------------------------------------------------------------
1 | var next_ad_int = next_ad_int || {};
2 | next_ad_int.util = next_ad_int.util || {};
3 |
4 | /**
5 | * @type {{findValue, findPermission}}
6 | */
7 | next_ad_int.util.ValueHelper = (function (ArrayUtil) {
8 | return {
9 | findValue: findValue,
10 | findPermission: findPermission,
11 | findMessage: findMessage
12 | };
13 |
14 | /**
15 | * Find the item from the given {@code dataArray} using the given {@code name} and return the
16 | * option_value property.
17 | *
18 | * @param name
19 | * @param dataArray
20 | * @param defaultValue
21 | *
22 | * @returns {*}
23 | */
24 | function findValue(name, dataArray, defaultValue) {
25 | var item = ArrayUtil.findByKey(name, dataArray);
26 |
27 | if (null == item) {
28 | return defaultValue || null;
29 | }
30 |
31 | return item['option_value'];
32 | }
33 |
34 | /**
35 | * Find the item from the given {@code dataArray} using the given {@code name} and return the
36 | * option_permission property.
37 | *
38 | * @param name
39 | * @param dataArray
40 | * @returns {*}
41 | */
42 | function findPermission(name, dataArray) {
43 | var item = ArrayUtil.findByKey(name, dataArray);
44 |
45 | if (null == item) {
46 | return null;
47 | }
48 |
49 | return item['option_permission'];
50 | }
51 |
52 | /**
53 | * Find the message from the given {@code dataArray} using the given {@code name} and return it.
54 | *
55 | * @param name
56 | * @param dataArray
57 | *
58 | * @returns {*}
59 | */
60 | function findMessage(name, dataArray) {
61 | return ArrayUtil.findByKey(name, dataArray);
62 | }
63 | })(next_ad_int.util.ArrayUtil);
64 |
--------------------------------------------------------------------------------
/views/option/element/verification_password.twig:
--------------------------------------------------------------------------------
1 | {% macro create(optionName, permission, inputId, i18n) %}
2 |
3 | {% set inline = getMetadata(optionName, 'INLINE')|join(' ') %}
4 | {% set description = getMetadata(optionName, 'DESCRIPTION') %}
5 | {% set angularAttributes = getMetadata(optionName, 'ANGULAR_ATTRIBUTES') %}
6 | {% set verificationStatus = '{{ verificationStatus }}' %}
7 | {% set newNetwork = isOnNetworkDashboard() %}
8 | {% set disabled = "" %}
9 |
10 | {% if newNetwork %}
11 | {% if not angularAttributes is empty %}
12 | {% set angularAttributes = angularAttributes ~ ' && (0))"' %}
13 | {% endif %}
14 | {% else %}
15 |
16 | {% if permission == 2 or permission == 1 %}
17 | {% set disabled = "disabled" %}
18 | {% else %}
19 | {% set disabled = "" %}
20 | {% endif %}
21 |
22 | {% if not angularAttributes is empty %}
23 | {% set angularAttributes = angularAttributes ~ '&& (1))"' %}
24 | {% endif %}
25 | {% endif %}
26 |
27 |
29 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | {% import "option/element/description.twig" as descriptionElement %}
39 | {{ descriptionElement.create(description) }}
40 |
41 | {% endmacro %}
--------------------------------------------------------------------------------
/views/option/element/default.twig:
--------------------------------------------------------------------------------
1 | {% macro create(optionName, permission, inputId, network) %}
2 |
3 | {% set inline = getMetadata(optionName, 'INLINE')|join(' ') %}
4 | {% set description = getMetadata(optionName, 'DESCRIPTION') %}
5 | {% set type = getMetadata(optionName, 'TYPE') %}
6 | {% set angularAttributes = getMetadata(optionName, 'ANGULAR_ATTRIBUTES') %}
7 | {% set newNetwork = isOnNetworkDashboard() %}
8 |
9 | {% if permission < 3 %}
10 | {% set disabled = "disabled" %}
11 | {% else %}
12 | {% set disabled = "" %}
13 | {% endif %}
14 |
15 | {% if not angularAttributes is empty %}
16 | {% if newNetwork %}
17 | {% set angularAttributes = angularAttributes ~ ' && (0))"' %}
18 | {% else %}
19 | {% set angularAttributes = angularAttributes ~ ' && (1))"' %}
20 | {% endif %}
21 | {% else %}
22 | {% set angularAttributes = '' %}
23 | {% endif %}
24 |
25 |
26 | {% if optionName == "base_dn" %}
27 |
28 | {% else %}
29 |
30 | {% endif %}
31 |
32 |
33 | {% import "option/element/error-msg.twig" as errorElement %}
34 | {{ errorElement.create(optionName) }}
35 |
36 |
37 | {% import "option/element/description.twig" as descriptionElement %}
38 | {{ descriptionElement.create(description) }}
39 |
40 | {% endmacro %}
--------------------------------------------------------------------------------
/src/plug-in/User/LocalUserResolver.php:
--------------------------------------------------------------------------------
1 |
11 | */
12 | class LocalUserResolver
13 | {
14 | /** @var ResolveLocalUser[] */
15 | private array $resolvers = [];
16 | private Logger $logger;
17 |
18 | public function __construct(Logger $logger)
19 | {
20 | $this->logger = $logger;
21 | }
22 |
23 | /**
24 | * @return ResolveLocalUser[]
25 | */
26 | public function getResolvers(): array
27 | {
28 | return $this->resolvers;
29 | }
30 |
31 | /**
32 | * Add a new resolver to the list of resolvers
33 | * @param ResolveLocalUser $resolveLocalUserBy
34 | * @return $this
35 | */
36 | public function add(ResolveLocalUser $resolveLocalUserBy): LocalUserResolver
37 | {
38 | $this->resolvers[] = $resolveLocalUserBy;
39 | return $this;
40 | }
41 |
42 | /**
43 | * Try each of the resolvers of this class and return the first match found.
44 | * @return \WP_User|null
45 | */
46 | public function resolve(): ?\WP_User
47 | {
48 | $usedResolvers = [];
49 |
50 | foreach ($this->resolvers as $resolver) {
51 | $description = $resolver->getDescription() ?? 'unknown';
52 | $r = $resolver->resolve();
53 |
54 | // a local WordPress user had been resolved by a given principal
55 | if ($r) {
56 | $this->logger->debug("User resolver '$description' returned a local WordPress user");
57 | return $r;
58 | }
59 |
60 | $usedResolvers[] = $description;
61 | }
62 |
63 | $this->logger->debug("A local WordPress user could not be found by any of the following resolvers: '" . implode(",", $usedResolvers) . "'");
64 |
65 | return null;
66 | }
67 | }
--------------------------------------------------------------------------------
/src/shared/Util/Validator/Rule/Conditional.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * @access
11 | */
12 | class Conditional extends RuleAdapter
13 | {
14 | /**
15 | * @var Rule[]
16 | */
17 | private $rules = array();
18 |
19 | /**
20 | * Conditions to match our data against, before we can run our validation.
21 | *
22 | * @var array
23 | */
24 | private $propertyCondition;
25 |
26 | /**
27 | * @param Rule[] $rules
28 | * @param array $propertyCondition
29 | */
30 | public function __construct($rules, array $propertyCondition)
31 | {
32 | parent::__construct('');
33 | $this->rules = $rules;
34 | $this->propertyCondition = $propertyCondition;
35 | }
36 |
37 | /**
38 | * Validate the given data.
39 | *
40 | * @param string $value
41 | * @param array $data
42 | *
43 | * @return bool|mixed
44 | */
45 | public function validate($value, $data)
46 | {
47 | if (!$this->areConditionsTrue($data)) {
48 | return true;
49 | }
50 |
51 | foreach ($this->rules as $rule) {
52 | $result = $rule->validate($value, $data);
53 |
54 | if (true !== $result) {
55 | return $result;
56 | }
57 | }
58 |
59 | return true;
60 | }
61 |
62 | /**
63 | * Check the given necessary conditions against our current data set.
64 | *
65 | * @param $data
66 | *
67 | * @return bool
68 | */
69 | protected function areConditionsTrue($data)
70 | {
71 | foreach ($this->propertyCondition as $key => $value) {
72 | $dataValue = $data[$key];
73 |
74 | if (isset($dataValue['option_value'])) {
75 | $dataValue = $dataValue['option_value'];
76 | }
77 |
78 | if ($dataValue != $value) {
79 | return false;
80 | }
81 | }
82 |
83 | return true;
84 | }
85 | }
--------------------------------------------------------------------------------
/src/plug-in/User/ResolveLocalUser.php:
--------------------------------------------------------------------------------
1 |
9 | */
10 | class ResolveLocalUser
11 | {
12 | private ?string $principal;
13 | private mixed $searchMethod;
14 | private ?string $description;
15 |
16 | /**
17 | * @param string|null $principal Principal to search for
18 | * @param callable $searchMethod How to search for the given principal
19 | * @param string|null $description Optional description for debug messages
20 | */
21 | public function __construct(?string $principal, callable $searchMethod, ?string $description = null)
22 | {
23 | $this->principal = $principal;
24 | $this->searchMethod = $searchMethod;
25 | $this->description = $description;
26 | }
27 |
28 | public function getPrincipal(): ?string
29 | {
30 | return $this->principal;
31 | }
32 |
33 | public function getSearchMethod(): callable
34 | {
35 | return $this->searchMethod;
36 | }
37 |
38 | public function getDescription(): ?string
39 | {
40 | return $this->description;
41 | }
42 |
43 | /**
44 | * Passes the getPrincipal to getSearchMethod and executes the search
45 | * @return \WP_User|null
46 | */
47 | public function resolve(): ?\WP_User
48 | {
49 | $method = $this->getSearchMethod();
50 |
51 | $r = $method($this->getPrincipal());
52 |
53 | if ($r instanceof \WP_User) {
54 | return $r;
55 | }
56 |
57 | return null;
58 | }
59 |
60 | /**
61 | * Create a new ResolveLocalUser instance
62 | *
63 | * @param string|null $principal
64 | * @param callable $searchMethod
65 | * @param string|null $description
66 | * @return ResolveLocalUser
67 | */
68 | public static function by(?string $principal, callable $searchMethod, ?string $description = null): ResolveLocalUser
69 | {
70 | return new static($principal, $searchMethod, $description);
71 | }
72 | }
--------------------------------------------------------------------------------
/views/option/element/select.twig:
--------------------------------------------------------------------------------
1 | {% macro create(optionName, permission, inputId) %}
2 |
3 | {% set value = getOptionValue(optionName, 1) %}
4 |
5 | {% set inline = getMetadata(optionName, 'INLINE')|join(' ') %}
6 | {% set description = getMetadata(optionName, 'DESCRIPTION') %}
7 | {% set elements = getMetadata(optionName, 'ELEMENTS') %}
8 | {% set angularAttributes = getMetadata(optionName, 'ANGULAR_ATTRIBUTES') %}
9 | {% set newNetwork = isOnNetworkDashboard() %}
10 |
11 | {% if permission == 2 or permission == 1 %}
12 | {% set disabled = "disabled" %}
13 | {% else %}
14 | {% set disabled = "" %}
15 | {% endif %}
16 | {% if not angularAttributes is empty %}
17 | {% if newNetwork %}
18 | {% set angularAttributes = angularAttributes ~ ' && (0))"' %}
19 | {% else %}
20 | {% set angularAttributes = angularAttributes ~ '&& (1))"' %}
21 | {% endif %}
22 | {% endif %}
23 |
41 |
42 |
43 | {% import "option/element/error-msg.twig" as errorElement %}
44 | {{ errorElement.create(optionName) }}
45 |
46 |
47 |
48 | {% import "option/element/description.twig" as descriptionElement %}
49 | {{ descriptionElement.create(description) }}
50 |
51 |
52 | {% endmacro %}
--------------------------------------------------------------------------------
/js/app/blog-options/controllers/blog.controller.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | app.controller('BlogController', BlogController);
3 |
4 | BlogController.$inject = ['$scope', '$timeout', 'DataService', 'PersistService', 'ngNotify'];
5 |
6 | function BlogController($scope, $timeout, DataService, PersistService, ngNotify) {
7 | $scope.runningRequests = 0;
8 |
9 | $scope.save = function () {
10 | var data = DataService.mergeScopeOptions($scope);
11 |
12 | PersistService.persistData(data.options).then(function (response) {
13 | $scope.$broadcast('validation', response);
14 |
15 | return response;
16 | }).then(function (result) {
17 | $scope.$emit('reset-form');
18 |
19 | if (result.status_success === true) {
20 | ngNotify.set(document['next_ad_int']['saving-success'], 'success');
21 |
22 | } else {
23 | ngNotify.set(document['next_ad_int']['saving-error'], 'error');
24 | }
25 |
26 | });
27 | };
28 |
29 | /**
30 | * Method used for evaluating if a value is present
31 | *
32 | * @returns {boolean}
33 | */
34 | $scope.is_input_empty = function(input_value) {
35 | return (input_value == '' || !input_value);
36 | };
37 |
38 | function activate() {
39 | $scope.runningRequests++;
40 |
41 | DataService.loadInitData().then(function (result) {
42 | $scope.$broadcast('options', result['options']);
43 | $scope.$broadcast('ldapAttributes', result['ldapAttributes']);
44 | $scope.$broadcast('dataTypes', result['dataTypes']);
45 | $scope.$broadcast('wpRoles', result['wpRoles']);
46 |
47 | $scope.runningRequests--;
48 | });
49 | }
50 |
51 | $timeout(activate);
52 | }
53 | })();
--------------------------------------------------------------------------------
/src/shared/Util/Validator/Validator.php:
--------------------------------------------------------------------------------
1 |
11 | * @author Sebastian Weinert
12 | * @author Danny Meißner
13 | *
14 | * @access public
15 | */
16 | class Validator
17 | {
18 | /**
19 | * An array of all validation rules registered.
20 | *
21 | * @var array
22 | */
23 | private $validationRules = array();
24 |
25 | /**
26 | * Validate the given data and return a new {@see Result}.
27 | *
28 | * @param array $data
29 | *
30 | * @return Result
31 | */
32 | public function validate($data)
33 | {
34 | $result = new Result();
35 |
36 | foreach ($this->validationRules as $name => $rules) {
37 | if (!isset($data[$name])) {
38 | continue; //TODO Revisit
39 | }
40 |
41 | $value = $data[$name];
42 |
43 | //TODO Find a better option
44 | if (is_array($value) && isset($value['option_value'])) {
45 | $value = $value['option_value'];
46 | }
47 |
48 | foreach ($rules as $rule) {
49 | /** @var Rule $rule */
50 | $validationResult = $rule->validate($value, $data);
51 |
52 | if (true !== $validationResult) {
53 | $result->addValidationResult($name, $validationResult);
54 | }
55 | }
56 | }
57 |
58 | return $result;
59 | }
60 |
61 | /**
62 | * Add a new rule to our registered rules.
63 | *
64 | * @param string $name
65 | * @param Rule $rule
66 | */
67 | public function addRule($name, Rule $rule)
68 | {
69 | if (!isset($this->validationRules[$name])) {
70 | $this->validationRules[$name] = array();
71 | }
72 |
73 | $this->validationRules[$name][] = $rule;
74 | }
75 |
76 | /**
77 | * Return the current validation rules.
78 | *
79 | * @return array
80 | */
81 | public function getValidationRules()
82 | {
83 | return $this->validationRules;
84 | }
85 | }
--------------------------------------------------------------------------------
/views/option/body.twig:
--------------------------------------------------------------------------------
1 | {# macro for generating tab bodies #}
2 | {% macro create(prefix, isProfile, i18n) %}
3 |
4 |
5 |
6 | {% import "option/group.twig" as group %}
7 | {% set grouping = getOptionsGrouping() %}
8 | {% set isOnNetworkDashboard = isOnNetworkDashboard() %}
9 |
10 | {# Create all tab bodies #}
11 | {% for tabName, optionGroups in grouping %}
12 | {% if isOptionGroupVisible(optionGroups) %}
13 | {# Create a tab body #}
14 | {% set tabId = 'tab_body_' ~ prefix ~ '__' ~ loop.index0 %}
15 |
16 | {% if loop.first %}
17 | {% set style = '' %}
18 | {% else %}
19 | {% set style = 'display: none' %}
20 | {% endif %}
21 |
22 | {% set tabId = 'tab_body_' ~ prefix ~ '__' ~ loop.index0 %}
23 |
24 |
26 | {{ group.create(optionGroups, isProfile, i18n) }}
27 | {% if isOnNetworkDashboard %}
28 |
31 |
32 | {{ i18n.haveToVerifyDomainConnection }}
33 | {% else %}
34 |
38 |
40 | {{ i18n.haveToVerifyDomainConnection }}
41 | {% endif %}
42 |
43 | {% endif %}
44 | {% endfor %}
45 |
46 |
47 |
48 | {% endmacro %}
--------------------------------------------------------------------------------
/src/shared/Util/Message/Message.php:
--------------------------------------------------------------------------------
1 |
9 | * @author Sebastian Weinert
10 | * @author Danny Meißner
11 | *
12 | * @access
13 | */
14 | class Message
15 | {
16 | /**
17 | * @var string $message
18 | */
19 | private $message;
20 | /**
21 | * @var string $type
22 | */
23 | private $type;
24 | /**
25 | * @var array
26 | */
27 | private $additionalInformation = array();
28 |
29 | private function __construct($message, $type, $additionalInformation)
30 | {
31 | $this->message = $message;
32 | $this->type = $type;
33 | $this->additionalInformation = $additionalInformation;
34 | }
35 |
36 | private function __clone()
37 | {
38 | }
39 |
40 | /**
41 | * Create a new success message.
42 | *
43 | * @param $message
44 | * @param array $additionalInformation
45 | *
46 | * @return Message
47 | */
48 | public static function success($message, $additionalInformation = array())
49 | {
50 | return new self($message, Type::SUCCESS, $additionalInformation);
51 | }
52 |
53 | /**
54 | * Create a new error message.
55 | *
56 | * @param $message
57 | * @param array $additionalInformation
58 | *
59 | * @return Message
60 | */
61 | public static function error($message, $additionalInformation = array())
62 | {
63 | return new self($message, Type::ERROR, $additionalInformation);
64 | }
65 |
66 | /**
67 | * Add an additional information to our message.
68 | *
69 | * @param $name
70 | * @param $value
71 | */
72 | public function addAdditionalInformation($name, $value)
73 | {
74 | $this->additionalInformation[$name] = $value;
75 | }
76 |
77 | /**
78 | * Convert the current message to an array.
79 | *
80 | * @return array
81 | */
82 | public function toArray()
83 | {
84 | return array(
85 | 'message' => $this->message,
86 | 'type' => $this->type,
87 | 'additionalInformation' => $this->additionalInformation,
88 | 'isMessage' => true,
89 | );
90 | }
91 | }
--------------------------------------------------------------------------------
/views/blog-profile-relationship.twig:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 | {% set sites = getSites() %}
8 | {% set profileIDs = findAllProfileIds() %}
9 | {% set defaultProfileID = findDefaultProfileId() %}
10 |
11 | {{ i18n.title }}
12 |
13 |
14 |
33 |
34 |
35 |
36 |
54 |
--------------------------------------------------------------------------------
/js/blog-options.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by the on 20.07.2015.
3 | */
4 | jQuery(document).ready(function () {
5 |
6 |
7 | jQuery('.save-blog-options').on('click', function () {
8 | var options = document['next_ad_int']['option_values']['blog'];
9 | var result = {};
10 |
11 | jQuery.each(options, function (name, obj) {
12 | result[name] = {
13 | 'option_value': obj.option_value()
14 | };
15 | });
16 |
17 | jQuery.post(
18 | ajaxurl,
19 | {
20 | 'action': 'next_ad_int_blog_options',
21 | 'data': result,
22 | 'security': document['next_ad_int']['security']
23 | },
24 | function (response) {
25 | if (response == 0) {
26 | var url = window.location.href;
27 | url = url.split('&tab=');
28 | url = url[0] + ('&tab=' + jQuery('.nav-tab-active').attr('tab_number'));
29 | window.location.href = url;
30 | } else {
31 |
32 | var options = document['next_ad_int']['option_values']['blog'];
33 | var optionNames = [];
34 | jQuery.each(options, function (name) {
35 | optionNames.push(name);
36 | });
37 |
38 | var responseObject = jQuery.parseJSON(response);
39 |
40 | optionNames.forEach(function (element) {
41 |
42 | var errorMsgElement = jQuery("#" + element + "_error_msg");
43 |
44 | if (responseObject[element] != undefined) {
45 |
46 | if (!errorMsgElement.length) {
47 | jQuery("#" + element + "__value").after('' + responseObject[element] + "
");
48 | }
49 | }
50 |
51 | if (errorMsgElement.length && responseObject[element] == undefined) {
52 | errorMsgElement.remove();
53 | }
54 | });
55 | }
56 | });
57 | });
58 |
59 |
60 | });
--------------------------------------------------------------------------------
/autoload.php:
--------------------------------------------------------------------------------
1 | __DIR__ . '/src/plug-in',
34 | "Dreitier\\" => __DIR__ . '/src/shared',
35 | ];
36 |
37 | // register our own namespaces.
38 | // @see https://stackoverflow.com/a/39774973/2545275
39 | foreach ($mapNamespacesToSourceDirectories as $namespace => $sourceDirectory) {
40 | spl_autoload_register(function ($classname) use ($namespace, $sourceDirectory) {
41 | // Check if the namespace matches the class we are looking for
42 | if (preg_match("#^" . preg_quote($namespace) . "#", $classname)) {
43 | // Remove the namespace from the file path since it's psr4
44 | $classname = str_replace($namespace, "", $classname);
45 | $filename = preg_replace("#\\\\#", "/", $classname) . ".php";
46 | $fullpath = $sourceDirectory . "/$filename";
47 |
48 | if (file_exists($fullpath)) {
49 | include_once $fullpath;
50 | }
51 | }
52 | });
53 | }
54 |
55 | // fallback to grant compatability for premium extensions
56 | require_once __DIR__ . '/src/compat-v2/stubs.php';
57 |
58 | define("NADI_PACKAGES_LOADED", true);
59 |
--------------------------------------------------------------------------------
/src/plug-in/Configuration/Option.php:
--------------------------------------------------------------------------------
1 | uninitializedAttributes = $uninitializedAttributes;
23 | }
24 |
25 | /**
26 | * Create a new Option
27 | * @param array $uninitializedAttributes
28 | * @return Option
29 | */
30 | public static function make(array $uninitializedAttributes = []): Option
31 | {
32 | return new static($uninitializedAttributes);
33 | }
34 |
35 | public function offsetSet($offset, $value): void
36 | {
37 | throw new \Exception("Option container is immutable");
38 | }
39 |
40 | public function offsetExists($offset): bool
41 | {
42 | return isset($this->uninitializedAttributes[$offset]);
43 | }
44 |
45 | public function offsetUnset($offset): void
46 | {
47 | throw new \Exception("Option container is immutable");
48 | }
49 |
50 | public function offsetGet($offset): mixed
51 | {
52 | if (isset($this->initializedAttributes[$offset])) {
53 | return $this->initializedAttributes[$offset];
54 | }
55 |
56 | if (!isset($this->uninitializedAttributes[$offset])) {
57 | return null;
58 | }
59 |
60 | // If attribute is a function, use it to initialize its value.
61 | // This allows accessing options before the 'init' hook (e.g. in `set_current_user`)
62 | // but prevents textdomain loading issues.
63 | $uninitialized = $this->uninitializedAttributes[$offset];
64 | $initialized = is_callable($uninitialized) ? $uninitialized() : $uninitialized;
65 |
66 | $this->initializedAttributes[$offset] = $initialized;
67 |
68 | return $initialized;
69 | }
70 | }
--------------------------------------------------------------------------------
/src/shared/Util/Assert.php:
--------------------------------------------------------------------------------
1 |
8 | * @access public
9 | */
10 | class Assert
11 | {
12 | private function __construct()
13 | {
14 | }
15 |
16 | /**
17 | * @param mixed $subject
18 | * @param null|string $msg
19 | * @throws \Exception if $subject is null
20 | */
21 | public static function notNull($subject, $msg = null)
22 | {
23 | if (null === $subject) {
24 | throw new \Exception(($msg ? $msg : "Given parameter must not be null"));
25 | }
26 | }
27 |
28 | /**
29 | * @param bool $subject
30 | * @param null|string $msg
31 | * @throws \Exception if $subject evaluates to false
32 | */
33 | public static function condition($subject, $msg = null)
34 | {
35 | if ($subject === false) {
36 | throw new \Exception(($msg ? $msg : "Given condition must be true but is '$subject'."));
37 | }
38 | }
39 |
40 | /**
41 | * @param mixed $subject
42 | * @param null|string $msg
43 | * @throws \Exception If $subject is not numeric
44 | */
45 | public static function numeric($subject, $msg = null)
46 | {
47 | if (!is_numeric($subject)) {
48 | throw new \Exception(($msg ? $msg : "Given parameter must be numeric but is '$subject'"));
49 | }
50 | }
51 |
52 | /**
53 | * @param mixed $subject
54 | * @param null|string $msg
55 | * @throws \Exception If $subject is null. If it is a string it length must be > 0 (without trimming).
56 | */
57 | public static function notEmpty($subject, $msg = null)
58 | {
59 | $defaultMsg = "Given parameter must not be empty";
60 | self::notNull($subject, $msg);
61 |
62 | if (is_string($subject) && (strlen($subject) == 0)) {
63 | throw new \Exception(($msg ? $msg : $defaultMsg));
64 | }
65 | }
66 |
67 | /**
68 | * @param mixed $subject
69 | * @param null|string $msg
70 | * @throws \Exception If $subject is not numeric or is less than zero.
71 | */
72 | public static function validId($subject, $msg = null)
73 | {
74 | self::numeric($subject, "Given parameter is not a valid numeric ID");
75 |
76 | if ($subject <= 0) {
77 | throw new \Exception(($msg ? $msg : "Given parameter must be greater than 0 but is '$subject'"));
78 | }
79 | }
80 | }
--------------------------------------------------------------------------------
/js/profile-options.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by the on 20.07.2015.
3 | */
4 | jQuery(document).ready(function () {
5 | function showOptionsOfSelectedProfile() {
6 | var selectedProfileId = jQuery('#selectedProfile').val();
7 | var profileOptionsOverview = '#profileOptionsOverview__' + selectedProfileId;
8 |
9 | jQuery('.profileOptionsOverview').hide();
10 | jQuery(profileOptionsOverview).show();
11 | }
12 |
13 | jQuery("#selectedProfile").change(showOptionsOfSelectedProfile);
14 | showOptionsOfSelectedProfile();
15 |
16 | //change the profile drop down menu to the last selected value
17 | if (window.location.href.indexOf('&profile=') > -1) {
18 | var profileNumber = window.location.href.split('&profile=')[1].split('&')[0];
19 | jQuery("#selectedProfile").val(parseInt(profileNumber));
20 | }
21 |
22 | jQuery('.save-blog-options').click(function () {
23 | var selectedProfileId = jQuery('#selectedProfile').val();
24 | var options = document['next_ad_int']['option_values'][selectedProfileId];
25 | var result = {};
26 |
27 | jQuery.each(options, function (name, obj) {
28 | result[name] = {
29 | 'option_value': obj['option_value'](),
30 | 'option_permission': obj['option_permission']()
31 | };
32 | });
33 |
34 | jQuery.post(
35 | ajaxurl,
36 | {
37 | 'action': 'next_ad_int_profile_options',
38 | 'data': {
39 | 'options': result,
40 | 'profile': selectedProfileId
41 | },
42 | 'security': document['next_ad_int']['security']
43 | },
44 | function (response) {
45 | if (response == 0) {
46 | var url = window.location.href;
47 | url = url.split('&tab=')[0];
48 | url = url.split('&profile=')[0];
49 | url = url + '&tab=' + jQuery('.nav-tab-active[profile_number=' + selectedProfileId + ']').attr('tab_number') + '&profile=' + selectedProfileId;
50 |
51 | window.location.href = url;
52 | } else {
53 | alert(response);
54 | }
55 | }
56 | );
57 | });
58 | })
59 | ;
--------------------------------------------------------------------------------
/views/user-profile-ad-attributes.twig:
--------------------------------------------------------------------------------
1 | {% if renderData.attributes|length > 0 %}
2 | {{ i18n.additionalInformation }}
3 | {% endif %}
4 |
5 |
6 |
7 | {% for attribute in renderData.attributes %}
8 |
9 |
10 |
11 | {% if attribute.noAttribute %}
12 |
13 | {{ attribute.description }}
14 |
15 | {% else %}
16 |
17 |
18 |
19 |
20 |
21 |
22 | {% if attribute.outputType == 'textarea' %}
23 |
25 | {% elseif attribute.outputType == 'text' %}
26 |
28 | {% else %}
29 | {{ attribute.value|nl2br }}
30 | {% endif %}
31 |
32 |
33 |
34 | {% endif %}
35 |
36 |
37 |
38 | {% endfor %}
39 |
40 | {% if renderData.adi_is_editable %}
41 | {% if renderData.require_password %}
42 |
43 |
44 |
46 |
47 |
48 |
50 |
51 | {{ i18n.youMustEnterPassword }}
52 |
53 |
54 |
55 | {% endif %}
56 | {% else %}
57 |
58 |
59 | {{ i18n.canNotBeEdited }} ~ {{ renderData.adi_synchronization_error_message }}
60 |
61 |
62 | {% endif %}
63 |
64 |
--------------------------------------------------------------------------------
/src/plug-in/User/Profile/Ui/PreventPasswordChange.php:
--------------------------------------------------------------------------------
1 |
15 | * @author Christopher Klein
16 | * @access public
17 | */
18 | class PreventPasswordChange
19 | {
20 | /** @var $multisiteConfigurationService Service */
21 | private $multisiteConfigurationService;
22 |
23 | /** @var $userManager Manager */
24 | private $userManager;
25 |
26 | /**
27 | * @param Service $multisiteConfigurationService
28 | * @param Manager $userManager
29 | */
30 | public function __construct(Service $multisiteConfigurationService,
31 | Manager $userManager)
32 | {
33 | $this->multisiteConfigurationService = $multisiteConfigurationService;
34 | $this->userManager = $userManager;
35 | }
36 |
37 | /**
38 | * Disable password fields for a user.
39 | */
40 | public function register()
41 | {
42 | // the callback functions have to decide whether to execute thm or not b/c they require the current user context
43 |
44 | // Is local password change disallowed?
45 | // disable password fields
46 | add_filter('show_password_fields', array($this, 'showPasswordFields'), 10, 2);
47 | }
48 |
49 | /**
50 | * Return the value of th setting "Allow local password changes"
51 | * @return bool
52 | */
53 | public function isPasswordChangeEnabled()
54 | {
55 | return $this->multisiteConfigurationService->getOptionValue(Options::ENABLE_PASSWORD_CHANGE);
56 | }
57 |
58 | /**
59 | * WordPress callback for showing/hiding the password fields
60 | *
61 | * @param bool $show setting from prior called plug-ins
62 | * @param WP_User $wpUser
63 | * @return mixed bool
64 | */
65 | public function showPasswordFields($show, $wpUser)
66 | {
67 | // if user is no AD member or a local user (admin etc.), the parent value has priority
68 | if (!$this->userManager->hasActiveDirectoryAccount($wpUser)) {
69 | return $show;
70 | }
71 |
72 | // user is AD member so decide by ADI setting
73 | return $this->isPasswordChangeEnabled();
74 | }
75 | }
--------------------------------------------------------------------------------
/js/app/profile-options/services/persistence.service.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | app.service('PersistService', PersistService);
3 |
4 | PersistService.$inject = ['$http', '$result', 'NotificationService'];
5 |
6 | function PersistService($http, $result, NotificationService) {
7 | var vm = this;
8 |
9 | vm.assignProfile = function (blogs, profileId) {
10 | var data = {
11 | profile: profileId,
12 | allblogs: jQuery.map(blogs, function (item) {
13 | return item['blog_id'];
14 | })
15 | };
16 |
17 | return $http.post('../admin-ajax.php', {
18 | action: 'next_ad_int_blog_profile_relationship',
19 | data: data,
20 | security: document['next_ad_int']['blog-rel-security']
21 | }).then(function () {
22 |
23 | });
24 | };
25 |
26 | vm.removeProfile = function (id) {
27 | return $http.post('../admin-ajax.php', {
28 | action: 'next_ad_int_profile_options',
29 | security: document.next_ad_int.security,
30 | subAction: 'removeProfile',
31 | id: id
32 | }).then($result);
33 | };
34 |
35 | vm.persistData = function (data) {
36 | return $http.post('../admin-ajax.php', {
37 | action: 'next_ad_int_profile_options',
38 | security: document.next_ad_int.security,
39 | subAction: 'persistProfileOptionsValues',
40 | data: data
41 | }).then($result);
42 | };
43 |
44 | vm.persist = function ($scope, _data, profileId) {
45 | var data = _data || JSON.parse(angular.toJson($scope.option));
46 | var dataPermission = JSON.parse(angular.toJson($scope.permission));
47 |
48 | var dataBuffer = {"options": {}};
49 |
50 | for (var option in data) {
51 | dataBuffer["options"][option] = {
52 | "option_value": data[option],
53 | "option_permission": dataPermission[option]
54 | };
55 | }
56 |
57 | dataBuffer["profile"] = profileId;
58 |
59 | return vm.persistData(dataBuffer).then($result).then(function (response) {
60 | NotificationService.showMessage(response);
61 | });
62 | };
63 |
64 | return vm;
65 | }
66 | })();
--------------------------------------------------------------------------------
/views/option/group.twig:
--------------------------------------------------------------------------------
1 | {# macro for generating option groups for a single tab body#}
2 | {% macro create(optionGroups, isProfile, i18n) %}
3 |
4 |
14 |
15 | {% import "option/lines.twig" as lines %}
16 | {% set newNetwork = isOnNetworkDashboard() %}
17 |
18 | {# Add all option groups of the current tab #}
19 | {% for optionGroupName, optionGroup in optionGroups %}
20 |
21 | {# Display the optionGroupName if it is not empty#}
22 | {% if optionGroupName and (optionGroupName != 'angular_controller' and optionGroupName != 'multisite_only') %}
23 |
24 | {{ optionGroupName }}
25 |
26 | {% endif %}
27 |
28 | {# Add the description or the array of descriptions to this option group #}
29 | {% if optionGroup.description is defined %}
30 | {{ optionGroup.description|join('
')|raw }}
31 | {% if optionGroupName is defined and newNetwork%}
32 |
33 |
34 |
35 | {{ i18n.managePermissions }}
36 |
37 |
38 | {% endif %}
39 | {% endif %}
40 |
41 | {# Do not add zero options#}
42 | {% if optionGroup.options is defined %}
43 | {# Add all option of this option group#}
44 |
45 | {{ lines.create(optionGroup.options, isProfile, i18n) }}
46 |
47 | {% endif %}
48 |
49 | {% endfor %}
50 |
51 | {% endmacro %}
--------------------------------------------------------------------------------
/views/option/element/editable_list.twig:
--------------------------------------------------------------------------------
1 | {% macro create(optionName, permission, inputId) %}
2 |
3 | {% set inline = getMetadata(optionName, 'INLINE')|join(' ') %}
4 | {% set description = getMetadata(optionName, 'DESCRIPTION') %}
5 | {% set elements = getMetadata(optionName, 'ELEMENTS') %}
6 | {% set angularAttributes = getMetadata(optionName, 'ANGULAR_ATTRIBUTES') %}
7 | {% set angularButtonAttributes = getMetadata(optionName, 'ANGULAR_BUTTON_ATTRIBUTES') %}
8 | {% set typeStructure = getMetadata(optionName, 'TYPE_STRUCTURE') %}
9 | {% set newNetwork = isOnNetworkDashboard() %}
10 |
11 |
12 | {% if permission == 2 or permission == 1 %}
13 | {% set disabled = "disabled" %}
14 | {% else %}
15 | {% set disabled = "" %}
16 | {% endif %}
17 |
18 | {% if not angularAttributes is empty %}
19 | {% if newNetwork %}
20 | {% set angularAttributes = angularAttributes ~ ' && (0))"' %}
21 | {% else %}
22 | {% set angularAttributes = angularAttributes ~ '&& (1))"' %}
23 | {% endif %}
24 | {% endif %}
25 |
26 |
27 |
31 |
32 |
33 |
34 | {% import "option/element/error-msg.twig" as errorElement %}
35 | {{ errorElement.create(optionName) }}
36 |
37 |
38 |
39 | -
40 |
41 |
42 |
46 |
47 |
48 |
49 |
50 | {% import "option/element/description.twig" as descriptionElement %}
51 | {{ descriptionElement.create(description) }}
52 |
53 | {% endmacro %}
--------------------------------------------------------------------------------
/src/shared/ActiveDirectory/Context.php:
--------------------------------------------------------------------------------
1 |
8 | * @access public
9 | * @since 2.2.0
10 | */
11 | class Context
12 | {
13 | /**
14 | * List of domain SIDs
15 | *
16 | * @var array
17 | */
18 | private $domainSids;
19 |
20 | /**
21 | * @param $domainSids
22 | * @throws \Exception
23 | */
24 | public function __construct(array $domainSids)
25 | {
26 | if (!is_array($domainSids) || (sizeof($domainSids) == 0)) {
27 | throw new \Exception("Atleast one domain SID must be configured");
28 | }
29 |
30 | $this->domainSids = array_map('strtoupper', $domainSids);
31 | }
32 |
33 | /**
34 | * Get the first defined domain SID, in an AD forest, this is the SID of the domain which NADI is connected to.
35 | * @return mixed
36 | */
37 | public function getPrimaryDomainSid()
38 | {
39 | return $this->domainSids[0];
40 | }
41 |
42 | /**
43 | * Retrieve all SIDs for this context.
44 | * @return array of strings
45 | */
46 | public function getForestSids()
47 | {
48 | return $this->domainSids;
49 | }
50 |
51 | /**
52 | * Return true if the given SID is part of one the SIDs defined for the context
53 | *
54 | * @param ?Sid $objectSid
55 | * @param false $primaryDomainOnly
56 | * @return bool
57 | */
58 | public function isMember(?Sid $objectSid, $primaryDomainOnly = false)
59 | {
60 | if (!$objectSid) {
61 | return false;
62 | }
63 |
64 | $useSid = $objectSid->getDomainPartAsSid();
65 |
66 | if (!$useSid) {
67 | return false;
68 | }
69 |
70 | $sidAsString = $useSid->getFormatted();
71 | $checkSids = $primaryDomainOnly ? [$this->domainSids[0]] : $this->domainSids;
72 |
73 | $r = in_array($sidAsString, $checkSids);
74 |
75 | return apply_filters(NEXT_ACTIVE_DIRECTORY_INTEGRATION_PREFIX . 'object_has_ad_context_membership', $r, $objectSid, $primaryDomainOnly, $this);
76 | }
77 |
78 | /**
79 | * Check the membership and throws an exception if the SID is not a member
80 | *
81 | * @param Sid $objectSid
82 | * @return bool
83 | * @throws \Exception
84 | */
85 | public function checkMembership(Sid $objectSid) {
86 | if (!$this->isMember($objectSid)) {
87 | throw new \Exception("SID '" . $objectSid . "' is not member of any of the following domain SIDs: " . $this);
88 | }
89 |
90 | return true;
91 | }
92 |
93 | public function __toString() {
94 | return "Context={domainSids={" . implode(",", $this->domainSids) . "}}" ;
95 | }
96 | }
--------------------------------------------------------------------------------
/css/alertify.min.css:
--------------------------------------------------------------------------------
1 | .alertify-logs>*{padding:12px 24px;color:#fff;box-shadow:0 2px 5px 0 rgba(0,0,0,.2);border-radius:1px}.alertify-logs>*,.alertify-logs>.default{background:rgba(0,0,0,.8)}.alertify-logs>.error{background:rgba(244,67,54,.8)}.alertify-logs>.success{background:rgba(76,175,80,.9)}.alertify{position:fixed;background-color:rgba(0,0,0,.3);left:0;right:0;top:0;bottom:0;width:100%;height:100%;z-index:99999}.alertify.hide{opacity:0;pointer-events:none}.alertify,.alertify.hide,.alertify.show{box-sizing:border-box;-webkit-transition:all .33s cubic-bezier(.25,.8,.25,1);transition:all .33s cubic-bezier(.25,.8,.25,1)}.alertify,.alertify *{box-sizing:border-box}.alertify .dialog{padding:12px}.alertify .alert,.alertify .dialog{width:100%;margin:0 auto;position:relative;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.alertify .alert>*,.alertify .dialog>*{width:400px;max-width:95%;margin:0 auto;text-align:center;padding:12px;background:#fff;box-shadow:0 2px 4px -1px rgba(0,0,0,.14),0 4px 5px 0 rgba(0,0,0,.098),0 1px 10px 0 rgba(0,0,0,.084)}.alertify .alert .msg,.alertify .dialog .msg{padding:12px;margin:0;text-align:left}.alertify .alert input,.alertify .dialog input{margin-bottom:15px;width:100%;font-size:100%;padding:12px}.alertify .alert input:focus,.alertify .dialog input:focus{outline-offset:-2px}.alertify .alert nav,.alertify .dialog nav{text-align:right}.alertify .alert nav button,.alertify .dialog nav button{background:0 0;box-sizing:border-box;color:rgba(0,0,0,.87);position:relative;outline:0;border:0;display:inline-block;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;padding:0 6px;margin:6px 8px;line-height:36px;min-height:36px;white-space:nowrap;min-width:88px;text-align:center;text-transform:uppercase;font-size:14px;text-decoration:none;cursor:pointer;border-radius:2px}.alertify .alert nav button:active,.alertify .alert nav button:hover,.alertify .dialog nav button:active,.alertify .dialog nav button:hover{background-color:rgba(0,0,0,.05)}.alertify .alert nav button:focus,.alertify .dialog nav button:focus{border-style:dashed}.alertify-logs{position:fixed;z-index:100;bottom:16px;left:16px}.alertify-logs>*{box-sizing:border-box;-webkit-transition:all .3s cubic-bezier(.25,.8,.25,1);transition:all .3s cubic-bezier(.25,.8,.25,1);margin-top:10px;position:relative;float:left;clear:both;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000;perspective:1000}.alertify-logs>.show{left:0;opacity:1}.alertify-logs>*,.alertify-logs>.hide{left:-110%;opacity:0}
--------------------------------------------------------------------------------
/js/app/blog-options/controllers/logging.controller.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 | app.controller('LoggingController', LoggingController);
4 |
5 | LoggingController.$inject = ['$scope', '$http', 'DataService', 'PersistService', 'ngNotify'];
6 |
7 | function LoggingController($scope, $http, DataService, PersistService, ngNotify) {
8 | var vm = this;
9 |
10 | $scope.isSaveDisabled = false;
11 |
12 | $scope.permissionOptions = DataService.getPermissionOptions();
13 |
14 |
15 | $scope.$on('options', function (event, data) {
16 | $scope.option = {
17 | logger_enable_logging: $valueHelper.findValue("logger_enable_logging", data),
18 | logger_custom_path: $valueHelper.findValue("logger_custom_path", data),
19 | };
20 |
21 | if ($valueHelper.findValue("domain_sid", data) == '') {
22 | $scope.isSaveDisabled = true;
23 | }
24 |
25 | $scope.permission = {
26 | logger_enable_logging: $valueHelper.findPermission("logger_enable_logging", data),
27 | logger_custom_path: $valueHelper.findPermission("logger_custom_path", data),
28 | };
29 | });
30 |
31 | $scope.$on('validation', function (event, data) {
32 | $scope.messages = {
33 | logger_enable_logging: $valueHelper.findMessage("logger_enable_logging", data),
34 | logger_custom_path: $valueHelper.findMessage("logger_custom_path", data),
35 | };
36 | });
37 |
38 | $scope.$on('verification', function (event, data) {
39 | $scope.isSaveDisabled = false;
40 | });
41 |
42 | $scope.containsErrors = function () {
43 | return (!$arrayUtil.containsOnlyNullValues($scope.messages));
44 | };
45 |
46 | $scope.activateLogging = function () {
47 | console.log("Save Logging information");
48 |
49 | var data = {
50 | options : {
51 | logger_enable_logging : $scope.option.logger_enable_logging,
52 | logger_custom_path : $scope.option.logger_custom_path
53 | }
54 | };
55 |
56 | PersistService.persistData(data.options).then(function (response) {
57 |
58 | if (response.status_success === true) {
59 | ngNotify.set(document['next_ad_int']['saving-success'], 'success');
60 |
61 | } else {
62 | ngNotify.set(document['next_ad_int']['saving-error'], 'error');
63 | }
64 | });
65 | }
66 | }
67 | })();
--------------------------------------------------------------------------------
/js/app/blog-options/controllers/security.controller.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | app.controller('SecurityController', SecurityController);
3 |
4 | SecurityController.$inject = ['$scope', 'ListService', 'DataService'];
5 |
6 | function SecurityController($scope, ListService, DataService) {
7 | var vm = this;
8 |
9 | $scope.isSaveDisabled = false;
10 |
11 | $scope.permissionOptions = DataService.getPermissionOptions();
12 |
13 | $scope.$on('options', function (event, data) {
14 | $scope.option = {
15 | enable_smartcard_user_login: $valueHelper.findValue("enable_smartcard_user_login", data),
16 | custom_login_page_enabled: $valueHelper.findValue("custom_login_page_enabled", data),
17 | custom_login_page_uri: $valueHelper.findValue("custom_login_page_uri", data),
18 | allow_xmlrpc_login: $valueHelper.findValue("allow_xmlrpc_login", data),
19 | };
20 |
21 | if ($valueHelper.findValue("domain_sid", data) == '') {
22 | $scope.isSaveDisabled = true;
23 | }
24 |
25 | $scope.permission = {
26 | enable_smartcard_user_login: $valueHelper.findPermission("enable_smartcard_user_login", data),
27 | custom_login_page_enabled: $valueHelper.findPermission("custom_login_page_enabled", data),
28 | custom_login_page_uri: $valueHelper.findPermission("custom_login_page_uri", data),
29 | allow_xmlrpc_login: $valueHelper.findPermission("allow_xmlrpc_login", data),
30 | };
31 | });
32 |
33 | $scope.$on('validation', function (event, data) {
34 | $scope.messages = {
35 | enable_smartcard_user_login: $valueHelper.findMessage("enable_smartcard_user_login", data),
36 | custom_login_page_enabled: $valueHelper.findMessage("custom_login_page_enabled", data),
37 | custom_login_page_uri: $valueHelper.findMessage("custom_login_page_uri", data),
38 | allow_xmlrpc_login: $valueHelper.findMessage("allow_xmlrpc_login", data)
39 | };
40 | });
41 |
42 | $scope.$on('verification', function (event, data) {
43 | $scope.isSaveDisabled = false;
44 | });
45 |
46 | $scope.getPreparedOptions = function () {
47 | var data = DataService.cleanOptions($scope.option);
48 | return data;
49 | };
50 |
51 | $scope.containsErrors = function () {
52 | return (!$arrayUtil.containsOnlyNullValues($scope.messages));
53 | };
54 |
55 | $scope.save = function() {
56 | $scope.$parent.save();
57 | };
58 | }
59 | })();
--------------------------------------------------------------------------------
/js/app/profile-options/controllers/delete.controller.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | app.controller('DeleteController', DeleteController);
3 |
4 | DeleteController.$inject = ['$rootScope', '$scope', 'PersistService', 'BrowserService'];
5 |
6 | function DeleteController($rootScope, $scope, PersistService, BrowserService) {
7 | $scope.profiles = [];
8 | $scope.associations = [];
9 | $scope.associationIds = [];
10 | $scope.show = false;
11 | $scope.profile = null;
12 | $scope.profileId = null;
13 | $scope.newProfile = '-1';
14 |
15 | $scope.showProfileList = false;
16 |
17 | $scope.$on('delete', function (event, profile, profiles, associations) {
18 | $scope.profile = profile;
19 | $scope.profileId = profile['profileId'];
20 | $scope.showProfileList = (associations.length > 0 && associations.length < 5);
21 | $scope.profiles = profiles;
22 |
23 | $scope.associations = associations;
24 | $scope.associationIds = jQuery.map(associations, function (item) {
25 | return item['blog_id'];
26 | }).join(',');
27 |
28 | $scope.show = true;
29 | });
30 |
31 | /**
32 | * Filter out the current active profile.
33 | *
34 | * @param value
35 | * @param index
36 | * @param array
37 | *
38 | * return {boolean}
39 | */
40 | $scope.newProfileFilter = function (value, index, array) {
41 | return (value != $scope.activeProfile);
42 | };
43 |
44 | /**
45 | * Cancel the delete process.
46 | */
47 | $scope.cancel = function () {
48 | $scope.show = false;
49 | };
50 |
51 | /**
52 | * Confirm the delete process.
53 | */
54 | $scope.confirm = function () {
55 | // if the profile is new, remove it and do not trigger the server
56 | if (-1 == $scope.profileId) {
57 | return;
58 | }
59 |
60 | if (null == $scope.profileId) {
61 | $rootScope.$broadcast('remove-profile', $scope.profile);
62 | $scope.show = false;
63 | return;
64 | }
65 |
66 | PersistService.assignProfile($scope.associations, $scope.newProfile).then(function () {
67 | // if the profile has already been persisted, remove it from the server
68 | PersistService.removeProfile($scope.profileId).then(function (result) {
69 | BrowserService.reload();
70 | });
71 | });
72 | };
73 | }
74 | })();
--------------------------------------------------------------------------------
/src/plug-in/Authentication/SingleSignOn/Profile/Matcher.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * @access
11 | * @since 2.2.0
12 | */
13 | class Matcher
14 | {
15 | /**
16 | * a profile found by a NETBIOS realm
17 | */
18 | const NETBIOS = "netbios";
19 |
20 | /**
21 | * a profile found by an account_suffix
22 | */
23 | const UPN_SUFFIX = "upn_suffix";
24 |
25 | /**
26 | * a profile found by its Kerberos realm
27 | */
28 | const KERBEROS_REALM = "kerberos_realm";
29 |
30 | /**
31 | * by default, we assume that the UPN suffix is used
32 | * @var string
33 | */
34 | private $type = self::UPN_SUFFIX;
35 |
36 | /**
37 | * profile assigned
38 | * @var array|null
39 | */
40 | private $profile = null;
41 |
42 | /**
43 | * @param $profile
44 | */
45 | public function __construct($profile)
46 | {
47 | $this->profile = $profile;
48 | }
49 |
50 | /**
51 | * Sets the type of the match
52 | *
53 | * @param $type
54 | * @return $this
55 | * @throws \Exception If the given type is non of NETBIOS, UPN_SUFFIX or KERBEROS_REALM
56 | */
57 | public function setType($type)
58 | {
59 | if (!in_array($type, array(self::NETBIOS, self::UPN_SUFFIX, self::KERBEROS_REALM))) {
60 | throw new \Exception("Unknown type");
61 | }
62 |
63 | $this->type = $type;
64 | return $this;
65 | }
66 |
67 | /**
68 | * @return string
69 | */
70 | public function getType()
71 | {
72 | return $this->type;
73 | }
74 |
75 | /**
76 | * @return array|null
77 | */
78 | public function getProfile()
79 | {
80 | return $this->profile;
81 | }
82 |
83 | /**
84 | * Wither which creates a new Matcherwith provided type
85 | * @param $type
86 | * @return $this
87 | * @throws \Exception
88 | */
89 | public function withType($type)
90 | {
91 | $r = new Matcher($this->profile);
92 |
93 | return $r->setType($type);
94 | }
95 |
96 | public function __toString()
97 | {
98 | return "Match={type='" . $this->type . "'}";
99 | }
100 |
101 | /**
102 | * Factory methods, which delegates to #withType
103 | *
104 | * @param $profile
105 | * @param $type
106 | * @return static
107 | * @throws \Exception
108 | */
109 | public static function create($profile, $type)
110 | {
111 | $r = new Matcher($profile);
112 | return $r->withType($type);
113 | }
114 |
115 | /**
116 | * Creates a null instance
117 | * @return null
118 | */
119 | public static function noMatch()
120 | {
121 | return null;
122 | }
123 | }
--------------------------------------------------------------------------------
/js/libraries/ng-notify.min.js:
--------------------------------------------------------------------------------
1 | !function(){"use strict";var a=angular.module("ngNotify",[]),b=!1;try{angular.module("ngSanitize")&&(angular.module("ngNotify").requires.push("ngSanitize"),b=!0)}catch(c){}var d='×';a.run(["$templateCache",function(a){a.put("templates/ng-notify/ng-notify.html",d)}]),a.provider("ngNotify",function(){this.$get=["$document","$compile","$log","$rootScope","$timeout","$interval","$templateCache",function(a,c,d,e,f,g,h){var i,j,k="",l=" ",m=3e3,n="ngn-sticky",o=1,p=-1,q=200,r=500,s=25,t=0,u=1,v={theme:"pure",position:"bottom",duration:m,type:"info",sticky:!1,button:!0,html:!1},w={notifyClass:"",notifyMessage:"",notifyStyle:{display:"none",opacity:t}},x={pure:k,prime:"ngn-prime",pastel:"ngn-pastel",pitchy:"ngn-pitchy"},y={info:"ngn-info",error:"ngn-error",success:"ngn-success",warn:"ngn-warn",grimace:"ngn-grimace"},z={bottom:"ngn-bottom",top:"ngn-top"},A=e.$new(),B=c(h.get("templates/ng-notify/ng-notify.html"))(A);A.ngNotify=angular.extend({},w),f(function(){a.find("body").append(B)});var C=function(a){var b=a.type||v.type;return(y[b]||y.info)+l},D=function(a){var b=a.theme||v.theme;return(x[b]||x.pure)+l},E=function(a){var b=a.position||v.position;return(z[b]||z.bottom)+l},F=function(a){var b=a.duration||v.duration;return angular.isNumber(b)?b:m},G=function(a){var b=void 0!==a.sticky?a.sticky:v.sticky;return b?!0:!1},H=function(a,b){var c=void 0!==a.button?a.button:v.button;return c&&b},I=function(a){if((a.html||v.html)&&!b)return d.debug("ngNotify warning: \ngSanitize couldn't be located. In order to use the 'html' option, be sure the ngSanitize source is included in your project."),!1;var c=void 0!==a.html?a.html:v.html;return c?!0:!1},J=function(a,b){var c=C(a)+D(a)+E(a);return c+=b?n:k},K=function(){A.ngNotify=angular.extend({},w)},L=function(a,b,c,d){var e=s/c;A.ngNotify.notifyStyle={display:"block",opacity:b};var f=function(){b+=a*e,A.ngNotify.notifyStyle.opacity=b,(t>=b||b>=u)&&(g.cancel(j),j=!1,d())};j||(j=g(f,s))},M=function(a,b){L(p,u,a,b)},N=function(a,b){L(o,t,a,b)};return A.dismiss=function(){M(r,function(){K()})},{config:function(a){a=a||{},angular.extend(v,a)},set:function(a,b){if(a){g.cancel(j),j=!1,f.cancel(i);var c={};"object"==typeof b?c=b:c.type=b;var d=G(c),e=F(c);angular.extend(A.ngNotify,{notifyHtml:I(c),notifyClass:J(c,d),notifyButton:H(c,d),notifyMessage:a}),N(q,function(){d||(i=f(function(){A.dismiss()},e))})}},dismiss:function(){A.dismiss()},addTheme:function(a,b){a&&b&&(x[a]=b)},addType:function(a,b){a&&b&&(y[a]=b)}}}]})}();
2 | //# sourceMappingURL=ng-notify.min.js.map
--------------------------------------------------------------------------------
/src/plug-in/Multisite/Site/Ui/ExtendSiteList.php:
--------------------------------------------------------------------------------
1 |
13 | * @access public
14 | */
15 | class ExtendSiteList
16 | {
17 | const ADI_PROFILE_COLUMN = 'adi-profile';
18 |
19 | /**
20 | * @var BlogConfigurationRepository
21 | */
22 | private $blogConfigurationRepository;
23 |
24 | /**
25 | * @var ProfileRepository
26 | */
27 | private $profileRepository;
28 |
29 | /**
30 | * @param BlogConfigurationRepository $blogConfigurationRepository
31 | * @param ProfileRepository $profileRepository
32 | */
33 | public function __construct(BlogConfigurationRepository $blogConfigurationRepository,
34 | ProfileRepository $profileRepository
35 | )
36 | {
37 | $this->blogConfigurationRepository = $blogConfigurationRepository;
38 | $this->profileRepository = $profileRepository;
39 | }
40 |
41 | /**
42 | * Add an 'user is disabled' indicator on the user management screen.
43 | */
44 | public function register()
45 | {
46 | add_filter('wpmu_blogs_columns', array($this, 'addColumns'), 10, 1);
47 | add_action('manage_sites_custom_column', array($this, 'addContent'), 1, 2);
48 | }
49 |
50 | /**
51 | * Add ADI profile column
52 | *
53 | * @param array $columns
54 | *
55 | * @return array
56 | */
57 | public function addColumns($columns)
58 | {
59 | $columns[self::ADI_PROFILE_COLUMN] = __('Active NADI profile', 'next-active-directory-integration');
60 |
61 | return $columns;
62 | }
63 |
64 | /**
65 | * Add the ADI profile for the current blog
66 | *
67 | * @param string $columnName
68 | * @param int $blogId
69 | *
70 | * @return string
71 | */
72 | public function addContent($columnName, $blogId)
73 | {
74 | if ($columnName == self::ADI_PROFILE_COLUMN) {
75 | $id = $this->blogConfigurationRepository->findProfileId($blogId);
76 | $isDefaultProfileUsed = $this->blogConfigurationRepository->isDefaultProfileUsed($blogId);
77 |
78 | if ($id) {
79 | $name = $this->profileRepository->findName($id, '');
80 |
81 | if ($isDefaultProfileUsed) {
82 | echo sprintf(__('%s (default profile)', 'next-active-directory-integration'), $name);
83 |
84 | return;
85 | }
86 |
87 | if ($name) {
88 | echo $name;
89 |
90 | return;
91 | }
92 | }
93 |
94 | echo "" . __('None assigned', 'next-active-directory-integration') . '';
95 | }
96 | }
97 | }
--------------------------------------------------------------------------------
/src/plug-in/Ui/Validator/Rule/DisallowInvalidWordPressRoles.php:
--------------------------------------------------------------------------------
1 |
18 | * @author Sebastian Weinert
19 | * @author Danny Meißner
20 | *
21 | * @access
22 | */
23 | class DisallowInvalidWordPressRoles extends RuleAdapter
24 | {
25 | /**
26 | * Validate the given data.
27 | *
28 | * @param string $value
29 | * @param array $data
30 | *
31 | * @return mixed
32 | */
33 | public function validate($value, $data)
34 | {
35 | $wpRoles = $this->getWpRoles($value);
36 |
37 | // check for invalid roles
38 | if ($this->containsInvalidRoles($wpRoles)) {
39 | $msg = $this->getMsg();
40 | return $msg[1];
41 | }
42 |
43 | // check for super user in blog
44 | if ($this->isOnNetworkDashboard()) {
45 | return true;
46 | }
47 |
48 | if (ArrayUtil::containsIgnoreCase(Manager::ROLE_SUPER_ADMIN, $wpRoles)) {
49 | $msg = $this->getMsg();
50 | return array(Type::ERROR => $msg[Type::ERROR][0]);
51 | }
52 |
53 | // all ok
54 | return true;
55 | }
56 |
57 | /**
58 | * Check if all @param $roles exist in the WordPress instance.
59 | *
60 | * @param $roles
61 | * @return bool
62 | */
63 | protected function containsInvalidRoles($roles)
64 | {
65 | $wpRoles = new \WP_Roles();
66 | foreach ($roles as $role) {
67 | if (!$wpRoles->is_role($role) && $role !== Manager::ROLE_SUPER_ADMIN) {
68 | return true;
69 | }
70 | }
71 |
72 | return false;
73 | }
74 |
75 | /**
76 | * Convert the given list string and retrieve all WordPress roles.
77 | *
78 | * @param $value
79 | *
80 | * @return array
81 | */
82 | protected function getWpRoles($value)
83 | {
84 | // convert the given string into separate lines
85 | $roleMappings = StringUtil::split($value, ';');
86 | // remove empty values from the array
87 | $roleMappings = array_filter($roleMappings);
88 |
89 | return array_map(function ($roleMappingString) {
90 | $roleMapping = StringUtil::split($roleMappingString, '=');
91 |
92 | return $roleMapping[1];
93 | }, $roleMappings);
94 | }
95 |
96 | /**
97 | * Check if the user is currently on the network Dashboard.
98 | *
99 | * @return bool
100 | */
101 | protected function isOnNetworkDashboard()
102 | {
103 | return Util::isOnNetworkDashboard();
104 | }
105 | }
--------------------------------------------------------------------------------
/js/app/profile-options/controllers/security.controller.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | app.controller('SecurityController', SecurityController);
3 |
4 | SecurityController.$inject = ['$scope', 'ListService', 'DataService'];
5 |
6 | function SecurityController($scope, ListService, DataService) {
7 | var vm = this;
8 |
9 | $scope.isSaveDisabled = false;
10 |
11 | $scope.$on('permissionItems', function (event, data) {
12 | $scope.permissionOptions = data;
13 | });
14 |
15 | $scope.$on('options', function (event, data) {
16 | $scope.option = {
17 | enable_smartcard_user_login: $valueHelper.findValue("enable_smartcard_user_login", data),
18 | custom_login_page_enabled: $valueHelper.findValue("custom_login_page_enabled", data),
19 | custom_login_page_uri: $valueHelper.findValue("custom_login_page_uri", data),
20 | allow_xmlrpc_login: $valueHelper.findValue("allow_xmlrpc_login", data)
21 | };
22 |
23 | if ($valueHelper.findValue("domain_sid", data) == '') {
24 | $scope.isSaveDisabled = true;
25 | } else {
26 | $scope.isSaveDisabled = false;
27 | }
28 |
29 | $scope.permission = {
30 | enable_smartcard_user_login: $valueHelper.findPermission("enable_smartcard_user_login", data),
31 | custom_login_page_enabled: $valueHelper.findPermission("custom_login_page_enabled", data),
32 | custom_login_page_uri: $valueHelper.findPermission("custom_login_page_uri", data),
33 | allow_xmlrpc_login: $valueHelper.findPermission("allow_xmlrpc_login", data)
34 | };
35 | });
36 |
37 | $scope.$on('validation', function (event, data) {
38 | $scope.messages = {
39 | enable_smartcard_user_login: $valueHelper.findMessage("enable_smartcard_user_login", data),
40 | custom_login_page_enabled: $valueHelper.findMessage("custom_login_page_enabled", data),
41 | custom_login_page_uri: $valueHelper.findMessage("custom_login_page_uri", data),
42 | allow_xmlrpc_login: $valueHelper.findMessage("allow_xmlrpc_login", data)
43 | };
44 | });
45 |
46 | $scope.$on('verification', function (event, data) {
47 | $scope.isSaveDisabled = false;
48 | });
49 |
50 | $scope.getPreparedOptions = function () {
51 | var data = DataService.cleanOptions($scope.option);
52 | return data;
53 | };
54 |
55 | $scope.containsErrors = function () {
56 | return (!$arrayUtil.containsOnlyNullValues($scope.messages));
57 | };
58 |
59 | $scope.save = function() {
60 | $scope.$parent.save();
61 | };
62 | }
63 | })();
--------------------------------------------------------------------------------
/js/libraries/angular-busy.min.js:
--------------------------------------------------------------------------------
1 | /*** An AngularJS module for reacting to when your app is busy.
2 | * @author Mike Grabski
3 | * @version v0.2.0
4 | * @link https://github.com/HackedByChinese/ng-busy.git
5 | * @license MIT
6 | */
7 | !function(a,b){"use strict";b.module("ngBusy.interceptor",[]).provider("busyInterceptor",function(){this.$get=["$rootScope","$q",function(a,b){function c(){e=f=0}function d(b){b.config.notBusy||(a.$broadcast("busy.end",{url:b.config.url,name:b.config.name,remaining:e-++f}),f>=e&&c())}var e=0,f=0;return{outstanding:function(){return e-f},request:function(c){return c.notBusy||(a.$broadcast("busy.begin",{url:c.url,name:c.name}),e++),c||b.when(c)},response:function(a){return d(a),a},responseError:function(a){return d(a),b.reject(a)}}}]}).config(["$httpProvider",function(a){a.interceptors.push("busyInterceptor")}]),b.module("ngBusy.busy",[]).directive("busy",["$parse","$timeout",function(a,c){return{restrict:"A",tranclude:!0,scope:{},controller:["$scope",function(a){this.setBusyMessageElement=function(b){a.busyMessageElement=b}}],link:function(d,e,f){f.$observe("busy",function(a){d.busyMessage=a}),f.$observe("busyWhenUrl",function(a){d.busyWhenUrl=a}),f.$observe("busyWhenName",function(a){d.busyWhenName=a}),f.$observe("busyAddClasses",function(a){d.busyAddClasses=a}),f.$observe("busyRemoveClasses",function(a){d.busyRemoveClasses=a}),f.$observe("busyDisabled",function(c){var e=a(c)(d);d.busyDisabled=b.isDefined(e)?e:!0}),f.$observe("notBusyWhenUrl",function(a){d.notBusyWhenUrl=a}),f.$observe("notBusyWhenName",function(a){d.notBusyWhenName=a}),f.$observe("notBusyAddClasses",function(a){d.notBusyAddClasses=a}),f.$observe("notBusyRemoveClasses",function(a){d.notBusyRemoveClasses=a}),f.$observe("notBusyDisabled",function(c){var e=a(c)(d);d.notBusyDisabled=b.isDefined(e)?e:!1}),d.isBusyFor=function(a,b){var c;return d[c=b?"busyWhenName":"notBusyWhenName"]?!!a.name&&!!a.name.match(d[c]):d[c=b?"busyWhenUrl":"notBusyWhenUrl"]?!!a.url&&!!a.url.match(d[c]):b===!0||a.remaining<=0},d.$on("busy.begin",function(a,b){if(!d.busy&&d.isBusyFor(b,!0)){d.originalContent=e.html(),d.busyDisabled&&c(function(){e.attr("disabled",!0)});var f=d.busyMessageElement?d.busyMessageElement.clone():null;(f||d.busyMessage)&&e.html("").append(f||d.busyMessage),e.removeClass(d.busyRemoveClasses).addClass(d.busyAddClasses),d.busy=!0}}),d.$on("busy.end",function(a,b){d.busy&&d.isBusyFor(b)&&(d.originalContent&&e.html(d.originalContent),e.attr("disabled",d.notBusyDisabled===!0),e.removeClass(d.notBusyRemoveClasses).addClass(d.notBusyAddClasses),d.busy=!1)})}}}]).directive("busyMessage",function(){return{restrict:"AE",transclude:!0,require:"^busy",template:"",replace:!0,compile:function(a,b,c){return function(a,b,d,e){e.setBusyMessageElement(c(a,function(){}))}}}}),b.module("ngBusy",["ngBusy.interceptor","ngBusy.busy"])}(window,window.angular);
8 | //# sourceMappingURL=angular-busy.map
--------------------------------------------------------------------------------
/js/app/blog-options/controllers/sso.controller.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | app.controller('SsoController', SsoController);
3 |
4 | SsoController.$inject = ['$scope', 'ListService', 'DataService'];
5 |
6 | function SsoController($scope, ListService, DataService) {
7 | var vm = this;
8 |
9 | $scope.isSaveDisabled = false;
10 |
11 | $scope.permissionOptions = DataService.getPermissionOptions();
12 |
13 | $scope.$on('options', function (event, data) {
14 | $scope.option = {
15 | sso: $valueHelper.findValue("sso", data),
16 | sso_user: $valueHelper.findValue("sso_user", data),
17 | sso_password: $valueHelper.findValue("sso_password", data),
18 | sso_environment_variable: $valueHelper.findValue("sso_environment_variable", data),
19 | sso_disable_for_xmlrpc: $valueHelper.findValue("sso_disable_for_xmlrpc", data),
20 | kerberos_realm_mappings: $valueHelper.findValue("kerberos_realm_mappings", data)
21 | };
22 |
23 | if ($valueHelper.findValue("domain_sid", data) == '') {
24 | $scope.isSaveDisabled = true;
25 | }
26 |
27 | $scope.permission = {
28 | sso: $valueHelper.findPermission("sso", data),
29 | sso_user: $valueHelper.findPermission("sso_user", data),
30 | sso_password: $valueHelper.findPermission("sso_password", data),
31 | sso_environment_variable: $valueHelper.findPermission("sso_environment_variable", data),
32 | sso_disable_for_xmlrpc: $valueHelper.findPermission("sso_disable_for_xmlrpc", data),
33 | kerberos_realm_mappings: $valueHelper.findPermission("kerberos_realm_mappings", data)
34 | };
35 | });
36 |
37 | $scope.$on('validation', function (event, data) {
38 | $scope.messages = {
39 | sso: $valueHelper.findMessage("sso", data),
40 | sso_user: $valueHelper.findMessage("sso_user", data),
41 | sso_password: $valueHelper.findMessage("sso_password", data),
42 | sso_environment_variable: $valueHelper.findMessage("sso_environment_variable", data),
43 | kerberos_realm_mappings: $valueHelper.findMessage("kerberos_realm_mappings", data)
44 | };
45 | });
46 |
47 | $scope.$on('verification', function (event, data) {
48 | $scope.isSaveDisabled = false;
49 | });
50 |
51 | $scope.getPreparedOptions = function () {
52 | var data = DataService.cleanOptions($scope.option);
53 | return data;
54 | };
55 |
56 | $scope.containsErrors = function () {
57 | return (!$arrayUtil.containsOnlyNullValues($scope.messages));
58 | };
59 |
60 | $scope.save = function() {
61 | $scope.$parent.save();
62 | };
63 | }
64 | })();
--------------------------------------------------------------------------------
/src/shared/Util/Session/SessionHandler.php:
--------------------------------------------------------------------------------
1 |
12 | * @author Danny Meißner
13 | *
14 | * @access
15 | */
16 | class SessionHandler
17 | {
18 | /**
19 | * @var SessionHandler
20 | */
21 | private static $instance = null;
22 |
23 | private function __construct()
24 | {
25 | }
26 |
27 | private function __clone()
28 | {
29 | }
30 |
31 | /**
32 | * Get the singleton instance of {@link SessionHandler}.
33 | *
34 | * @return SessionHandler
35 | */
36 | public static function getInstance()
37 | {
38 | $args = func_get_args();
39 | $instance = self::$instance;
40 |
41 | if (sizeof($args) > 0) {
42 | $instance = $args[0];
43 | }
44 |
45 | if ($instance == null) {
46 | // create new instance
47 | self::$instance = new SessionHandler();
48 | self::$instance->startSession();
49 | } else {
50 | // get instance from parameter
51 | self::$instance = $instance;
52 | }
53 |
54 | return self::$instance;
55 | }
56 |
57 | /**
58 | * Save the given value in the session using the next_ad_int_ prefix and {@code $key} as key.
59 | *
60 | * @param $key
61 | * @param $value
62 | */
63 | public function setValue($key, $value)
64 | {
65 | $sessionKey = $this->normalizeKey($key);
66 | $_SESSION[$sessionKey] = $value;
67 | }
68 |
69 | /**
70 | * Retrieve the value from the session using the next_ad_int_ prefix and {@code $key} as key.
71 | *
72 | * @param $key
73 | * @param null $default
74 | *
75 | * @return null
76 | */
77 | public function getValue($key, $default = null)
78 | {
79 | $sessionKey = $this->normalizeKey($key);
80 |
81 | if (!isset($_SESSION[$sessionKey])) {
82 | return $default;
83 | }
84 |
85 | return $_SESSION[$sessionKey];
86 | }
87 |
88 | /**
89 | * Remove an entry from the session.
90 | *
91 | * @param $key
92 | */
93 | public function clearValue($key)
94 | {
95 | $sessionKey = $this->normalizeKey($key);
96 |
97 | unset($_SESSION[$sessionKey]);
98 | }
99 |
100 | /**
101 | * Return the normalized key.
102 | *
103 | * @param $key
104 | *
105 | * @return string
106 | */
107 | protected function normalizeKey($key)
108 | {
109 | if (StringUtil::startsWith(NEXT_ACTIVE_DIRECTORY_INTEGRATION_PREFIX, $key)) {
110 | return $key;
111 | }
112 |
113 | return NEXT_ACTIVE_DIRECTORY_INTEGRATION_PREFIX . $key;
114 | }
115 |
116 | /**
117 | * Check if the session is not started and start it.
118 | */
119 | protected function startSession()
120 | {
121 | $native = Util::native();
122 |
123 | if ('' === $native->getSessionId()) {
124 | $native->startSession();
125 | }
126 | }
127 | }
--------------------------------------------------------------------------------
/js/app/profile-options/controllers/credential.controller.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | app.controller('PasswordController', PasswordController);
3 |
4 | PasswordController.$inject = ['$scope', 'DataService'];
5 |
6 | function PasswordController($scope, DataService) {
7 | var vm = this;
8 |
9 | $scope.isSaveDisabled = false;
10 |
11 | $scope.$on('permissionItems', function (event, data) {
12 | $scope.permissionOptions = data;
13 | });
14 |
15 | $scope.$on('options', function (event, data) {
16 | $scope.option = {
17 | no_random_password: $valueHelper.findValue("no_random_password", data),
18 | enable_password_change: $valueHelper.findValue("enable_password_change", data),
19 | fallback_to_local_password: $valueHelper.findValue("fallback_to_local_password", data),
20 | auto_update_password: $valueHelper.findValue("auto_update_password", data),
21 | enable_lost_password_recovery: $valueHelper.findValue("enable_lost_password_recovery", data),
22 | };
23 |
24 | if ($valueHelper.findValue("domain_sid", data) == '') {
25 | $scope.isSaveDisabled = true;
26 | } else {
27 | $scope.isSaveDisabled = false;
28 | }
29 |
30 | $scope.permission = {
31 | no_random_password: $valueHelper.findPermission("no_random_password", data),
32 | enable_password_change: $valueHelper.findPermission("enable_password_change", data),
33 | fallback_to_local_password: $valueHelper.findPermission("fallback_to_local_password", data),
34 | auto_update_password: $valueHelper.findPermission("auto_update_password", data),
35 | enable_lost_password_recovery: $valueHelper.findPermission("enable_lost_password_recovery", data),
36 | };
37 | });
38 |
39 | $scope.$on('validation', function (event, data) {
40 | $scope.messages = {
41 | no_random_password: $valueHelper.findMessage("no_random_password", data),
42 | enable_password_change: $valueHelper.findMessage("enable_password_change", data),
43 | fallback_to_local_password: $valueHelper.findMessage("fallback_to_local_password", data),
44 | auto_update_password: $valueHelper.findMessage("auto_update_password", data),
45 | enable_lost_password_recovery: $valueHelper.findMessage("enable_lost_password_recovery", data)
46 | };
47 | });
48 |
49 | $scope.$on('verification', function (event, data) {
50 | $scope.isSaveDisabled = false;
51 | });
52 |
53 | $scope.getPreparedOptions = function () {
54 | var data = DataService.cleanOptions($scope.option);
55 | return data;
56 | };
57 |
58 | $scope.containsErrors = function () {
59 | return (!$arrayUtil.containsOnlyNullValues($scope.messages));
60 | };
61 | }
62 | })();
--------------------------------------------------------------------------------
/src/shared/WordPress/Multisite/View/Page/PageAdapter.php:
--------------------------------------------------------------------------------
1 |
11 | * @author Sebastian Weinert
12 | *
13 | * @access public
14 | */
15 | abstract class PageAdapter implements Page
16 | {
17 | /** @var TwigContainer */
18 | protected $twigContainer;
19 |
20 | /**
21 | * Adi_Page_PageAbstract constructor.
22 | *
23 | * @param TwigContainer $twigContainer
24 | */
25 | protected function __construct(TwigContainer $twigContainer)
26 | {
27 | $this->twigContainer = $twigContainer;
28 | }
29 |
30 | /**
31 | * Render the provided data as JSON and exit
32 | *
33 | * @param mixed $data
34 | */
35 | protected function renderJson($data)
36 | {
37 | $this->display('ajax-json.twig', array('data' => $data));
38 | exit;
39 | }
40 |
41 | /**
42 | * Check if the user has the permission to view this page and either send a message or render the page.
43 | *
44 | * @param string $template
45 | * @param array $params
46 | *
47 | * @return string
48 | */
49 | protected function render($template, $params = array())
50 | {
51 | // check if the user is able to view this site
52 | $this->checkCapability();
53 |
54 | // get twig and render the display
55 | $twig = $this->twigContainer->getTwig();
56 |
57 | return $twig->render($template, $params);
58 | }
59 |
60 | /**
61 | * Get the rendered template and display it.
62 | *
63 | * @param $template
64 | * @param array $params
65 | */
66 | protected function display($template, $params = array())
67 | {
68 | echo $this->render($template, $params);
69 | }
70 |
71 | /**
72 | * Check if the current user can see this page.
73 | * If not an error will be shown.
74 | */
75 | protected function checkCapability()
76 | {
77 | if (!$this->currentUserHasCapability()) {
78 | $message = esc_html__('You do not have sufficient permissions to access this page.', 'next-active-directory-integration');
79 | wp_die($message);
80 | }
81 | }
82 |
83 | /**
84 | * @see check_ajax_referer()
85 | */
86 | protected function checkNonce()
87 | {
88 | check_ajax_referer($this->getNonce(), 'security', true);
89 | }
90 |
91 | /**
92 | * Check if the current user has the given capability.
93 | *
94 | * @return bool
95 | */
96 | protected function currentUserHasCapability()
97 | {
98 | return current_user_can($this->getCapability());
99 | }
100 |
101 | /**
102 | * Get the current capability to check if the user has permission to view this page.
103 | *
104 | * @return string
105 | */
106 | protected abstract function getCapability();
107 |
108 | /**
109 | * Get the current nonce value.
110 | *
111 | * @return mixed
112 | */
113 | protected abstract function getNonce();
114 | }
--------------------------------------------------------------------------------
/js/app/blog-options/controllers/credential.controller.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | app.controller('PasswordController', PasswordController);
3 |
4 | PasswordController.$inject = ['$scope', 'DataService'];
5 |
6 | function PasswordController($scope, DataService) {
7 | var vm = this;
8 |
9 | $scope.isSaveDisabled = false;
10 |
11 | $scope.permissionOptions = DataService.getPermissionOptions();
12 |
13 | $scope.$on('options', function (event, data) {
14 | $scope.option = {
15 | no_random_password: $valueHelper.findValue("no_random_password", data),
16 | enable_password_change: $valueHelper.findValue("enable_password_change", data),
17 | fallback_to_local_password: $valueHelper.findValue("fallback_to_local_password", data),
18 | auto_update_password: $valueHelper.findValue("auto_update_password", data),
19 | enable_lost_password_recovery: $valueHelper.findValue("enable_lost_password_recovery", data),
20 | };
21 |
22 | if ($valueHelper.findValue("domain_sid", data) == '') {
23 | $scope.isSaveDisabled = true;
24 | }
25 |
26 | $scope.permission = {
27 | no_random_password: $valueHelper.findPermission("no_random_password", data),
28 | enable_password_change: $valueHelper.findPermission("enable_password_change", data),
29 | fallback_to_local_password: $valueHelper.findPermission("fallback_to_local_password", data),
30 | auto_update_password: $valueHelper.findPermission("auto_update_password", data),
31 | enable_lost_password_recovery: $valueHelper.findPermission("enable_lost_password_recovery", data),
32 | verification_username : $valueHelper.findPermission("verification_username", data),
33 | verification_password : $valueHelper.findPermission("verification_password", data)
34 | };
35 | });
36 |
37 | $scope.$on('validation', function (event, data) {
38 | $scope.messages = {
39 | no_random_password: $valueHelper.findMessage("no_random_password", data),
40 | enable_password_change: $valueHelper.findMessage("enable_password_change", data),
41 | fallback_to_local_password: $valueHelper.findMessage("fallback_to_local_password", data),
42 | auto_update_password: $valueHelper.findMessage("auto_update_password", data),
43 | enable_lost_password_recovery: $valueHelper.findMessage("enable_lost_password_recovery", data)
44 | };
45 | });
46 |
47 | $scope.$on('verification', function (event, data) {
48 | $scope.isSaveDisabled = false;
49 | });
50 |
51 | $scope.getPreparedOptions = function () {
52 | return DataService.cleanOptions($scope.option);
53 | };
54 |
55 | $scope.containsErrors = function () {
56 | return (!$arrayUtil.containsOnlyNullValues($scope.messages));
57 | };
58 | }
59 | })();
--------------------------------------------------------------------------------
/js/app/profile-options/controllers/sso.controller.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | app.controller('SsoController', SsoController);
3 |
4 | SsoController.$inject = ['$scope', 'ListService', 'DataService'];
5 |
6 | function SsoController($scope, ListService, DataService) {
7 | var vm = this;
8 |
9 | $scope.isSaveDisabled = false;
10 |
11 | $scope.$on('permissionItems', function (event, data) {
12 | $scope.permissionOptions = data;
13 | });
14 |
15 | $scope.$on('options', function (event, data) {
16 | $scope.option = {
17 | sso: $valueHelper.findValue("sso", data),
18 | sso_user: $valueHelper.findValue("sso_user", data),
19 | sso_password: $valueHelper.findValue("sso_password", data),
20 | sso_environment_variable: $valueHelper.findValue("sso_environment_variable", data),
21 | sso_disable_for_xmlrpc: $valueHelper.findValue("sso_disable_for_xmlrpc", data),
22 | kerberos_realm_mappings: $valueHelper.findValue("kerberos_realm_mappings", data)
23 | };
24 |
25 | if ($valueHelper.findValue("domain_sid", data) == '') {
26 | $scope.isSaveDisabled = true;
27 | } else {
28 | $scope.isSaveDisabled = false;
29 | }
30 |
31 | $scope.permission = {
32 | sso: $valueHelper.findPermission("sso", data),
33 | sso_user: $valueHelper.findPermission("sso_user", data),
34 | sso_password: $valueHelper.findPermission("sso_password", data),
35 | sso_environment_variable: $valueHelper.findPermission("sso_environment_variable", data),
36 | sso_disable_for_xmlrpc: $valueHelper.findPermission("sso_disable_for_xmlrpc", data),
37 | kerberos_realm_mappings: $valueHelper.findPermission("kerberos_realm_mappings", data)
38 | };
39 | });
40 |
41 | $scope.$on('validation', function (event, data) {
42 | $scope.messages = {
43 | sso: $valueHelper.findMessage("sso", data),
44 | sso_user: $valueHelper.findMessage("sso_user", data),
45 | sso_password: $valueHelper.findMessage("sso_password", data),
46 | sso_environment_variable: $valueHelper.findMessage("sso_environment_variable", data),
47 | kerberos_realm_mappings: $valueHelper.findMessage("kerberos_realm_mappings", data)
48 | };
49 | });
50 |
51 | $scope.$on('verification', function (event, data) {
52 | $scope.isSaveDisabled = false;
53 | });
54 |
55 | $scope.getPreparedOptions = function () {
56 | var data = DataService.cleanOptions($scope.option);
57 | return data;
58 | };
59 |
60 | $scope.containsErrors = function () {
61 | return (!$arrayUtil.containsOnlyNullValues($scope.messages));
62 | };
63 |
64 | $scope.save = function() {
65 | $scope.$parent.save();
66 | };
67 | }
68 | })();
--------------------------------------------------------------------------------
/src/plug-in/Role/Mapping.php:
--------------------------------------------------------------------------------
1 |
9 | * @access public
10 | */
11 | class Mapping
12 | {
13 | /**
14 | * @var array
15 | */
16 | private $securityGroups = array();
17 |
18 | /**
19 | * @var array
20 | */
21 | private $wordPressRoles = array();
22 |
23 | /**
24 | * @var string
25 | */
26 | private $guidOrUsername;
27 |
28 | /**
29 | * @param string $guidOrUsername
30 | */
31 | public function __construct($guidOrUsername)
32 | {
33 | $this->guidOrUsername = $guidOrUsername;
34 | }
35 |
36 | /**
37 | * Set the Active Directory security groups
38 | *
39 | * @param array $securityGroups
40 | */
41 | public function setSecurityGroups($securityGroups)
42 | {
43 | if (!is_array($securityGroups)) {
44 | $securityGroups = array();
45 | }
46 |
47 | $this->securityGroups = $securityGroups;
48 | }
49 |
50 | /**
51 | * Get Active Directory security groups
52 | * @return array
53 | */
54 | public function getSecurityGroups()
55 | {
56 | return $this->securityGroups;
57 | }
58 |
59 | /**
60 | * Set the user's WordPress roles
61 | *
62 | * @param array $wordPressRoles
63 | */
64 | public function setWordPressRoles($wordPressRoles)
65 | {
66 | if (!is_array($wordPressRoles)) {
67 | $wordPressRoles = array();
68 | }
69 |
70 | $this->wordPressRoles = $wordPressRoles;
71 | }
72 |
73 | /**
74 | * Get the user's WordPress roles
75 | * @return array
76 | */
77 | public function getWordPressRoles()
78 | {
79 | return $this->wordPressRoles;
80 | }
81 |
82 |
83 | /**
84 | * Does the current mapping belong to the security group?
85 | *
86 | * @param string $securityGroup
87 | *
88 | * @return bool
89 | */
90 | public function isInSecurityGroup($securityGroup)
91 | {
92 | return in_array($securityGroup, $this->securityGroups);
93 | }
94 |
95 | /**
96 | * Get all security groups which are assigned
97 | *
98 | * @param $securityGroups
99 | *
100 | * @return array elements with matching groups
101 | */
102 | public function getMatchingGroups($securityGroups)
103 | {
104 | $equalGroups = array_intersect($this->securityGroups, $securityGroups);
105 |
106 | return array_values($equalGroups);
107 | }
108 |
109 | /**
110 | * Merge the given $roleMapping into this object.
111 | *
112 | * @param Mapping $otherRoleMapping
113 | */
114 | public function merge(Mapping $otherRoleMapping)
115 | {
116 | $this->securityGroups += $otherRoleMapping->getSecurityGroups();
117 | $this->wordPressRoles += $otherRoleMapping->getWordPressRoles();
118 | }
119 |
120 | public function __toString()
121 | {
122 | return "Mapping " . $this->guidOrUsername . "={ad_security_groups='" . implode(", ", $this->securityGroups)
123 | . "',wordpress_roles='" . implode(', ', $this->wordPressRoles) . "'}";
124 | }
125 | }
--------------------------------------------------------------------------------
/src/shared/WordPress/Multisite/Ui/BlogConfigurationController.php:
--------------------------------------------------------------------------------
1 |
13 | * @access public
14 | */
15 | class BlogConfigurationController
16 | {
17 | /* @var BlogConfigurationRepository $blogConfigurationRepository */
18 | private $blogConfigurationRepository;
19 |
20 | /* @var Provider */
21 | private $optionProvider;
22 |
23 | /**
24 | * @param BlogConfigurationRepository $blogConfigurationRepository
25 | * @param Provider $optionProvider
26 | */
27 | public function __construct(BlogConfigurationRepository $blogConfigurationRepository,
28 | Provider $optionProvider
29 | )
30 | {
31 | $this->blogConfigurationRepository = $blogConfigurationRepository;
32 | $this->optionProvider = $optionProvider;
33 | }
34 |
35 | /**
36 | * Convert the response from the frontend and save it in the database.
37 | * This methods stores the new option values for blog options.
38 | *
39 | * @param array $options
40 | *
41 | * @return array
42 | */
43 | public function saveBlogOptions($options)
44 | {
45 | try {
46 | $this->saveBlogOptionsInternal($options);
47 | } catch (\Exception $e) {
48 | return array("status_success" => false);
49 | }
50 |
51 | return array("status_success" => true);
52 |
53 | }
54 |
55 | /**
56 | * Convert the response from the frontend and save it in the database.
57 | * This methods stores the new option values for blog options.
58 | *
59 | * @param array $options
60 | */
61 | protected function saveBlogOptionsInternal($options)
62 | {
63 | foreach ($options as $optionName => $option) {
64 | if (!$this->validateOption($optionName, $option)) {
65 | continue;
66 | }
67 |
68 | $this->persistOption($optionName, $option);
69 | }
70 | }
71 |
72 | /**
73 | * Persist an single option value change from the $_POST response.
74 | *
75 | * @param string $optionName
76 | * @param array $option
77 | *
78 | * @return string
79 | */
80 | public function persistOption($optionName, $option)
81 | {
82 | $r = $this->blogConfigurationRepository->persistSanitizedValue(get_current_blog_id(), $optionName, $option);
83 |
84 | return $r;
85 | }
86 |
87 | /**
88 | * Validate option. The option name must exist and the option value must be defined.
89 | *
90 | * @param string $optionName
91 | * @param array $option
92 | *
93 | * @return bool
94 | */
95 | public function validateOption($optionName, $option)
96 | {
97 | if (!isset($option)) {
98 | return false;
99 | }
100 |
101 | if (!$this->optionProvider->existOption($optionName)) {
102 | return false;
103 | }
104 |
105 | return true;
106 | }
107 | }
--------------------------------------------------------------------------------
/src/plug-in/Multisite/Ui/MultisiteMenu.php:
--------------------------------------------------------------------------------
1 |
16 | * @author Sebastian Weinert
17 | *
18 | * @access public
19 | */
20 | class MultisiteMenu extends MenuAdapter
21 | {
22 | /** @var BlogProfileRelationshipPage | Page */
23 | private $blogProfileRelationshipPage;
24 |
25 | /** @var NadiMultisiteConfigurationPage | Page */
26 | private $profileConfigurationPage;
27 |
28 | /**
29 | * @param Provider $optionProvider
30 | * @param BlogProfileRelationshipPage $blogProfileRelationshipPage
31 | * @param NadiMultisiteConfigurationPage $nadiMultisiteConfigurationPage
32 | */
33 | public function __construct(Provider $optionProvider,
34 | BlogProfileRelationshipPage $blogProfileRelationshipPage,
35 | NadiMultisiteConfigurationPage $nadiMultisiteConfigurationPage
36 | )
37 | {
38 | parent::__construct($optionProvider);
39 |
40 | $this->blogProfileRelationshipPage = $blogProfileRelationshipPage;
41 | $this->profileConfigurationPage = $nadiMultisiteConfigurationPage;
42 | }
43 |
44 | /**
45 | * Register all menu pages.
46 | */
47 | public function register()
48 | {
49 | add_action(Actions::ADI_MENU_NETWORK_ADMIN_MENU, array($this, 'registerMenu'));
50 |
51 | $this->addAjaxListener($this->blogProfileRelationshipPage);
52 | $this->addAjaxListener($this->profileConfigurationPage);
53 | }
54 |
55 | /**
56 | * Register all pages for the network admin menu
57 | */
58 | public function registerMenu()
59 | {
60 | $permission = 'manage_network';
61 | $renderMethodName = 'renderNetwork';
62 | $networkMenuTitle = esc_html__('Active Directory Integration', 'next-active-directory-integration');
63 | $networkMenuSlug = $this->blogProfileRelationshipPage->getSlug(); // the header of the group must have the slug of the first item
64 |
65 | // add menu header
66 | add_menu_page($networkMenuTitle, $networkMenuTitle, $permission, $networkMenuSlug);
67 |
68 | // add sub menus
69 | $this->addSubMenu($networkMenuSlug, $permission, $this->blogProfileRelationshipPage, $renderMethodName);
70 | $profileConfigurationPage = $this->addSubMenu($networkMenuSlug, $permission, $this->profileConfigurationPage, $renderMethodName);
71 |
72 | add_action('admin_enqueue_scripts', array($this, 'loadScriptsAndStyle'));
73 | add_action('load-' . $profileConfigurationPage, array($this, 'addHelpTab'));
74 | }
75 |
76 | /**
77 | * Add scripts/css to the network admin menu.
78 | *
79 | * @param $hook
80 | */
81 | public function loadScriptsAndStyle($hook)
82 | {
83 | $this->blogProfileRelationshipPage->loadNetworkScriptsAndStyle($hook);
84 | $this->profileConfigurationPage->loadNetworkScriptsAndStyle($hook);
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/shared/Ldap/UserQuery.php:
--------------------------------------------------------------------------------
1 |
11 | * @access public
12 | * @since 2.0.0
13 | */
14 | class UserQuery
15 | {
16 | /**
17 | * @var string sAMAccountName, userPrincipalName, netbiosName
18 | */
19 | private $principal;
20 |
21 | /**
22 | * @var boolean
23 | */
24 | private $isGuid = false;
25 |
26 | /**
27 | * @var Credentials
28 | */
29 | private $credentials = null;
30 |
31 | private function __construct(?Credentials $credentials = null, ?string $principal = null)
32 | {
33 | $this->principal = $principal;
34 | $this->credentials = $credentials;
35 | }
36 |
37 | /**
38 | * Mark that the principal is a guid
39 | * @return $this
40 | */
41 | public function setGuid()
42 | {
43 | $this->isGuid = true;
44 | return $this;
45 | }
46 |
47 | /**
48 | * Return if this query is for a guid
49 | * @return bool
50 | */
51 | public function isGuid()
52 | {
53 | return $this->isGuid;
54 | }
55 |
56 | /**
57 | * @return mixed|string|null
58 | */
59 | public function getPrincipal()
60 | {
61 | return $this->principal;
62 | }
63 |
64 | /**
65 | * @return Credentials|null
66 | */
67 | public function getCredentials()
68 | {
69 | return $this->credentials;
70 | }
71 |
72 | /**
73 | * Creates a new UserQuery instance with the given principal but the same credentials;
74 | * @param string $principal
75 | * @return UserQuery
76 | */
77 | public function withPrincipal(string $principal)
78 | {
79 | return new UserQuery($this->credentials, $principal);
80 | }
81 |
82 | public function withGuid(string $guid)
83 | {
84 | $r = new UserQuery($this->credentials, $guid);
85 | return $r->setGuid();
86 | }
87 |
88 | /**
89 | * Factory method to create a new UserQuery based upon a principal
90 | *
91 | * @param string $principal
92 | * @param Credentials|null $credentials
93 | * @return UserQuery
94 | */
95 | public static function forPrincipal($principal, ?Credentials $credentials = null)
96 | {
97 | return new UserQuery($credentials, $principal);
98 | }
99 |
100 | /**
101 | * Factory method to create a new UserQuery solely based upon a Credentials instance
102 | * @param Credentials $credentials
103 | * @return UserQuery
104 | */
105 | public static function forCredentials(Credentials $credentials)
106 | {
107 | return new UserQuery($credentials);
108 | }
109 |
110 | /**
111 | * Factory method to create a new UserQuery based upon an objectGuid
112 | * @param string $guid
113 | * @param Credentials|null $credentials
114 | * @return mixed
115 | */
116 | public static function forGuid($guid, ?Credentials $credentials = null)
117 | {
118 | $r = new UserQuery($credentials, $guid);
119 | return $r->setGuid();
120 | }
121 |
122 | public function __toString()
123 | {
124 | return "UserQuery={principal='" . $this->principal . "',isGuid='" . $this->isGuid() . "'}";
125 | }
126 | }
--------------------------------------------------------------------------------
/src/shared/Util/Encryption.php:
--------------------------------------------------------------------------------
1 |
16 | * @access public
17 | */
18 | class Encryption
19 | {
20 | /** @var Logger */
21 | private $logger;
22 |
23 | public function __construct()
24 | {
25 | $this->logger = NadiLog::getInstance();
26 | }
27 |
28 | /**
29 | * Return `AUTH_SALT` constant or an empty string if not defined.
30 | * This has been added to make NADI compatible with newer PHP versions and WordPress installation in which `AUTH_SALT` is not defined.
31 | *
32 | * To be able to change the `AUTH_SALT`, one can define a key `NEXT_ACTIVE_DIRECTORY_INTEGRATION_ENCRYPTION_KEY` with the old `AUTH_SALT`.
33 | *
34 | * @issue #164
35 | * @issue #173
36 | * @see https://github.com/NeosIT/active-directory-integration2/issues/164
37 | */
38 | public static function getSalt()
39 | {
40 | if (defined('NEXT_ACTIVE_DIRECTORY_INTEGRATION_ENCRYPTION_KEY')) {
41 | return NEXT_ACTIVE_DIRECTORY_INTEGRATION_ENCRYPTION_KEY;
42 | }
43 |
44 | if (defined('AUTH_SALT')) {
45 | return AUTH_SALT;
46 | }
47 |
48 | return '';
49 | }
50 |
51 | /**
52 | * This method will encrypt the $plainText and return the encrypted text.
53 | *
54 | * @param $plainText
55 | *
56 | * @return string
57 | */
58 | public function encrypt($plainText)
59 | {
60 | $password = 'Next Active Directory Integration' . self::getSalt();
61 |
62 | try {
63 | $encryptedText = Crypto::encryptWithPassword($plainText, $password);
64 | } catch (\Exception $e) {
65 | // prevent the PHP stack trace display by catching all exception because the stack trace can contain the $password.
66 | $this->logger->warning('Plain text can not be encrypted. ' . $e->getMessage());
67 |
68 | return false;
69 | }
70 |
71 | return $encryptedText;
72 | }
73 |
74 | /**
75 | * This method will decrypt the $encryptedText and return the plain text.
76 | *
77 | * @param $encryptedText
78 | *
79 | * @return string
80 | */
81 | public function decrypt($encryptedText)
82 | {
83 | $password = 'Next Active Directory Integration' . self::getSalt();
84 |
85 | // do not decrypt empty texts
86 | if (!$encryptedText) {
87 | return false;
88 | }
89 |
90 | try {
91 | $plainText = Crypto::decryptWithPassword($encryptedText, $password);
92 | } catch (\Exception $e) {
93 | // prevent the PHP stack trace display by catching all exception because the stack trace can contain the $password.
94 | $this->logger->warning('Encrypted text "' . $encryptedText . '" can not be decrypted. ' . $e->getMessage());
95 |
96 | return false;
97 | }
98 |
99 | return $plainText;
100 | }
101 | }
--------------------------------------------------------------------------------
/src/plug-in/Ui/Menu/MenuAdapter.php:
--------------------------------------------------------------------------------
1 |
16 | * @access public
17 | */
18 | abstract class MenuAdapter
19 | {
20 | /**
21 | * @var Provider
22 | */
23 | private $optionProvider;
24 |
25 | /**
26 | * @param Provider $optionProvider
27 | */
28 | public function __construct(Provider $optionProvider)
29 | {
30 | $this->optionProvider = $optionProvider;
31 | }
32 |
33 | /**
34 | * Register all menu pages.
35 | */
36 | abstract public function register();
37 |
38 | /**
39 | * Adds the given ajax listener for the given page.
40 | *
41 | * @access protected
42 | * @param Page $page
43 | * @return bool|true|void
44 | */
45 | function addAjaxListener($page)
46 | {
47 | if (!$page instanceof Page) {
48 | return false;
49 | }
50 |
51 | $wordPressAjaxListener = 'wpAjaxListener';
52 |
53 | return add_action(Actions::ADI_MENU_WP_AJAX_PREFIX . $page->wpAjaxSlug(), array(
54 | $page, $wordPressAjaxListener,
55 | ));
56 | }
57 |
58 | /**
59 | * Add help tab.
60 | */
61 | public function addHelpTab()
62 | {
63 | // gets all the OptionMetaData
64 | $options = $this->optionProvider->getAll();
65 | $screen = get_current_screen();
66 |
67 | foreach ($options as $optionName => $option) {
68 | if (!isset($option[Attribute::DETAIL])) {
69 | continue;
70 | }
71 |
72 | $data = $this->generateHelpTabEntry($option, $optionName);
73 | $screen->add_help_tab($data);
74 | }
75 | }
76 |
77 | /**
78 | * Return help tab entry.
79 | *
80 | * @access protected
81 | * @param $screen
82 | * @param array $option
83 | * @param string $optionName
84 | *
85 | * @return array
86 | */
87 | protected function generateHelpTabEntry($option, $optionName)
88 | {
89 | $title = ArrayUtil::get(Attribute::TITLE, $option, '');
90 | $detail = ArrayUtil::get(Attribute::DETAIL, $option, '');
91 | $content = '' . StringUtil::concat($detail, '
') . '
';
92 |
93 | return array(
94 | 'id' => $optionName,
95 | 'title' => $title,
96 | 'content' => $content,
97 | );
98 | }
99 |
100 | /**
101 | * Adds a sub menu to the given main menu.
102 | *
103 | * @access protected
104 | * @param string $mainMenuSlug
105 | * @param mixed $permission
106 | * @param Page $page
107 | * @param string $callbackMethodName
108 | *
109 | * @return bool|false|string
110 | */
111 | public function addSubMenu($mainMenuSlug, $permission, $page, $callbackMethodName)
112 | {
113 | if (!$page instanceof Page) {
114 | return false;
115 | }
116 |
117 | $pageTitle = $page->getTitle();
118 | $pageSlug = $page->getSlug();
119 |
120 | return add_submenu_page($mainMenuSlug, $pageTitle, $pageTitle, $permission, $pageSlug, array($page, $callbackMethodName));
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/index.php:
--------------------------------------------------------------------------------
1 | check()) {
36 | return;
37 | }
38 | }
39 |
40 | // start plugin
41 | $adiPlugin = new \Dreitier\Nadi\Init();
42 |
43 | // register basic hooks
44 | register_activation_hook(__FILE__, array($adiPlugin, 'activation'));
45 | register_uninstall_hook(__FILE__, array(\Dreitier\Nadi\Init::class /* static */, 'uninstall'));
46 |
47 | add_action('plugins_loaded', 'next_ad_int_angular_ajax_params_to_post');
48 |
49 | // #204: register `init` hook to make loading the textdomain possible
50 | add_action('init', array($adiPlugin, '_init'));
51 |
52 | // register any hooks after the plug-in has been activated e.g. to display notices for a migration of options
53 | add_action('admin_init', array($adiPlugin, 'postActivation'));
54 |
55 | // --- Normal Blog / Single Site ---
56 | // execute the plugin and their hooks after the 'plugins_loaded' hook has been called
57 | // so we can use WordPress functions for lazy-loading
58 | add_action('set_current_user', array($adiPlugin, 'run'));
59 |
60 | // --- Active Multisite dashboard ---
61 | // we need to register a second hook to decide if the network dashboard is shown.
62 | // another possible solution would be using the hook 'redirect_network_admin_request' from network/admin.php but
63 | // the loading of the menu happens to early
64 | add_action('set_current_user', array($adiPlugin, 'runMultisite'));
65 |
66 | /**
67 | * Global accessor for Next ADI dependencies.
68 | * You can call this function in your own extensions to gain access to the internals of NADI.
69 | *
70 | * @return \Dreitier\Nadi\Dependencies
71 | */
72 | function next_ad_int()
73 | {
74 | return \Dreitier\Nadi\Dependencies::getInstance();
75 | }
76 |
77 | function next_ad_int_logger()
78 | {
79 | return \Dreitier\Nadi\Log\NadiLog::getInstance();
80 | }
81 |
82 |
--------------------------------------------------------------------------------
/js/app/profile-options/controllers/logging.controller.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | app.controller('LoggingController', LoggingController);
3 |
4 | LoggingController.$inject = ['$scope', '$http', 'PersistService', 'ngNotify'];
5 |
6 | function LoggingController($scope, $http, PersistService, ngNotify) {
7 | var vm = this;
8 |
9 | $scope.isSaveDisabled = false;
10 |
11 | $scope.$on('permissionItems', function (event, data) {
12 | $scope.permissionOptions = data;
13 | });
14 |
15 |
16 | $scope.$on('options', function (event, data) {
17 | $scope.option = {
18 | logger_enable_logging: $valueHelper.findValue("logger_enable_logging", data),
19 | logger_custom_path: $valueHelper.findValue("logger_custom_path", data),
20 | };
21 |
22 | if ($valueHelper.findValue("domain_sid", data) == '') {
23 | $scope.isSaveDisabled = true;
24 | } else {
25 | $scope.isSaveDisabled = false;
26 | }
27 |
28 | $scope.permission = {
29 | logger_enable_logging: $valueHelper.findPermission("logger_enable_logging", data),
30 | logger_custom_path: $valueHelper.findPermission("logger_custom_path", data),
31 | };
32 | });
33 |
34 | $scope.$on('validation', function (event, data) {
35 | $scope.messages = {
36 | logger_enable_logging: $valueHelper.findMessage("logger_enable_logging", data),
37 | logger_custom_path: $valueHelper.findMessage("logger_custom_path", data),
38 | };
39 | });
40 |
41 | $scope.$on('verification', function (event, data) {
42 | $scope.isSaveDisabled = false;
43 | });
44 |
45 |
46 | $scope.containsErrors = function () {
47 | return (!$arrayUtil.containsOnlyNullValues($scope.messages));
48 | };
49 |
50 |
51 | $scope.activateLogging = function () {
52 | console.log("Save Logging information");
53 | console.log($scope.$parent.activeProfile.profileId);
54 |
55 | var data = {
56 | options : {
57 | logger_enable_logging : {
58 | option_value : $scope.option.logger_enable_logging,
59 | option_permission : $scope.permission.logger_enable_logging
60 | },
61 | logger_custom_path : {
62 | option_value : $scope.option.logger_custom_path,
63 | option_permission : $scope.permission.logger_custom_path
64 | },
65 | profile_name : {
66 | option_value : $scope.$parent.activeProfile.profileName,
67 | option_permission : undefined
68 | }
69 | },
70 | profile: $scope.$parent.activeProfile.profileId
71 | };
72 |
73 | PersistService.persistData(data).then(function (response) {
74 |
75 | if (response.type === 'success') {
76 | ngNotify.set(document['next_ad_int']['saving-success'], 'success');
77 |
78 | } else {
79 | ngNotify.set(document['next_ad_int']['saving-error'], 'error');
80 | }
81 | });
82 | }
83 |
84 | }
85 | })();
--------------------------------------------------------------------------------
/src/plug-in/Authentication/VerificationService.php:
--------------------------------------------------------------------------------
1 |
17 | */
18 | class VerificationService
19 | {
20 |
21 | /** @var Connection */
22 | private $ldapConnection;
23 |
24 | /**
25 | * @var Repository
26 | */
27 | private $ldapAttributeRepository;
28 | /** @var Logger */
29 | private $logger;
30 |
31 | /**
32 | * @param Connection $ldapConnection
33 | * @param Repository $ldapAttributeRepository
34 | */
35 | public function __construct(Connection $ldapConnection,
36 | Repository $ldapAttributeRepository
37 | )
38 | {
39 | $this->ldapConnection = $ldapConnection;
40 | $this->ldapAttributeRepository = $ldapAttributeRepository;
41 | $this->logger = NadiLog::getInstance();
42 | }
43 |
44 | /**
45 | * Check if the connection to the Active Directory can be established.
46 | * Receive objectSid from user used to authenticate.
47 | *
48 | * @param array $data
49 | *
50 | * @return bool|Sid
51 | */
52 | public function findActiveDirectoryDomainSid($data)
53 | {
54 | $config = new ConnectionDetails();
55 | $username = $data["verification_username"];
56 |
57 | $config->setDomainControllers($data["domain_controllers"]);
58 | $config->setPort($data["port"]);
59 | $config->setEncryption($data["encryption"]);
60 | $config->setAllowSelfSigned($data["allow_self_signed"]);
61 | $config->setNetworkTimeout($data["network_timeout"]);
62 | $config->setBaseDn($data["base_dn"]);
63 | $config->setUsername($username);
64 | $config->setPassword($data["verification_password"]);
65 |
66 | $this->ldapConnection->connect($config);
67 |
68 | $isConnected = $this->ldapConnection->isConnected();
69 |
70 | if ($isConnected) {
71 | $attributeService = $this->getCustomAttributeService();
72 | $objectSid = $attributeService->getObjectSid(PrincipalResolver::createCredentials($username));
73 |
74 | // ADI-412: There *should* be an objectSID as we now fall back from sAMAccountName to userPrincipalName
75 | if (false === $objectSid) {
76 | $this->logger->error("objectSID for AD user '" . $username . "' could not be found. Please check that for this account has been defined a full userPrincipalName including the UPN suffix.");
77 |
78 | return false;
79 | }
80 |
81 | return $objectSid;
82 | }
83 |
84 | return false;
85 | }
86 |
87 | public function findActiveDirectoryNetBiosName($data)
88 | {
89 | $attributeService = $this->getCustomAttributeService();
90 | $netBIOSname = $attributeService->getnetBiosName($data["verification_username"]);
91 |
92 | if ($netBIOSname) {
93 | return $netBIOSname;
94 | }
95 |
96 | return false;
97 | }
98 |
99 | /**
100 | * Get service for verification process
101 | *
102 | * @return Service
103 | */
104 | public function getCustomAttributeService()
105 | {
106 | return new \Dreitier\Ldap\Attribute\Service($this->ldapConnection, $this->ldapAttributeRepository);
107 | }
108 | }
--------------------------------------------------------------------------------
/src/shared/ActiveDirectory/Sid.php:
--------------------------------------------------------------------------------
1 |
14 | * @access public
15 | */
16 | class Sid
17 | {
18 | /**
19 | * Binary representation
20 | * @var mixed
21 | */
22 | private $binary;
23 |
24 | /**
25 | * Formatted as "S-1-"...
26 | * @var string
27 | */
28 | private $formatted;
29 |
30 | /**
31 | * Hex representation
32 | * @var string
33 | */
34 | private $hex;
35 |
36 | private function __construct($binary, $formatted, $hex)
37 | {
38 | $this->binary = $binary;
39 | $this->formatted = $formatted;
40 | $this->hex = $hex;
41 | }
42 |
43 | /**
44 | * Get formatted SID as "S-..."
45 | * @return string
46 | */
47 | public function getFormatted()
48 | {
49 | return $this->formatted;
50 | }
51 |
52 | /**
53 | * Get SID as binary string
54 | *
55 | * @return mixed
56 | */
57 | public function getBinary()
58 | {
59 | return $this->binary;
60 | }
61 |
62 | /**
63 | * Get SID as hex
64 | * @return string
65 | */
66 | public function getHex()
67 | {
68 | return $this->hex;
69 | }
70 |
71 | /**
72 | * Based upon this SID, the domain part will be extracted
73 | *
74 | * @return Sid
75 | */
76 | public function getDomainPartAsSid()
77 | {
78 | // this pattern defined the domain part of a SID
79 | // @see https://en.wikipedia.org/wiki/Security_Identifier
80 | $pattern = '/^(S\-1\-5\-21\-\d+\-\d+\-\d+)+(\-.*)?/';
81 |
82 | if (preg_match($pattern, $this->formatted, $ret)) {
83 | return self::of(strtoupper($ret[1]));
84 | }
85 |
86 | return NULL;
87 | }
88 |
89 | /**
90 | * Create a new SID instance
91 | * @param $objectSid either binary representation, "S-..." format or hex format
92 | * @return Sid|null null if conversion failed
93 | */
94 | public static function of($objectSid)
95 | {
96 | $binary = null;
97 | $formatted = null;
98 | $hex = null;
99 |
100 | if (empty($objectSid)) {
101 | $objectSid = "";
102 | }
103 |
104 | // if the object SID does not start with an S- prefix, it is probably binary encoded
105 | if (StringUtil::startsWith('S-', $objectSid)) {
106 | $hex = AdLdap::sidStringToHex($objectSid);
107 | $binary = hex2bin($hex);
108 | $formatted = $objectSid;
109 | }
110 | // only allow hex parameter
111 | // @see https://stackoverflow.com/a/43600382/2545275
112 | else if (trim($objectSid, '0..9A..Fa..f') == '') {
113 | $hex = $objectSid;
114 | $binary = hex2bin($hex);
115 | $formatted = AdLdap::convertBinarySidToString($binary);
116 | }
117 | // check for binary type
118 | // @see https://stackoverflow.com/a/25344979/2545275
119 | else if (preg_match('~[^\x20-\x7E\t\r\n]~', $objectSid)) {
120 | $binary = $objectSid;
121 | $hex = bin2hex($binary);
122 | $formatted = adLDAP::convertBinarySidToString($objectSid);
123 | }
124 |
125 | if (!$binary || !$formatted || !$hex) {
126 | return null;
127 | }
128 |
129 | return new Sid($binary, $formatted, $hex);
130 | }
131 |
132 | public function __toString()
133 | {
134 | return "SID={objectSID='" . $this->formatted . "'}";
135 | }
136 | }
--------------------------------------------------------------------------------