Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/HuasoFoundries/phpPgAdmin6.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/Database/Traits/RoleTrait.php')
-rw-r--r--src/Database/Traits/RoleTrait.php1083
1 files changed, 1083 insertions, 0 deletions
diff --git a/src/Database/Traits/RoleTrait.php b/src/Database/Traits/RoleTrait.php
new file mode 100644
index 00000000..fc15a197
--- /dev/null
+++ b/src/Database/Traits/RoleTrait.php
@@ -0,0 +1,1083 @@
+<?php
+
+/**
+ * PHPPgAdmin6
+ */
+
+namespace PHPPgAdmin\Database\Traits;
+
+/**
+ * Common trait for roles and users manipulation.
+ */
+trait RoleTrait
+{
+ /**
+ * Returns all roles in the database cluster.
+ *
+ * @param string $rolename (optional) The role name to exclude from the select
+ *
+ * @return \ADORecordSet|bool|int|string
+ */
+ public function getRoles($rolename = '')
+ {
+ $sql = '
+ SELECT
+ r.rolname,
+ r1.rolname as group,
+ r.rolsuper,
+ r.rolcreatedb,
+ r.rolcreaterole,
+ r.rolinherit,
+ r.rolcanlogin,
+ r.rolconnlimit,
+ r.rolvaliduntil,
+ r.rolconfig
+ FROM pg_catalog.pg_roles r
+ LEFT JOIN pg_catalog.pg_auth_members m ON (m.member = r.oid)
+ LEFT JOIN pg_roles r1 ON (m.roleid=r1.oid)
+ ';
+
+ if ($rolename) {
+ $sql .= \sprintf(
+ ' WHERE r.rolname!=\'%s\'',
+ $rolename
+ );
+ }
+
+ $sql .= ' ORDER BY r.rolname';
+
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Returns information about a single role.
+ *
+ * @param string $rolename The name of the role to retrieve
+ *
+ * @return \ADORecordSet|bool|int|string
+ */
+ public function getRole($rolename)
+ {
+ $this->clean($rolename);
+
+ $sql = \sprintf(
+ '
+ SELECT
+ r.rolname,
+ r1.rolname as group,
+ r.rolsuper,
+ r.rolcreatedb,
+ r.rolcreaterole,
+ r.rolinherit,
+ r.rolcanlogin,
+ r.rolconnlimit,
+ r.rolvaliduntil,
+ r.rolconfig
+ FROM pg_catalog.pg_roles r
+ LEFT JOIN pg_catalog.pg_auth_members m ON (m.member = r.oid)
+ LEFT JOIN pg_roles r1 ON (m.roleid=r1.oid)
+ WHERE r.rolname=\'%s\'',
+ $rolename
+ );
+
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Returns all users in the database cluster.
+ *
+ * @return \ADORecordSet|bool|int|string
+ */
+ public function getUsers()
+ {
+ $sql = 'SELECT
+ r.usename,
+ r1.rolname as group,
+ r.usesuper,
+ r.valuntil AS useexpires,
+ r.useconfig
+ FROM pg_catalog.pg_user r
+ LEFT JOIN pg_catalog.pg_auth_members m ON (m.member = r.usesysid)
+ LEFT JOIN pg_roles r1 ON (m.roleid=r1.oid)';
+
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Returns information about a single user.
+ *
+ * @param string $username The username of the user to retrieve
+ *
+ * @return \ADORecordSet|bool|int|string
+ */
+ public function getUser($username)
+ {
+ $this->clean($username);
+
+ $sql = \sprintf(
+ 'SELECT
+ r.usename,
+ r1.rolname as group,
+ r.usesuper,
+ r.valuntil AS useexpires,
+ r.useconfig
+ FROM pg_catalog.pg_user r
+ LEFT JOIN pg_catalog.pg_auth_members m ON (m.member = r.usesysid)
+ LEFT JOIN pg_roles r1 ON (m.roleid=r1.oid)
+ WHERE r.usename=\'%s\'',
+ $username
+ );
+
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Creates a new role.
+ *
+ * @param string $rolename The name of the role to create
+ * @param string $password A password for the role
+ * @param bool $superuser Boolean whether or not the role is a superuser
+ * @param bool $createdb Boolean whether or not the role can create databases
+ * @param bool $createrole Boolean whether or not the role can create other roles
+ * @param bool $inherits Boolean whether or not the role inherits the privileges from parent roles
+ * @param bool $login Boolean whether or not the role will be allowed to login
+ * @param int $connlimit Number of concurrent connections the role can make
+ * @param string $expiry String Format 'YYYY-MM-DD HH:MM:SS'. '' means never expire
+ * @param array $new_roles_to_add (array) Roles to which the new role will be immediately added as a new member
+ * @param array $new_members_of_role (array) Roles which are automatically added as members of the new role
+ * @param array $new_admins_of_role (array) Roles which are automatically added as admin members of the new role
+ *
+ * @return int|string
+ */
+ public function createRole(
+ $rolename,
+ $password,
+ $superuser,
+ $createdb,
+ $createrole,
+ $inherits,
+ $login,
+ $connlimit,
+ $expiry,
+ $new_roles_to_add,
+ $new_members_of_role,
+ $new_admins_of_role
+ ) {
+ $enc = $this->_encryptPassword($rolename, $password);
+ $this->fieldClean($rolename);
+ $this->clean($enc);
+ $this->clean($connlimit);
+ $this->clean($expiry);
+ $this->fieldArrayClean($new_roles_to_add);
+ $this->fieldArrayClean($new_members_of_role);
+ $this->fieldArrayClean($new_admins_of_role);
+
+ $sql = \sprintf(
+ 'CREATE ROLE "%s"',
+ $rolename
+ );
+
+ if ('' !== $password) {
+ $sql .= \sprintf(
+ ' WITH ENCRYPTED PASSWORD \'%s\'',
+ $enc
+ );
+ }
+
+ $sql .= $superuser ? ' SUPERUSER' : ' NOSUPERUSER';
+ $sql .= $createdb ? ' CREATEDB' : ' NOCREATEDB';
+ $sql .= $createrole ? ' CREATEROLE' : ' NOCREATEROLE';
+ $sql .= $inherits ? ' INHERIT' : ' NOINHERIT';
+ $sql .= $login ? ' LOGIN' : ' NOLOGIN';
+
+ if ('' !== $connlimit) {
+ $sql .= \sprintf(
+ ' CONNECTION LIMIT %s',
+ $connlimit
+ );
+ } else {
+ $sql .= ' CONNECTION LIMIT -1';
+ }
+
+ if ('' !== $expiry) {
+ $sql .= \sprintf(
+ ' VALID UNTIL \'%s\'',
+ $expiry
+ );
+ } else {
+ $sql .= " VALID UNTIL 'infinity'";
+ }
+
+ if (\is_array($new_roles_to_add) && 0 < \count($new_roles_to_add)) {
+ $sql .= ' IN ROLE "' . \implode('", "', $new_roles_to_add) . '"';
+ }
+
+ if (\is_array($new_members_of_role) && 0 < \count($new_members_of_role)) {
+ $sql .= ' ROLE "' . \implode('", "', $new_members_of_role) . '"';
+ }
+
+ if (\is_array($new_admins_of_role) && 0 < \count($new_admins_of_role)) {
+ $sql .= ' ADMIN "' . \implode('", "', $new_admins_of_role) . '"';
+ }
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Helper function that computes encypted PostgreSQL passwords.
+ *
+ * @param string $username The username
+ * @param string $password The password
+ *
+ * @return string
+ */
+ public function _encryptPassword($username, $password)
+ {
+ return 'md5' . \md5($password . $username);
+ }
+
+ /**
+ * Adjusts a role's info and renames it.
+ *
+ * @param string $rolename The name of the role to adjust
+ * @param string $password A password for the role
+ * @param bool $superuser Boolean whether or not the role is a superuser
+ * @param bool $createdb Boolean whether or not the role can create databases
+ * @param bool $createrole Boolean whether or not the role can create other roles
+ * @param bool $inherits Boolean whether or not the role inherits the privileges from parent roles
+ * @param bool $login Boolean whether or not the role will be allowed to login
+ * @param int $connlimit Number of concurrent connections the role can make
+ * @param string $expiry string Format 'YYYY-MM-DD HH:MM:SS'. '' means never expire
+ * @param array $new_roles_to_add (array) Roles to which the role will be immediately added as a new member
+ * @param array $new_members_of_role (array) Roles which are automatically added as members of the role
+ * @param array $new_admins_of_role (array) Roles which are automatically added as admin members of the role
+ * @param string $original_parent_roles Original roles whose the role belongs to, comma separated
+ * @param string $original_members Original roles that are members of the role, comma separated
+ * @param string $original_admins Original roles that are admin members of the role, comma separated
+ * @param string $newrolename The new name of the role
+ *
+ * @return int
+ *
+ * @psalm-return -3|-2|-1|0|1
+ */
+ public function setRenameRole(
+ $rolename,
+ $password,
+ $superuser,
+ $createdb,
+ $createrole,
+ $inherits,
+ $login,
+ $connlimit,
+ $expiry,
+ $new_roles_to_add,
+ $new_members_of_role,
+ $new_admins_of_role,
+ $original_parent_roles,
+ $original_members,
+ $original_admins,
+ $newrolename
+ ) {
+ $status = $this->beginTransaction();
+
+ if (0 !== $status) {
+ return -1;
+ }
+
+ if ($rolename !== $newrolename) {
+ $status = $this->renameRole($rolename, $newrolename);
+
+ if (0 !== $status) {
+ $this->rollbackTransaction();
+
+ return -3;
+ }
+ $rolename = $newrolename;
+ }
+
+ $status = $this->setRole(
+ $rolename,
+ $password,
+ $superuser,
+ $createdb,
+ $createrole,
+ $inherits,
+ $login,
+ $connlimit,
+ $expiry,
+ $new_roles_to_add,
+ $new_members_of_role,
+ $new_admins_of_role,
+ $original_parent_roles,
+ $original_members,
+ $original_admins
+ );
+
+ if (0 !== $status) {
+ $this->rollbackTransaction();
+
+ return -2;
+ }
+
+ return $this->endTransaction();
+ }
+
+ /**
+ * Renames a role.
+ *
+ * @param string $rolename The name of the role to rename
+ * @param string $newrolename The new name of the role
+ *
+ * @return int|string
+ */
+ public function renameRole($rolename, $newrolename)
+ {
+ $this->fieldClean($rolename);
+ $this->fieldClean($newrolename);
+
+ $sql = \sprintf(
+ 'ALTER ROLE "%s" RENAME TO "%s"',
+ $rolename,
+ $newrolename
+ );
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Adjusts a role's info.
+ *
+ * @param string $rolename The name of the role to adjust
+ * @param string $password A password for the role
+ * @param bool $superuser Boolean whether or not the role is a superuser
+ * @param bool $createdb Boolean whether or not the role can create databases
+ * @param bool $createrole Boolean whether or not the role can create other roles
+ * @param bool $inherits Boolean whether or not the role inherits the privileges from parent roles
+ * @param bool $login Boolean whether or not the role will be allowed to login
+ * @param int $connlimit Number of concurrent connections the role can make
+ * @param string $expiry string Format 'YYYY-MM-DD HH:MM:SS'. '' means never expire
+ * @param array $new_roles_to_add (array) Roles to which the role will be immediately added as a new member
+ * @param array $new_members_of_role (array) Roles which are automatically added as members of the role
+ * @param array $new_admins_of_role (array) Roles which are automatically added as admin members of the role
+ * @param string $original_parent_roles Original roles whose the role belongs to, comma separated
+ * @param string $original_members Original roles that are members of the role, comma separated
+ * @param string $original_admins Original roles that are admin members of the role, comma separated
+ *
+ * @return int
+ *
+ * @psalm-return -1|0
+ */
+ public function setRole(
+ $rolename,
+ $password,
+ $superuser,
+ $createdb,
+ $createrole,
+ $inherits,
+ $login,
+ $connlimit,
+ $expiry,
+ $new_roles_to_add,
+ $new_members_of_role,
+ $new_admins_of_role,
+ $original_parent_roles,
+ $original_members,
+ $original_admins
+ ) {
+ $this->fieldClean($rolename);
+
+ $this->fieldArrayClean($new_roles_to_add);
+ $this->fieldArrayClean($new_members_of_role);
+ $this->fieldArrayClean($new_admins_of_role);
+
+ $status = $this->_alterRole($rolename, $password, $connlimit, $expiry, $superuser, $createdb, $createrole, $inherits, $login);
+
+ if (0 !== $status) {
+ return -1;
+ }
+
+ // If there were existing users with the requested role,
+ // assign their roles to the new user, and remove said
+ // role from them if they are not among the new authorized members
+ if ($original_parent_roles) {
+ $status = $this->_dealWithOldParentRoles($original_parent_roles, $new_roles_to_add, $rolename);
+
+ if (0 !== $status) {
+ return -1;
+ }
+ }
+
+ if ($original_members) {
+ $status = $this->_dealWithOriginalMembers($original_members, $new_members_of_role, $rolename);
+
+ if (0 !== $status) {
+ return -1;
+ }
+ }
+
+ if ($original_admins) {
+ $status = $this->_dealWithOriginalAdmins($original_admins, $new_admins_of_role, $rolename);
+
+ if (0 !== $status) {
+ return -1;
+ }
+ }
+
+ return $status;
+ }
+
+ /**
+ * Grants membership in a role.
+ *
+ * @param string $role The name of the target role
+ * @param string $rolename The name of the role that will belong to the target role
+ * @param int $admin (optional) Flag to grant the admin option
+ *
+ * @return int|string
+ */
+ public function grantRole($role, $rolename, $admin = 0)
+ {
+ $this->fieldClean($role);
+ $this->fieldClean($rolename);
+
+ $sql = \sprintf(
+ 'GRANT "%s" TO "%s"',
+ $role,
+ $rolename
+ );
+
+ if (1 === $admin) {
+ $sql .= ' WITH ADMIN OPTION';
+ }
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Revokes membership in a role.
+ *
+ * @param string $role The name of the target role
+ * @param string $rolename The name of the role that will not belong to the target role
+ * @param int $admin (optional) Flag to revoke only the admin option
+ * @param string $type (optional) Type of revoke: RESTRICT | CASCADE
+ *
+ * @return int|string
+ */
+ public function revokeRole($role, $rolename, $admin = 0, $type = 'RESTRICT')
+ {
+ $this->fieldClean($role);
+ $this->fieldClean($rolename);
+
+ $sql = 'REVOKE ';
+
+ if (1 === $admin) {
+ $sql .= 'ADMIN OPTION FOR ';
+ }
+
+ $sql .= \sprintf(
+ '"%s" FROM "%s" %s',
+ $role,
+ $rolename,
+ $type
+ );
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Removes a role.
+ *
+ * @param string $rolename The name of the role to drop
+ *
+ * @return int|string
+ */
+ public function dropRole($rolename)
+ {
+ $this->fieldClean($rolename);
+
+ $sql = \sprintf(
+ 'DROP ROLE "%s"',
+ $rolename
+ );
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Creates a new user.
+ *
+ * @param string $username The username of the user to create
+ * @param string $password A password for the user
+ * @param bool $createdb boolean Whether or not the user can create databases
+ * @param bool $createuser boolean Whether or not the user can create other users
+ * @param string $expiry string Format 'YYYY-MM-DD HH:MM:SS'. '' means never expire
+ * @param array $groups The groups to create the user in
+ *
+ * @return int|string
+ *
+ * @internal param $group (array) The groups to create the user in
+ */
+ public function createUser($username, $password, $createdb, $createuser, $expiry, $groups)
+ {
+ $enc = $this->_encryptPassword($username, $password);
+ $this->fieldClean($username);
+ $this->clean($enc);
+ $this->clean($expiry);
+ $this->fieldArrayClean($groups);
+
+ $sql = \sprintf(
+ 'CREATE USER "%s"',
+ $username
+ );
+
+ if ('' !== $password) {
+ $sql .= \sprintf(
+ ' WITH ENCRYPTED PASSWORD \'%s\'',
+ $enc
+ );
+ }
+
+ $sql .= $createdb ? ' CREATEDB' : ' NOCREATEDB';
+ $sql .= $createuser ? ' CREATEUSER' : ' NOCREATEUSER';
+
+ if (\is_array($groups) && 0 < \count($groups)) {
+ $sql .= ' IN GROUP "' . \implode('", "', $groups) . '"';
+ }
+
+ if ('' !== $expiry) {
+ $sql .= \sprintf(
+ ' VALID UNTIL \'%s\'',
+ $expiry
+ );
+ } else {
+ $sql .= " VALID UNTIL 'infinity'";
+ }
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Adjusts a user's info and renames the user.
+ *
+ * @param string $username The username of the user to modify
+ * @param string $password A new password for the user
+ * @param bool $createdb boolean Whether or not the user can create databases
+ * @param bool $createuser boolean Whether or not the user can create other users
+ * @param string $expiry string Format 'YYYY-MM-DD HH:MM:SS'. '' means never expire.
+ * @param string $newname The new name of the user
+ *
+ * @return int
+ *
+ * @psalm-return -3|-2|-1|0|1
+ */
+ public function setRenameUser($username, $password, $createdb, $createuser, $expiry, $newname)
+ {
+ $status = $this->beginTransaction();
+
+ if (0 !== $status) {
+ return -1;
+ }
+
+ if ($username !== $newname) {
+ $status = $this->renameUser($username, $newname);
+
+ if (0 !== $status) {
+ $this->rollbackTransaction();
+
+ return -3;
+ }
+ $username = $newname;
+ }
+
+ $status = $this->setUser($username, $password, $createdb, $createuser, $expiry);
+
+ if (0 !== $status) {
+ $this->rollbackTransaction();
+
+ return -2;
+ }
+
+ return $this->endTransaction();
+ }
+
+ /**
+ * Renames a user.
+ *
+ * @param string $username The username of the user to rename
+ * @param string $newname The new name of the user
+ *
+ * @return int|string
+ */
+ public function renameUser($username, $newname)
+ {
+ $this->fieldClean($username);
+ $this->fieldClean($newname);
+
+ $sql = \sprintf(
+ 'ALTER USER "%s" RENAME TO "%s"',
+ $username,
+ $newname
+ );
+
+ return $this->execute($sql);
+ }
+
+ // Tablespace functions
+
+ /**
+ * Adjusts a user's info.
+ *
+ * @param string $username The username of the user to modify
+ * @param string $password A new password for the user
+ * @param bool $createdb boolean Whether or not the user can create databases
+ * @param bool $createuser boolean Whether or not the user can create other users
+ * @param string $expiry string Format 'YYYY-MM-DD HH:MM:SS'. '' means never expire.
+ *
+ * @return int|string
+ */
+ public function setUser($username, $password, $createdb, $createuser, $expiry)
+ {
+ $enc = $this->_encryptPassword($username, $password);
+ $this->fieldClean($username);
+ $this->clean($enc);
+ $this->clean($expiry);
+
+ $sql = \sprintf(
+ 'ALTER USER "%s"',
+ $username
+ );
+
+ if ('' !== $password) {
+ $sql .= \sprintf(
+ ' WITH ENCRYPTED PASSWORD \'%s\'',
+ $enc
+ );
+ }
+
+ $sql .= $createdb ? ' CREATEDB' : ' NOCREATEDB';
+ $sql .= $createuser ? ' CREATEUSER' : ' NOCREATEUSER';
+
+ if ('' !== $expiry) {
+ $sql .= \sprintf(
+ ' VALID UNTIL \'%s\'',
+ $expiry
+ );
+ } else {
+ $sql .= " VALID UNTIL 'infinity'";
+ }
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Removes a user.
+ *
+ * @param string $username The username of the user to drop
+ *
+ * @return int|string
+ */
+ public function dropUser($username)
+ {
+ $this->fieldClean($username);
+
+ $sql = \sprintf(
+ 'DROP USER "%s"',
+ $username
+ );
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Changes a role's password.
+ *
+ * @param string $rolename The role name
+ * @param string $password The new password
+ *
+ * @return int|string
+ */
+ public function changePassword($rolename, $password)
+ {
+ $enc = $this->_encryptPassword($rolename, $password);
+ $this->fieldClean($rolename);
+ $this->clean($enc);
+
+ $sql = \sprintf(
+ 'ALTER ROLE "%s" WITH ENCRYPTED PASSWORD \'%s\'',
+ $rolename,
+ $enc
+ );
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Adds a group member.
+ *
+ * @param string $groname The name of the group
+ * @param string $user The name of the user to add to the group
+ *
+ * @return int|string
+ */
+ public function addGroupMember($groname, $user)
+ {
+ $this->fieldClean($groname);
+ $this->fieldClean($user);
+
+ $sql = \sprintf(
+ 'ALTER GROUP "%s" ADD USER "%s"',
+ $groname,
+ $user
+ );
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Returns all role names which the role belongs to.
+ *
+ * @param string $rolename The role name
+ *
+ * @return \ADORecordSet|bool|int|string
+ */
+ public function getMemberOf($rolename)
+ {
+ $this->clean($rolename);
+
+ $sql = \sprintf(
+ '
+ SELECT rolname FROM pg_catalog.pg_roles R, pg_auth_members M
+ WHERE R.oid=M.roleid
+ AND member IN (
+ SELECT oid FROM pg_catalog.pg_roles
+ WHERE rolname=\'%s\')
+ ORDER BY rolname',
+ $rolename
+ );
+
+ return $this->selectSet($sql);
+ }
+
+ // Administration functions
+
+ /**
+ * Returns all role names that are members of a role.
+ *
+ * @param string $rolename The role name
+ * @param string $admin (optional) Find only admin members
+ *
+ * @return \ADORecordSet|bool|int|string
+ */
+ public function getMembers($rolename, $admin = 'f')
+ {
+ $this->clean($rolename);
+
+ $sql = \sprintf(
+ '
+ SELECT rolname FROM pg_catalog.pg_roles R, pg_auth_members M
+ WHERE R.oid=M.member AND admin_option=\'%s\'
+ AND roleid IN (SELECT oid FROM pg_catalog.pg_roles
+ WHERE rolname=\'%s\')
+ ORDER BY rolname',
+ $admin,
+ $rolename
+ );
+
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Removes a group member.
+ *
+ * @param string $groname The name of the group
+ * @param string $user The name of the user to remove from the group
+ *
+ * @return int|string
+ */
+ public function dropGroupMember($groname, $user)
+ {
+ $this->fieldClean($groname);
+ $this->fieldClean($user);
+
+ $sql = \sprintf(
+ 'ALTER GROUP "%s" DROP USER "%s"',
+ $groname,
+ $user
+ );
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Return users in a specific group.
+ *
+ * @param string $groname The name of the group
+ *
+ * @return \ADORecordSet|bool|int|string
+ */
+ public function getGroup($groname)
+ {
+ $this->clean($groname);
+
+ $sql = \sprintf(
+ '
+ SELECT s.usename FROM pg_catalog.pg_user s, pg_catalog.pg_group g
+ WHERE g.groname=\'%s\' AND s.usesysid = ANY (g.grolist)
+ ORDER BY s.usename',
+ $groname
+ );
+
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Returns all groups in the database cluser.
+ *
+ * @return \ADORecordSet|bool|int|string
+ */
+ public function getGroups()
+ {
+ $sql = 'SELECT groname FROM pg_group ORDER BY groname';
+
+ return $this->selectSet($sql);
+ }
+
+ /**
+ * Creates a new group.
+ *
+ * @param string $groname The name of the group
+ * @param array $users An array of users to add to the group
+ *
+ * @return int|string
+ */
+ public function createGroup($groname, $users)
+ {
+ $this->fieldClean($groname);
+
+ $sql = \sprintf(
+ 'CREATE GROUP "%s"',
+ $groname
+ );
+
+ if (\is_array($users) && 0 < \count($users)) {
+ $this->fieldArrayClean($users);
+ $sql .= ' WITH USER "' . \implode('", "', $users) . '"';
+ }
+
+ return $this->execute($sql);
+ }
+
+ /**
+ * Removes a group.
+ *
+ * @param string $groname The name of the group to drop
+ *
+ * @return int|string
+ */
+ public function dropGroup($groname)
+ {
+ $this->fieldClean($groname);
+
+ $sql = \sprintf(
+ 'DROP GROUP "%s"',
+ $groname
+ );
+
+ return $this->execute($sql);
+ }
+
+ abstract public function fieldClean(&$str);
+
+ abstract public function beginTransaction();
+
+ abstract public function rollbackTransaction();
+
+ abstract public function endTransaction();
+
+ abstract public function execute($sql);
+
+ abstract public function setComment($obj_type, $obj_name, $table, $comment, $basetype = null);
+
+ abstract public function selectSet($sql);
+
+ abstract public function clean(&$str);
+
+ abstract public function hasGrantOption();
+
+ abstract public function getFunction($function_oid);
+
+ abstract public function fieldArrayClean(&$arr);
+
+ /**
+ * @psalm-return -1|0
+ *
+ * @param mixed $original_parent_roles
+ * @param mixed $new_roles_to_add
+ * @param mixed $rolename
+ *
+ * @return int
+ */
+ private function _dealWithOldParentRoles($original_parent_roles, $new_roles_to_add, $rolename)
+ {
+ $old = \explode(',', $original_parent_roles);
+
+ // Grant the roles of the old role owners to the new owner
+ foreach ($new_roles_to_add as $m) {
+ if (!\in_array($m, $old, true)) {
+ $status = $this->grantRole($m, $rolename);
+
+ if (0 !== $status) {
+ return -1;
+ }
+ }
+ }
+
+ // Revoke the new role to the old members if they don't have the requested role name
+
+ foreach ($old as $o) {
+ if (!\in_array($o, $new_roles_to_add, true)) {
+ $status = $this->revokeRole($o, $rolename, 0, 'CASCADE');
+
+ if (0 !== $status) {
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * @psalm-return -1|0
+ *
+ * @param mixed $original_members
+ * @param mixed $new_members_of_role
+ * @param mixed $rolename
+ *
+ * @return int
+ */
+ private function _dealWithOriginalMembers($original_members, $new_members_of_role, $rolename)
+ {
+ //members
+ $old = \explode(',', $original_members);
+
+ foreach ($new_members_of_role as $m) {
+ if (!\in_array($m, $old, true)) {
+ $status = $this->grantRole($rolename, $m);
+
+ if (0 !== $status) {
+ return -1;
+ }
+ }
+ }
+
+ if ($original_members) {
+ foreach ($old as $o) {
+ if (!\in_array($o, $new_members_of_role, true)) {
+ $status = $this->revokeRole($rolename, $o, 0, 'CASCADE');
+
+ if (0 !== $status) {
+ return -1;
+ }
+ }
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * @psalm-return -1|0
+ *
+ * @param mixed $original_admins
+ * @param mixed $new_admins_of_role
+ * @param mixed $rolename
+ *
+ * @return int
+ */
+ private function _dealWithOriginalAdmins($original_admins, $new_admins_of_role, $rolename)
+ {
+ $old = \explode(',', $original_admins);
+
+ foreach ($new_admins_of_role as $m) {
+ if (!\in_array($m, $old, true)) {
+ $status = $this->grantRole($rolename, $m, 1);
+
+ if (0 !== $status) {
+ return -1;
+ }
+ }
+ }
+
+ foreach ($old as $o) {
+ if (!\in_array($o, $new_admins_of_role, true)) {
+ $status = $this->revokeRole($rolename, $o, 1, 'CASCADE');
+
+ if (0 !== $status) {
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * @param mixed $rolename
+ * @param mixed $password
+ * @param mixed $connlimit
+ * @param mixed $expiry
+ * @param mixed $superuser
+ * @param mixed $createdb
+ * @param mixed $createrole
+ * @param mixed $inherits
+ * @param mixed $login
+ *
+ * @return int|string
+ */
+ private function _alterRole($rolename, $password, $connlimit, $expiry, $superuser, $createdb, $createrole, $inherits, $login)
+ {
+ $enc = $this->_encryptPassword($rolename, $password);
+ $this->clean($enc);
+ $this->clean($connlimit);
+ $this->clean($expiry);
+
+ $sql = \sprintf(
+ 'ALTER ROLE "%s"',
+ $rolename
+ );
+
+ if ('' !== $password) {
+ $sql .= \sprintf(
+ ' WITH ENCRYPTED PASSWORD \'%s\'',
+ $enc
+ );
+ }
+
+ $sql .= $superuser ? ' SUPERUSER' : ' NOSUPERUSER';
+ $sql .= $createdb ? ' CREATEDB' : ' NOCREATEDB';
+ $sql .= $createrole ? ' CREATEROLE' : ' NOCREATEROLE';
+ $sql .= $inherits ? ' INHERIT' : ' NOINHERIT';
+ $sql .= $login ? ' LOGIN' : ' NOLOGIN';
+
+ if ('' !== $connlimit) {
+ $sql .= \sprintf(
+ ' CONNECTION LIMIT %s',
+ $connlimit
+ );
+ } else {
+ $sql .= ' CONNECTION LIMIT -1';
+ }
+
+ if ('' !== $expiry) {
+ $sql .= \sprintf(
+ ' VALID UNTIL \'%s\'',
+ $expiry
+ );
+ } else {
+ $sql .= " VALID UNTIL 'infinity'";
+ }
+
+ return $this->execute($sql);
+ }
+}