Passed
Push — master ( 62399c...5c21d1 )
by John
10:04
created

Database::getDisplayName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 9
nc 1
nop 1
dl 0
loc 13
rs 9.9666
c 2
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Aaron Wood <[email protected]>
6
 * @author Loki3000 <[email protected]>
7
 * @author Roeland Jago Douma <[email protected]>
8
 * @author John Molakvoæ <[email protected]>
9
 *
10
 * @license AGPL-3.0
11
 *
12
 * This code is free software: you can redistribute it and/or modify
13
 * it under the terms of the GNU Affero General Public License, version 3,
14
 * as published by the Free Software Foundation.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
 * GNU Affero General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU Affero General Public License, version 3,
22
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
23
 *
24
 */
25
/*
26
 *
27
 * The following SQL statement is just a help for developers and will not be
28
 * executed!
29
 *
30
 * CREATE TABLE `groups` (
31
 *   `gid` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
32
 *   PRIMARY KEY (`gid`)
33
 * ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
34
 *
35
 * CREATE TABLE `group_user` (
36
 *   `gid` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
37
 *   `uid` varchar(64) COLLATE utf8_unicode_ci NOT NULL
38
 * ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
39
 *
40
 */
41
42
namespace OC\Group;
43
44
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
45
use OCP\DB\QueryBuilder\IQueryBuilder;
46
use OCP\Group\Backend\ABackend;
47
use OCP\Group\Backend\IAddToGroupBackend;
48
use OCP\Group\Backend\ICountDisabledInGroup;
49
use OCP\Group\Backend\ICountUsersBackend;
50
use OCP\Group\Backend\ICreateGroupBackend;
51
use OCP\Group\Backend\IDeleteGroupBackend;
52
use OCP\Group\Backend\IGetDisplayNameBackend;
53
use OCP\Group\Backend\IGroupDetailsBackend;
54
use OCP\Group\Backend\IRemoveFromGroupBackend;
55
use OCP\Group\Backend\ISetDisplayNameBackend;
56
use OCP\IDBConnection;
57
58
/**
59
 * Class for group management in a SQL Database (e.g. MySQL, SQLite)
60
 */
61
class Database extends ABackend
62
	implements IAddToGroupBackend,
63
	           ICountDisabledInGroup,
64
	           ICountUsersBackend,
65
	           ICreateGroupBackend,
66
	           IDeleteGroupBackend,
67
	           IGetDisplayNameBackend,
68
	           IGroupDetailsBackend,
69
	           IRemoveFromGroupBackend,
70
	           ISetDisplayNameBackend {
71
72
	/** @var string[] */
73
	private $groupCache = [];
74
75
	/** @var IDBConnection */
76
	private $dbConn;
77
78
	/**
79
	 * \OC\Group\Database constructor.
80
	 *
81
	 * @param IDBConnection|null $dbConn
82
	 */
83
	public function __construct(IDBConnection $dbConn = null) {
84
		$this->dbConn = $dbConn;
85
	}
86
87
	/**
88
	 * FIXME: This function should not be required!
89
	 */
90
	private function fixDI() {
91
		if ($this->dbConn === null) {
92
			$this->dbConn = \OC::$server->getDatabaseConnection();
93
		}
94
	}
95
96
	/**
97
	 * Try to create a new group
98
	 * @param string $gid The name of the group to create
99
	 * @return bool
100
	 *
101
	 * Tries to create a new group. If the group name already exists, false will
102
	 * be returned.
103
	 */
104
	public function createGroup(string $gid): bool {
105
		$this->fixDI();
106
107
		try {
108
			// Add group
109
			$builder = $this->dbConn->getQueryBuilder();
110
			$result = $builder->insert('groups')
111
				->setValue('gid', $builder->createNamedParameter($gid))
112
				->setValue('displayname', $builder->createNamedParameter($gid))
113
				->execute();
114
		} catch(UniqueConstraintViolationException $e) {
115
			$result = 0;
116
		}
117
118
		// Add to cache
119
		$this->groupCache[$gid] = $gid;
120
121
		return $result === 1;
122
	}
123
124
	/**
125
	 * delete a group
126
	 * @param string $gid gid of the group to delete
127
	 * @return bool
128
	 *
129
	 * Deletes a group and removes it from the group_user-table
130
	 */
131
	public function deleteGroup(string $gid): bool {
132
		$this->fixDI();
133
134
		// Delete the group
135
		$qb = $this->dbConn->getQueryBuilder();
136
		$qb->delete('groups')
137
			->where($qb->expr()->eq('gid', $qb->createNamedParameter($gid)))
138
			->execute();
139
140
		// Delete the group-user relation
141
		$qb = $this->dbConn->getQueryBuilder();
142
		$qb->delete('group_user')
143
			->where($qb->expr()->eq('gid', $qb->createNamedParameter($gid)))
144
			->execute();
145
146
		// Delete the group-groupadmin relation
147
		$qb = $this->dbConn->getQueryBuilder();
148
		$qb->delete('group_admin')
149
			->where($qb->expr()->eq('gid', $qb->createNamedParameter($gid)))
150
			->execute();
151
152
		// Delete from cache
153
		unset($this->groupCache[$gid]);
154
155
		return true;
156
	}
157
158
	/**
159
	 * is user in group?
160
	 * @param string $uid uid of the user
161
	 * @param string $gid gid of the group
162
	 * @return bool
163
	 *
164
	 * Checks whether the user is member of a group or not.
165
	 */
166
	public function inGroup( $uid, $gid ) {
167
		$this->fixDI();
168
169
		// check
170
		$qb = $this->dbConn->getQueryBuilder();
171
		$cursor = $qb->select('uid')
172
			->from('group_user')
173
			->where($qb->expr()->eq('gid', $qb->createNamedParameter($gid)))
174
			->andWhere($qb->expr()->eq('uid', $qb->createNamedParameter($uid)))
175
			->execute();
176
177
		$result = $cursor->fetch();
178
		$cursor->closeCursor();
179
180
		return $result ? true : false;
181
	}
182
183
	/**
184
	 * Add a user to a group
185
	 * @param string $uid Name of the user to add to group
186
	 * @param string $gid Name of the group in which add the user
187
	 * @return bool
188
	 *
189
	 * Adds a user to a group.
190
	 */
191
	public function addToGroup(string $uid, string $gid): bool {
192
		$this->fixDI();
193
194
		// No duplicate entries!
195
		if( !$this->inGroup( $uid, $gid )) {
196
			$qb = $this->dbConn->getQueryBuilder();
197
			$qb->insert('group_user')
198
				->setValue('uid', $qb->createNamedParameter($uid))
199
				->setValue('gid', $qb->createNamedParameter($gid))
200
				->execute();
201
			return true;
202
		}else{
203
			return false;
204
		}
205
	}
206
207
	/**
208
	 * Removes a user from a group
209
	 * @param string $uid Name of the user to remove from group
210
	 * @param string $gid Name of the group from which remove the user
211
	 * @return bool
212
	 *
213
	 * removes the user from a group.
214
	 */
215
	public function removeFromGroup(string $uid, string $gid): bool {
216
		$this->fixDI();
217
218
		$qb = $this->dbConn->getQueryBuilder();
219
		$qb->delete('group_user')
220
			->where($qb->expr()->eq('uid', $qb->createNamedParameter($uid)))
221
			->andWhere($qb->expr()->eq('gid', $qb->createNamedParameter($gid)))
222
			->execute();
223
224
		return true;
225
	}
226
227
	/**
228
	 * Get all groups a user belongs to
229
	 * @param string $uid Name of the user
230
	 * @return array an array of group names
231
	 *
232
	 * This function fetches all groups a user belongs to. It does not check
233
	 * if the user exists at all.
234
	 */
235
	public function getUserGroups( $uid ) {
236
		//guests has empty or null $uid
237
		if ($uid === null || $uid === '') {
238
			return [];
239
		}
240
241
		$this->fixDI();
242
243
		// No magic!
244
		$qb = $this->dbConn->getQueryBuilder();
245
		$cursor = $qb->select('gid')
246
			->from('group_user')
247
			->where($qb->expr()->eq('uid', $qb->createNamedParameter($uid)))
248
			->execute();
249
250
		$groups = [];
251
		while( $row = $cursor->fetch()) {
252
			$groups[] = $row['gid'];
253
			$this->groupCache[$row['gid']] = $row['gid'];
254
		}
255
		$cursor->closeCursor();
256
257
		return $groups;
258
	}
259
260
	/**
261
	 * get a list of all groups
262
	 * @param string $search
263
	 * @param int $limit
264
	 * @param int $offset
265
	 * @return array an array of group names
266
	 *
267
	 * Returns a list with all groups
268
	 */
269
	public function getGroups($search = '', $limit = null, $offset = null) {
270
		$this->fixDI();
271
272
		$query = $this->dbConn->getQueryBuilder();
273
		$query->select('gid')
274
			->from('groups')
275
			->orderBy('gid', 'ASC');
276
277
		if ($search !== '') {
278
			$query->where($query->expr()->iLike('gid', $query->createNamedParameter(
279
				'%' . $this->dbConn->escapeLikeParameter($search) . '%'
280
			)));
281
		}
282
283
		$query->setMaxResults($limit)
284
			->setFirstResult($offset);
285
		$result = $query->execute();
286
287
		$groups = [];
288
		while ($row = $result->fetch()) {
289
			$groups[] = $row['gid'];
290
		}
291
		$result->closeCursor();
292
293
		return $groups;
294
	}
295
296
	/**
297
	 * check if a group exists
298
	 * @param string $gid
299
	 * @return bool
300
	 */
301
	public function groupExists($gid) {
302
		$this->fixDI();
303
304
		// Check cache first
305
		if (isset($this->groupCache[$gid])) {
306
			return true;
307
		}
308
309
		$qb = $this->dbConn->getQueryBuilder();
310
		$cursor = $qb->select('gid')
311
			->from('groups')
312
			->where($qb->expr()->eq('gid', $qb->createNamedParameter($gid)))
313
			->execute();
314
		$result = $cursor->fetch();
315
		$cursor->closeCursor();
316
317
		if ($result !== false) {
318
			$this->groupCache[$gid] = $gid;
319
			return true;
320
		}
321
		return false;
322
	}
323
324
	/**
325
	 * get a list of all users in a group
326
	 * @param string $gid
327
	 * @param string $search
328
	 * @param int $limit
329
	 * @param int $offset
330
	 * @return array an array of user ids
331
	 */
332
	public function usersInGroup($gid, $search = '', $limit = -1, $offset = 0) {
333
		$this->fixDI();
334
335
		$query = $this->dbConn->getQueryBuilder();
336
		$query->select('uid')
337
			->from('group_user')
338
			->where($query->expr()->eq('gid', $query->createNamedParameter($gid)))
339
			->orderBy('uid', 'ASC');
340
341
		if ($search !== '') {
342
			$query->andWhere($query->expr()->like('uid', $query->createNamedParameter(
343
				'%' . $this->dbConn->escapeLikeParameter($search) . '%'
344
			)));
345
		}
346
347
		if ($limit !== -1) {
348
			$query->setMaxResults($limit);
349
		}
350
		if ($offset !== 0) {
351
			$query->setFirstResult($offset);
352
		}
353
354
		$result = $query->execute();
355
356
		$users = [];
357
		while ($row = $result->fetch()) {
358
			$users[] = $row['uid'];
359
		}
360
		$result->closeCursor();
361
362
		return $users;
363
	}
364
365
	/**
366
	 * get the number of all users matching the search string in a group
367
	 * @param string $gid
368
	 * @param string $search
369
	 * @return int
370
	 */
371
	public function countUsersInGroup(string $gid, string $search = ''): int {
372
		$this->fixDI();
373
374
		$query = $this->dbConn->getQueryBuilder();
375
		$query->select($query->func()->count('*', 'num_users'))
376
			->from('group_user')
377
			->where($query->expr()->eq('gid', $query->createNamedParameter($gid)));
378
379
		if ($search !== '') {
380
			$query->andWhere($query->expr()->like('uid', $query->createNamedParameter(
381
				'%' . $this->dbConn->escapeLikeParameter($search) . '%'
382
			)));
383
		}
384
385
		$result = $query->execute();
386
		$count = $result->fetchColumn();
387
		$result->closeCursor();
388
389
		if ($count !== false) {
390
			$count = (int)$count;
391
		} else {
392
			$count = 0;
393
		}
394
395
		return $count;
396
	}
397
398
	/**
399
	 * get the number of disabled users in a group
400
	 *
401
	 * @param string $search
402
	 * @return int|bool
403
	 */
404
	public function countDisabledInGroup(string $gid): int {
405
		$this->fixDI();
406
407
		$query = $this->dbConn->getQueryBuilder();
408
		$query->select($query->createFunction('COUNT(DISTINCT ' . $query->getColumnName('uid') . ')'))
409
			->from('preferences', 'p')
410
			->innerJoin('p', 'group_user', 'g', $query->expr()->eq('p.userid', 'g.uid'))
411
			->where($query->expr()->eq('appid', $query->createNamedParameter('core')))
412
			->andWhere($query->expr()->eq('configkey', $query->createNamedParameter('enabled')))
413
			->andWhere($query->expr()->eq('configvalue', $query->createNamedParameter('false'), IQueryBuilder::PARAM_STR))
414
			->andWhere($query->expr()->eq('gid', $query->createNamedParameter($gid), IQueryBuilder::PARAM_STR));
415
416
		$result = $query->execute();
417
		$count = $result->fetchColumn();
418
		$result->closeCursor();
419
420
		if ($count !== false) {
421
			$count = (int)$count;
422
		} else {
423
			$count = 0;
424
		}
425
426
		return $count;
427
	}
428
429
	public function getDisplayName(string $gid): string {
430
		$this->fixDI();
431
432
		$query = $this->dbConn->getQueryBuilder();
433
		$query->select('displayname')
434
			->from('groups')
435
			->where($query->expr()->eq('gid', $query->createNamedParameter($gid)));
436
437
		$result = $query->execute();
438
		$displayName = $result->fetchColumn();
439
		$result->closeCursor();
440
441
		return (string) $displayName;
442
	}
443
444
	public function getGroupDetails(string $gid): array {
445
		$displayName = $this->getDisplayName($gid);
446
		if ($displayName !== '') {
447
			return ['displayName' => $displayName];
448
		}
449
450
		return [];
451
	}
452
453
	public function setDisplayName(string $gid, string $displayName): bool {
454
		if (!$this->groupExists($gid)) {
455
			return false;
456
		}
457
458
		$this->fixDI();
459
460
		$displayName = trim($displayName);
461
		if ($displayName === '') {
462
			$displayName = $gid;
463
		}
464
465
		$query = $this->dbConn->getQueryBuilder();
466
		$query->update('groups')
467
			->set('displayname', $query->createNamedParameter($displayName))
468
			->where($query->expr()->eq('gid', $query->createNamedParameter($gid)));
469
		$query->execute();
470
471
		return true;
472
	}
473
474
}
475