Skip to content

Commit

Permalink
feat: add support to groups
Browse files Browse the repository at this point in the history
Signed-off-by: Vitor Mattos <[email protected]>
  • Loading branch information
vitormattos committed Oct 5, 2024
1 parent 3d14896 commit d87d0ee
Show file tree
Hide file tree
Showing 5 changed files with 188 additions and 1 deletion.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ This app has no user interface. All configuration is done via Nextcloud's system
//'count_users' => 'SELECT COUNT (*) FROM users',
//'get_home' => '',
//'create_user' => 'INSERT INTO users (local, domain, password_hash) VALUES (split_part(:username, \'@\', 1), split_part(:username, \'@\', 2), :password_hash)',
// 'get_in_groups' => 'SELECT id AS gid, name AS displayname FROM groups WHERE (id ILIKE :search) OR (name ILIKE :search)',
// 'get_groups' => 'SELECT id AS gid, name AS displayname FROM groups WHERE (id ILIKE :search) OR (name ILIKE :search)',
// 'get_user_groups' => "SELECT u.user_login FROM groups g JOIN users u ON g.user_id = u.id WHERE u.user_login = :username",
// 'get_user_in_group' => 'SELECT id AS gid, name AS displayname FROM groups WHERE (id ILIKE :search) OR (name ILIKE :search)',
// 'get_group_exists' => "SELECT EXISTS(SELECT 1 FROM groups WHERE g.name = :group)",
// 'get_group_details' => "SELECT g.name FROM groups WHERE name = :group",
),
//'hash_algorithm_for_new_passwords' => 'bcrypt',
),
Expand Down
2 changes: 1 addition & 1 deletion appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,6 @@ these databases. This has not been tested, though.]]></description>
<repository type="git">https://github.com/PanCakeConnaisseur/user_backend_sql_raw</repository>
<screenshot small-thumbnail="https://raw.githubusercontent.com/PanCakeConnaisseur/user_backend_sql_raw/2eb5221f0725a9ab09fde6384dea62463c7c52e5/screenshot-dark-small.jpg">https://raw.githubusercontent.com/PanCakeConnaisseur/user_backend_sql_raw/2eb5221f0725a9ab09fde6384dea62463c7c52e5/screenshot-dark-large.jpg</screenshot>
<dependencies>
<nextcloud min-version="26" max-version="29"/>
<nextcloud min-version="26" max-version="31"/>
</dependencies>
</info>
4 changes: 4 additions & 0 deletions lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
use OCP\AppFramework\Bootstrap\IRegistrationContext;
use Psr\Container\ContainerInterface;
use \OCP\AppFramework\App;
use OCP\Server;

class Application extends App implements IBootstrap
{
Expand All @@ -46,5 +47,8 @@ public function boot(IBootContext $context): void
$userBackendSqlRaw = $context->getAppContainer()->get(\OCA\UserBackendSqlRaw\UserBackend::class);
$userManager = $context->getAppContainer()->get('OCP\IUserManager');
$userManager->registerBackend($userBackendSqlRaw);

$groupBackend = $context->getAppContainer()->get(\OCA\UserBackendSqlRaw\Backend\GroupBackend::class);
Server::get(\OCP\IGroupManager::class)->addBackend($groupBackend);
}
}
140 changes: 140 additions & 0 deletions lib/Backend/GroupBackend.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
<?php
/**
* @copyright Copyright (c) 2024 Vitor Mattos <[email protected]>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

namespace OCA\UserBackendSqlRaw\Backend;

use OCA\UserBackendSqlRaw\Config;
use OCA\UserBackendSqlRaw\Db;
use OCP\Group\Backend\ABackend;
use OCP\Group\Backend\IGroupDetailsBackend;
use Psr\Log\LoggerInterface;

class GroupBackend extends ABackend implements IGroupDetailsBackend
{
public function __construct(
private LoggerInterface $logger,
private Config $config,
private Db $db,
) {
}

public function inGroup($uid, $gid): bool
{
$queryFromConfig = $this->config->getQueryInGroup();
if (empty($queryFromConfig)) {
return false;
}
$statement = $this->db->getDbHandle()->prepare($queryFromConfig);
$statement->execute(['username' => $uid, 'group' => $gid]);
$inGroup = $statement->fetchColumn();
return (bool) $inGroup;
}

public function getUserGroups($uid)
{
$queryFromConfig = $this->config->getQueryUserGroups();
if (empty($queryFromConfig)) {
return [];
}
$statement = $this->db->getDbHandle()->prepare($queryFromConfig);
$statement->execute(['username' => $uid]);
$groups = $statement->fetchAll(\PDO::FETCH_COLUMN, 0);
return $groups;
}

public function getGroups($search = '', $limit = -1, $offset = 0)
{
$queryFromConfig = $this->config->getQueryGroups();
if (empty($queryFromConfig)) {
return [];
}
isset($limit) && $limit > 0 ? $limitSegment = ' LIMIT :limit' : $limitSegment = '';
isset($offset) && $offset > 0? $offsetSegment = ' OFFSET :offset' : $offsetSegment = '';
$finalQuery = $queryFromConfig . $limitSegment . $offsetSegment;
$statement = $this->db->getDbHandle()->prepare($finalQuery);
// Because MariaDB can not handle string parameters for LIMIT/OFFSET we have to bind the
// values "manually" instead of passing an array to execute(). This is another instance of
// MariaDB making the code "uglier".
$statement->bindValue(':search', '%' . $search . '%', \PDO::PARAM_STR);
if (isset($limit) && $limit > 0) {
$statement->bindValue(':limit', intval($limit), \PDO::PARAM_INT);
}
if (isset($offset) && $offset > 0) {
$statement->bindValue(':offset', intval($offset), \PDO::PARAM_INT);
}
$statement->execute();
$groups = $statement->fetchAll(\PDO::FETCH_COLUMN, 0);
return $groups;
}

public function groupExists($gid)
{
$queryFromConfig = $this->config->getQueryGroupExists();
if (empty($queryFromConfig)) {
return false;
}
$statement = $this->db->getDbHandle()->prepare($queryFromConfig);
$statement->execute(['group' => $gid]);
$groupExists = $statement->fetchColumn();
return (bool) $groupExists;
}

public function usersInGroup($gid, $search = '', $limit = -1, $offset = 0)
{
$queryFromConfig = $this->config->getQueryUsersInGroup();
if (empty($queryFromConfig)) {
return [];
}
isset($limit) && $limit > 0 ? $limitSegment = ' LIMIT :limit' : $limitSegment = '';
isset($offset) && $offset > 0? $offsetSegment = ' OFFSET :offset' : $offsetSegment = '';
$finalQuery = $queryFromConfig . $limitSegment . $offsetSegment;
$statement = $this->db->getDbHandle()->prepare($finalQuery);
// Because MariaDB can not handle string parameters for LIMIT/OFFSET we have to bind the
// values "manually" instead of passing an array to execute(). This is another instance of
// MariaDB making the code "uglier".
$statement->bindValue(':search', '%' . $search . '%', \PDO::PARAM_STR);
$statement->bindValue(':group', $gid, \PDO::PARAM_STR);
if (isset($limit) && $limit > 0) {
$statement->bindValue(':limit', intval($limit), \PDO::PARAM_INT);
}
if (isset($offset) && $offset > 0) {
$statement->bindValue(':offset', intval($offset), \PDO::PARAM_INT);
}
$statement->execute();
$groups = $statement->fetchAll(\PDO::FETCH_COLUMN, 0);
return $groups;
}

public function getGroupDetails(string $gid): array
{
$queryFromConfig = $this->config->getQueryGroupDetails();
if (empty($queryFromConfig)) {
return [];
}
$statement = $this->db->getDbHandle()->prepare($queryFromConfig);
$statement->execute(['group' => $gid]);
$groupDetails = $statement->fetchColumn();
if (!$groupDetails) {
return [];
}
return ['displayName' => $groupDetails];
}
}
37 changes: 37 additions & 0 deletions lib/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ class Config
const CONFIG_KEY_GET_HOME = 'get_home';
const CONFIG_KEY_CREATE_USER = 'create_user';

const CONFIG_KEY_IN_GROUPS = 'get_in_groups';
const CONFIG_KEY_GROUPS = 'get_groups';
const CONFIG_KEY_USER_GROUPS = 'get_user_groups';
const CONFIG_KEY_USERS_IN_GROUP = 'get_users_in_group';
const CONFIG_KEY_GROUP_EXISTS = 'get_group_exists';
const CONFIG_KEY_GROUP_DETAILS = 'get_group_details';

/* @var LoggerInterface */
private $logger;
private $appConfiguration;
Expand Down Expand Up @@ -235,6 +242,36 @@ public function getQueryCreateUser()
return $this->getQueryStringOrFalse(self::CONFIG_KEY_CREATE_USER);
}

public function getQueryInGroup()
{
return $this->getQueryStringOrFalse(self::CONFIG_KEY_IN_GROUPS);
}

public function getQueryGroups()
{
return $this->getQueryStringOrFalse(self::CONFIG_KEY_GROUPS);
}

public function getQueryUserGroups()
{
return $this->getQueryStringOrFalse(self::CONFIG_KEY_USER_GROUPS);
}

public function getQueryUsersInGroup()
{
return $this->getQueryStringOrFalse(self::CONFIG_KEY_USERS_IN_GROUP);
}

public function getQueryGroupExists()
{
return $this->getQueryStringOrFalse(self::CONFIG_KEY_GROUP_EXISTS);
}

public function getQueryGroupDetails()
{
return $this->getQueryStringOrFalse(self::CONFIG_KEY_GROUP_DETAILS);
}



/**
Expand Down

0 comments on commit d87d0ee

Please sign in to comment.