PasswdModule::execute()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 9
c 0
b 0
f 0
nc 4
nop 0
dl 0
loc 12
rs 9.9666
1
<?php
2
3
/**
4
 * Passwd module.
5
 * Module that will be used to change passwords of the user.
6
 */
7
class PasswdModule extends Module {
8
	/**
9
	 * Process the incoming events that were fire by the client.
10
	 */
11
	#[Override]
12
	public function execute() {
13
		foreach ($this->data as $actionType => $actionData) {
14
			if (isset($actionType)) {
15
				try {
16
					match ($actionType) {
17
						'save' => $this->save($actionData),
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->save($actionData) targeting PasswdModule::save() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
18
						default => $this->handleUnknownActionType($actionType),
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->handleUnknownActionType($actionType) targeting Module::handleUnknownActionType() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
19
					};
20
				}
21
				catch (MAPIException $e) {
22
					$this->sendFeedback(false, $this->errorDetailsFromException($e));
23
				}
24
			}
25
		}
26
	}
27
28
	/**
29
	 * Change the password of user. Do some calidation and call proper methods based on
30
	 * zarafa setup.
31
	 *
32
	 * @param array $data data sent by client
33
	 */
34
	public function save($data) {
35
		$errorMessage = '';
36
37
		// some sanity checks
38
		if (empty($data)) {
39
			$errorMessage = _('No data received.');
40
		}
41
42
		if (empty($data['username'])) {
43
			$errorMessage = _('Account is empty.');
44
		}
45
46
		if (empty($data['current_password'])) {
47
			$errorMessage = _('Current password is empty.');
48
		}
49
50
		if (empty($data['new_password']) || empty($data['new_password_repeat'])) {
51
			$errorMessage = _('New password is empty.');
52
		}
53
54
		if ($data['new_password'] !== $data['new_password_repeat']) {
55
			$errorMessage = _('New passwords do not match.');
56
		}
57
58
		if (empty($errorMessage)) {
59
			$this->saveInDB($data);
60
		}
61
		else {
62
			$this->sendFeedback(false, [
63
				'type' => ERROR_ZARAFA,
64
				'info' => [
65
					'display_message' => $errorMessage,
66
				],
67
			]);
68
		}
69
	}
70
71
	/**
72
	 * Function will try to change user's password via MAPI in SOAP connection.
73
	 *
74
	 * @param array $data data sent by client
75
	 */
76
	public function saveInDB($data) {
77
		$errorMessage = '';
78
		$userName = $GLOBALS['mapisession']->getSMTPAddress();
79
		$newPassword = $data['new_password'];
80
81
		// When a session password is available it may not correspond to the user's
82
		// actual password (e.g. when authenticated via grommunio-auth/Keycloak). We rely
83
		// on the backend to verify the provided current password instead of validating it
84
		// against the session value.
85
		if (defined('PLUGIN_PASSWD_USE_ZCORE') && PLUGIN_PASSWD_USE_ZCORE) {
86
			try {
87
				$result = nsp_setuserpasswd($userName, $data['current_password'], $newPassword);
88
				// password changed successfully
89
				if ($result) {
90
					$this->sendFeedback(true, [
91
						'info' => [
92
							'display_message' => _('Password is changed successfully.'),
93
						],
94
					]);
95
					// write new password to session because we don't want user to re-authenticate
96
					session_start();
97
					$encryptionStore = EncryptionStore::getInstance();
98
					$encryptionStore->add('password', $newPassword);
99
					session_write_close();
100
101
					return;
102
				}
103
			}
104
			catch (MAPIException) {
105
				if (mapi_last_hresult() == MAPI_E_NO_ACCESS) {
106
					$errorMessage = _('Your password is wrong or you have insufficient permission to change password');
107
				}
108
			}
109
			if (empty($errorMessage)) {
110
				$errorMessage = _('Password is not changed.');
111
			}
112
		}
113
		else {
114
			$url = (defined('PLUGIN_PASSWD_ADMIN_API_ENDPOINT') && PLUGIN_PASSWD_ADMIN_API_ENDPOINT) ?
115
				PLUGIN_PASSWD_ADMIN_API_ENDPOINT :
116
				'http://[::1]:8080/api/v1/passwd';
117
			$result = file_get_contents($url, false, stream_context_create([
118
				'http' => [
119
					'header' => [
120
						'Content-type: application/json',
121
					],
122
					'method' => 'PUT',
123
					'content' => json_encode([
124
						"user" => $userName,
125
						"old" => $data['current_password'],
126
						"new" => $newPassword,
127
					]),
128
				],
129
			]));
130
131
			if ($result === false) {
132
				$errorMessage = _('Error changing password. Please verify your password or contact the system administrator.');
133
			}
134
			else {
135
				$this->sendFeedback(true, [
136
					'info' => [
137
						'display_message' => _('Password has been changed successfully.'),
138
					],
139
				]);
140
				// write new password to session because we don't want user to re-authenticate
141
				session_start();
142
				$encryptionStore = EncryptionStore::getInstance();
143
				$encryptionStore->add('password', $newPassword);
144
				session_write_close();
145
146
				return;
147
			}
148
			if (empty($errorMessage)) {
149
				$errorMessage = _('Password is not changed.');
150
			}
151
		}
152
153
		if (!empty($errorMessage)) {
154
			$this->sendFeedback(false, [
155
				'type' => ERROR_ZARAFA,
156
				'info' => [
157
					'display_message' => $errorMessage,
158
				],
159
			]);
160
		}
161
	}
162
}
163