Skip to content

Commit 9ea8261

Browse files
authored
Merge pull request #190 from rotdrop/production/cafevdb/stable27
Production/cafevdb/stable27
2 parents 91e8cac + 3cc3bf2 commit 9ea8261

11 files changed

Lines changed: 212 additions & 59 deletions

File tree

README.md

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ Name | Description | Details
6363
**Email sync** | Sync e-mail address with the Nextcloud.<br/>- *None* - Disables this feature. This is the default option.<br/>- *Synchronise only once* - Copy the e-mail address to the Nextcloud preferences if its not set.<br/>- *Nextcloud always wins* - Always copy the e-mail address to the database. This updates the user table.<br/>- *SQL always wins* - Always copy the e-mail address to the Nextcloud preferences. | Optional.<br/>Default: *None*.<br/>Requires: user *Email* column.
6464
**Quota sync** | Sync user quota with the Nextcloud.<br/>- *None* - Disables this feature. This is the default option.<br/>- *Synchronise only once* - Copy the user quota to the Nextcloud preferences if its not set.<br/>- *Nextcloud always wins* - Always copy the user quota to the database. This updates the user table.<br/>- *SQL always wins* - Always copy the user quota to the Nextcloud preferences. | Optional.<br/>Default: *None*.<br/>Requires: user *Quota* column.
6565
**Home mode** | User storage path.<br/>- *Default* - Let the Nextcloud manage this. The default option.<br/>- *Query* - Use location from the user table pointed by the *home* column.<br/>- *Static* - Use static location pointed by the *Home Location* option. | Optional<br/>Default: *Default*.
66-
**Home location** | User storage path for the `Static` *Home mode*. The `%u` variable is replaced with the username of the user. | Mandatory if the *Home mode* is set to `Static`.
66+
**Home location** | User storage path for the `Static` *Home mode*. The `%u` variable is replaced with the uid of the user. | Mandatory if the *Home mode* is set to `Static`.
6767
**Default group** | Default group for all 'User SQL' users. | Optional.
6868

6969
#### User table
@@ -74,7 +74,7 @@ Name | Description | Details
7474
--- | --- | ---
7575
**Table name** | The table name. | Mandatory for user backend.
7676
**UID** | User ID column. | Mandatory for user backend.
77-
**Username** | Username column. | Optional.
77+
**Username** | Username column which is used **only** for password verification. | Optional. If unsure leave it blank and use only the `uid` column.
7878
**Email** | E-mail column. | Mandatory for *Email sync* option.
7979
**Quota** | Quota column. | Mandatory for *Quota sync* option.
8080
**Home** | Home path column. | Mandatory for `Query` *Home sync* option.
@@ -120,12 +120,15 @@ For all options to work three tables are required:
120120
If you already have an existing database you can always create database views which fits this model,
121121
but be aware that some functionalities requires data changes (update queries).
122122

123-
If you don't have any database model yet you can use below tables (MySQL):
123+
If you don't have any database model yet you can use below tables
124+
(MySQL). Please note that the optional `username` above really is only
125+
used for password matching and defaults to be equal to the `uid`
126+
column. You also may want to compare with the `oc_users` and
127+
`oc_groups` table from you Nextcloud instance.
124128
```
125129
CREATE TABLE sql_user
126130
(
127-
uid INT PRIMARY KEY AUTO_INCREMENT,
128-
username VARCHAR(16) NOT NULL UNIQUE,
131+
uid VARCHAR(64) PRIMARY KEY,
129132
display_name TEXT NULL,
130133
email TEXT NULL,
131134
quota TEXT NULL,
@@ -139,15 +142,15 @@ CREATE TABLE sql_user
139142
140143
CREATE TABLE sql_group
141144
(
142-
gid INT PRIMARY KEY AUTO_INCREMENT,
143-
name VARCHAR(16) NOT NULL UNIQUE,
144-
admin BOOLEAN NOT NULL DEFAULT FALSE
145+
gid VARCHAR(64) PRIMARY KEY,
146+
name VARCHAR(255) NOT NULL,
147+
admin BOOLEAN NOT NULL DEFAULT FALSE
145148
);
146149
147150
CREATE TABLE sql_user_group
148151
(
149-
uid INT NOT NULL,
150-
gid INT NOT NULL,
152+
uid VARCHAR(64),
153+
gid VARCHAR(64),
151154
PRIMARY KEY (uid, gid),
152155
FOREIGN KEY (uid) REFERENCES sql_user (uid),
153156
FOREIGN KEY (gid) REFERENCES sql_group (gid),

appinfo/info.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
</types>
2222
<category>auth</category>
2323
<dependencies>
24-
<php min-version="7.1"/>
25-
<nextcloud min-version="21" max-version="23"/>
24+
<php min-version="8.0"/>
25+
<nextcloud min-version="25" max-version="27"/>
2626
</dependencies>
2727
<settings>
2828
<admin>\OCA\UserSQL\Settings\Admin</admin>

lib/Backend/GroupBackend.php

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,11 @@
3131
use OCP\Group\Backend\ICountUsersBackend;
3232
use OCP\Group\Backend\IGroupDetailsBackend;
3333
use OCP\Group\Backend\IIsAdminBackend;
34+
use OCP\Group\Backend\ISearchableGroupBackend;
3435
use OCP\ILogger;
36+
use OCP\IUserManager;
37+
38+
use OC\User\LazyUser;
3539

3640
/**
3741
* The SQL group backend manager.
@@ -41,7 +45,8 @@
4145
final class GroupBackend extends ABackend implements
4246
ICountUsersBackend,
4347
IGroupDetailsBackend,
44-
IIsAdminBackend
48+
IIsAdminBackend,
49+
ISearchableGroupBackend
4550
{
4651
const USER_SQL_GID = "user_sql";
4752

@@ -354,16 +359,16 @@ public function usersInGroup($gid, $search = "", $limit = -1, $offset = 0)
354359
["app" => $this->appName]
355360
);
356361

357-
$cacheKey = self::class . "group_users_" . $gid . "_" . $search . "_"
362+
$cacheKey = self::class . "group_uids_" . $gid . "_" . $search . "_"
358363
. $limit . "_" . $offset;
359-
$users = $this->cache->get($cacheKey);
364+
$uids = $this->cache->get($cacheKey);
360365

361-
if (!is_null($users)) {
366+
if (!is_null($uids)) {
362367
$this->logger->debug(
363368
"Returning from cache usersInGroup($gid, $search, $limit, $offset): count("
364-
. count($users) . ")", ["app" => $this->appName]
369+
. count($uids) . ")", ["app" => $this->appName]
365370
);
366-
return $users;
371+
return $uids;
367372
}
368373

369374
$uids = $this->groupRepository->findAllUidsBySearchTerm(
@@ -383,6 +388,50 @@ public function usersInGroup($gid, $search = "", $limit = -1, $offset = 0)
383388
return $uids;
384389
}
385390

391+
/**
392+
* @inheritdoc
393+
*/
394+
public function searchInGroup(string $gid, string $search = '', int $limit = -1, int $offset = 0): array
395+
{
396+
$this->logger->debug(
397+
"Entering searchInGroup($gid, $search, $limit, $offset)",
398+
["app" => $this->appName]
399+
);
400+
401+
$cacheKey = self::class . "group_users_" . $gid . "_" . $search . "_"
402+
. $limit . "_" . $offset;
403+
$names = $this->cache->get($cacheKey);
404+
405+
if ($names === null) {
406+
$names = $this->groupRepository->findAllUsersBySearchTerm(
407+
$this->substituteGid($gid), "%" . $search . "%", $limit, $offset
408+
);
409+
410+
if ($names === false) {
411+
return [];
412+
}
413+
414+
$this->cache->set($cacheKey, $names);
415+
$this->logger->debug(
416+
"Using from DB searchInGroup($gid, $search, $limit, $offset): count("
417+
. count($names) . ")", ["app" => $this->appName]
418+
);
419+
} else {
420+
$this->logger->debug(
421+
"Using from cache searchInGroup($gid, $search, $limit, $offset): count("
422+
. count($names) . ")", ["app" => $this->appName]
423+
);
424+
}
425+
426+
$users = [];
427+
$userManager = \OCP\Server::get(IUserManager::class);
428+
foreach ($names as $uid => $name) {
429+
$users[$uid] = new LazyUser($uid, $userManager, $name);
430+
}
431+
432+
return $users;
433+
}
434+
386435
/**
387436
* @inheritdoc
388437
*/

lib/Backend/UserBackend.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,18 @@ public function getUsers($search = "", $limit = null, $offset = null, $callback
459459
"Returning from cache getUsers($search, $limit, $offset): count("
460460
. count($users) . ")", ["app" => $this->appName]
461461
);
462+
// convert to user-model
463+
foreach ($users as $index => $cachedUser) {
464+
if (!is_array($cachedUser)) {
465+
break;
466+
}
467+
$user = new User();
468+
foreach ($cachedUser as $key => $value) {
469+
$user->{$key} = $value;
470+
}
471+
$users[$index] = $user;
472+
}
473+
462474
return $users;
463475
}
464476

lib/Constant/Query.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ final class Query
3232
const COUNT_GROUPS = "count_groups";
3333
const COUNT_USERS = "count_users";
3434
const FIND_GROUP = "find_group";
35+
const FIND_GROUP_UIDS = "find_group_uids";
3536
const FIND_GROUP_USERS = "find_group_users";
3637
const FIND_GROUPS = "find_groups";
3738
const FIND_USER_BY_UID = "find_user_by_uid";

lib/Controller/SettingsController.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ public function __construct(
9292
* Verify the database connection parameters.
9393
*
9494
* @return array The request status.
95+
*
96+
* @AuthorizedAdminSetting(settings=OCA\UserSQL\Settings\Admin)
9597
*/
9698
public function verifyDbConnection()
9799
{
@@ -189,6 +191,8 @@ private function getConnection()
189191
* Save application properties.
190192
*
191193
* @return array The request status.
194+
*
195+
* @AuthorizedAdminSetting(settings=OCA\UserSQL\Settings\Admin)
192196
*/
193197
public function saveProperties()
194198
{
@@ -329,6 +333,8 @@ private function cryptoClassConfiguration($cryptoClass)
329333
* Clear the application cache memory.
330334
*
331335
* @return array The request status.
336+
*
337+
* @AuthorizedAdminSetting(settings=OCA\UserSQL\Settings\Admin)
332338
*/
333339
public function clearCache()
334340
{
@@ -356,6 +362,8 @@ public function clearCache()
356362
* Autocomplete for table select options.
357363
*
358364
* @return array The database table list.
365+
*
366+
* @AuthorizedAdminSetting(settings=OCA\UserSQL\Settings\Admin)
359367
*/
360368
public function tableAutocomplete()
361369
{
@@ -385,6 +393,8 @@ public function tableAutocomplete()
385393
* Autocomplete for column select options - user table.
386394
*
387395
* @return array The database table's column list.
396+
*
397+
* @AuthorizedAdminSetting(settings=OCA\UserSQL\Settings\Admin)
388398
*/
389399
public function userTableAutocomplete()
390400
{
@@ -430,6 +440,8 @@ private function columnAutocomplete($table)
430440
* Autocomplete for column select options - user_group table.
431441
*
432442
* @return array The database table's column list.
443+
*
444+
* @AuthorizedAdminSetting(settings=OCA\UserSQL\Settings\Admin)
433445
*/
434446
public function userGroupTableAutocomplete()
435447
{
@@ -451,6 +463,8 @@ public function userGroupTableAutocomplete()
451463
* Autocomplete for column select options - group table.
452464
*
453465
* @return array The database table's column list.
466+
*
467+
* @AuthorizedAdminSetting(settings=OCA\UserSQL\Settings\Admin)
454468
*/
455469
public function groupTableAutocomplete()
456470
{
@@ -473,6 +487,8 @@ public function groupTableAutocomplete()
473487
*
474488
* @return array Password algorithm parameters.
475489
* @throws ReflectionException Whenever Opt class cannot be initiated.
490+
*
491+
* @AuthorizedAdminSetting(settings=OCA\UserSQL\Settings\Admin)
476492
*/
477493
public function cryptoParams()
478494
{

lib/Properties.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -203,15 +203,15 @@ public function getArray()
203203
/**
204204
* @inheritdoc
205205
*/
206-
public function offsetExists($offset)
206+
public function offsetExists(mixed $offset):bool
207207
{
208208
return isset($this->data[$offset]);
209209
}
210210

211211
/**
212212
* @inheritdoc
213213
*/
214-
public function offsetGet($offset)
214+
public function offsetGet(mixed $offset):mixed
215215
{
216216
if (isset($this->data[$offset])) {
217217
return $this->data[$offset];
@@ -223,7 +223,7 @@ public function offsetGet($offset)
223223
/**
224224
* @inheritdoc
225225
*/
226-
public function offsetSet($offset, $value)
226+
public function offsetSet(mixed $offset, mixed $value):void
227227
{
228228
if ($offset == Opt::SAFE_STORE) {
229229
$this->safeStore = ($value === App::TRUE_VALUE);
@@ -255,7 +255,7 @@ public function offsetSet($offset, $value)
255255
/**
256256
* @inheritdoc
257257
*/
258-
public function offsetUnset($offset)
258+
public function offsetUnset(mixed $offset):void
259259
{
260260
if ($offset == Opt::SAFE_STORE) {
261261
$this->safeStore = App::FALSE_VALUE;

lib/Query/DataQuery.php

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -109,26 +109,30 @@ private function execQuery(
109109
}
110110

111111
$query = $this->queryProvider[$queryName];
112-
$result = $this->connection->prepare($query, $limit, $offset);
112+
113+
try {
114+
$result = $this->connection->prepare($query, $limit, $offset);
115+
} catch (DBALException $exception) {
116+
$this->logger->logException(
117+
$exception, [ 'message' => "Could not prepare the query: " . $query ]
118+
);
119+
return false;
120+
}
113121

114122
foreach ($params as $param => $value) {
115123
$result->bindValue(":" . $param, $value);
116124
}
117125

118-
$this->logger->debug(
119-
"Executing query: " . $query . ", " . implode(",", $params),
120-
["app" => $this->appName]
121-
);
126+
$this->logger->debug("Executing query: " . $query . ", " . implode(",", $params));
122127

123128
try {
124129
$result = $result->execute();
125130
return $result;
126131

127132
} catch (DBALException $exception) {
128-
$this->logger->error(
129-
"Could not execute the query: " . $exception->getMessage(),
130-
["app" => $this->appName]
131-
);
133+
$this->logger->logException(
134+
$exception, [ 'message' => "Could not execute the query: " . $query ]
135+
);
132136
return false;
133137
}
134138
}
@@ -219,6 +223,27 @@ public function queryColumn(
219223
return $result->fetchFirstColumn();
220224
}
221225

226+
/**
227+
* Fetch values from all columns which the given query returns.
228+
*
229+
* @param string $queryName The query to execute.
230+
* @param array $params The query parameters to bind.
231+
* @param int $limit Results limit. Defaults to -1 (no limit).
232+
* @param int $offset Results offset. Defaults to 0.
233+
*
234+
* @return array|bool Queried column or FALSE on failure.
235+
*/
236+
public function queryColumns(
237+
$queryName, $params = [], $limit = -1, $offset = 0
238+
) {
239+
$result = $this->execQuery($queryName, $params, $limit, $offset);
240+
if ($result === false) {
241+
return false;
242+
}
243+
244+
return $result->fetchAll();
245+
}
246+
222247
/**
223248
* Fetch entity returned by the given query.
224249
*

0 commit comments

Comments
 (0)