Passed
Push — master ( b8b2e7...0ab5b3 )
by Blizzz
23:57 queued 11s
created
lib/private/AppFramework/Middleware/OCSMiddleware.php 1 patch
Indentation   +116 added lines, -116 removed lines patch added patch discarded remove patch
@@ -40,123 +40,123 @@
 block discarded – undo
40 40
 
41 41
 class OCSMiddleware extends Middleware {
42 42
 
43
-	/** @var IRequest */
44
-	private $request;
45
-
46
-	/** @var int */
47
-	private $ocsVersion;
48
-
49
-	/**
50
-	 * @param IRequest $request
51
-	 */
52
-	public function __construct(IRequest $request) {
53
-		$this->request = $request;
54
-	}
55
-
56
-	/**
57
-	 * @param Controller $controller
58
-	 * @param string $methodName
59
-	 */
60
-	public function beforeController($controller, $methodName) {
61
-		if ($controller instanceof OCSController) {
62
-			if (substr_compare($this->request->getScriptName(), '/ocs/v2.php', -strlen('/ocs/v2.php')) === 0) {
63
-				$this->ocsVersion = 2;
64
-			} else {
65
-				$this->ocsVersion = 1;
66
-			}
67
-			$controller->setOCSVersion($this->ocsVersion);
68
-		}
69
-	}
70
-
71
-	/**
72
-	 * @param Controller $controller
73
-	 * @param string $methodName
74
-	 * @param \Exception $exception
75
-	 * @throws \Exception
76
-	 * @return BaseResponse
77
-	 */
78
-	public function afterException($controller, $methodName, \Exception $exception) {
79
-		if ($controller instanceof OCSController && $exception instanceof OCSException) {
80
-			$code = $exception->getCode();
81
-			if ($code === 0) {
82
-				$code = \OCP\AppFramework\OCSController::RESPOND_UNKNOWN_ERROR;
83
-			}
84
-
85
-			return $this->buildNewResponse($controller, $code, $exception->getMessage());
86
-		}
87
-
88
-		throw $exception;
89
-	}
90
-
91
-	/**
92
-	 * @param Controller $controller
93
-	 * @param string $methodName
94
-	 * @param Response $response
95
-	 * @return \OCP\AppFramework\Http\Response
96
-	 */
97
-	public function afterController($controller, $methodName, Response $response) {
98
-		/*
43
+    /** @var IRequest */
44
+    private $request;
45
+
46
+    /** @var int */
47
+    private $ocsVersion;
48
+
49
+    /**
50
+     * @param IRequest $request
51
+     */
52
+    public function __construct(IRequest $request) {
53
+        $this->request = $request;
54
+    }
55
+
56
+    /**
57
+     * @param Controller $controller
58
+     * @param string $methodName
59
+     */
60
+    public function beforeController($controller, $methodName) {
61
+        if ($controller instanceof OCSController) {
62
+            if (substr_compare($this->request->getScriptName(), '/ocs/v2.php', -strlen('/ocs/v2.php')) === 0) {
63
+                $this->ocsVersion = 2;
64
+            } else {
65
+                $this->ocsVersion = 1;
66
+            }
67
+            $controller->setOCSVersion($this->ocsVersion);
68
+        }
69
+    }
70
+
71
+    /**
72
+     * @param Controller $controller
73
+     * @param string $methodName
74
+     * @param \Exception $exception
75
+     * @throws \Exception
76
+     * @return BaseResponse
77
+     */
78
+    public function afterException($controller, $methodName, \Exception $exception) {
79
+        if ($controller instanceof OCSController && $exception instanceof OCSException) {
80
+            $code = $exception->getCode();
81
+            if ($code === 0) {
82
+                $code = \OCP\AppFramework\OCSController::RESPOND_UNKNOWN_ERROR;
83
+            }
84
+
85
+            return $this->buildNewResponse($controller, $code, $exception->getMessage());
86
+        }
87
+
88
+        throw $exception;
89
+    }
90
+
91
+    /**
92
+     * @param Controller $controller
93
+     * @param string $methodName
94
+     * @param Response $response
95
+     * @return \OCP\AppFramework\Http\Response
96
+     */
97
+    public function afterController($controller, $methodName, Response $response) {
98
+        /*
99 99
 		 * If a different middleware has detected that a request unauthorized or forbidden
100 100
 		 * we need to catch the response and convert it to a proper OCS response.
101 101
 		 */
102
-		if ($controller instanceof OCSController && !($response instanceof BaseResponse)) {
103
-			if ($response->getStatus() === Http::STATUS_UNAUTHORIZED) {
104
-				$message = '';
105
-				if ($response instanceof JSONResponse) {
106
-					/** @var DataResponse $response */
107
-					$message = $response->getData()['message'];
108
-				}
109
-
110
-				return $this->buildNewResponse($controller, OCSController::RESPOND_UNAUTHORISED, $message);
111
-			}
112
-			if ($response->getStatus() === Http::STATUS_FORBIDDEN) {
113
-				$message = '';
114
-				if ($response instanceof JSONResponse) {
115
-					/** @var DataResponse $response */
116
-					$message = $response->getData()['message'];
117
-				}
118
-
119
-				return $this->buildNewResponse($controller, Http::STATUS_FORBIDDEN, $message);
120
-			}
121
-		}
122
-
123
-		return $response;
124
-	}
125
-
126
-	/**
127
-	 * @param Controller $controller
128
-	 * @param int $code
129
-	 * @param string $message
130
-	 * @return V1Response|V2Response
131
-	 */
132
-	private function buildNewResponse(Controller $controller, $code, $message) {
133
-		$format = $this->getFormat($controller);
134
-
135
-		$data = new DataResponse();
136
-		$data->setStatus($code);
137
-		if ($this->ocsVersion === 1) {
138
-			$response = new V1Response($data, $format, $message);
139
-		} else {
140
-			$response = new V2Response($data, $format, $message);
141
-		}
142
-
143
-		return $response;
144
-	}
145
-
146
-	/**
147
-	 * @param Controller $controller
148
-	 * @return string
149
-	 */
150
-	private function getFormat(Controller $controller) {
151
-		// get format from the url format or request format parameter
152
-		$format = $this->request->getParam('format');
153
-
154
-		// if none is given try the first Accept header
155
-		if ($format === null) {
156
-			$headers = $this->request->getHeader('Accept');
157
-			$format = $controller->getResponderByHTTPHeader($headers, 'xml');
158
-		}
159
-
160
-		return $format;
161
-	}
102
+        if ($controller instanceof OCSController && !($response instanceof BaseResponse)) {
103
+            if ($response->getStatus() === Http::STATUS_UNAUTHORIZED) {
104
+                $message = '';
105
+                if ($response instanceof JSONResponse) {
106
+                    /** @var DataResponse $response */
107
+                    $message = $response->getData()['message'];
108
+                }
109
+
110
+                return $this->buildNewResponse($controller, OCSController::RESPOND_UNAUTHORISED, $message);
111
+            }
112
+            if ($response->getStatus() === Http::STATUS_FORBIDDEN) {
113
+                $message = '';
114
+                if ($response instanceof JSONResponse) {
115
+                    /** @var DataResponse $response */
116
+                    $message = $response->getData()['message'];
117
+                }
118
+
119
+                return $this->buildNewResponse($controller, Http::STATUS_FORBIDDEN, $message);
120
+            }
121
+        }
122
+
123
+        return $response;
124
+    }
125
+
126
+    /**
127
+     * @param Controller $controller
128
+     * @param int $code
129
+     * @param string $message
130
+     * @return V1Response|V2Response
131
+     */
132
+    private function buildNewResponse(Controller $controller, $code, $message) {
133
+        $format = $this->getFormat($controller);
134
+
135
+        $data = new DataResponse();
136
+        $data->setStatus($code);
137
+        if ($this->ocsVersion === 1) {
138
+            $response = new V1Response($data, $format, $message);
139
+        } else {
140
+            $response = new V2Response($data, $format, $message);
141
+        }
142
+
143
+        return $response;
144
+    }
145
+
146
+    /**
147
+     * @param Controller $controller
148
+     * @return string
149
+     */
150
+    private function getFormat(Controller $controller) {
151
+        // get format from the url format or request format parameter
152
+        $format = $this->request->getParam('format');
153
+
154
+        // if none is given try the first Accept header
155
+        if ($format === null) {
156
+            $headers = $this->request->getHeader('Accept');
157
+            $format = $controller->getResponderByHTTPHeader($headers, 'xml');
158
+        }
159
+
160
+        return $format;
161
+    }
162 162
 }
Please login to merge, or discard this patch.
lib/private/AppFramework/OCS/V1Response.php 1 patch
Indentation   +41 added lines, -41 removed lines patch added patch discarded remove patch
@@ -29,52 +29,52 @@
 block discarded – undo
29 29
 
30 30
 class V1Response extends BaseResponse {
31 31
 
32
-	/**
33
-	 * The V1 endpoint has very limited http status codes basically everything
34
-	 * is status 200 except 401
35
-	 *
36
-	 * @return int
37
-	 */
38
-	public function getStatus() {
39
-		$status = parent::getStatus();
40
-		if ($status === OCSController::RESPOND_UNAUTHORISED) {
41
-			return Http::STATUS_UNAUTHORIZED;
42
-		}
32
+    /**
33
+     * The V1 endpoint has very limited http status codes basically everything
34
+     * is status 200 except 401
35
+     *
36
+     * @return int
37
+     */
38
+    public function getStatus() {
39
+        $status = parent::getStatus();
40
+        if ($status === OCSController::RESPOND_UNAUTHORISED) {
41
+            return Http::STATUS_UNAUTHORIZED;
42
+        }
43 43
 
44
-		return Http::STATUS_OK;
45
-	}
44
+        return Http::STATUS_OK;
45
+    }
46 46
 
47
-	/**
48
-	 * In v1 all OK is 100
49
-	 *
50
-	 * @return int
51
-	 */
52
-	public function getOCSStatus() {
53
-		$status = parent::getOCSStatus();
47
+    /**
48
+     * In v1 all OK is 100
49
+     *
50
+     * @return int
51
+     */
52
+    public function getOCSStatus() {
53
+        $status = parent::getOCSStatus();
54 54
 
55
-		if ($status === Http::STATUS_OK) {
56
-			return 100;
57
-		}
55
+        if ($status === Http::STATUS_OK) {
56
+            return 100;
57
+        }
58 58
 
59
-		return $status;
60
-	}
59
+        return $status;
60
+    }
61 61
 
62
-	/**
63
-	 * Construct the meta part of the response
64
-	 * And then late the base class render
65
-	 *
66
-	 * @return string
67
-	 */
68
-	public function render() {
69
-		$meta = [
70
-			'status' => $this->getOCSStatus() === 100 ? 'ok' : 'failure',
71
-			'statuscode' => $this->getOCSStatus(),
72
-			'message' => $this->getOCSStatus() === 100 ? 'OK' : $this->statusMessage,
73
-		];
62
+    /**
63
+     * Construct the meta part of the response
64
+     * And then late the base class render
65
+     *
66
+     * @return string
67
+     */
68
+    public function render() {
69
+        $meta = [
70
+            'status' => $this->getOCSStatus() === 100 ? 'ok' : 'failure',
71
+            'statuscode' => $this->getOCSStatus(),
72
+            'message' => $this->getOCSStatus() === 100 ? 'OK' : $this->statusMessage,
73
+        ];
74 74
 
75
-		$meta['totalitems'] = $this->itemsCount !== null ? (string)$this->itemsCount : '';
76
-		$meta['itemsperpage'] = $this->itemsPerPage !== null ? (string)$this->itemsPerPage: '';
75
+        $meta['totalitems'] = $this->itemsCount !== null ? (string)$this->itemsCount : '';
76
+        $meta['itemsperpage'] = $this->itemsPerPage !== null ? (string)$this->itemsPerPage: '';
77 77
 
78
-		return $this->renderResult($meta);
79
-	}
78
+        return $this->renderResult($meta);
79
+    }
80 80
 }
Please login to merge, or discard this patch.
apps/provisioning_api/lib/Middleware/ProvisioningApiMiddleware.php 1 patch
Indentation   +45 added lines, -45 removed lines patch added patch discarded remove patch
@@ -38,55 +38,55 @@
 block discarded – undo
38 38
 
39 39
 class ProvisioningApiMiddleware extends Middleware {
40 40
 
41
-	/** @var IControllerMethodReflector */
42
-	private $reflector;
41
+    /** @var IControllerMethodReflector */
42
+    private $reflector;
43 43
 
44
-	/** @var bool */
45
-	private $isAdmin;
44
+    /** @var bool */
45
+    private $isAdmin;
46 46
 
47
-	/** @var bool */
48
-	private $isSubAdmin;
47
+    /** @var bool */
48
+    private $isSubAdmin;
49 49
 
50
-	/**
51
-	 * ProvisioningApiMiddleware constructor.
52
-	 *
53
-	 * @param IControllerMethodReflector $reflector
54
-	 * @param bool $isAdmin
55
-	 * @param bool $isSubAdmin
56
-	 */
57
-	public function __construct(
58
-		IControllerMethodReflector $reflector,
59
-		bool $isAdmin,
60
-		bool $isSubAdmin) {
61
-		$this->reflector = $reflector;
62
-		$this->isAdmin = $isAdmin;
63
-		$this->isSubAdmin = $isSubAdmin;
64
-	}
50
+    /**
51
+     * ProvisioningApiMiddleware constructor.
52
+     *
53
+     * @param IControllerMethodReflector $reflector
54
+     * @param bool $isAdmin
55
+     * @param bool $isSubAdmin
56
+     */
57
+    public function __construct(
58
+        IControllerMethodReflector $reflector,
59
+        bool $isAdmin,
60
+        bool $isSubAdmin) {
61
+        $this->reflector = $reflector;
62
+        $this->isAdmin = $isAdmin;
63
+        $this->isSubAdmin = $isSubAdmin;
64
+    }
65 65
 
66
-	/**
67
-	 * @param Controller $controller
68
-	 * @param string $methodName
69
-	 *
70
-	 * @throws NotSubAdminException
71
-	 */
72
-	public function beforeController($controller, $methodName) {
73
-		if (!$this->isAdmin && !$this->reflector->hasAnnotation('NoSubAdminRequired') && !$this->isSubAdmin) {
74
-			throw new NotSubAdminException();
75
-		}
76
-	}
66
+    /**
67
+     * @param Controller $controller
68
+     * @param string $methodName
69
+     *
70
+     * @throws NotSubAdminException
71
+     */
72
+    public function beforeController($controller, $methodName) {
73
+        if (!$this->isAdmin && !$this->reflector->hasAnnotation('NoSubAdminRequired') && !$this->isSubAdmin) {
74
+            throw new NotSubAdminException();
75
+        }
76
+    }
77 77
 
78
-	/**
79
-	 * @param Controller $controller
80
-	 * @param string $methodName
81
-	 * @param \Exception $exception
82
-	 * @throws \Exception
83
-	 * @return Response
84
-	 */
85
-	public function afterException($controller, $methodName, \Exception $exception) {
86
-		if ($exception instanceof NotSubAdminException) {
87
-			throw new OCSException($exception->getMessage(), Http::STATUS_FORBIDDEN);
88
-		}
78
+    /**
79
+     * @param Controller $controller
80
+     * @param string $methodName
81
+     * @param \Exception $exception
82
+     * @throws \Exception
83
+     * @return Response
84
+     */
85
+    public function afterException($controller, $methodName, \Exception $exception) {
86
+        if ($exception instanceof NotSubAdminException) {
87
+            throw new OCSException($exception->getMessage(), Http::STATUS_FORBIDDEN);
88
+        }
89 89
 
90
-		throw $exception;
91
-	}
90
+        throw $exception;
91
+    }
92 92
 }
Please login to merge, or discard this patch.
apps/provisioning_api/lib/Controller/GroupsController.php 1 patch
Indentation   +266 added lines, -266 removed lines patch added patch discarded remove patch
@@ -52,270 +52,270 @@
 block discarded – undo
52 52
 
53 53
 class GroupsController extends AUserData {
54 54
 
55
-	/** @var LoggerInterface */
56
-	private $logger;
57
-
58
-	public function __construct(string $appName,
59
-								IRequest $request,
60
-								IUserManager $userManager,
61
-								IConfig $config,
62
-								IGroupManager $groupManager,
63
-								IUserSession $userSession,
64
-								IAccountManager $accountManager,
65
-								IFactory $l10nFactory,
66
-								LoggerInterface $logger) {
67
-		parent::__construct($appName,
68
-			$request,
69
-			$userManager,
70
-			$config,
71
-			$groupManager,
72
-			$userSession,
73
-			$accountManager,
74
-			$l10nFactory
75
-		);
76
-
77
-		$this->logger = $logger;
78
-	}
79
-
80
-	/**
81
-	 * returns a list of groups
82
-	 *
83
-	 * @NoAdminRequired
84
-	 *
85
-	 * @param string $search
86
-	 * @param int $limit
87
-	 * @param int $offset
88
-	 * @return DataResponse
89
-	 */
90
-	public function getGroups(string $search = '', int $limit = null, int $offset = 0): DataResponse {
91
-		$groups = $this->groupManager->search($search, $limit, $offset);
92
-		$groups = array_map(function ($group) {
93
-			/** @var IGroup $group */
94
-			return $group->getGID();
95
-		}, $groups);
96
-
97
-		return new DataResponse(['groups' => $groups]);
98
-	}
99
-
100
-	/**
101
-	 * returns a list of groups details with ids and displaynames
102
-	 *
103
-	 * @NoAdminRequired
104
-	 *
105
-	 * @param string $search
106
-	 * @param int $limit
107
-	 * @param int $offset
108
-	 * @return DataResponse
109
-	 */
110
-	public function getGroupsDetails(string $search = '', int $limit = null, int $offset = 0): DataResponse {
111
-		$groups = $this->groupManager->search($search, $limit, $offset);
112
-		$groups = array_map(function ($group) {
113
-			/** @var IGroup $group */
114
-			return [
115
-				'id' => $group->getGID(),
116
-				'displayname' => $group->getDisplayName(),
117
-				'usercount' => $group->count(),
118
-				'disabled' => $group->countDisabled(),
119
-				'canAdd' => $group->canAddUser(),
120
-				'canRemove' => $group->canRemoveUser(),
121
-			];
122
-		}, $groups);
123
-
124
-		return new DataResponse(['groups' => $groups]);
125
-	}
126
-
127
-	/**
128
-	 * @NoAdminRequired
129
-	 *
130
-	 * @param string $groupId
131
-	 * @return DataResponse
132
-	 * @throws OCSException
133
-	 *
134
-	 * @deprecated 14 Use getGroupUsers
135
-	 */
136
-	public function getGroup(string $groupId): DataResponse {
137
-		return $this->getGroupUsers($groupId);
138
-	}
139
-
140
-	/**
141
-	 * returns an array of users in the specified group
142
-	 *
143
-	 * @NoAdminRequired
144
-	 *
145
-	 * @param string $groupId
146
-	 * @return DataResponse
147
-	 * @throws OCSException
148
-	 */
149
-	public function getGroupUsers(string $groupId): DataResponse {
150
-		$groupId = urldecode($groupId);
151
-
152
-		$user = $this->userSession->getUser();
153
-		$isSubadminOfGroup = false;
154
-
155
-		// Check the group exists
156
-		$group = $this->groupManager->get($groupId);
157
-		if ($group !== null) {
158
-			$isSubadminOfGroup = $this->groupManager->getSubAdmin()->isSubAdminOfGroup($user, $group);
159
-		} else {
160
-			throw new OCSNotFoundException('The requested group could not be found');
161
-		}
162
-
163
-		// Check subadmin has access to this group
164
-		if ($this->groupManager->isAdmin($user->getUID())
165
-		   || $isSubadminOfGroup) {
166
-			$users = $this->groupManager->get($groupId)->getUsers();
167
-			$users = array_map(function ($user) {
168
-				/** @var IUser $user */
169
-				return $user->getUID();
170
-			}, $users);
171
-			$users = array_values($users);
172
-			return new DataResponse(['users' => $users]);
173
-		}
174
-
175
-		throw new OCSForbiddenException();
176
-	}
177
-
178
-	/**
179
-	 * returns an array of users details in the specified group
180
-	 *
181
-	 * @NoAdminRequired
182
-	 *
183
-	 * @param string $groupId
184
-	 * @param string $search
185
-	 * @param int $limit
186
-	 * @param int $offset
187
-	 * @return DataResponse
188
-	 * @throws OCSException
189
-	 */
190
-	public function getGroupUsersDetails(string $groupId, string $search = '', int $limit = null, int $offset = 0): DataResponse {
191
-		$groupId = urldecode($groupId);
192
-		$currentUser = $this->userSession->getUser();
193
-
194
-		// Check the group exists
195
-		$group = $this->groupManager->get($groupId);
196
-		if ($group !== null) {
197
-			$isSubadminOfGroup = $this->groupManager->getSubAdmin()->isSubAdminOfGroup($currentUser, $group);
198
-		} else {
199
-			throw new OCSException('The requested group could not be found', OCSController::RESPOND_NOT_FOUND);
200
-		}
201
-
202
-		// Check subadmin has access to this group
203
-		if ($this->groupManager->isAdmin($currentUser->getUID()) || $isSubadminOfGroup) {
204
-			$users = $group->searchUsers($search, $limit, $offset);
205
-
206
-			// Extract required number
207
-			$usersDetails = [];
208
-			foreach ($users as $user) {
209
-				try {
210
-					/** @var IUser $user */
211
-					$userId = (string)$user->getUID();
212
-					$userData = $this->getUserData($userId);
213
-					// Do not insert empty entry
214
-					if (!empty($userData)) {
215
-						$usersDetails[$userId] = $userData;
216
-					} else {
217
-						// Logged user does not have permissions to see this user
218
-						// only showing its id
219
-						$usersDetails[$userId] = ['id' => $userId];
220
-					}
221
-				} catch (OCSNotFoundException $e) {
222
-					// continue if a users ceased to exist.
223
-				}
224
-			}
225
-			return new DataResponse(['users' => $usersDetails]);
226
-		}
227
-
228
-		throw new OCSException('The requested group could not be found', OCSController::RESPOND_NOT_FOUND);
229
-	}
230
-
231
-	/**
232
-	 * creates a new group
233
-	 *
234
-	 * @PasswordConfirmationRequired
235
-	 *
236
-	 * @param string $groupid
237
-	 * @return DataResponse
238
-	 * @throws OCSException
239
-	 */
240
-	public function addGroup(string $groupid): DataResponse {
241
-		// Validate name
242
-		if (empty($groupid)) {
243
-			$this->logger->error('Group name not supplied', ['app' => 'provisioning_api']);
244
-			throw new OCSException('Invalid group name', 101);
245
-		}
246
-		// Check if it exists
247
-		if ($this->groupManager->groupExists($groupid)) {
248
-			throw new OCSException('group exists', 102);
249
-		}
250
-		$this->groupManager->createGroup($groupid);
251
-		return new DataResponse();
252
-	}
253
-
254
-	/**
255
-	 * @PasswordConfirmationRequired
256
-	 *
257
-	 * @param string $groupId
258
-	 * @param string $key
259
-	 * @param string $value
260
-	 * @return DataResponse
261
-	 * @throws OCSException
262
-	 */
263
-	public function updateGroup(string $groupId, string $key, string $value): DataResponse {
264
-		$groupId = urldecode($groupId);
265
-
266
-		if ($key === 'displayname') {
267
-			$group = $this->groupManager->get($groupId);
268
-			if ($group->setDisplayName($value)) {
269
-				return new DataResponse();
270
-			}
271
-
272
-			throw new OCSException('Not supported by backend', 101);
273
-		} else {
274
-			throw new OCSException('', OCSController::RESPOND_UNKNOWN_ERROR);
275
-		}
276
-	}
277
-
278
-	/**
279
-	 * @PasswordConfirmationRequired
280
-	 *
281
-	 * @param string $groupId
282
-	 * @return DataResponse
283
-	 * @throws OCSException
284
-	 */
285
-	public function deleteGroup(string $groupId): DataResponse {
286
-		$groupId = urldecode($groupId);
287
-
288
-		// Check it exists
289
-		if (!$this->groupManager->groupExists($groupId)) {
290
-			throw new OCSException('', 101);
291
-		} elseif ($groupId === 'admin' || !$this->groupManager->get($groupId)->delete()) {
292
-			// Cannot delete admin group
293
-			throw new OCSException('', 102);
294
-		}
295
-
296
-		return new DataResponse();
297
-	}
298
-
299
-	/**
300
-	 * @param string $groupId
301
-	 * @return DataResponse
302
-	 * @throws OCSException
303
-	 */
304
-	public function getSubAdminsOfGroup(string $groupId): DataResponse {
305
-		// Check group exists
306
-		$targetGroup = $this->groupManager->get($groupId);
307
-		if ($targetGroup === null) {
308
-			throw new OCSException('Group does not exist', 101);
309
-		}
310
-
311
-		/** @var IUser[] $subadmins */
312
-		$subadmins = $this->groupManager->getSubAdmin()->getGroupsSubAdmins($targetGroup);
313
-		// New class returns IUser[] so convert back
314
-		$uids = [];
315
-		foreach ($subadmins as $user) {
316
-			$uids[] = $user->getUID();
317
-		}
318
-
319
-		return new DataResponse($uids);
320
-	}
55
+    /** @var LoggerInterface */
56
+    private $logger;
57
+
58
+    public function __construct(string $appName,
59
+                                IRequest $request,
60
+                                IUserManager $userManager,
61
+                                IConfig $config,
62
+                                IGroupManager $groupManager,
63
+                                IUserSession $userSession,
64
+                                IAccountManager $accountManager,
65
+                                IFactory $l10nFactory,
66
+                                LoggerInterface $logger) {
67
+        parent::__construct($appName,
68
+            $request,
69
+            $userManager,
70
+            $config,
71
+            $groupManager,
72
+            $userSession,
73
+            $accountManager,
74
+            $l10nFactory
75
+        );
76
+
77
+        $this->logger = $logger;
78
+    }
79
+
80
+    /**
81
+     * returns a list of groups
82
+     *
83
+     * @NoAdminRequired
84
+     *
85
+     * @param string $search
86
+     * @param int $limit
87
+     * @param int $offset
88
+     * @return DataResponse
89
+     */
90
+    public function getGroups(string $search = '', int $limit = null, int $offset = 0): DataResponse {
91
+        $groups = $this->groupManager->search($search, $limit, $offset);
92
+        $groups = array_map(function ($group) {
93
+            /** @var IGroup $group */
94
+            return $group->getGID();
95
+        }, $groups);
96
+
97
+        return new DataResponse(['groups' => $groups]);
98
+    }
99
+
100
+    /**
101
+     * returns a list of groups details with ids and displaynames
102
+     *
103
+     * @NoAdminRequired
104
+     *
105
+     * @param string $search
106
+     * @param int $limit
107
+     * @param int $offset
108
+     * @return DataResponse
109
+     */
110
+    public function getGroupsDetails(string $search = '', int $limit = null, int $offset = 0): DataResponse {
111
+        $groups = $this->groupManager->search($search, $limit, $offset);
112
+        $groups = array_map(function ($group) {
113
+            /** @var IGroup $group */
114
+            return [
115
+                'id' => $group->getGID(),
116
+                'displayname' => $group->getDisplayName(),
117
+                'usercount' => $group->count(),
118
+                'disabled' => $group->countDisabled(),
119
+                'canAdd' => $group->canAddUser(),
120
+                'canRemove' => $group->canRemoveUser(),
121
+            ];
122
+        }, $groups);
123
+
124
+        return new DataResponse(['groups' => $groups]);
125
+    }
126
+
127
+    /**
128
+     * @NoAdminRequired
129
+     *
130
+     * @param string $groupId
131
+     * @return DataResponse
132
+     * @throws OCSException
133
+     *
134
+     * @deprecated 14 Use getGroupUsers
135
+     */
136
+    public function getGroup(string $groupId): DataResponse {
137
+        return $this->getGroupUsers($groupId);
138
+    }
139
+
140
+    /**
141
+     * returns an array of users in the specified group
142
+     *
143
+     * @NoAdminRequired
144
+     *
145
+     * @param string $groupId
146
+     * @return DataResponse
147
+     * @throws OCSException
148
+     */
149
+    public function getGroupUsers(string $groupId): DataResponse {
150
+        $groupId = urldecode($groupId);
151
+
152
+        $user = $this->userSession->getUser();
153
+        $isSubadminOfGroup = false;
154
+
155
+        // Check the group exists
156
+        $group = $this->groupManager->get($groupId);
157
+        if ($group !== null) {
158
+            $isSubadminOfGroup = $this->groupManager->getSubAdmin()->isSubAdminOfGroup($user, $group);
159
+        } else {
160
+            throw new OCSNotFoundException('The requested group could not be found');
161
+        }
162
+
163
+        // Check subadmin has access to this group
164
+        if ($this->groupManager->isAdmin($user->getUID())
165
+           || $isSubadminOfGroup) {
166
+            $users = $this->groupManager->get($groupId)->getUsers();
167
+            $users = array_map(function ($user) {
168
+                /** @var IUser $user */
169
+                return $user->getUID();
170
+            }, $users);
171
+            $users = array_values($users);
172
+            return new DataResponse(['users' => $users]);
173
+        }
174
+
175
+        throw new OCSForbiddenException();
176
+    }
177
+
178
+    /**
179
+     * returns an array of users details in the specified group
180
+     *
181
+     * @NoAdminRequired
182
+     *
183
+     * @param string $groupId
184
+     * @param string $search
185
+     * @param int $limit
186
+     * @param int $offset
187
+     * @return DataResponse
188
+     * @throws OCSException
189
+     */
190
+    public function getGroupUsersDetails(string $groupId, string $search = '', int $limit = null, int $offset = 0): DataResponse {
191
+        $groupId = urldecode($groupId);
192
+        $currentUser = $this->userSession->getUser();
193
+
194
+        // Check the group exists
195
+        $group = $this->groupManager->get($groupId);
196
+        if ($group !== null) {
197
+            $isSubadminOfGroup = $this->groupManager->getSubAdmin()->isSubAdminOfGroup($currentUser, $group);
198
+        } else {
199
+            throw new OCSException('The requested group could not be found', OCSController::RESPOND_NOT_FOUND);
200
+        }
201
+
202
+        // Check subadmin has access to this group
203
+        if ($this->groupManager->isAdmin($currentUser->getUID()) || $isSubadminOfGroup) {
204
+            $users = $group->searchUsers($search, $limit, $offset);
205
+
206
+            // Extract required number
207
+            $usersDetails = [];
208
+            foreach ($users as $user) {
209
+                try {
210
+                    /** @var IUser $user */
211
+                    $userId = (string)$user->getUID();
212
+                    $userData = $this->getUserData($userId);
213
+                    // Do not insert empty entry
214
+                    if (!empty($userData)) {
215
+                        $usersDetails[$userId] = $userData;
216
+                    } else {
217
+                        // Logged user does not have permissions to see this user
218
+                        // only showing its id
219
+                        $usersDetails[$userId] = ['id' => $userId];
220
+                    }
221
+                } catch (OCSNotFoundException $e) {
222
+                    // continue if a users ceased to exist.
223
+                }
224
+            }
225
+            return new DataResponse(['users' => $usersDetails]);
226
+        }
227
+
228
+        throw new OCSException('The requested group could not be found', OCSController::RESPOND_NOT_FOUND);
229
+    }
230
+
231
+    /**
232
+     * creates a new group
233
+     *
234
+     * @PasswordConfirmationRequired
235
+     *
236
+     * @param string $groupid
237
+     * @return DataResponse
238
+     * @throws OCSException
239
+     */
240
+    public function addGroup(string $groupid): DataResponse {
241
+        // Validate name
242
+        if (empty($groupid)) {
243
+            $this->logger->error('Group name not supplied', ['app' => 'provisioning_api']);
244
+            throw new OCSException('Invalid group name', 101);
245
+        }
246
+        // Check if it exists
247
+        if ($this->groupManager->groupExists($groupid)) {
248
+            throw new OCSException('group exists', 102);
249
+        }
250
+        $this->groupManager->createGroup($groupid);
251
+        return new DataResponse();
252
+    }
253
+
254
+    /**
255
+     * @PasswordConfirmationRequired
256
+     *
257
+     * @param string $groupId
258
+     * @param string $key
259
+     * @param string $value
260
+     * @return DataResponse
261
+     * @throws OCSException
262
+     */
263
+    public function updateGroup(string $groupId, string $key, string $value): DataResponse {
264
+        $groupId = urldecode($groupId);
265
+
266
+        if ($key === 'displayname') {
267
+            $group = $this->groupManager->get($groupId);
268
+            if ($group->setDisplayName($value)) {
269
+                return new DataResponse();
270
+            }
271
+
272
+            throw new OCSException('Not supported by backend', 101);
273
+        } else {
274
+            throw new OCSException('', OCSController::RESPOND_UNKNOWN_ERROR);
275
+        }
276
+    }
277
+
278
+    /**
279
+     * @PasswordConfirmationRequired
280
+     *
281
+     * @param string $groupId
282
+     * @return DataResponse
283
+     * @throws OCSException
284
+     */
285
+    public function deleteGroup(string $groupId): DataResponse {
286
+        $groupId = urldecode($groupId);
287
+
288
+        // Check it exists
289
+        if (!$this->groupManager->groupExists($groupId)) {
290
+            throw new OCSException('', 101);
291
+        } elseif ($groupId === 'admin' || !$this->groupManager->get($groupId)->delete()) {
292
+            // Cannot delete admin group
293
+            throw new OCSException('', 102);
294
+        }
295
+
296
+        return new DataResponse();
297
+    }
298
+
299
+    /**
300
+     * @param string $groupId
301
+     * @return DataResponse
302
+     * @throws OCSException
303
+     */
304
+    public function getSubAdminsOfGroup(string $groupId): DataResponse {
305
+        // Check group exists
306
+        $targetGroup = $this->groupManager->get($groupId);
307
+        if ($targetGroup === null) {
308
+            throw new OCSException('Group does not exist', 101);
309
+        }
310
+
311
+        /** @var IUser[] $subadmins */
312
+        $subadmins = $this->groupManager->getSubAdmin()->getGroupsSubAdmins($targetGroup);
313
+        // New class returns IUser[] so convert back
314
+        $uids = [];
315
+        foreach ($subadmins as $user) {
316
+            $uids[] = $user->getUID();
317
+        }
318
+
319
+        return new DataResponse($uids);
320
+    }
321 321
 }
Please login to merge, or discard this patch.
apps/provisioning_api/lib/Controller/UsersController.php 1 patch
Indentation   +1089 added lines, -1089 removed lines patch added patch discarded remove patch
@@ -75,1093 +75,1093 @@
 block discarded – undo
75 75
 
76 76
 class UsersController extends AUserData {
77 77
 
78
-	/** @var IAppManager */
79
-	private $appManager;
80
-	/** @var IURLGenerator */
81
-	protected $urlGenerator;
82
-	/** @var LoggerInterface */
83
-	private $logger;
84
-	/** @var IFactory */
85
-	protected $l10nFactory;
86
-	/** @var NewUserMailHelper */
87
-	private $newUserMailHelper;
88
-	/** @var ISecureRandom */
89
-	private $secureRandom;
90
-	/** @var RemoteWipe */
91
-	private $remoteWipe;
92
-	/** @var KnownUserService */
93
-	private $knownUserService;
94
-	/** @var IEventDispatcher */
95
-	private $eventDispatcher;
96
-
97
-	public function __construct(string $appName,
98
-								IRequest $request,
99
-								IUserManager $userManager,
100
-								IConfig $config,
101
-								IAppManager $appManager,
102
-								IGroupManager $groupManager,
103
-								IUserSession $userSession,
104
-								IAccountManager $accountManager,
105
-								IURLGenerator $urlGenerator,
106
-								LoggerInterface $logger,
107
-								IFactory $l10nFactory,
108
-								NewUserMailHelper $newUserMailHelper,
109
-								ISecureRandom $secureRandom,
110
-								RemoteWipe $remoteWipe,
111
-								KnownUserService $knownUserService,
112
-								IEventDispatcher $eventDispatcher) {
113
-		parent::__construct($appName,
114
-							$request,
115
-							$userManager,
116
-							$config,
117
-							$groupManager,
118
-							$userSession,
119
-							$accountManager,
120
-							$l10nFactory);
121
-
122
-		$this->appManager = $appManager;
123
-		$this->urlGenerator = $urlGenerator;
124
-		$this->logger = $logger;
125
-		$this->l10nFactory = $l10nFactory;
126
-		$this->newUserMailHelper = $newUserMailHelper;
127
-		$this->secureRandom = $secureRandom;
128
-		$this->remoteWipe = $remoteWipe;
129
-		$this->knownUserService = $knownUserService;
130
-		$this->eventDispatcher = $eventDispatcher;
131
-	}
132
-
133
-	/**
134
-	 * @NoAdminRequired
135
-	 *
136
-	 * returns a list of users
137
-	 *
138
-	 * @param string $search
139
-	 * @param int $limit
140
-	 * @param int $offset
141
-	 * @return DataResponse
142
-	 */
143
-	public function getUsers(string $search = '', int $limit = null, int $offset = 0): DataResponse {
144
-		$user = $this->userSession->getUser();
145
-		$users = [];
146
-
147
-		// Admin? Or SubAdmin?
148
-		$uid = $user->getUID();
149
-		$subAdminManager = $this->groupManager->getSubAdmin();
150
-		if ($this->groupManager->isAdmin($uid)) {
151
-			$users = $this->userManager->search($search, $limit, $offset);
152
-		} elseif ($subAdminManager->isSubAdmin($user)) {
153
-			$subAdminOfGroups = $subAdminManager->getSubAdminsGroups($user);
154
-			foreach ($subAdminOfGroups as $key => $group) {
155
-				$subAdminOfGroups[$key] = $group->getGID();
156
-			}
157
-
158
-			$users = [];
159
-			foreach ($subAdminOfGroups as $group) {
160
-				$users = array_merge($users, $this->groupManager->displayNamesInGroup($group, $search, $limit, $offset));
161
-			}
162
-		}
163
-
164
-		$users = array_keys($users);
165
-
166
-		return new DataResponse([
167
-			'users' => $users
168
-		]);
169
-	}
170
-
171
-	/**
172
-	 * @NoAdminRequired
173
-	 *
174
-	 * returns a list of users and their data
175
-	 */
176
-	public function getUsersDetails(string $search = '', int $limit = null, int $offset = 0): DataResponse {
177
-		$currentUser = $this->userSession->getUser();
178
-		$users = [];
179
-
180
-		// Admin? Or SubAdmin?
181
-		$uid = $currentUser->getUID();
182
-		$subAdminManager = $this->groupManager->getSubAdmin();
183
-		if ($this->groupManager->isAdmin($uid)) {
184
-			$users = $this->userManager->search($search, $limit, $offset);
185
-			$users = array_keys($users);
186
-		} elseif ($subAdminManager->isSubAdmin($currentUser)) {
187
-			$subAdminOfGroups = $subAdminManager->getSubAdminsGroups($currentUser);
188
-			foreach ($subAdminOfGroups as $key => $group) {
189
-				$subAdminOfGroups[$key] = $group->getGID();
190
-			}
191
-
192
-			$users = [];
193
-			foreach ($subAdminOfGroups as $group) {
194
-				$users[] = array_keys($this->groupManager->displayNamesInGroup($group, $search, $limit, $offset));
195
-			}
196
-			$users = array_merge(...$users);
197
-		}
198
-
199
-		$usersDetails = [];
200
-		foreach ($users as $userId) {
201
-			$userId = (string) $userId;
202
-			$userData = $this->getUserData($userId);
203
-			// Do not insert empty entry
204
-			if (!empty($userData)) {
205
-				$usersDetails[$userId] = $userData;
206
-			} else {
207
-				// Logged user does not have permissions to see this user
208
-				// only showing its id
209
-				$usersDetails[$userId] = ['id' => $userId];
210
-			}
211
-		}
212
-
213
-		return new DataResponse([
214
-			'users' => $usersDetails
215
-		]);
216
-	}
217
-
218
-
219
-	/**
220
-	 * @NoAdminRequired
221
-	 * @NoSubAdminRequired
222
-	 *
223
-	 * @param string $location
224
-	 * @param array $search
225
-	 * @return DataResponse
226
-	 */
227
-	public function searchByPhoneNumbers(string $location, array $search): DataResponse {
228
-		$phoneUtil = PhoneNumberUtil::getInstance();
229
-
230
-		if ($phoneUtil->getCountryCodeForRegion($location) === 0) {
231
-			// Not a valid region code
232
-			return new DataResponse([], Http::STATUS_BAD_REQUEST);
233
-		}
234
-
235
-		/** @var IUser $user */
236
-		$user = $this->userSession->getUser();
237
-		$knownTo = $user->getUID();
238
-		$defaultPhoneRegion = $this->config->getSystemValueString('default_phone_region');
239
-
240
-		$normalizedNumberToKey = [];
241
-		foreach ($search as $key => $phoneNumbers) {
242
-			foreach ($phoneNumbers as $phone) {
243
-				try {
244
-					$phoneNumber = $phoneUtil->parse($phone, $location);
245
-					if ($phoneNumber instanceof PhoneNumber && $phoneUtil->isValidNumber($phoneNumber)) {
246
-						$normalizedNumber = $phoneUtil->format($phoneNumber, PhoneNumberFormat::E164);
247
-						$normalizedNumberToKey[$normalizedNumber] = (string) $key;
248
-					}
249
-				} catch (NumberParseException $e) {
250
-				}
251
-
252
-				if ($defaultPhoneRegion !== '' && $defaultPhoneRegion !== $location && strpos($phone, '0') === 0) {
253
-					// If the number has a leading zero (no country code),
254
-					// we also check the default phone region of the instance,
255
-					// when it's different to the user's given region.
256
-					try {
257
-						$phoneNumber = $phoneUtil->parse($phone, $defaultPhoneRegion);
258
-						if ($phoneNumber instanceof PhoneNumber && $phoneUtil->isValidNumber($phoneNumber)) {
259
-							$normalizedNumber = $phoneUtil->format($phoneNumber, PhoneNumberFormat::E164);
260
-							$normalizedNumberToKey[$normalizedNumber] = (string) $key;
261
-						}
262
-					} catch (NumberParseException $e) {
263
-					}
264
-				}
265
-			}
266
-		}
267
-
268
-		$phoneNumbers = array_keys($normalizedNumberToKey);
269
-
270
-		if (empty($phoneNumbers)) {
271
-			return new DataResponse();
272
-		}
273
-
274
-		// Cleanup all previous entries and only allow new matches
275
-		$this->knownUserService->deleteKnownTo($knownTo);
276
-
277
-		$userMatches = $this->accountManager->searchUsers(IAccountManager::PROPERTY_PHONE, $phoneNumbers);
278
-
279
-		if (empty($userMatches)) {
280
-			return new DataResponse();
281
-		}
282
-
283
-		$cloudUrl = rtrim($this->urlGenerator->getAbsoluteURL('/'), '/');
284
-		if (strpos($cloudUrl, 'http://') === 0) {
285
-			$cloudUrl = substr($cloudUrl, strlen('http://'));
286
-		} elseif (strpos($cloudUrl, 'https://') === 0) {
287
-			$cloudUrl = substr($cloudUrl, strlen('https://'));
288
-		}
289
-
290
-		$matches = [];
291
-		foreach ($userMatches as $phone => $userId) {
292
-			// Not using the ICloudIdManager as that would run a search for each contact to find the display name in the address book
293
-			$matches[$normalizedNumberToKey[$phone]] = $userId . '@' . $cloudUrl;
294
-			$this->knownUserService->storeIsKnownToUser($knownTo, $userId);
295
-		}
296
-
297
-		return new DataResponse($matches);
298
-	}
299
-
300
-	/**
301
-	 * @throws OCSException
302
-	 */
303
-	private function createNewUserId(): string {
304
-		$attempts = 0;
305
-		do {
306
-			$uidCandidate = $this->secureRandom->generate(10, ISecureRandom::CHAR_HUMAN_READABLE);
307
-			if (!$this->userManager->userExists($uidCandidate)) {
308
-				return $uidCandidate;
309
-			}
310
-			$attempts++;
311
-		} while ($attempts < 10);
312
-		throw new OCSException('Could not create non-existing user id', 111);
313
-	}
314
-
315
-	/**
316
-	 * @PasswordConfirmationRequired
317
-	 * @NoAdminRequired
318
-	 *
319
-	 * @param string $userid
320
-	 * @param string $password
321
-	 * @param string $displayName
322
-	 * @param string $email
323
-	 * @param array $groups
324
-	 * @param array $subadmin
325
-	 * @param string $quota
326
-	 * @param string $language
327
-	 * @return DataResponse
328
-	 * @throws OCSException
329
-	 */
330
-	public function addUser(string $userid,
331
-							string $password = '',
332
-							string $displayName = '',
333
-							string $email = '',
334
-							array $groups = [],
335
-							array $subadmin = [],
336
-							string $quota = '',
337
-							string $language = ''): DataResponse {
338
-		$user = $this->userSession->getUser();
339
-		$isAdmin = $this->groupManager->isAdmin($user->getUID());
340
-		$subAdminManager = $this->groupManager->getSubAdmin();
341
-
342
-		if (empty($userid) && $this->config->getAppValue('core', 'newUser.generateUserID', 'no') === 'yes') {
343
-			$userid = $this->createNewUserId();
344
-		}
345
-
346
-		if ($this->userManager->userExists($userid)) {
347
-			$this->logger->error('Failed addUser attempt: User already exists.', ['app' => 'ocs_api']);
348
-			throw new OCSException('User already exists', 102);
349
-		}
350
-
351
-		if ($groups !== []) {
352
-			foreach ($groups as $group) {
353
-				if (!$this->groupManager->groupExists($group)) {
354
-					throw new OCSException('group '.$group.' does not exist', 104);
355
-				}
356
-				if (!$isAdmin && !$subAdminManager->isSubAdminOfGroup($user, $this->groupManager->get($group))) {
357
-					throw new OCSException('insufficient privileges for group '. $group, 105);
358
-				}
359
-			}
360
-		} else {
361
-			if (!$isAdmin) {
362
-				throw new OCSException('no group specified (required for subadmins)', 106);
363
-			}
364
-		}
365
-
366
-		$subadminGroups = [];
367
-		if ($subadmin !== []) {
368
-			foreach ($subadmin as $groupid) {
369
-				$group = $this->groupManager->get($groupid);
370
-				// Check if group exists
371
-				if ($group === null) {
372
-					throw new OCSException('Subadmin group does not exist',  102);
373
-				}
374
-				// Check if trying to make subadmin of admin group
375
-				if ($group->getGID() === 'admin') {
376
-					throw new OCSException('Cannot create subadmins for admin group', 103);
377
-				}
378
-				// Check if has permission to promote subadmins
379
-				if (!$subAdminManager->isSubAdminOfGroup($user, $group) && !$isAdmin) {
380
-					throw new OCSForbiddenException('No permissions to promote subadmins');
381
-				}
382
-				$subadminGroups[] = $group;
383
-			}
384
-		}
385
-
386
-		$generatePasswordResetToken = false;
387
-		if ($password === '') {
388
-			if ($email === '') {
389
-				throw new OCSException('To send a password link to the user an email address is required.', 108);
390
-			}
391
-
392
-			$passwordEvent = new GenerateSecurePasswordEvent();
393
-			$this->eventDispatcher->dispatchTyped($passwordEvent);
394
-
395
-			$password = $passwordEvent->getPassword();
396
-			if ($password === null) {
397
-				// Fallback: ensure to pass password_policy in any case
398
-				$password = $this->secureRandom->generate(10)
399
-					. $this->secureRandom->generate(1, ISecureRandom::CHAR_UPPER)
400
-					. $this->secureRandom->generate(1, ISecureRandom::CHAR_LOWER)
401
-					. $this->secureRandom->generate(1, ISecureRandom::CHAR_DIGITS)
402
-					. $this->secureRandom->generate(1, ISecureRandom::CHAR_SYMBOLS);
403
-			}
404
-			$generatePasswordResetToken = true;
405
-		}
406
-
407
-		if ($email === '' && $this->config->getAppValue('core', 'newUser.requireEmail', 'no') === 'yes') {
408
-			throw new OCSException('Required email address was not provided', 110);
409
-		}
410
-
411
-		try {
412
-			$newUser = $this->userManager->createUser($userid, $password);
413
-			$this->logger->info('Successful addUser call with userid: ' . $userid, ['app' => 'ocs_api']);
414
-
415
-			foreach ($groups as $group) {
416
-				$this->groupManager->get($group)->addUser($newUser);
417
-				$this->logger->info('Added userid ' . $userid . ' to group ' . $group, ['app' => 'ocs_api']);
418
-			}
419
-			foreach ($subadminGroups as $group) {
420
-				$subAdminManager->createSubAdmin($newUser, $group);
421
-			}
422
-
423
-			if ($displayName !== '') {
424
-				$this->editUser($userid, 'display', $displayName);
425
-			}
426
-
427
-			if ($quota !== '') {
428
-				$this->editUser($userid, 'quota', $quota);
429
-			}
430
-
431
-			if ($language !== '') {
432
-				$this->editUser($userid, 'language', $language);
433
-			}
434
-
435
-			// Send new user mail only if a mail is set
436
-			if ($email !== '') {
437
-				$newUser->setEMailAddress($email);
438
-				if ($this->config->getAppValue('core', 'newUser.sendEmail', 'yes') === 'yes') {
439
-					try {
440
-						$emailTemplate = $this->newUserMailHelper->generateTemplate($newUser, $generatePasswordResetToken);
441
-						$this->newUserMailHelper->sendMail($newUser, $emailTemplate);
442
-					} catch (\Exception $e) {
443
-						// Mail could be failing hard or just be plain not configured
444
-						// Logging error as it is the hardest of the two
445
-						$this->logger->error("Unable to send the invitation mail to $email",
446
-							[
447
-								'app' => 'ocs_api',
448
-								'exception' => $e,
449
-							]
450
-						);
451
-					}
452
-				}
453
-			}
454
-
455
-			return new DataResponse(['id' => $userid]);
456
-		} catch (HintException $e) {
457
-			$this->logger->warning('Failed addUser attempt with hint exception.',
458
-				[
459
-					'app' => 'ocs_api',
460
-					'exception' => $e,
461
-				]
462
-			);
463
-			throw new OCSException($e->getHint(), 107);
464
-		} catch (OCSException $e) {
465
-			$this->logger->warning('Failed addUser attempt with ocs exeption.',
466
-				[
467
-					'app' => 'ocs_api',
468
-					'exception' => $e,
469
-				]
470
-			);
471
-			throw $e;
472
-		} catch (\InvalidArgumentException $e) {
473
-			$this->logger->error('Failed addUser attempt with invalid argument exeption.',
474
-				[
475
-					'app' => 'ocs_api',
476
-					'exception' => $e,
477
-				]
478
-			);
479
-			throw new OCSException($e->getMessage(), 101);
480
-		} catch (\Exception $e) {
481
-			$this->logger->error('Failed addUser attempt with exception.',
482
-				[
483
-					'app' => 'ocs_api',
484
-					'exception' => $e
485
-				]
486
-			);
487
-			throw new OCSException('Bad request', 101);
488
-		}
489
-	}
490
-
491
-	/**
492
-	 * @NoAdminRequired
493
-	 * @NoSubAdminRequired
494
-	 *
495
-	 * gets user info
496
-	 *
497
-	 * @param string $userId
498
-	 * @return DataResponse
499
-	 * @throws OCSException
500
-	 */
501
-	public function getUser(string $userId): DataResponse {
502
-		$includeScopes = false;
503
-		$currentUser = $this->userSession->getUser();
504
-		if ($currentUser && $currentUser->getUID() === $userId) {
505
-			$includeScopes = true;
506
-		}
507
-
508
-		$data = $this->getUserData($userId, $includeScopes);
509
-		// getUserData returns empty array if not enough permissions
510
-		if (empty($data)) {
511
-			throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
512
-		}
513
-		return new DataResponse($data);
514
-	}
515
-
516
-	/**
517
-	 * @NoAdminRequired
518
-	 * @NoSubAdminRequired
519
-	 *
520
-	 * gets user info from the currently logged in user
521
-	 *
522
-	 * @return DataResponse
523
-	 * @throws OCSException
524
-	 */
525
-	public function getCurrentUser(): DataResponse {
526
-		$user = $this->userSession->getUser();
527
-		if ($user) {
528
-			$data = $this->getUserData($user->getUID(), true);
529
-			// rename "displayname" to "display-name" only for this call to keep
530
-			// the API stable.
531
-			$data['display-name'] = $data['displayname'];
532
-			unset($data['displayname']);
533
-			return new DataResponse($data);
534
-		}
535
-
536
-		throw new OCSException('', OCSController::RESPOND_UNAUTHORISED);
537
-	}
538
-
539
-	/**
540
-	 * @NoAdminRequired
541
-	 * @NoSubAdminRequired
542
-	 *
543
-	 * @return DataResponse
544
-	 * @throws OCSException
545
-	 */
546
-	public function getEditableFields(?string $userId = null): DataResponse {
547
-		$currentLoggedInUser = $this->userSession->getUser();
548
-		if (!$currentLoggedInUser instanceof IUser) {
549
-			throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
550
-		}
551
-
552
-		$permittedFields = [];
553
-
554
-		if ($userId !== $currentLoggedInUser->getUID()) {
555
-			$targetUser = $this->userManager->get($userId);
556
-			if (!$targetUser instanceof IUser) {
557
-				throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
558
-			}
559
-
560
-			$subAdminManager = $this->groupManager->getSubAdmin();
561
-			if (!$this->groupManager->isAdmin($currentLoggedInUser->getUID())
562
-				&& !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
563
-				throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
564
-			}
565
-		} else {
566
-			$targetUser = $currentLoggedInUser;
567
-		}
568
-
569
-		// Editing self (display, email)
570
-		if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
571
-			if ($targetUser->getBackend() instanceof ISetDisplayNameBackend
572
-				|| $targetUser->getBackend()->implementsActions(Backend::SET_DISPLAYNAME)) {
573
-				$permittedFields[] = IAccountManager::PROPERTY_DISPLAYNAME;
574
-			}
575
-			$permittedFields[] = IAccountManager::PROPERTY_EMAIL;
576
-		}
577
-
578
-		$permittedFields[] = IAccountManager::PROPERTY_PHONE;
579
-		$permittedFields[] = IAccountManager::PROPERTY_ADDRESS;
580
-		$permittedFields[] = IAccountManager::PROPERTY_WEBSITE;
581
-		$permittedFields[] = IAccountManager::PROPERTY_TWITTER;
582
-
583
-		return new DataResponse($permittedFields);
584
-	}
585
-
586
-	/**
587
-	 * @NoAdminRequired
588
-	 * @NoSubAdminRequired
589
-	 * @PasswordConfirmationRequired
590
-	 *
591
-	 * edit users
592
-	 *
593
-	 * @param string $userId
594
-	 * @param string $key
595
-	 * @param string $value
596
-	 * @return DataResponse
597
-	 * @throws OCSException
598
-	 */
599
-	public function editUser(string $userId, string $key, string $value): DataResponse {
600
-		$currentLoggedInUser = $this->userSession->getUser();
601
-
602
-		$targetUser = $this->userManager->get($userId);
603
-		if ($targetUser === null) {
604
-			throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
605
-		}
606
-
607
-		$permittedFields = [];
608
-		if ($targetUser->getUID() === $currentLoggedInUser->getUID()) {
609
-			// Editing self (display, email)
610
-			if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
611
-				if ($targetUser->getBackend() instanceof ISetDisplayNameBackend
612
-					|| $targetUser->getBackend()->implementsActions(Backend::SET_DISPLAYNAME)) {
613
-					$permittedFields[] = 'display';
614
-					$permittedFields[] = IAccountManager::PROPERTY_DISPLAYNAME;
615
-				}
616
-				$permittedFields[] = IAccountManager::PROPERTY_EMAIL;
617
-			}
618
-
619
-			$permittedFields[] = IAccountManager::PROPERTY_DISPLAYNAME . self::SCOPE_SUFFIX;
620
-			$permittedFields[] = IAccountManager::PROPERTY_EMAIL . self::SCOPE_SUFFIX;
621
-
622
-			$permittedFields[] = 'password';
623
-			if ($this->config->getSystemValue('force_language', false) === false ||
624
-				$this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
625
-				$permittedFields[] = 'language';
626
-			}
627
-
628
-			if ($this->config->getSystemValue('force_locale', false) === false ||
629
-				$this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
630
-				$permittedFields[] = 'locale';
631
-			}
632
-
633
-			$permittedFields[] = IAccountManager::PROPERTY_PHONE;
634
-			$permittedFields[] = IAccountManager::PROPERTY_ADDRESS;
635
-			$permittedFields[] = IAccountManager::PROPERTY_WEBSITE;
636
-			$permittedFields[] = IAccountManager::PROPERTY_TWITTER;
637
-			$permittedFields[] = IAccountManager::PROPERTY_PHONE . self::SCOPE_SUFFIX;
638
-			$permittedFields[] = IAccountManager::PROPERTY_ADDRESS . self::SCOPE_SUFFIX;
639
-			$permittedFields[] = IAccountManager::PROPERTY_WEBSITE . self::SCOPE_SUFFIX;
640
-			$permittedFields[] = IAccountManager::PROPERTY_TWITTER . self::SCOPE_SUFFIX;
641
-
642
-			$permittedFields[] = IAccountManager::PROPERTY_AVATAR . self::SCOPE_SUFFIX;
643
-
644
-			// If admin they can edit their own quota
645
-			if ($this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
646
-				$permittedFields[] = 'quota';
647
-			}
648
-		} else {
649
-			// Check if admin / subadmin
650
-			$subAdminManager = $this->groupManager->getSubAdmin();
651
-			if ($this->groupManager->isAdmin($currentLoggedInUser->getUID())
652
-			|| $subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
653
-				// They have permissions over the user
654
-				if ($targetUser->getBackend() instanceof ISetDisplayNameBackend
655
-					|| $targetUser->getBackend()->implementsActions(Backend::SET_DISPLAYNAME)) {
656
-					$permittedFields[] = 'display';
657
-					$permittedFields[] = IAccountManager::PROPERTY_DISPLAYNAME;
658
-				}
659
-				$permittedFields[] = IAccountManager::PROPERTY_EMAIL;
660
-				$permittedFields[] = 'password';
661
-				$permittedFields[] = 'language';
662
-				$permittedFields[] = 'locale';
663
-				$permittedFields[] = IAccountManager::PROPERTY_PHONE;
664
-				$permittedFields[] = IAccountManager::PROPERTY_ADDRESS;
665
-				$permittedFields[] = IAccountManager::PROPERTY_WEBSITE;
666
-				$permittedFields[] = IAccountManager::PROPERTY_TWITTER;
667
-				$permittedFields[] = 'quota';
668
-			} else {
669
-				// No rights
670
-				throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
671
-			}
672
-		}
673
-		// Check if permitted to edit this field
674
-		if (!in_array($key, $permittedFields)) {
675
-			throw new OCSException('', 103);
676
-		}
677
-		// Process the edit
678
-		switch ($key) {
679
-			case 'display':
680
-			case IAccountManager::PROPERTY_DISPLAYNAME:
681
-				$targetUser->setDisplayName($value);
682
-				break;
683
-			case 'quota':
684
-				$quota = $value;
685
-				if ($quota !== 'none' && $quota !== 'default') {
686
-					if (is_numeric($quota)) {
687
-						$quota = (float) $quota;
688
-					} else {
689
-						$quota = \OCP\Util::computerFileSize($quota);
690
-					}
691
-					if ($quota === false) {
692
-						throw new OCSException('Invalid quota value '.$value, 102);
693
-					}
694
-					if ($quota === -1) {
695
-						$quota = 'none';
696
-					} else {
697
-						$quota = \OCP\Util::humanFileSize($quota);
698
-					}
699
-				}
700
-				$targetUser->setQuota($quota);
701
-				break;
702
-			case 'password':
703
-				try {
704
-					if (!$targetUser->canChangePassword()) {
705
-						throw new OCSException('Setting the password is not supported by the users backend', 103);
706
-					}
707
-					$targetUser->setPassword($value);
708
-				} catch (HintException $e) { // password policy error
709
-					throw new OCSException($e->getMessage(), 103);
710
-				}
711
-				break;
712
-			case 'language':
713
-				$languagesCodes = $this->l10nFactory->findAvailableLanguages();
714
-				if (!in_array($value, $languagesCodes, true) && $value !== 'en') {
715
-					throw new OCSException('Invalid language', 102);
716
-				}
717
-				$this->config->setUserValue($targetUser->getUID(), 'core', 'lang', $value);
718
-				break;
719
-			case 'locale':
720
-				if (!$this->l10nFactory->localeExists($value)) {
721
-					throw new OCSException('Invalid locale', 102);
722
-				}
723
-				$this->config->setUserValue($targetUser->getUID(), 'core', 'locale', $value);
724
-				break;
725
-			case IAccountManager::PROPERTY_EMAIL:
726
-				if (filter_var($value, FILTER_VALIDATE_EMAIL) || $value === '') {
727
-					$targetUser->setEMailAddress($value);
728
-				} else {
729
-					throw new OCSException('', 102);
730
-				}
731
-				break;
732
-			case IAccountManager::PROPERTY_PHONE:
733
-			case IAccountManager::PROPERTY_ADDRESS:
734
-			case IAccountManager::PROPERTY_WEBSITE:
735
-			case IAccountManager::PROPERTY_TWITTER:
736
-				$userAccount = $this->accountManager->getAccount($targetUser);
737
-				$userProperty = $userAccount->getProperty($key);
738
-				if ($userProperty->getValue() !== $value) {
739
-					try {
740
-						$userProperty->setValue($value);
741
-						$this->accountManager->updateAccount($userAccount);
742
-
743
-						if ($userProperty->getName() === IAccountManager::PROPERTY_PHONE) {
744
-							$this->knownUserService->deleteByContactUserId($targetUser->getUID());
745
-						}
746
-					} catch (\InvalidArgumentException $e) {
747
-						throw new OCSException('Invalid ' . $e->getMessage(), 102);
748
-					}
749
-				}
750
-				break;
751
-			case IAccountManager::PROPERTY_DISPLAYNAME . self::SCOPE_SUFFIX:
752
-			case IAccountManager::PROPERTY_EMAIL . self::SCOPE_SUFFIX:
753
-			case IAccountManager::PROPERTY_PHONE . self::SCOPE_SUFFIX:
754
-			case IAccountManager::PROPERTY_ADDRESS . self::SCOPE_SUFFIX:
755
-			case IAccountManager::PROPERTY_WEBSITE . self::SCOPE_SUFFIX:
756
-			case IAccountManager::PROPERTY_TWITTER . self::SCOPE_SUFFIX:
757
-			case IAccountManager::PROPERTY_AVATAR . self::SCOPE_SUFFIX:
758
-				$propertyName = substr($key, 0, strlen($key) - strlen(self::SCOPE_SUFFIX));
759
-				$userAccount = $this->accountManager->getAccount($targetUser);
760
-				$userProperty = $userAccount->getProperty($propertyName);
761
-				if ($userProperty->getScope() !== $value) {
762
-					try {
763
-						$userProperty->setScope($value);
764
-						$this->accountManager->updateAccount($userAccount);
765
-					} catch (\InvalidArgumentException $e) {
766
-						throw new OCSException('Invalid ' . $e->getMessage(), 102);
767
-					}
768
-				}
769
-				break;
770
-			default:
771
-				throw new OCSException('', 103);
772
-		}
773
-		return new DataResponse();
774
-	}
775
-
776
-	/**
777
-	 * @PasswordConfirmationRequired
778
-	 * @NoAdminRequired
779
-	 *
780
-	 * @param string $userId
781
-	 *
782
-	 * @return DataResponse
783
-	 *
784
-	 * @throws OCSException
785
-	 */
786
-	public function wipeUserDevices(string $userId): DataResponse {
787
-		/** @var IUser $currentLoggedInUser */
788
-		$currentLoggedInUser = $this->userSession->getUser();
789
-
790
-		$targetUser = $this->userManager->get($userId);
791
-
792
-		if ($targetUser === null) {
793
-			throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
794
-		}
795
-
796
-		if ($targetUser->getUID() === $currentLoggedInUser->getUID()) {
797
-			throw new OCSException('', 101);
798
-		}
799
-
800
-		// If not permitted
801
-		$subAdminManager = $this->groupManager->getSubAdmin();
802
-		if (!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
803
-			throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
804
-		}
805
-
806
-		$this->remoteWipe->markAllTokensForWipe($targetUser);
807
-
808
-		return new DataResponse();
809
-	}
810
-
811
-	/**
812
-	 * @PasswordConfirmationRequired
813
-	 * @NoAdminRequired
814
-	 *
815
-	 * @param string $userId
816
-	 * @return DataResponse
817
-	 * @throws OCSException
818
-	 */
819
-	public function deleteUser(string $userId): DataResponse {
820
-		$currentLoggedInUser = $this->userSession->getUser();
821
-
822
-		$targetUser = $this->userManager->get($userId);
823
-
824
-		if ($targetUser === null) {
825
-			throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
826
-		}
827
-
828
-		if ($targetUser->getUID() === $currentLoggedInUser->getUID()) {
829
-			throw new OCSException('', 101);
830
-		}
831
-
832
-		// If not permitted
833
-		$subAdminManager = $this->groupManager->getSubAdmin();
834
-		if (!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
835
-			throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
836
-		}
837
-
838
-		// Go ahead with the delete
839
-		if ($targetUser->delete()) {
840
-			return new DataResponse();
841
-		} else {
842
-			throw new OCSException('', 101);
843
-		}
844
-	}
845
-
846
-	/**
847
-	 * @PasswordConfirmationRequired
848
-	 * @NoAdminRequired
849
-	 *
850
-	 * @param string $userId
851
-	 * @return DataResponse
852
-	 * @throws OCSException
853
-	 * @throws OCSForbiddenException
854
-	 */
855
-	public function disableUser(string $userId): DataResponse {
856
-		return $this->setEnabled($userId, false);
857
-	}
858
-
859
-	/**
860
-	 * @PasswordConfirmationRequired
861
-	 * @NoAdminRequired
862
-	 *
863
-	 * @param string $userId
864
-	 * @return DataResponse
865
-	 * @throws OCSException
866
-	 * @throws OCSForbiddenException
867
-	 */
868
-	public function enableUser(string $userId): DataResponse {
869
-		return $this->setEnabled($userId, true);
870
-	}
871
-
872
-	/**
873
-	 * @param string $userId
874
-	 * @param bool $value
875
-	 * @return DataResponse
876
-	 * @throws OCSException
877
-	 */
878
-	private function setEnabled(string $userId, bool $value): DataResponse {
879
-		$currentLoggedInUser = $this->userSession->getUser();
880
-
881
-		$targetUser = $this->userManager->get($userId);
882
-		if ($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
883
-			throw new OCSException('', 101);
884
-		}
885
-
886
-		// If not permitted
887
-		$subAdminManager = $this->groupManager->getSubAdmin();
888
-		if (!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
889
-			throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
890
-		}
891
-
892
-		// enable/disable the user now
893
-		$targetUser->setEnabled($value);
894
-		return new DataResponse();
895
-	}
896
-
897
-	/**
898
-	 * @NoAdminRequired
899
-	 * @NoSubAdminRequired
900
-	 *
901
-	 * @param string $userId
902
-	 * @return DataResponse
903
-	 * @throws OCSException
904
-	 */
905
-	public function getUsersGroups(string $userId): DataResponse {
906
-		$loggedInUser = $this->userSession->getUser();
907
-
908
-		$targetUser = $this->userManager->get($userId);
909
-		if ($targetUser === null) {
910
-			throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
911
-		}
912
-
913
-		if ($targetUser->getUID() === $loggedInUser->getUID() || $this->groupManager->isAdmin($loggedInUser->getUID())) {
914
-			// Self lookup or admin lookup
915
-			return new DataResponse([
916
-				'groups' => $this->groupManager->getUserGroupIds($targetUser)
917
-			]);
918
-		} else {
919
-			$subAdminManager = $this->groupManager->getSubAdmin();
920
-
921
-			// Looking up someone else
922
-			if ($subAdminManager->isUserAccessible($loggedInUser, $targetUser)) {
923
-				// Return the group that the method caller is subadmin of for the user in question
924
-				/** @var IGroup[] $getSubAdminsGroups */
925
-				$getSubAdminsGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
926
-				foreach ($getSubAdminsGroups as $key => $group) {
927
-					$getSubAdminsGroups[$key] = $group->getGID();
928
-				}
929
-				$groups = array_intersect(
930
-					$getSubAdminsGroups,
931
-					$this->groupManager->getUserGroupIds($targetUser)
932
-				);
933
-				return new DataResponse(['groups' => $groups]);
934
-			} else {
935
-				// Not permitted
936
-				throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
937
-			}
938
-		}
939
-	}
940
-
941
-	/**
942
-	 * @PasswordConfirmationRequired
943
-	 * @NoAdminRequired
944
-	 *
945
-	 * @param string $userId
946
-	 * @param string $groupid
947
-	 * @return DataResponse
948
-	 * @throws OCSException
949
-	 */
950
-	public function addToGroup(string $userId, string $groupid = ''): DataResponse {
951
-		if ($groupid === '') {
952
-			throw new OCSException('', 101);
953
-		}
954
-
955
-		$group = $this->groupManager->get($groupid);
956
-		$targetUser = $this->userManager->get($userId);
957
-		if ($group === null) {
958
-			throw new OCSException('', 102);
959
-		}
960
-		if ($targetUser === null) {
961
-			throw new OCSException('', 103);
962
-		}
963
-
964
-		// If they're not an admin, check they are a subadmin of the group in question
965
-		$loggedInUser = $this->userSession->getUser();
966
-		$subAdminManager = $this->groupManager->getSubAdmin();
967
-		if (!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) {
968
-			throw new OCSException('', 104);
969
-		}
970
-
971
-		// Add user to group
972
-		$group->addUser($targetUser);
973
-		return new DataResponse();
974
-	}
975
-
976
-	/**
977
-	 * @PasswordConfirmationRequired
978
-	 * @NoAdminRequired
979
-	 *
980
-	 * @param string $userId
981
-	 * @param string $groupid
982
-	 * @return DataResponse
983
-	 * @throws OCSException
984
-	 */
985
-	public function removeFromGroup(string $userId, string $groupid): DataResponse {
986
-		$loggedInUser = $this->userSession->getUser();
987
-
988
-		if ($groupid === null || trim($groupid) === '') {
989
-			throw new OCSException('', 101);
990
-		}
991
-
992
-		$group = $this->groupManager->get($groupid);
993
-		if ($group === null) {
994
-			throw new OCSException('', 102);
995
-		}
996
-
997
-		$targetUser = $this->userManager->get($userId);
998
-		if ($targetUser === null) {
999
-			throw new OCSException('', 103);
1000
-		}
1001
-
1002
-		// If they're not an admin, check they are a subadmin of the group in question
1003
-		$subAdminManager = $this->groupManager->getSubAdmin();
1004
-		if (!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) {
1005
-			throw new OCSException('', 104);
1006
-		}
1007
-
1008
-		// Check they aren't removing themselves from 'admin' or their 'subadmin; group
1009
-		if ($targetUser->getUID() === $loggedInUser->getUID()) {
1010
-			if ($this->groupManager->isAdmin($loggedInUser->getUID())) {
1011
-				if ($group->getGID() === 'admin') {
1012
-					throw new OCSException('Cannot remove yourself from the admin group', 105);
1013
-				}
1014
-			} else {
1015
-				// Not an admin, so the user must be a subadmin of this group, but that is not allowed.
1016
-				throw new OCSException('Cannot remove yourself from this group as you are a SubAdmin', 105);
1017
-			}
1018
-		} elseif (!$this->groupManager->isAdmin($loggedInUser->getUID())) {
1019
-			/** @var IGroup[] $subAdminGroups */
1020
-			$subAdminGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
1021
-			$subAdminGroups = array_map(function (IGroup $subAdminGroup) {
1022
-				return $subAdminGroup->getGID();
1023
-			}, $subAdminGroups);
1024
-			$userGroups = $this->groupManager->getUserGroupIds($targetUser);
1025
-			$userSubAdminGroups = array_intersect($subAdminGroups, $userGroups);
1026
-
1027
-			if (count($userSubAdminGroups) <= 1) {
1028
-				// Subadmin must not be able to remove a user from all their subadmin groups.
1029
-				throw new OCSException('Not viable to remove user from the last group you are SubAdmin of', 105);
1030
-			}
1031
-		}
1032
-
1033
-		// Remove user from group
1034
-		$group->removeUser($targetUser);
1035
-		return new DataResponse();
1036
-	}
1037
-
1038
-	/**
1039
-	 * Creates a subadmin
1040
-	 *
1041
-	 * @PasswordConfirmationRequired
1042
-	 *
1043
-	 * @param string $userId
1044
-	 * @param string $groupid
1045
-	 * @return DataResponse
1046
-	 * @throws OCSException
1047
-	 */
1048
-	public function addSubAdmin(string $userId, string $groupid): DataResponse {
1049
-		$group = $this->groupManager->get($groupid);
1050
-		$user = $this->userManager->get($userId);
1051
-
1052
-		// Check if the user exists
1053
-		if ($user === null) {
1054
-			throw new OCSException('User does not exist', 101);
1055
-		}
1056
-		// Check if group exists
1057
-		if ($group === null) {
1058
-			throw new OCSException('Group does not exist',  102);
1059
-		}
1060
-		// Check if trying to make subadmin of admin group
1061
-		if ($group->getGID() === 'admin') {
1062
-			throw new OCSException('Cannot create subadmins for admin group', 103);
1063
-		}
1064
-
1065
-		$subAdminManager = $this->groupManager->getSubAdmin();
1066
-
1067
-		// We cannot be subadmin twice
1068
-		if ($subAdminManager->isSubAdminOfGroup($user, $group)) {
1069
-			return new DataResponse();
1070
-		}
1071
-		// Go
1072
-		$subAdminManager->createSubAdmin($user, $group);
1073
-		return new DataResponse();
1074
-	}
1075
-
1076
-	/**
1077
-	 * Removes a subadmin from a group
1078
-	 *
1079
-	 * @PasswordConfirmationRequired
1080
-	 *
1081
-	 * @param string $userId
1082
-	 * @param string $groupid
1083
-	 * @return DataResponse
1084
-	 * @throws OCSException
1085
-	 */
1086
-	public function removeSubAdmin(string $userId, string $groupid): DataResponse {
1087
-		$group = $this->groupManager->get($groupid);
1088
-		$user = $this->userManager->get($userId);
1089
-		$subAdminManager = $this->groupManager->getSubAdmin();
1090
-
1091
-		// Check if the user exists
1092
-		if ($user === null) {
1093
-			throw new OCSException('User does not exist', 101);
1094
-		}
1095
-		// Check if the group exists
1096
-		if ($group === null) {
1097
-			throw new OCSException('Group does not exist', 101);
1098
-		}
1099
-		// Check if they are a subadmin of this said group
1100
-		if (!$subAdminManager->isSubAdminOfGroup($user, $group)) {
1101
-			throw new OCSException('User is not a subadmin of this group', 102);
1102
-		}
1103
-
1104
-		// Go
1105
-		$subAdminManager->deleteSubAdmin($user, $group);
1106
-		return new DataResponse();
1107
-	}
1108
-
1109
-	/**
1110
-	 * Get the groups a user is a subadmin of
1111
-	 *
1112
-	 * @param string $userId
1113
-	 * @return DataResponse
1114
-	 * @throws OCSException
1115
-	 */
1116
-	public function getUserSubAdminGroups(string $userId): DataResponse {
1117
-		$groups = $this->getUserSubAdminGroupsData($userId);
1118
-		return new DataResponse($groups);
1119
-	}
1120
-
1121
-	/**
1122
-	 * @NoAdminRequired
1123
-	 * @PasswordConfirmationRequired
1124
-	 *
1125
-	 * resend welcome message
1126
-	 *
1127
-	 * @param string $userId
1128
-	 * @return DataResponse
1129
-	 * @throws OCSException
1130
-	 */
1131
-	public function resendWelcomeMessage(string $userId): DataResponse {
1132
-		$currentLoggedInUser = $this->userSession->getUser();
1133
-
1134
-		$targetUser = $this->userManager->get($userId);
1135
-		if ($targetUser === null) {
1136
-			throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
1137
-		}
1138
-
1139
-		// Check if admin / subadmin
1140
-		$subAdminManager = $this->groupManager->getSubAdmin();
1141
-		if (!$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
1142
-			&& !$this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
1143
-			// No rights
1144
-			throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
1145
-		}
1146
-
1147
-		$email = $targetUser->getEMailAddress();
1148
-		if ($email === '' || $email === null) {
1149
-			throw new OCSException('Email address not available', 101);
1150
-		}
1151
-
1152
-		try {
1153
-			$emailTemplate = $this->newUserMailHelper->generateTemplate($targetUser, false);
1154
-			$this->newUserMailHelper->sendMail($targetUser, $emailTemplate);
1155
-		} catch (\Exception $e) {
1156
-			$this->logger->error("Can't send new user mail to $email",
1157
-				[
1158
-					'app' => 'settings',
1159
-					'exception' => $e,
1160
-				]
1161
-			);
1162
-			throw new OCSException('Sending email failed', 102);
1163
-		}
1164
-
1165
-		return new DataResponse();
1166
-	}
78
+    /** @var IAppManager */
79
+    private $appManager;
80
+    /** @var IURLGenerator */
81
+    protected $urlGenerator;
82
+    /** @var LoggerInterface */
83
+    private $logger;
84
+    /** @var IFactory */
85
+    protected $l10nFactory;
86
+    /** @var NewUserMailHelper */
87
+    private $newUserMailHelper;
88
+    /** @var ISecureRandom */
89
+    private $secureRandom;
90
+    /** @var RemoteWipe */
91
+    private $remoteWipe;
92
+    /** @var KnownUserService */
93
+    private $knownUserService;
94
+    /** @var IEventDispatcher */
95
+    private $eventDispatcher;
96
+
97
+    public function __construct(string $appName,
98
+                                IRequest $request,
99
+                                IUserManager $userManager,
100
+                                IConfig $config,
101
+                                IAppManager $appManager,
102
+                                IGroupManager $groupManager,
103
+                                IUserSession $userSession,
104
+                                IAccountManager $accountManager,
105
+                                IURLGenerator $urlGenerator,
106
+                                LoggerInterface $logger,
107
+                                IFactory $l10nFactory,
108
+                                NewUserMailHelper $newUserMailHelper,
109
+                                ISecureRandom $secureRandom,
110
+                                RemoteWipe $remoteWipe,
111
+                                KnownUserService $knownUserService,
112
+                                IEventDispatcher $eventDispatcher) {
113
+        parent::__construct($appName,
114
+                            $request,
115
+                            $userManager,
116
+                            $config,
117
+                            $groupManager,
118
+                            $userSession,
119
+                            $accountManager,
120
+                            $l10nFactory);
121
+
122
+        $this->appManager = $appManager;
123
+        $this->urlGenerator = $urlGenerator;
124
+        $this->logger = $logger;
125
+        $this->l10nFactory = $l10nFactory;
126
+        $this->newUserMailHelper = $newUserMailHelper;
127
+        $this->secureRandom = $secureRandom;
128
+        $this->remoteWipe = $remoteWipe;
129
+        $this->knownUserService = $knownUserService;
130
+        $this->eventDispatcher = $eventDispatcher;
131
+    }
132
+
133
+    /**
134
+     * @NoAdminRequired
135
+     *
136
+     * returns a list of users
137
+     *
138
+     * @param string $search
139
+     * @param int $limit
140
+     * @param int $offset
141
+     * @return DataResponse
142
+     */
143
+    public function getUsers(string $search = '', int $limit = null, int $offset = 0): DataResponse {
144
+        $user = $this->userSession->getUser();
145
+        $users = [];
146
+
147
+        // Admin? Or SubAdmin?
148
+        $uid = $user->getUID();
149
+        $subAdminManager = $this->groupManager->getSubAdmin();
150
+        if ($this->groupManager->isAdmin($uid)) {
151
+            $users = $this->userManager->search($search, $limit, $offset);
152
+        } elseif ($subAdminManager->isSubAdmin($user)) {
153
+            $subAdminOfGroups = $subAdminManager->getSubAdminsGroups($user);
154
+            foreach ($subAdminOfGroups as $key => $group) {
155
+                $subAdminOfGroups[$key] = $group->getGID();
156
+            }
157
+
158
+            $users = [];
159
+            foreach ($subAdminOfGroups as $group) {
160
+                $users = array_merge($users, $this->groupManager->displayNamesInGroup($group, $search, $limit, $offset));
161
+            }
162
+        }
163
+
164
+        $users = array_keys($users);
165
+
166
+        return new DataResponse([
167
+            'users' => $users
168
+        ]);
169
+    }
170
+
171
+    /**
172
+     * @NoAdminRequired
173
+     *
174
+     * returns a list of users and their data
175
+     */
176
+    public function getUsersDetails(string $search = '', int $limit = null, int $offset = 0): DataResponse {
177
+        $currentUser = $this->userSession->getUser();
178
+        $users = [];
179
+
180
+        // Admin? Or SubAdmin?
181
+        $uid = $currentUser->getUID();
182
+        $subAdminManager = $this->groupManager->getSubAdmin();
183
+        if ($this->groupManager->isAdmin($uid)) {
184
+            $users = $this->userManager->search($search, $limit, $offset);
185
+            $users = array_keys($users);
186
+        } elseif ($subAdminManager->isSubAdmin($currentUser)) {
187
+            $subAdminOfGroups = $subAdminManager->getSubAdminsGroups($currentUser);
188
+            foreach ($subAdminOfGroups as $key => $group) {
189
+                $subAdminOfGroups[$key] = $group->getGID();
190
+            }
191
+
192
+            $users = [];
193
+            foreach ($subAdminOfGroups as $group) {
194
+                $users[] = array_keys($this->groupManager->displayNamesInGroup($group, $search, $limit, $offset));
195
+            }
196
+            $users = array_merge(...$users);
197
+        }
198
+
199
+        $usersDetails = [];
200
+        foreach ($users as $userId) {
201
+            $userId = (string) $userId;
202
+            $userData = $this->getUserData($userId);
203
+            // Do not insert empty entry
204
+            if (!empty($userData)) {
205
+                $usersDetails[$userId] = $userData;
206
+            } else {
207
+                // Logged user does not have permissions to see this user
208
+                // only showing its id
209
+                $usersDetails[$userId] = ['id' => $userId];
210
+            }
211
+        }
212
+
213
+        return new DataResponse([
214
+            'users' => $usersDetails
215
+        ]);
216
+    }
217
+
218
+
219
+    /**
220
+     * @NoAdminRequired
221
+     * @NoSubAdminRequired
222
+     *
223
+     * @param string $location
224
+     * @param array $search
225
+     * @return DataResponse
226
+     */
227
+    public function searchByPhoneNumbers(string $location, array $search): DataResponse {
228
+        $phoneUtil = PhoneNumberUtil::getInstance();
229
+
230
+        if ($phoneUtil->getCountryCodeForRegion($location) === 0) {
231
+            // Not a valid region code
232
+            return new DataResponse([], Http::STATUS_BAD_REQUEST);
233
+        }
234
+
235
+        /** @var IUser $user */
236
+        $user = $this->userSession->getUser();
237
+        $knownTo = $user->getUID();
238
+        $defaultPhoneRegion = $this->config->getSystemValueString('default_phone_region');
239
+
240
+        $normalizedNumberToKey = [];
241
+        foreach ($search as $key => $phoneNumbers) {
242
+            foreach ($phoneNumbers as $phone) {
243
+                try {
244
+                    $phoneNumber = $phoneUtil->parse($phone, $location);
245
+                    if ($phoneNumber instanceof PhoneNumber && $phoneUtil->isValidNumber($phoneNumber)) {
246
+                        $normalizedNumber = $phoneUtil->format($phoneNumber, PhoneNumberFormat::E164);
247
+                        $normalizedNumberToKey[$normalizedNumber] = (string) $key;
248
+                    }
249
+                } catch (NumberParseException $e) {
250
+                }
251
+
252
+                if ($defaultPhoneRegion !== '' && $defaultPhoneRegion !== $location && strpos($phone, '0') === 0) {
253
+                    // If the number has a leading zero (no country code),
254
+                    // we also check the default phone region of the instance,
255
+                    // when it's different to the user's given region.
256
+                    try {
257
+                        $phoneNumber = $phoneUtil->parse($phone, $defaultPhoneRegion);
258
+                        if ($phoneNumber instanceof PhoneNumber && $phoneUtil->isValidNumber($phoneNumber)) {
259
+                            $normalizedNumber = $phoneUtil->format($phoneNumber, PhoneNumberFormat::E164);
260
+                            $normalizedNumberToKey[$normalizedNumber] = (string) $key;
261
+                        }
262
+                    } catch (NumberParseException $e) {
263
+                    }
264
+                }
265
+            }
266
+        }
267
+
268
+        $phoneNumbers = array_keys($normalizedNumberToKey);
269
+
270
+        if (empty($phoneNumbers)) {
271
+            return new DataResponse();
272
+        }
273
+
274
+        // Cleanup all previous entries and only allow new matches
275
+        $this->knownUserService->deleteKnownTo($knownTo);
276
+
277
+        $userMatches = $this->accountManager->searchUsers(IAccountManager::PROPERTY_PHONE, $phoneNumbers);
278
+
279
+        if (empty($userMatches)) {
280
+            return new DataResponse();
281
+        }
282
+
283
+        $cloudUrl = rtrim($this->urlGenerator->getAbsoluteURL('/'), '/');
284
+        if (strpos($cloudUrl, 'http://') === 0) {
285
+            $cloudUrl = substr($cloudUrl, strlen('http://'));
286
+        } elseif (strpos($cloudUrl, 'https://') === 0) {
287
+            $cloudUrl = substr($cloudUrl, strlen('https://'));
288
+        }
289
+
290
+        $matches = [];
291
+        foreach ($userMatches as $phone => $userId) {
292
+            // Not using the ICloudIdManager as that would run a search for each contact to find the display name in the address book
293
+            $matches[$normalizedNumberToKey[$phone]] = $userId . '@' . $cloudUrl;
294
+            $this->knownUserService->storeIsKnownToUser($knownTo, $userId);
295
+        }
296
+
297
+        return new DataResponse($matches);
298
+    }
299
+
300
+    /**
301
+     * @throws OCSException
302
+     */
303
+    private function createNewUserId(): string {
304
+        $attempts = 0;
305
+        do {
306
+            $uidCandidate = $this->secureRandom->generate(10, ISecureRandom::CHAR_HUMAN_READABLE);
307
+            if (!$this->userManager->userExists($uidCandidate)) {
308
+                return $uidCandidate;
309
+            }
310
+            $attempts++;
311
+        } while ($attempts < 10);
312
+        throw new OCSException('Could not create non-existing user id', 111);
313
+    }
314
+
315
+    /**
316
+     * @PasswordConfirmationRequired
317
+     * @NoAdminRequired
318
+     *
319
+     * @param string $userid
320
+     * @param string $password
321
+     * @param string $displayName
322
+     * @param string $email
323
+     * @param array $groups
324
+     * @param array $subadmin
325
+     * @param string $quota
326
+     * @param string $language
327
+     * @return DataResponse
328
+     * @throws OCSException
329
+     */
330
+    public function addUser(string $userid,
331
+                            string $password = '',
332
+                            string $displayName = '',
333
+                            string $email = '',
334
+                            array $groups = [],
335
+                            array $subadmin = [],
336
+                            string $quota = '',
337
+                            string $language = ''): DataResponse {
338
+        $user = $this->userSession->getUser();
339
+        $isAdmin = $this->groupManager->isAdmin($user->getUID());
340
+        $subAdminManager = $this->groupManager->getSubAdmin();
341
+
342
+        if (empty($userid) && $this->config->getAppValue('core', 'newUser.generateUserID', 'no') === 'yes') {
343
+            $userid = $this->createNewUserId();
344
+        }
345
+
346
+        if ($this->userManager->userExists($userid)) {
347
+            $this->logger->error('Failed addUser attempt: User already exists.', ['app' => 'ocs_api']);
348
+            throw new OCSException('User already exists', 102);
349
+        }
350
+
351
+        if ($groups !== []) {
352
+            foreach ($groups as $group) {
353
+                if (!$this->groupManager->groupExists($group)) {
354
+                    throw new OCSException('group '.$group.' does not exist', 104);
355
+                }
356
+                if (!$isAdmin && !$subAdminManager->isSubAdminOfGroup($user, $this->groupManager->get($group))) {
357
+                    throw new OCSException('insufficient privileges for group '. $group, 105);
358
+                }
359
+            }
360
+        } else {
361
+            if (!$isAdmin) {
362
+                throw new OCSException('no group specified (required for subadmins)', 106);
363
+            }
364
+        }
365
+
366
+        $subadminGroups = [];
367
+        if ($subadmin !== []) {
368
+            foreach ($subadmin as $groupid) {
369
+                $group = $this->groupManager->get($groupid);
370
+                // Check if group exists
371
+                if ($group === null) {
372
+                    throw new OCSException('Subadmin group does not exist',  102);
373
+                }
374
+                // Check if trying to make subadmin of admin group
375
+                if ($group->getGID() === 'admin') {
376
+                    throw new OCSException('Cannot create subadmins for admin group', 103);
377
+                }
378
+                // Check if has permission to promote subadmins
379
+                if (!$subAdminManager->isSubAdminOfGroup($user, $group) && !$isAdmin) {
380
+                    throw new OCSForbiddenException('No permissions to promote subadmins');
381
+                }
382
+                $subadminGroups[] = $group;
383
+            }
384
+        }
385
+
386
+        $generatePasswordResetToken = false;
387
+        if ($password === '') {
388
+            if ($email === '') {
389
+                throw new OCSException('To send a password link to the user an email address is required.', 108);
390
+            }
391
+
392
+            $passwordEvent = new GenerateSecurePasswordEvent();
393
+            $this->eventDispatcher->dispatchTyped($passwordEvent);
394
+
395
+            $password = $passwordEvent->getPassword();
396
+            if ($password === null) {
397
+                // Fallback: ensure to pass password_policy in any case
398
+                $password = $this->secureRandom->generate(10)
399
+                    . $this->secureRandom->generate(1, ISecureRandom::CHAR_UPPER)
400
+                    . $this->secureRandom->generate(1, ISecureRandom::CHAR_LOWER)
401
+                    . $this->secureRandom->generate(1, ISecureRandom::CHAR_DIGITS)
402
+                    . $this->secureRandom->generate(1, ISecureRandom::CHAR_SYMBOLS);
403
+            }
404
+            $generatePasswordResetToken = true;
405
+        }
406
+
407
+        if ($email === '' && $this->config->getAppValue('core', 'newUser.requireEmail', 'no') === 'yes') {
408
+            throw new OCSException('Required email address was not provided', 110);
409
+        }
410
+
411
+        try {
412
+            $newUser = $this->userManager->createUser($userid, $password);
413
+            $this->logger->info('Successful addUser call with userid: ' . $userid, ['app' => 'ocs_api']);
414
+
415
+            foreach ($groups as $group) {
416
+                $this->groupManager->get($group)->addUser($newUser);
417
+                $this->logger->info('Added userid ' . $userid . ' to group ' . $group, ['app' => 'ocs_api']);
418
+            }
419
+            foreach ($subadminGroups as $group) {
420
+                $subAdminManager->createSubAdmin($newUser, $group);
421
+            }
422
+
423
+            if ($displayName !== '') {
424
+                $this->editUser($userid, 'display', $displayName);
425
+            }
426
+
427
+            if ($quota !== '') {
428
+                $this->editUser($userid, 'quota', $quota);
429
+            }
430
+
431
+            if ($language !== '') {
432
+                $this->editUser($userid, 'language', $language);
433
+            }
434
+
435
+            // Send new user mail only if a mail is set
436
+            if ($email !== '') {
437
+                $newUser->setEMailAddress($email);
438
+                if ($this->config->getAppValue('core', 'newUser.sendEmail', 'yes') === 'yes') {
439
+                    try {
440
+                        $emailTemplate = $this->newUserMailHelper->generateTemplate($newUser, $generatePasswordResetToken);
441
+                        $this->newUserMailHelper->sendMail($newUser, $emailTemplate);
442
+                    } catch (\Exception $e) {
443
+                        // Mail could be failing hard or just be plain not configured
444
+                        // Logging error as it is the hardest of the two
445
+                        $this->logger->error("Unable to send the invitation mail to $email",
446
+                            [
447
+                                'app' => 'ocs_api',
448
+                                'exception' => $e,
449
+                            ]
450
+                        );
451
+                    }
452
+                }
453
+            }
454
+
455
+            return new DataResponse(['id' => $userid]);
456
+        } catch (HintException $e) {
457
+            $this->logger->warning('Failed addUser attempt with hint exception.',
458
+                [
459
+                    'app' => 'ocs_api',
460
+                    'exception' => $e,
461
+                ]
462
+            );
463
+            throw new OCSException($e->getHint(), 107);
464
+        } catch (OCSException $e) {
465
+            $this->logger->warning('Failed addUser attempt with ocs exeption.',
466
+                [
467
+                    'app' => 'ocs_api',
468
+                    'exception' => $e,
469
+                ]
470
+            );
471
+            throw $e;
472
+        } catch (\InvalidArgumentException $e) {
473
+            $this->logger->error('Failed addUser attempt with invalid argument exeption.',
474
+                [
475
+                    'app' => 'ocs_api',
476
+                    'exception' => $e,
477
+                ]
478
+            );
479
+            throw new OCSException($e->getMessage(), 101);
480
+        } catch (\Exception $e) {
481
+            $this->logger->error('Failed addUser attempt with exception.',
482
+                [
483
+                    'app' => 'ocs_api',
484
+                    'exception' => $e
485
+                ]
486
+            );
487
+            throw new OCSException('Bad request', 101);
488
+        }
489
+    }
490
+
491
+    /**
492
+     * @NoAdminRequired
493
+     * @NoSubAdminRequired
494
+     *
495
+     * gets user info
496
+     *
497
+     * @param string $userId
498
+     * @return DataResponse
499
+     * @throws OCSException
500
+     */
501
+    public function getUser(string $userId): DataResponse {
502
+        $includeScopes = false;
503
+        $currentUser = $this->userSession->getUser();
504
+        if ($currentUser && $currentUser->getUID() === $userId) {
505
+            $includeScopes = true;
506
+        }
507
+
508
+        $data = $this->getUserData($userId, $includeScopes);
509
+        // getUserData returns empty array if not enough permissions
510
+        if (empty($data)) {
511
+            throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
512
+        }
513
+        return new DataResponse($data);
514
+    }
515
+
516
+    /**
517
+     * @NoAdminRequired
518
+     * @NoSubAdminRequired
519
+     *
520
+     * gets user info from the currently logged in user
521
+     *
522
+     * @return DataResponse
523
+     * @throws OCSException
524
+     */
525
+    public function getCurrentUser(): DataResponse {
526
+        $user = $this->userSession->getUser();
527
+        if ($user) {
528
+            $data = $this->getUserData($user->getUID(), true);
529
+            // rename "displayname" to "display-name" only for this call to keep
530
+            // the API stable.
531
+            $data['display-name'] = $data['displayname'];
532
+            unset($data['displayname']);
533
+            return new DataResponse($data);
534
+        }
535
+
536
+        throw new OCSException('', OCSController::RESPOND_UNAUTHORISED);
537
+    }
538
+
539
+    /**
540
+     * @NoAdminRequired
541
+     * @NoSubAdminRequired
542
+     *
543
+     * @return DataResponse
544
+     * @throws OCSException
545
+     */
546
+    public function getEditableFields(?string $userId = null): DataResponse {
547
+        $currentLoggedInUser = $this->userSession->getUser();
548
+        if (!$currentLoggedInUser instanceof IUser) {
549
+            throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
550
+        }
551
+
552
+        $permittedFields = [];
553
+
554
+        if ($userId !== $currentLoggedInUser->getUID()) {
555
+            $targetUser = $this->userManager->get($userId);
556
+            if (!$targetUser instanceof IUser) {
557
+                throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
558
+            }
559
+
560
+            $subAdminManager = $this->groupManager->getSubAdmin();
561
+            if (!$this->groupManager->isAdmin($currentLoggedInUser->getUID())
562
+                && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
563
+                throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
564
+            }
565
+        } else {
566
+            $targetUser = $currentLoggedInUser;
567
+        }
568
+
569
+        // Editing self (display, email)
570
+        if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
571
+            if ($targetUser->getBackend() instanceof ISetDisplayNameBackend
572
+                || $targetUser->getBackend()->implementsActions(Backend::SET_DISPLAYNAME)) {
573
+                $permittedFields[] = IAccountManager::PROPERTY_DISPLAYNAME;
574
+            }
575
+            $permittedFields[] = IAccountManager::PROPERTY_EMAIL;
576
+        }
577
+
578
+        $permittedFields[] = IAccountManager::PROPERTY_PHONE;
579
+        $permittedFields[] = IAccountManager::PROPERTY_ADDRESS;
580
+        $permittedFields[] = IAccountManager::PROPERTY_WEBSITE;
581
+        $permittedFields[] = IAccountManager::PROPERTY_TWITTER;
582
+
583
+        return new DataResponse($permittedFields);
584
+    }
585
+
586
+    /**
587
+     * @NoAdminRequired
588
+     * @NoSubAdminRequired
589
+     * @PasswordConfirmationRequired
590
+     *
591
+     * edit users
592
+     *
593
+     * @param string $userId
594
+     * @param string $key
595
+     * @param string $value
596
+     * @return DataResponse
597
+     * @throws OCSException
598
+     */
599
+    public function editUser(string $userId, string $key, string $value): DataResponse {
600
+        $currentLoggedInUser = $this->userSession->getUser();
601
+
602
+        $targetUser = $this->userManager->get($userId);
603
+        if ($targetUser === null) {
604
+            throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
605
+        }
606
+
607
+        $permittedFields = [];
608
+        if ($targetUser->getUID() === $currentLoggedInUser->getUID()) {
609
+            // Editing self (display, email)
610
+            if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
611
+                if ($targetUser->getBackend() instanceof ISetDisplayNameBackend
612
+                    || $targetUser->getBackend()->implementsActions(Backend::SET_DISPLAYNAME)) {
613
+                    $permittedFields[] = 'display';
614
+                    $permittedFields[] = IAccountManager::PROPERTY_DISPLAYNAME;
615
+                }
616
+                $permittedFields[] = IAccountManager::PROPERTY_EMAIL;
617
+            }
618
+
619
+            $permittedFields[] = IAccountManager::PROPERTY_DISPLAYNAME . self::SCOPE_SUFFIX;
620
+            $permittedFields[] = IAccountManager::PROPERTY_EMAIL . self::SCOPE_SUFFIX;
621
+
622
+            $permittedFields[] = 'password';
623
+            if ($this->config->getSystemValue('force_language', false) === false ||
624
+                $this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
625
+                $permittedFields[] = 'language';
626
+            }
627
+
628
+            if ($this->config->getSystemValue('force_locale', false) === false ||
629
+                $this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
630
+                $permittedFields[] = 'locale';
631
+            }
632
+
633
+            $permittedFields[] = IAccountManager::PROPERTY_PHONE;
634
+            $permittedFields[] = IAccountManager::PROPERTY_ADDRESS;
635
+            $permittedFields[] = IAccountManager::PROPERTY_WEBSITE;
636
+            $permittedFields[] = IAccountManager::PROPERTY_TWITTER;
637
+            $permittedFields[] = IAccountManager::PROPERTY_PHONE . self::SCOPE_SUFFIX;
638
+            $permittedFields[] = IAccountManager::PROPERTY_ADDRESS . self::SCOPE_SUFFIX;
639
+            $permittedFields[] = IAccountManager::PROPERTY_WEBSITE . self::SCOPE_SUFFIX;
640
+            $permittedFields[] = IAccountManager::PROPERTY_TWITTER . self::SCOPE_SUFFIX;
641
+
642
+            $permittedFields[] = IAccountManager::PROPERTY_AVATAR . self::SCOPE_SUFFIX;
643
+
644
+            // If admin they can edit their own quota
645
+            if ($this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
646
+                $permittedFields[] = 'quota';
647
+            }
648
+        } else {
649
+            // Check if admin / subadmin
650
+            $subAdminManager = $this->groupManager->getSubAdmin();
651
+            if ($this->groupManager->isAdmin($currentLoggedInUser->getUID())
652
+            || $subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
653
+                // They have permissions over the user
654
+                if ($targetUser->getBackend() instanceof ISetDisplayNameBackend
655
+                    || $targetUser->getBackend()->implementsActions(Backend::SET_DISPLAYNAME)) {
656
+                    $permittedFields[] = 'display';
657
+                    $permittedFields[] = IAccountManager::PROPERTY_DISPLAYNAME;
658
+                }
659
+                $permittedFields[] = IAccountManager::PROPERTY_EMAIL;
660
+                $permittedFields[] = 'password';
661
+                $permittedFields[] = 'language';
662
+                $permittedFields[] = 'locale';
663
+                $permittedFields[] = IAccountManager::PROPERTY_PHONE;
664
+                $permittedFields[] = IAccountManager::PROPERTY_ADDRESS;
665
+                $permittedFields[] = IAccountManager::PROPERTY_WEBSITE;
666
+                $permittedFields[] = IAccountManager::PROPERTY_TWITTER;
667
+                $permittedFields[] = 'quota';
668
+            } else {
669
+                // No rights
670
+                throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
671
+            }
672
+        }
673
+        // Check if permitted to edit this field
674
+        if (!in_array($key, $permittedFields)) {
675
+            throw new OCSException('', 103);
676
+        }
677
+        // Process the edit
678
+        switch ($key) {
679
+            case 'display':
680
+            case IAccountManager::PROPERTY_DISPLAYNAME:
681
+                $targetUser->setDisplayName($value);
682
+                break;
683
+            case 'quota':
684
+                $quota = $value;
685
+                if ($quota !== 'none' && $quota !== 'default') {
686
+                    if (is_numeric($quota)) {
687
+                        $quota = (float) $quota;
688
+                    } else {
689
+                        $quota = \OCP\Util::computerFileSize($quota);
690
+                    }
691
+                    if ($quota === false) {
692
+                        throw new OCSException('Invalid quota value '.$value, 102);
693
+                    }
694
+                    if ($quota === -1) {
695
+                        $quota = 'none';
696
+                    } else {
697
+                        $quota = \OCP\Util::humanFileSize($quota);
698
+                    }
699
+                }
700
+                $targetUser->setQuota($quota);
701
+                break;
702
+            case 'password':
703
+                try {
704
+                    if (!$targetUser->canChangePassword()) {
705
+                        throw new OCSException('Setting the password is not supported by the users backend', 103);
706
+                    }
707
+                    $targetUser->setPassword($value);
708
+                } catch (HintException $e) { // password policy error
709
+                    throw new OCSException($e->getMessage(), 103);
710
+                }
711
+                break;
712
+            case 'language':
713
+                $languagesCodes = $this->l10nFactory->findAvailableLanguages();
714
+                if (!in_array($value, $languagesCodes, true) && $value !== 'en') {
715
+                    throw new OCSException('Invalid language', 102);
716
+                }
717
+                $this->config->setUserValue($targetUser->getUID(), 'core', 'lang', $value);
718
+                break;
719
+            case 'locale':
720
+                if (!$this->l10nFactory->localeExists($value)) {
721
+                    throw new OCSException('Invalid locale', 102);
722
+                }
723
+                $this->config->setUserValue($targetUser->getUID(), 'core', 'locale', $value);
724
+                break;
725
+            case IAccountManager::PROPERTY_EMAIL:
726
+                if (filter_var($value, FILTER_VALIDATE_EMAIL) || $value === '') {
727
+                    $targetUser->setEMailAddress($value);
728
+                } else {
729
+                    throw new OCSException('', 102);
730
+                }
731
+                break;
732
+            case IAccountManager::PROPERTY_PHONE:
733
+            case IAccountManager::PROPERTY_ADDRESS:
734
+            case IAccountManager::PROPERTY_WEBSITE:
735
+            case IAccountManager::PROPERTY_TWITTER:
736
+                $userAccount = $this->accountManager->getAccount($targetUser);
737
+                $userProperty = $userAccount->getProperty($key);
738
+                if ($userProperty->getValue() !== $value) {
739
+                    try {
740
+                        $userProperty->setValue($value);
741
+                        $this->accountManager->updateAccount($userAccount);
742
+
743
+                        if ($userProperty->getName() === IAccountManager::PROPERTY_PHONE) {
744
+                            $this->knownUserService->deleteByContactUserId($targetUser->getUID());
745
+                        }
746
+                    } catch (\InvalidArgumentException $e) {
747
+                        throw new OCSException('Invalid ' . $e->getMessage(), 102);
748
+                    }
749
+                }
750
+                break;
751
+            case IAccountManager::PROPERTY_DISPLAYNAME . self::SCOPE_SUFFIX:
752
+            case IAccountManager::PROPERTY_EMAIL . self::SCOPE_SUFFIX:
753
+            case IAccountManager::PROPERTY_PHONE . self::SCOPE_SUFFIX:
754
+            case IAccountManager::PROPERTY_ADDRESS . self::SCOPE_SUFFIX:
755
+            case IAccountManager::PROPERTY_WEBSITE . self::SCOPE_SUFFIX:
756
+            case IAccountManager::PROPERTY_TWITTER . self::SCOPE_SUFFIX:
757
+            case IAccountManager::PROPERTY_AVATAR . self::SCOPE_SUFFIX:
758
+                $propertyName = substr($key, 0, strlen($key) - strlen(self::SCOPE_SUFFIX));
759
+                $userAccount = $this->accountManager->getAccount($targetUser);
760
+                $userProperty = $userAccount->getProperty($propertyName);
761
+                if ($userProperty->getScope() !== $value) {
762
+                    try {
763
+                        $userProperty->setScope($value);
764
+                        $this->accountManager->updateAccount($userAccount);
765
+                    } catch (\InvalidArgumentException $e) {
766
+                        throw new OCSException('Invalid ' . $e->getMessage(), 102);
767
+                    }
768
+                }
769
+                break;
770
+            default:
771
+                throw new OCSException('', 103);
772
+        }
773
+        return new DataResponse();
774
+    }
775
+
776
+    /**
777
+     * @PasswordConfirmationRequired
778
+     * @NoAdminRequired
779
+     *
780
+     * @param string $userId
781
+     *
782
+     * @return DataResponse
783
+     *
784
+     * @throws OCSException
785
+     */
786
+    public function wipeUserDevices(string $userId): DataResponse {
787
+        /** @var IUser $currentLoggedInUser */
788
+        $currentLoggedInUser = $this->userSession->getUser();
789
+
790
+        $targetUser = $this->userManager->get($userId);
791
+
792
+        if ($targetUser === null) {
793
+            throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
794
+        }
795
+
796
+        if ($targetUser->getUID() === $currentLoggedInUser->getUID()) {
797
+            throw new OCSException('', 101);
798
+        }
799
+
800
+        // If not permitted
801
+        $subAdminManager = $this->groupManager->getSubAdmin();
802
+        if (!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
803
+            throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
804
+        }
805
+
806
+        $this->remoteWipe->markAllTokensForWipe($targetUser);
807
+
808
+        return new DataResponse();
809
+    }
810
+
811
+    /**
812
+     * @PasswordConfirmationRequired
813
+     * @NoAdminRequired
814
+     *
815
+     * @param string $userId
816
+     * @return DataResponse
817
+     * @throws OCSException
818
+     */
819
+    public function deleteUser(string $userId): DataResponse {
820
+        $currentLoggedInUser = $this->userSession->getUser();
821
+
822
+        $targetUser = $this->userManager->get($userId);
823
+
824
+        if ($targetUser === null) {
825
+            throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
826
+        }
827
+
828
+        if ($targetUser->getUID() === $currentLoggedInUser->getUID()) {
829
+            throw new OCSException('', 101);
830
+        }
831
+
832
+        // If not permitted
833
+        $subAdminManager = $this->groupManager->getSubAdmin();
834
+        if (!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
835
+            throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
836
+        }
837
+
838
+        // Go ahead with the delete
839
+        if ($targetUser->delete()) {
840
+            return new DataResponse();
841
+        } else {
842
+            throw new OCSException('', 101);
843
+        }
844
+    }
845
+
846
+    /**
847
+     * @PasswordConfirmationRequired
848
+     * @NoAdminRequired
849
+     *
850
+     * @param string $userId
851
+     * @return DataResponse
852
+     * @throws OCSException
853
+     * @throws OCSForbiddenException
854
+     */
855
+    public function disableUser(string $userId): DataResponse {
856
+        return $this->setEnabled($userId, false);
857
+    }
858
+
859
+    /**
860
+     * @PasswordConfirmationRequired
861
+     * @NoAdminRequired
862
+     *
863
+     * @param string $userId
864
+     * @return DataResponse
865
+     * @throws OCSException
866
+     * @throws OCSForbiddenException
867
+     */
868
+    public function enableUser(string $userId): DataResponse {
869
+        return $this->setEnabled($userId, true);
870
+    }
871
+
872
+    /**
873
+     * @param string $userId
874
+     * @param bool $value
875
+     * @return DataResponse
876
+     * @throws OCSException
877
+     */
878
+    private function setEnabled(string $userId, bool $value): DataResponse {
879
+        $currentLoggedInUser = $this->userSession->getUser();
880
+
881
+        $targetUser = $this->userManager->get($userId);
882
+        if ($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
883
+            throw new OCSException('', 101);
884
+        }
885
+
886
+        // If not permitted
887
+        $subAdminManager = $this->groupManager->getSubAdmin();
888
+        if (!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
889
+            throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
890
+        }
891
+
892
+        // enable/disable the user now
893
+        $targetUser->setEnabled($value);
894
+        return new DataResponse();
895
+    }
896
+
897
+    /**
898
+     * @NoAdminRequired
899
+     * @NoSubAdminRequired
900
+     *
901
+     * @param string $userId
902
+     * @return DataResponse
903
+     * @throws OCSException
904
+     */
905
+    public function getUsersGroups(string $userId): DataResponse {
906
+        $loggedInUser = $this->userSession->getUser();
907
+
908
+        $targetUser = $this->userManager->get($userId);
909
+        if ($targetUser === null) {
910
+            throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
911
+        }
912
+
913
+        if ($targetUser->getUID() === $loggedInUser->getUID() || $this->groupManager->isAdmin($loggedInUser->getUID())) {
914
+            // Self lookup or admin lookup
915
+            return new DataResponse([
916
+                'groups' => $this->groupManager->getUserGroupIds($targetUser)
917
+            ]);
918
+        } else {
919
+            $subAdminManager = $this->groupManager->getSubAdmin();
920
+
921
+            // Looking up someone else
922
+            if ($subAdminManager->isUserAccessible($loggedInUser, $targetUser)) {
923
+                // Return the group that the method caller is subadmin of for the user in question
924
+                /** @var IGroup[] $getSubAdminsGroups */
925
+                $getSubAdminsGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
926
+                foreach ($getSubAdminsGroups as $key => $group) {
927
+                    $getSubAdminsGroups[$key] = $group->getGID();
928
+                }
929
+                $groups = array_intersect(
930
+                    $getSubAdminsGroups,
931
+                    $this->groupManager->getUserGroupIds($targetUser)
932
+                );
933
+                return new DataResponse(['groups' => $groups]);
934
+            } else {
935
+                // Not permitted
936
+                throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
937
+            }
938
+        }
939
+    }
940
+
941
+    /**
942
+     * @PasswordConfirmationRequired
943
+     * @NoAdminRequired
944
+     *
945
+     * @param string $userId
946
+     * @param string $groupid
947
+     * @return DataResponse
948
+     * @throws OCSException
949
+     */
950
+    public function addToGroup(string $userId, string $groupid = ''): DataResponse {
951
+        if ($groupid === '') {
952
+            throw new OCSException('', 101);
953
+        }
954
+
955
+        $group = $this->groupManager->get($groupid);
956
+        $targetUser = $this->userManager->get($userId);
957
+        if ($group === null) {
958
+            throw new OCSException('', 102);
959
+        }
960
+        if ($targetUser === null) {
961
+            throw new OCSException('', 103);
962
+        }
963
+
964
+        // If they're not an admin, check they are a subadmin of the group in question
965
+        $loggedInUser = $this->userSession->getUser();
966
+        $subAdminManager = $this->groupManager->getSubAdmin();
967
+        if (!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) {
968
+            throw new OCSException('', 104);
969
+        }
970
+
971
+        // Add user to group
972
+        $group->addUser($targetUser);
973
+        return new DataResponse();
974
+    }
975
+
976
+    /**
977
+     * @PasswordConfirmationRequired
978
+     * @NoAdminRequired
979
+     *
980
+     * @param string $userId
981
+     * @param string $groupid
982
+     * @return DataResponse
983
+     * @throws OCSException
984
+     */
985
+    public function removeFromGroup(string $userId, string $groupid): DataResponse {
986
+        $loggedInUser = $this->userSession->getUser();
987
+
988
+        if ($groupid === null || trim($groupid) === '') {
989
+            throw new OCSException('', 101);
990
+        }
991
+
992
+        $group = $this->groupManager->get($groupid);
993
+        if ($group === null) {
994
+            throw new OCSException('', 102);
995
+        }
996
+
997
+        $targetUser = $this->userManager->get($userId);
998
+        if ($targetUser === null) {
999
+            throw new OCSException('', 103);
1000
+        }
1001
+
1002
+        // If they're not an admin, check they are a subadmin of the group in question
1003
+        $subAdminManager = $this->groupManager->getSubAdmin();
1004
+        if (!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) {
1005
+            throw new OCSException('', 104);
1006
+        }
1007
+
1008
+        // Check they aren't removing themselves from 'admin' or their 'subadmin; group
1009
+        if ($targetUser->getUID() === $loggedInUser->getUID()) {
1010
+            if ($this->groupManager->isAdmin($loggedInUser->getUID())) {
1011
+                if ($group->getGID() === 'admin') {
1012
+                    throw new OCSException('Cannot remove yourself from the admin group', 105);
1013
+                }
1014
+            } else {
1015
+                // Not an admin, so the user must be a subadmin of this group, but that is not allowed.
1016
+                throw new OCSException('Cannot remove yourself from this group as you are a SubAdmin', 105);
1017
+            }
1018
+        } elseif (!$this->groupManager->isAdmin($loggedInUser->getUID())) {
1019
+            /** @var IGroup[] $subAdminGroups */
1020
+            $subAdminGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
1021
+            $subAdminGroups = array_map(function (IGroup $subAdminGroup) {
1022
+                return $subAdminGroup->getGID();
1023
+            }, $subAdminGroups);
1024
+            $userGroups = $this->groupManager->getUserGroupIds($targetUser);
1025
+            $userSubAdminGroups = array_intersect($subAdminGroups, $userGroups);
1026
+
1027
+            if (count($userSubAdminGroups) <= 1) {
1028
+                // Subadmin must not be able to remove a user from all their subadmin groups.
1029
+                throw new OCSException('Not viable to remove user from the last group you are SubAdmin of', 105);
1030
+            }
1031
+        }
1032
+
1033
+        // Remove user from group
1034
+        $group->removeUser($targetUser);
1035
+        return new DataResponse();
1036
+    }
1037
+
1038
+    /**
1039
+     * Creates a subadmin
1040
+     *
1041
+     * @PasswordConfirmationRequired
1042
+     *
1043
+     * @param string $userId
1044
+     * @param string $groupid
1045
+     * @return DataResponse
1046
+     * @throws OCSException
1047
+     */
1048
+    public function addSubAdmin(string $userId, string $groupid): DataResponse {
1049
+        $group = $this->groupManager->get($groupid);
1050
+        $user = $this->userManager->get($userId);
1051
+
1052
+        // Check if the user exists
1053
+        if ($user === null) {
1054
+            throw new OCSException('User does not exist', 101);
1055
+        }
1056
+        // Check if group exists
1057
+        if ($group === null) {
1058
+            throw new OCSException('Group does not exist',  102);
1059
+        }
1060
+        // Check if trying to make subadmin of admin group
1061
+        if ($group->getGID() === 'admin') {
1062
+            throw new OCSException('Cannot create subadmins for admin group', 103);
1063
+        }
1064
+
1065
+        $subAdminManager = $this->groupManager->getSubAdmin();
1066
+
1067
+        // We cannot be subadmin twice
1068
+        if ($subAdminManager->isSubAdminOfGroup($user, $group)) {
1069
+            return new DataResponse();
1070
+        }
1071
+        // Go
1072
+        $subAdminManager->createSubAdmin($user, $group);
1073
+        return new DataResponse();
1074
+    }
1075
+
1076
+    /**
1077
+     * Removes a subadmin from a group
1078
+     *
1079
+     * @PasswordConfirmationRequired
1080
+     *
1081
+     * @param string $userId
1082
+     * @param string $groupid
1083
+     * @return DataResponse
1084
+     * @throws OCSException
1085
+     */
1086
+    public function removeSubAdmin(string $userId, string $groupid): DataResponse {
1087
+        $group = $this->groupManager->get($groupid);
1088
+        $user = $this->userManager->get($userId);
1089
+        $subAdminManager = $this->groupManager->getSubAdmin();
1090
+
1091
+        // Check if the user exists
1092
+        if ($user === null) {
1093
+            throw new OCSException('User does not exist', 101);
1094
+        }
1095
+        // Check if the group exists
1096
+        if ($group === null) {
1097
+            throw new OCSException('Group does not exist', 101);
1098
+        }
1099
+        // Check if they are a subadmin of this said group
1100
+        if (!$subAdminManager->isSubAdminOfGroup($user, $group)) {
1101
+            throw new OCSException('User is not a subadmin of this group', 102);
1102
+        }
1103
+
1104
+        // Go
1105
+        $subAdminManager->deleteSubAdmin($user, $group);
1106
+        return new DataResponse();
1107
+    }
1108
+
1109
+    /**
1110
+     * Get the groups a user is a subadmin of
1111
+     *
1112
+     * @param string $userId
1113
+     * @return DataResponse
1114
+     * @throws OCSException
1115
+     */
1116
+    public function getUserSubAdminGroups(string $userId): DataResponse {
1117
+        $groups = $this->getUserSubAdminGroupsData($userId);
1118
+        return new DataResponse($groups);
1119
+    }
1120
+
1121
+    /**
1122
+     * @NoAdminRequired
1123
+     * @PasswordConfirmationRequired
1124
+     *
1125
+     * resend welcome message
1126
+     *
1127
+     * @param string $userId
1128
+     * @return DataResponse
1129
+     * @throws OCSException
1130
+     */
1131
+    public function resendWelcomeMessage(string $userId): DataResponse {
1132
+        $currentLoggedInUser = $this->userSession->getUser();
1133
+
1134
+        $targetUser = $this->userManager->get($userId);
1135
+        if ($targetUser === null) {
1136
+            throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
1137
+        }
1138
+
1139
+        // Check if admin / subadmin
1140
+        $subAdminManager = $this->groupManager->getSubAdmin();
1141
+        if (!$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
1142
+            && !$this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
1143
+            // No rights
1144
+            throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
1145
+        }
1146
+
1147
+        $email = $targetUser->getEMailAddress();
1148
+        if ($email === '' || $email === null) {
1149
+            throw new OCSException('Email address not available', 101);
1150
+        }
1151
+
1152
+        try {
1153
+            $emailTemplate = $this->newUserMailHelper->generateTemplate($targetUser, false);
1154
+            $this->newUserMailHelper->sendMail($targetUser, $emailTemplate);
1155
+        } catch (\Exception $e) {
1156
+            $this->logger->error("Can't send new user mail to $email",
1157
+                [
1158
+                    'app' => 'settings',
1159
+                    'exception' => $e,
1160
+                ]
1161
+            );
1162
+            throw new OCSException('Sending email failed', 102);
1163
+        }
1164
+
1165
+        return new DataResponse();
1166
+    }
1167 1167
 }
Please login to merge, or discard this patch.