1
0
mirror of synced 2026-10-23 07:08:55 +03:00

Add new options like INHERIT and SET to the Role's membership tab. #6451

This commit is contained in:
Anil Sahoo
2026-01-20 11:53:32 +05:30
committed by GitHub
parent 93605c0baa
commit 0cac007970
45 changed files with 1237 additions and 147 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 70 KiB

View File

@@ -65,15 +65,26 @@ Use the *Privileges* tab to grant privileges to the role.
* Move the *Bypass RLS?* switch to the *Yes* position to control whether a
role can bypasses every row-level security (RLS) policy. The default value is *No*.
Click the *Membership* tab to continue.
.. image:: images/role_membership.png
:alt: Role dialog membership tab
:align: center
* Specify member of the role in the *Member of* field and specify the members in the *Member* field.
Confirm each selection by checking the checkbox to the right of the role name;
delete a selection by clicking the *x* to the left of the role name.
Membership conveys the privileges granted to the specified role to each of
its members.
Use the *Membership* tab to define role memberships. A role can be a member of
other roles and can have other roles as members.
* Use *Member of* section to specify roles of which the current role
is a member. To assign *Admin Option* for a selected role, click on
the appropriate checkbox.
* Use *Members* section to specify roles that are members of the current
role. To assign *Admin Option* for a selected role, click on the appropriate checkbox.
Click the *Add* icon (+) to add more roles; to discard a
role, click the trash icon to the left of the row and confirm the deletion
in the *Delete Row* popup.
**Note:** Apart from *Admin Option*, *Inherit Option* and *Set Option* are available for both *Member of* section and *Members* section from PostgreSQL version >= 16.
Click the *Parameters* tab to continue.

View File

@@ -207,40 +207,32 @@ class RoleView(PGChildNodeView):
:param id: id of role
:param data: input role data
"""
def _part_dict_list(dict_list, condition, list_key=None):
def _part_dict_list(dict_list, condition):
ret_val = []
for d in dict_list:
if condition(d):
ret_val.append(d[list_key])
ret_val.append(d)
return ret_val
if id == -1:
data['members'] = []
data['admins'] = []
data['admins'] = _part_dict_list(
data['rolmembership'], lambda d: d['admin'], 'role')
data['members'] = _part_dict_list(
data['rolmembership'], lambda d: not d['admin'], 'role')
data['rolmembership_list'] = data['rolmembership']
else:
data['admins'] = _part_dict_list(
data['rolmembership'].get('added', []),
lambda d: d['admin'], 'role')
data['members'] = _part_dict_list(
data['rolmembership'].get('added', []),
lambda d: not d['admin'], 'role')
data['rolmembership_list'] = data['rolmembership'].get('added', [])
data['admins'].extend(_part_dict_list(
data['rolmembership'].get('changed', []),
lambda d: d['admin'], 'role'))
data['revoked_admins'] = _part_dict_list(
data['rolmembership'].get('changed', []),
lambda d: not d['admin'], 'role')
if self.manager.version < 160000:
data['rolmembership_list'].extend(_part_dict_list(
data['rolmembership'].get('changed', []),
lambda d: d['admin']))
data['rolmembership_revoked_admins'] = _part_dict_list(
data['rolmembership'].get('changed', []),
lambda d: not d['admin'])
else:
data['rolmembership_list'].extend(
data['rolmembership'].get('changed', []))
data['revoked'] = _part_dict_list(
data['rolmembership'].get('deleted', []),
lambda _: True, 'role')
data['rolmembership_revoked_list'] = (
data['rolmembership'].get('deleted', []))
def _process_rolmembers(self, id, data):
"""
@@ -248,39 +240,32 @@ class RoleView(PGChildNodeView):
:param id:
:param data:
"""
def _part_dict_list(dict_list, condition, list_key=None):
def _part_dict_list(dict_list, condition):
ret_val = []
for d in dict_list:
if condition(d):
ret_val.append(d[list_key])
ret_val.append(d)
return ret_val
if id == -1:
data['rol_members'] = []
data['rol_admins'] = []
data['rol_members_list'] = data['rolmembers']
data['rol_admins'] = _part_dict_list(
data['rolmembers'], lambda d: d['admin'], 'role')
data['rol_members'] = _part_dict_list(
data['rolmembers'], lambda d: not d['admin'], 'role')
else:
data['rol_admins'] = _part_dict_list(
data['rolmembers'].get('added', []),
lambda d: d['admin'], 'role')
data['rol_members'] = _part_dict_list(
data['rolmembers'].get('added', []),
lambda d: not d['admin'], 'role')
data['rol_members_list'] = data['rolmembers'].get('added', [])
data['rol_admins'].extend(_part_dict_list(
data['rolmembers'].get('changed', []),
lambda d: d['admin'], 'role'))
data['rol_revoked_admins'] = _part_dict_list(
data['rolmembers'].get('changed', []),
lambda d: not d['admin'], 'role')
if self.manager.version < 160000:
data['rol_members_list'].extend(_part_dict_list(
data['rolmembers'].get('changed', []),
lambda d: d['admin']))
data['rol_members_revoked_admins'] = _part_dict_list(
data['rolmembers'].get('changed', []),
lambda d: not d['admin'])
else:
data['rol_members_list'].extend(
data['rolmembers'].get('changed', []))
data['rol_revoked'] = _part_dict_list(
data['rolmembers'].get('deleted', []),
lambda _: True, 'role')
data['rol_members_revoked_list'] = (
data['rolmembers'].get('deleted', []))
def _validate_rolemembers(self, id, data):
"""
@@ -298,13 +283,21 @@ following format:
rolmembers:[{
role: [rolename],
admin: True/False
admin: True/False,
inherit: True/False,
set: True/False,
},
...
]""")
if not self._validate_input_dict_for_new(data['rolmembers'],
['role', 'admin']):
if (self.manager.version < 160000 and
not self._validate_input_dict_for_new(
data['rolmembers'], ['role', 'admin'])):
return msg
elif (self.manager.version >= 160000 and
not self._validate_input_dict_for_new(
data['rolmembers'],
['role', 'admin', 'inherit', 'set'])):
return msg
self._process_rolmembers(id, data)
@@ -316,26 +309,38 @@ JSON objects in the following format:
rolmembers:{
'added': [{
role: [rolename],
admin: True/False
admin: True/False,
inherit: True/False,
set: True/False,
},
...
],
'deleted': [{
role: [rolename],
admin: True/False
admin: True/False,
inherit: True/False,
set: True/False,
},
...
],
'updated': [{
role: [rolename],
admin: True/False
admin: True/False,
inherit: True/False,
set: True/False,
},
...
]
""")
if not self._validate_input_dict_for_update(data['rolmembers'],
['role', 'admin'],
['role']):
if (self.manager.version < 160000 and
not self._validate_input_dict_for_update(
data['rolmembers'], ['role', 'admin'], ['role'])):
return msg
elif (self.manager.version >= 160000 and
not self._validate_input_dict_for_update(
data['rolmembers'],
['role', 'admin', 'inherit', 'set'],
['role'])):
return msg
self._process_rolmembers(id, data)
@@ -357,13 +362,21 @@ following format:
rolmembership:[{
role: [rolename],
admin: True/False
admin: True/False,
inherit: True/False,
set: True/False,
},
...
]""")
if not self._validate_input_dict_for_new(
data['rolmembership'], ['role', 'admin']):
if (self.manager.version < 160000 and
not self._validate_input_dict_for_new(
data['rolmembership'], ['role', 'admin'])):
return msg
elif (self.manager.version >= 160000 and
not self._validate_input_dict_for_new(
data['rolmembership'],
['role', 'admin', 'inherit', 'set'])):
return msg
self._process_rolemembership(id, data)
@@ -375,25 +388,38 @@ JSON objects in the following format:
rolmembership:{
'added': [{
role: [rolename],
admin: True/False
admin: True/False,
inherit: True/False,
set: True/False,
},
...
],
'deleted': [{
role: [rolename],
admin: True/False
admin: True/False,
inherit: True/False,
set: True/False,
},
...
],
'updated': [{
role: [rolename],
admin: True/False
admin: True/False,
inherit: True/False,
set: True/False,
},
...
]
""")
if not self._validate_input_dict_for_update(
data['rolmembership'], ['role', 'admin'], ['role']):
if (self.manager.version < 160000 and
not self._validate_input_dict_for_update(
data['rolmembership'], ['role', 'admin'], ['role'])):
return msg
elif (self.manager.version >= 160000 and
not self._validate_input_dict_for_update(
data['rolmembership'],
['role', 'admin', 'inherit', 'set'],
['role'])):
return msg
self._process_rolemembership(id, data)
@@ -792,16 +818,29 @@ rolmembership:{
})
row['seclabels'] = res
def _set_rolemembership(self, row):
def _set_rolemembers(self, row):
if 'rolmembers' in row and row['rolmembers'] is not None:
rolmembers = []
for role in row['rolmembers']:
role = re.search(r'([01])(.+)', role)
rolmembers.append({
'role': role.group(2),
'admin': True if role.group(1) == '1' else False
})
if self.manager.version < 160000:
m = re.match(r'^([01])(.+)$', role or '')
if not m:
continue
rolmembers.append({
'role': m.group(2),
'admin': m.group(1) == '1'
})
else:
m = re.match(r'^([01])([01])([01])(.+)$', role or '')
if not m:
continue
rolmembers.append({
'role': m.group(4),
'admin': m.group(1) == '1',
'inherit': m.group(2) == '1',
'set': m.group(3) == '1'
})
row['rolmembers'] = rolmembers
def transform(self, rset):
@@ -810,14 +849,27 @@ rolmembership:{
roles = row['rolmembership']
row['rolpassword'] = ''
for role in roles:
role = re.search(r'([01])(.+)', role)
res.append({
'role': role.group(2),
'admin': True if role.group(1) == '1' else False
})
if self.manager.version < 160000:
m = re.match(r'^([01])(.+)$', role or '')
if not m:
continue
res.append({
'role': m.group(2),
'admin': m.group(1) == '1'
})
else:
m = re.match(r'^([01])([01])([01])(.+)$', role or '')
if not m:
continue
res.append({
'role': m.group(4),
'admin': m.group(1) == '1',
'inherit': m.group(2) == '1',
'set': m.group(3) == '1'
})
row['rolmembership'] = res
self._set_seclabels(row)
self._set_rolemembership(row)
self._set_rolemembers(row)
@check_precondition(action='properties')
def properties(self, gid, sid, rid):

View File

@@ -58,12 +58,20 @@ export default class RoleSchema extends BaseUISchema {
memberDataFormatter(rawData) {
let members = '';
if(_.isObject(rawData)) {
const serverVersion = this.nodeInfo?.server?.version || 0;
rawData.forEach(member => {
let withAdmin = '';
if(member.admin) { withAdmin = ' [WITH ADMIN]';}
let badges = '';
if (serverVersion >= 160000) {
const admin = (member.admin ?? false).toString().toUpperCase();
const inherit = (member.inherit ?? false).toString().toUpperCase();
const set = (member.set ?? true).toString().toUpperCase();
badges = ` [WITH ADMIN ${admin}, INHERIT ${inherit}, SET ${set}]`;
} else {
badges = member.admin ? ' [WITH ADMIN OPTION]' : '';
}
if (members.length > 0) { members += ', '; }
members = members + (member.role + withAdmin);
members = members + (member.role + badges);
});
}
return members;
@@ -177,7 +185,7 @@ export default class RoleSchema extends BaseUISchema {
type: 'text',
controlProps: {
formatter: {
fromRaw: obj.memberDataFormatter,
fromRaw: (raw) => obj.memberDataFormatter(raw),
},
}
},
@@ -198,7 +206,7 @@ export default class RoleSchema extends BaseUISchema {
type: 'text',
controlProps: {
formatter: {
fromRaw: obj.memberDataFormatter,
fromRaw: (raw) => obj.memberDataFormatter(raw),
},
}
},

View File

@@ -0,0 +1,68 @@
{% import 'macros/security.macros' as SECLABEL %}
{% import 'macros/variable.macros' as VARIABLE %}
CREATE ROLE {{ conn|qtIdent(data.rolname) }} WITH{% if data.rolcanlogin and data.rolcanlogin is sameas True %}
LOGIN{% else %}
NOLOGIN{% endif %}{% if data.rolsuper %}
SUPERUSER{% else %}
NOSUPERUSER{% endif %}{% if data.rolcreatedb %}
CREATEDB{% else %}
NOCREATEDB{% endif %}{% if data.rolcreaterole %}
CREATEROLE{% else %}
NOCREATEROLE{% endif %}{% if data.rolinherit is sameas true %}
INHERIT{% else %}
NOINHERIT{% endif %}{% if data.rolreplication %}
REPLICATION{% else %}
NOREPLICATION{% endif %}{% if data.rolbypassrls %}
BYPASSRLS{% else %}
NOBYPASSRLS{% endif %}{% if 'rolconnlimit' in data and data.rolconnlimit is number and data.rolconnlimit >= -1 %}
CONNECTION LIMIT {{ data.rolconnlimit }}{% endif %}{% if data.rolvaliduntil and data.rolvaliduntil is not none %}
VALID UNTIL {{ data.rolvaliduntil|qtLiteral(conn) }} {% endif %}{% if data.rolpassword %}
PASSWORD {% if data.rolpassword is none %}NULL{% else %}{% if dummy %}'xxxxxx'{% else %} {{ data.rolpassword|qtLiteral(conn) }}{% endif %}{% endif %}{% endif %};
{% if data.rolmembership_list and data.rolmembership_list|length > 0 %}
{% for item in data.rolmembership_list %}
{% set admin_opt = item.admin|default(false) %}
{% set inherit_opt = item.inherit|default(false) %}
{% set set_opt = item.set|default(true) %}
GRANT {{ conn|qtIdent(item.role) }} TO {{ conn|qtIdent(data.rolname) }}{% if 'admin' in item or 'inherit' in item or 'set' in item %} WITH ADMIN {{ admin_opt }}, INHERIT {{ inherit_opt }}, SET {{ set_opt }}{% endif %};
{% endfor %}
{% endif %}
{% if data.seclabels and data.seclabels|length > 0 %}
{% for r in data.seclabels %}
{{ SECLABEL.APPLY(conn, 'ROLE', data.rolname, r.provider, r.label) }}
{% endfor %}{% endif %}{% if data.variables %}
{% for var in data.variables %}
{{ VARIABLE.APPLY(conn, var.database, data.rolname, var.name, var.value) }}
{% endfor %}{% endif %}{% if data.description %}
COMMENT ON ROLE {{ conn|qtIdent(data.rolname) }} IS {{ data.description|qtLiteral(conn) }};
{% endif %}
{% if data.rol_members_list and data.rol_members_list|length > 0 %}
{% for item in data.rol_members_list %}
{% set admin_opt = item.admin|default(false) %}
{% set inherit_opt = item.inherit|default(false) %}
{% set set_opt = item.set|default(true) %}
GRANT {{ conn|qtIdent(data.rolname) }} TO {{ conn|qtIdent(item.role) }}{% if 'admin' in item or 'inherit' in item or 'set' in item %} WITH ADMIN {{ admin_opt }}, INHERIT {{ inherit_opt }}, SET {{ set_opt }}{% endif %};
{% endfor %}
{% endif %}

View File

@@ -0,0 +1,40 @@
SELECT
r.oid, r.*,
pg_catalog.shobj_description(r.oid, 'pg_authid') AS description,
ARRAY(
SELECT
CASE WHEN am.admin_option THEN '1' ELSE '0' END
|| CASE WHEN am.inherit_option THEN '1' ELSE '0' END
|| CASE WHEN am.set_option THEN '1' ELSE '0' END
|| rm.rolname
FROM
(SELECT * FROM pg_catalog.pg_auth_members WHERE member = r.oid) am
LEFT JOIN pg_catalog.pg_roles rm ON (rm.oid = am.roleid)
ORDER BY rm.rolname
) AS rolmembership,
(SELECT pg_catalog.array_agg(provider || '=' || label) FROM pg_catalog.pg_shseclabel sl1 WHERE sl1.objoid=r.oid) AS seclabels
{% if rid %}
,ARRAY(
SELECT
CASE WHEN pg.admin_option THEN '1' ELSE '0' END
|| CASE WHEN pg.inherit_option THEN '1' ELSE '0' END
|| CASE WHEN pg.set_option THEN '1' ELSE '0' END
|| pg.usename
FROM
(SELECT pg_roles.rolname AS usename,
pg_auth_members.admin_option AS admin_option,
pg_auth_members.inherit_option AS inherit_option,
pg_auth_members.set_option AS set_option
FROM pg_catalog.pg_roles
JOIN pg_catalog.pg_auth_members
ON pg_roles.oid = pg_auth_members.member
AND pg_auth_members.roleid = {{ rid|qtLiteral(conn) }}::oid) pg
ORDER BY pg.usename
) rolmembers
{% endif %}
FROM
pg_catalog.pg_roles r
{% if rid %}
WHERE r.oid = {{ rid|qtLiteral(conn) }}::oid
{% endif %}
ORDER BY r.rolcanlogin, r.rolname

View File

@@ -0,0 +1,130 @@
SELECT
pg_catalog.array_to_string(array_agg(sql), E'\n\n') AS sql
FROM
(SELECT
'-- Role: ' ||
pg_catalog.quote_ident(rolname) ||
E'\n-- DROP ROLE IF EXISTS ' ||
pg_catalog.quote_ident(rolname) || E';\n\nCREATE ROLE ' ||
pg_catalog.quote_ident(rolname) || E' WITH\n ' ||
CASE WHEN rolcanlogin THEN 'LOGIN' ELSE 'NOLOGIN' END || E'\n ' ||
CASE WHEN rolsuper THEN 'SUPERUSER' ELSE 'NOSUPERUSER' END || E'\n ' ||
CASE WHEN rolinherit THEN 'INHERIT' ELSE 'NOINHERIT' END || E'\n ' ||
CASE WHEN rolcreatedb THEN 'CREATEDB' ELSE 'NOCREATEDB' END || E'\n ' ||
CASE WHEN rolcreaterole THEN 'CREATEROLE' ELSE 'NOCREATEROLE' END || E'\n ' ||
-- PostgreSQL >= 9.1
CASE WHEN rolreplication THEN 'REPLICATION' ELSE 'NOREPLICATION' END || E'\n ' ||
CASE WHEN rolbypassrls THEN 'BYPASSRLS' ELSE 'NOBYPASSRLS' END ||
CASE WHEN rolconnlimit != -1 THEN E'\n CONNECTION LIMIT ' || rolconnlimit ELSE '' END ||
{% if show_password %}
(SELECT CASE
WHEN (rolpassword LIKE 'md5%%' or rolpassword LIKE 'SCRAM%%') THEN E'\n ENCRYPTED PASSWORD ''' || rolpassword || ''''
WHEN rolpassword IS NOT NULL THEN E'\n PASSWORD ''' || rolpassword || ''''
ELSE '' END FROM pg_catalog.pg_authid au WHERE au.oid=r.oid) ||
{% endif %}
CASE WHEN rolvaliduntil IS NOT NULL THEN E'\n VALID UNTIL ' || pg_catalog.quote_literal(rolvaliduntil::text) ELSE '' END || ';' AS sql
FROM
pg_catalog.pg_roles r
WHERE
r.oid=%(rid)s::OID
UNION ALL
(SELECT
pg_catalog.array_to_string(array_agg(sql), E'\n') AS sql
FROM
(SELECT
'GRANT ' || pg_catalog.array_to_string(pg_catalog.array_agg(rolname ORDER BY rolname), ', ') || ' TO ' || pg_catalog.quote_ident(pg_catalog.pg_get_userbyid(%(rid)s::OID)) ||
CASE WHEN admin_option OR inherit_option OR set_option THEN
' WITH ' ||
(CASE WHEN admin_option THEN 'ADMIN OPTION' ELSE '' END ||
CASE WHEN inherit_option THEN (CASE WHEN admin_option THEN ', ' ELSE '' END) || 'INHERIT OPTION' ELSE '' END ||
CASE WHEN set_option THEN (CASE WHEN admin_option OR inherit_option THEN ', ' ELSE '' END) || 'SET OPTION' ELSE '' END)
ELSE '' END || ';' AS sql
FROM
(SELECT
pg_catalog.quote_ident(r.rolname) AS rolname,
m.admin_option AS admin_option,
m.inherit_option AS inherit_option,
m.set_option AS set_option
FROM
pg_catalog.pg_auth_members m
LEFT JOIN pg_catalog.pg_roles r ON (m.roleid = r.oid)
WHERE
m.member=%(rid)s::OID
ORDER BY
r.rolname
) a
GROUP BY admin_option, inherit_option, set_option) s)
UNION ALL
(SELECT
pg_catalog.array_to_string(array_agg(sql), E'\n') AS sql
FROM
(SELECT
'ALTER ROLE ' || pg_catalog.quote_ident(rolname) || ' SET ' || param || ' TO ' || CASE WHEN param IN ('search_path', 'temp_tablespaces') THEN value ELSE pg_catalog.quote_literal(value) END || ';' AS sql
FROM
(SELECT
rolcanlogin, rolname, pg_catalog.split_part(rolconfig, '=', 1) AS param, pg_catalog.replace(rolconfig, pg_catalog.split_part(rolconfig, '=', 1) || '=', '') AS value
FROM
(SELECT
pg_catalog.unnest(rolconfig) AS rolconfig, rolcanlogin, rolname
FROM
pg_catalog.pg_roles
WHERE
oid=%(rid)s::OID
) r
) a) b)
-- PostgreSQL >= 9.0
UNION ALL
(SELECT
pg_catalog.array_to_string(array_agg(sql), E'\n') AS sql
FROM
(SELECT
'ALTER ROLE ' || pg_catalog.quote_ident(pg_get_userbyid(%(rid)s::OID)) ||
' IN DATABASE ' || pg_catalog.quote_ident(datname) ||
' SET ' || param|| ' TO ' ||
CASE
WHEN param IN ('search_path', 'temp_tablespaces') THEN value
ELSE pg_catalog.quote_literal(value)
END || ';' AS sql
FROM
(SELECT
datname, pg_catalog.split_part(rolconfig, '=', 1) AS param, pg_catalog.replace(rolconfig, pg_catalog.split_part(rolconfig, '=', 1) || '=', '') AS value
FROM
(SELECT
d.datname, pg_catalog.unnest(c.setconfig) AS rolconfig
FROM
(SELECT *
FROM
pg_catalog.pg_db_role_setting dr
WHERE
dr.setrole=%(rid)s::OID AND dr.setdatabase!=0) c
LEFT JOIN pg_catalog.pg_database d ON (d.oid = c.setdatabase)
) a
) b
) d
)
UNION ALL
(SELECT
'COMMENT ON ROLE ' || pg_catalog.quote_ident(pg_get_userbyid(%(rid)s::OID)) || ' IS ' || pg_catalog.quote_literal(description) || ';' AS sql
FROM
(SELECT pg_catalog.shobj_description(%(rid)s::OID, 'pg_authid') AS description) a
WHERE
description IS NOT NULL)
-- PostgreSQL >= 9.2
UNION ALL
(SELECT
pg_catalog.array_to_string(array_agg(sql), E'\n') AS sql
FROM
(SELECT
'SECURITY LABEL FOR ' || provider ||
E'\n ON ROLE ' || pg_catalog.quote_ident(rolname) ||
E'\n IS ' || pg_catalog.quote_literal(label) || ';' AS sql
FROM
(SELECT
label, provider, rolname
FROM
(SELECT *
FROM
pg_catalog.pg_shseclabel sl1
WHERE sl1.objoid=%(rid)s::OID) s
LEFT JOIN pg_catalog.pg_roles r ON (s.objoid=r.oid)) a) b
)) AS a

View File

@@ -0,0 +1,119 @@
{% import 'macros/security.macros' as SECLABEL %}
{% import 'macros/variable.macros' as VARIABLE %}
{% if 'rolname' in data %}
{% set rolname=data.rolname %}
ALTER ROLE {{ conn|qtIdent(role) }}
RENAME TO {{ conn|qtIdent(rolname) }};
{% else %}
{% set rolname=role %}
{% endif %}
{% if data|hasAny(alterKeys) %}
ALTER ROLE {{ conn|qtIdent(rolname) }}{% if 'rolcanlogin' in data %}
{% if data.rolcanlogin %}
LOGIN{% else %}
NOLOGIN{% endif %}{% endif %}{% if 'rolsuper' in data %}
{% if data.rolsuper %}
SUPERUSER{% else %}
NOSUPERUSER{% endif %}{% endif %}{% if 'rolcreatedb' in data %}
{% if data.rolcreatedb %}
CREATEDB{% else %}
NOCREATEDB{% endif %}{% endif %}{% if 'rolcreaterole' in data %}
{% if data.rolcreaterole %}
CREATEROLE{% else %}
NOCREATEROLE{% endif %}{% endif %}{% if 'rolinherit' in data %}
{% if data.rolinherit %}
INHERIT{% else %}
NOINHERIT{% endif %}{% endif %}{% if 'rolreplication' in data %}
{% if data.rolreplication %}
REPLICATION{% else %}
NOREPLICATION{% endif %}{% endif %}{% if 'rolbypassrls' in data %}
{% if data.rolbypassrls %}
BYPASSRLS{% else %}
NOBYPASSRLS{% endif %}{% endif %}{% if 'rolconnlimit' in data and data.rolconnlimit is number and data.rolconnlimit >= -1 %}
CONNECTION LIMIT {{ data.rolconnlimit }}
{% endif %}{% if 'rolvaliduntil' in data %}
VALID UNTIL {% if data.rolvaliduntil and data.rolvaliduntil is not none %}{{ data.rolvaliduntil|qtLiteral(conn) }}{% else %}'infinity'
{% endif %}{% endif %}{% if 'rolpassword' in data %}
PASSWORD{% if data.rolpassword is none %} NULL{% else %}{% if dummy %} 'xxxxxx'{% else %} {{ data.rolpassword|qtLiteral(conn) }}{% endif %}{% endif %}{% endif %};{% endif %}
{% if data.rolmembership_revoked_list and data.rolmembership_revoked_list|length > 0 %}
{% for item in data.rolmembership_revoked_list %}
REVOKE {{ conn|qtIdent(item.role) }} FROM {{ conn|qtIdent(rolname) }};
{% endfor %}
{% endif %}
{% if data.rolmembership_list and data.rolmembership_list|length > 0 %}
{% for item in data.rolmembership_list %}
GRANT {{ conn|qtIdent(item.role) }} TO {{ conn|qtIdent(rolname) }}{% if 'admin' in item or 'inherit' in item or 'set' in item %} WITH ADMIN {{ item.admin }}, INHERIT {{ item.inherit }}, SET {{ item.set }}{% endif %};
{% endfor %}
{% endif %}
{% if data.seclabels and
data.seclabels|length > 0
%}{% set seclabels = data.seclabels %}
{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
{% for r in seclabels.deleted %}
{{ SECLABEL.DROP(conn, 'ROLE', rolname, r.provider) }}
{% endfor %}
{% endif %}
{% if 'added' in seclabels and seclabels.added|length > 0 %}
{% for r in seclabels.added %}
{{ SECLABEL.APPLY(conn, 'ROLE', rolname, r.provider, r.label) }}
{% endfor %}
{% endif %}
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
{% for r in seclabels.changed %}
{{ SECLABEL.APPLY(conn, 'ROLE', rolname, r.provider, r.label) }}
{% endfor %}
{% endif %}
{% endif %}
{% if 'variables' in data and data.variables|length > 0 %}
{% set variables = data.variables %}
{% if 'deleted' in variables and variables.deleted|length > 0 %}
{% for var in variables.deleted %}
{{ VARIABLE.RESET(conn, var.database, rolname, var.name) }}
{% endfor %}{% endif %}
{% if 'added' in variables and variables.added|length > 0 %}
{% for var in variables.added %}
{{ VARIABLE.APPLY(conn, var.database, rolname, var.name, var.value) }}
{% endfor %}{% endif %}
{% if 'changed' in variables and variables.changed|length > 0 %}
{% for var in variables.changed %}
{{ VARIABLE.APPLY(conn, var.database, rolname, var.name, var.value) }}
{% endfor %}
{% endif %}
{% endif %}
{% if 'description' in data %}
COMMENT ON ROLE {{ conn|qtIdent(rolname) }} IS {{ data.description|qtLiteral(conn) }};
{% endif %}
{% if data.rol_members_revoked_list and data.rol_members_revoked_list|length > 0 %}
{% for item in data.rol_members_revoked_list %}
REVOKE {{ conn|qtIdent(rolname) }} FROM {{ conn|qtIdent(item.role) }};
{% endfor %}
{% endif %}
{% if data.rol_members_list and data.rol_members_list|length > 0 %}
{% for item in data.rol_members_list %}
GRANT {{ conn|qtIdent(rolname) }} TO {{ conn|qtIdent(item.role) }} {% if 'admin' in item or 'inherit' in item or 'set' in item %} WITH ADMIN {{ item.admin }}, INHERIT {{ item.inherit }}, SET {{ item.set }}{% endif %};
{% endfor %}
{% endif %}

View File

@@ -34,13 +34,14 @@ CREATE ROLE {{ conn|qtIdent(data.rolname) }} WITH{% if data.rolcanlogin and data
VALID UNTIL {{ data.rolvaliduntil|qtLiteral(conn) }} {% endif %}{% if data.rolpassword %}
PASSWORD {% if data.rolpassword is none %}NULL{% else %}{% if dummy %}'xxxxxx'{% else %} {{ data.rolpassword|qtLiteral(conn) }}{% endif %}{% endif %}{% endif %};{% if data.members and data.members|length > 0 %}
GRANT {{ conn|qtIdent(data.members)|join(', ') }} TO {{ conn|qtIdent(data.rolname) }};{% endif %}{% if data.admins and data.admins|length > 0 %}
GRANT {{ conn|qtIdent(data.admins)|join(', ') }} TO {{ conn|qtIdent(data.rolname) }} WITH ADMIN OPTION;{% endif %}{% if data.seclabels and data.seclabels|length > 0 %}
PASSWORD {% if data.rolpassword is none %}NULL{% else %}{% if dummy %}'xxxxxx'{% else %} {{ data.rolpassword|qtLiteral(conn) }}{% endif %}{% endif %}{% endif %};
{% if data.rolmembership_list and data.rolmembership_list|length > 0 %}
{% for item in data.rolmembership_list %}
GRANT {{ conn|qtIdent(item.role) }} TO {{ conn|qtIdent(data.rolname) }}{% if 'admin' in item and item.admin %} WITH ADMIN OPTION{% endif %};
{% endfor %}
{% endif %}
{% if data.seclabels and data.seclabels|length > 0 %}
{% for r in data.seclabels %}
{{ SECLABEL.APPLY(conn, 'ROLE', data.rolname, r.provider, r.label) }}
@@ -53,10 +54,9 @@ GRANT {{ conn|qtIdent(data.admins)|join(', ') }} TO {{ conn|qtIdent(data.rolname
COMMENT ON ROLE {{ conn|qtIdent(data.rolname) }} IS {{ data.description|qtLiteral(conn) }};
{% endif %}
{% if data.rol_members_list and data.rol_members_list|length > 0 %}
{% for item in data.rol_members_list %}
{% if data.rol_admins and data.rol_admins|length > 0 %}
GRANT {{ conn|qtIdent(data.rolname) }} TO {{ conn|qtIdent(data.rol_admins)|join(', ') }} WITH ADMIN OPTION;{% endif %}{% if data.rol_members and data.rol_members|length > 0 %}
GRANT {{ conn|qtIdent(data.rolname) }} TO {{ conn|qtIdent(data.rol_members)|join(', ') }};
GRANT {{ conn|qtIdent(data.rolname) }} TO {{ conn|qtIdent(item.role) }}{% if 'admin' in item and item.admin %} WITH ADMIN OPTION{% endif %};
{% endfor %}
{% endif %}

View File

@@ -15,7 +15,7 @@ FROM
-- PostgreSQL >= 9.1
CASE WHEN rolreplication THEN 'REPLICATION' ELSE 'NOREPLICATION' END || E'\n ' ||
CASE WHEN rolbypassrls THEN 'BYPASSRLS' ELSE 'NOBYPASSRLS' END ||
CASE WHEN rolconnlimit > 0 THEN E'\n CONNECTION LIMIT ' || rolconnlimit ELSE '' END ||
CASE WHEN rolconnlimit != -1 THEN E'\n CONNECTION LIMIT ' || rolconnlimit ELSE '' END ||
{% if show_password %}
(SELECT CASE
WHEN (rolpassword LIKE 'md5%%' or rolpassword LIKE 'SCRAM%%') THEN E'\n ENCRYPTED PASSWORD ''' || rolpassword || ''''

View File

@@ -42,22 +42,32 @@ ALTER ROLE {{ conn|qtIdent(rolname) }}{% if 'rolcanlogin' in data %}
CONNECTION LIMIT {{ data.rolconnlimit }}
{% endif %}{% if 'rolvaliduntil' in data %}
VALID UNTIL {% if data.rolvaliduntil %}{{ data.rolvaliduntil|qtLiteral(conn) }}{% else %}'infinity'
VALID UNTIL {% if data.rolvaliduntil and data.rolvaliduntil is not none %}{{ data.rolvaliduntil|qtLiteral(conn) }}{% else %}'infinity'
{% endif %}{% endif %}{% if 'rolpassword' in data %}
PASSWORD{% if data.rolpassword is none %} NULL{% else %}{% if dummy %} 'xxxxxx'{% else %} {{ data.rolpassword|qtLiteral(conn) }}{% endif %}{% endif %}{% endif %};{% endif %}
{% if 'revoked_admins' in data and
data.revoked_admins|length > 0
%}
{% if data.rolmembership_revoked_list and data.rolmembership_revoked_list|length > 0 %}
{% for item in data.rolmembership_revoked_list %}
REVOKE ADMIN OPTION FOR {{ conn|qtIdent(data.revoked_admins)|join(', ') }} FROM {{ conn|qtIdent(rolname) }};{% endif %}{% if 'revoked' in data and data.revoked|length > 0 %}
REVOKE {{ conn|qtIdent(item.role) }} FROM {{ conn|qtIdent(rolname) }};
{% endfor %}
{% endif %}
{% if data.rolmembership_list and data.rolmembership_list|length > 0 %}
{% for item in data.rolmembership_list %}
REVOKE {{ conn|qtIdent(data.revoked)|join(', ') }} FROM {{ conn|qtIdent(rolname) }};{% endif %}{% if data.admins and data.admins|length > 0 %}
GRANT {{ conn|qtIdent(item.role) }} TO {{ conn|qtIdent(rolname) }}{% if 'admin' in item and item.admin %} WITH ADMIN OPTION{% endif %};
{% endfor %}
{% endif %}
{% if data.rolmembership_revoked_admins and data.rolmembership_revoked_admins|length > 0 %}
{% for item in data.rolmembership_revoked_admins %}
{% if 'admin' in item and not item.admin %}
GRANT {{ conn|qtIdent(data.admins)|join(', ') }} TO {{ conn|qtIdent(rolname) }} WITH ADMIN OPTION;{% endif %}{% if data.members and data.members|length > 0 %}
GRANT {{ conn|qtIdent(data.members)|join(', ') }} TO {{ conn|qtIdent(rolname) }};{% endif %}{% if data.seclabels and
REVOKE ADMIN OPTION FOR {{ conn|qtIdent(item.role) }} FROM {{ conn|qtIdent(rolname) }};
{% endif %}
{% endfor %}
{% endif %}
{% if data.seclabels and
data.seclabels|length > 0
%}{% set seclabels = data.seclabels %}
{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
@@ -103,15 +113,23 @@ GRANT {{ conn|qtIdent(data.members)|join(', ') }} TO {{ conn|qtIdent(rolname) }}
COMMENT ON ROLE {{ conn|qtIdent(rolname) }} IS {{ data.description|qtLiteral(conn) }};
{% endif %}
{% if data.rol_members_revoked_list and data.rol_members_revoked_list|length > 0 %}
{% for item in data.rol_members_revoked_list %}
{% if 'rol_revoked_admins' in data and
data.rol_revoked_admins|length > 0
%}
REVOKE {{ conn|qtIdent(rolname) }} FROM {{ conn|qtIdent(item.role) }};
{% endfor %}
{% endif %}
{% if data.rol_members_list and data.rol_members_list|length > 0 %}
{% for item in data.rol_members_list %}
REVOKE ADMIN OPTION FOR {{ conn|qtIdent(rolname) }} FROM {{ conn|qtIdent(data.rol_revoked_admins)|join(', ') }};{% endif %}{% if 'rol_revoked' in data and data.rol_revoked|length > 0 %}
GRANT {{ conn|qtIdent(rolname) }} TO {{ conn|qtIdent(item.role) }}{% if 'admin' in item and item.admin %} WITH ADMIN OPTION{% endif %};
{% endfor %}
{% endif %}
{% if data.rol_members_revoked_admins and data.rol_members_revoked_admins|length > 0 %}
{% for item in data.rol_members_revoked_admins %}
{% if 'admin' in item and not item.admin %}
REVOKE {{ conn|qtIdent(rolname) }} FROM {{ conn|qtIdent(data.rol_revoked)|join(', ') }};{% endif %}{% if data.rol_admins and data.rol_admins|length > 0 %}
GRANT {{ conn|qtIdent(rolname) }} TO {{ conn|qtIdent(data.rol_admins)|join(', ') }} WITH ADMIN OPTION;{% endif %}{% if data.rol_members and data.rol_members|length > 0 %}
GRANT {{ conn|qtIdent(rolname) }} TO {{ conn|qtIdent(data.rol_members)|join(', ') }};{% endif %}
REVOKE ADMIN OPTION FOR {{ conn|qtIdent(rolname) }} FROM {{ conn|qtIdent(item.role) }};
{% endif %}
{% endfor %}
{% endif %}

View File

@@ -0,0 +1 @@
COMMENT ON ROLE "Role1_$%{}[]()&*^!@""'`\/#" IS 'This is detailed description';

View File

@@ -0,0 +1,13 @@
-- Role: "Role1_$%{}[]()&*^!@""'`\/#"
-- DROP ROLE IF EXISTS "Role1_$%{}[]()&*^!@""'`\/#";
CREATE ROLE "Role1_$%{}[]()&*^!@""'`\/#" WITH
LOGIN
SUPERUSER
INHERIT
CREATEDB
CREATEROLE
REPLICATION
BYPASSRLS;
COMMENT ON ROLE "Role1_$%{}[]()&*^!@""'`\/#" IS 'This is detailed description';

View File

@@ -0,0 +1,2 @@
ALTER ROLE "Role1_$%{}[]()&*^!@""'`\/#"
RENAME TO "Role2_$%{}[]()&*^!@""'`\/#";

View File

@@ -0,0 +1,13 @@
-- Role: "Role2_$%{}[]()&*^!@""'`\/#"
-- DROP ROLE IF EXISTS "Role2_$%{}[]()&*^!@""'`\/#";
CREATE ROLE "Role2_$%{}[]()&*^!@""'`\/#" WITH
LOGIN
SUPERUSER
INHERIT
CREATEDB
CREATEROLE
REPLICATION
BYPASSRLS;
COMMENT ON ROLE "Role2_$%{}[]()&*^!@""'`\/#" IS 'This is detailed description';

View File

@@ -0,0 +1,12 @@
ALTER ROLE "Role2_$%{}[]()&*^!@""'`\/#"
NOSUPERUSER
NOCREATEDB
NOREPLICATION
NOBYPASSRLS
CONNECTION LIMIT 100
VALID UNTIL '2050-01-01T00:00:00+05:30'
PASSWORD 'xxxxxx';
ALTER ROLE "Role2_$%{}[]()&*^!@""'`\/#" IN DATABASE postgres
SET application_name TO 'pg4';

View File

@@ -0,0 +1,18 @@
-- Role: "Role2_$%{}[]()&*^!@""'`\/#"
-- DROP ROLE IF EXISTS "Role2_$%{}[]()&*^!@""'`\/#";
CREATE ROLE "Role2_$%{}[]()&*^!@""'`\/#" WITH
LOGIN
NOSUPERUSER
INHERIT
NOCREATEDB
CREATEROLE
NOREPLICATION
NOBYPASSRLS
CONNECTION LIMIT 100
ENCRYPTED PASSWORD '<PASSWORD>'
VALID UNTIL '<TIMESTAMPTZ_1>';
ALTER ROLE "Role2_$%{}[]()&*^!@""'`\/#" IN DATABASE postgres SET application_name TO 'pg4';
COMMENT ON ROLE "Role2_$%{}[]()&*^!@""'`\/#" IS 'This is detailed description';

View File

@@ -0,0 +1 @@
COMMENT ON ROLE "Role1_$%{}[]()&*^!@""'`\/#" IS 'This is detailed description';

View File

@@ -0,0 +1,13 @@
-- Role: "Role1_$%{}[]()&*^!@""'`\/#"
-- DROP ROLE IF EXISTS "Role1_$%{}[]()&*^!@""'`\/#";
CREATE ROLE "Role1_$%{}[]()&*^!@""'`\/#" WITH
NOLOGIN
NOSUPERUSER
INHERIT
NOCREATEDB
NOCREATEROLE
NOREPLICATION
NOBYPASSRLS;
COMMENT ON ROLE "Role1_$%{}[]()&*^!@""'`\/#" IS 'This is detailed description';

View File

@@ -0,0 +1,2 @@
ALTER ROLE "Role1_$%{}[]()&*^!@""'`\/#"
RENAME TO "Role2_$%{}[]()&*^!@""'`\/#";

View File

@@ -0,0 +1,13 @@
-- Role: "Role2_$%{}[]()&*^!@""'`\/#"
-- DROP ROLE IF EXISTS "Role2_$%{}[]()&*^!@""'`\/#";
CREATE ROLE "Role2_$%{}[]()&*^!@""'`\/#" WITH
NOLOGIN
NOSUPERUSER
INHERIT
NOCREATEDB
NOCREATEROLE
NOREPLICATION
NOBYPASSRLS;
COMMENT ON ROLE "Role2_$%{}[]()&*^!@""'`\/#" IS 'This is detailed description';

View File

@@ -0,0 +1,19 @@
ALTER ROLE "Role2_$%{}[]()&*^!@""'`\/#"
SUPERUSER
CREATEDB
NOREPLICATION
CONNECTION LIMIT 100
VALID UNTIL '2050-01-01T00:00:00+05:30'
PASSWORD 'xxxxxx';
GRANT test_rolemembership_1 TO "Role2_$%{}[]()&*^!@""'`\/#" WITH ADMIN True, INHERIT True, SET True;
GRANT test_rolemembership_2 TO "Role2_$%{}[]()&*^!@""'`\/#" WITH ADMIN False, INHERIT False, SET False;
ALTER ROLE "Role2_$%{}[]()&*^!@""'`\/#" IN DATABASE postgres
SET application_name TO 'pg4';
GRANT "Role2_$%{}[]()&*^!@""'`\/#" TO test_rolemembership_3 WITH ADMIN True, INHERIT True, SET True;
GRANT "Role2_$%{}[]()&*^!@""'`\/#" TO test_rolemembership_4 WITH ADMIN False, INHERIT False, SET False;

View File

@@ -0,0 +1,21 @@
-- Role: "Role2_$%{}[]()&*^!@""'`\/#"
-- DROP ROLE IF EXISTS "Role2_$%{}[]()&*^!@""'`\/#";
CREATE ROLE "Role2_$%{}[]()&*^!@""'`\/#" WITH
NOLOGIN
SUPERUSER
INHERIT
CREATEDB
NOCREATEROLE
NOREPLICATION
NOBYPASSRLS
CONNECTION LIMIT 100
ENCRYPTED PASSWORD '<PASSWORD>'
VALID UNTIL '<TIMESTAMPTZ_1>';
GRANT test_rolemembership_2 TO "Role2_$%{}[]()&*^!@""'`\/#";
GRANT test_rolemembership_1 TO "Role2_$%{}[]()&*^!@""'`\/#" WITH ADMIN OPTION, INHERIT OPTION, SET OPTION;
ALTER ROLE "Role2_$%{}[]()&*^!@""'`\/#" IN DATABASE postgres SET application_name TO 'pg4';
COMMENT ON ROLE "Role2_$%{}[]()&*^!@""'`\/#" IS 'This is detailed description';

View File

@@ -0,0 +1,7 @@
GRANT test_rolemembership_1 TO "Role2_$%{}[]()&*^!@""'`\/#" WITH ADMIN False, INHERIT False, SET False;
GRANT test_rolemembership_2 TO "Role2_$%{}[]()&*^!@""'`\/#" WITH ADMIN True, INHERIT True, SET True;
GRANT "Role2_$%{}[]()&*^!@""'`\/#" TO test_rolemembership_3 WITH ADMIN False, INHERIT False, SET False;
GRANT "Role2_$%{}[]()&*^!@""'`\/#" TO test_rolemembership_4 WITH ADMIN True, INHERIT True, SET True;

View File

@@ -0,0 +1,21 @@
-- Role: "Role2_$%{}[]()&*^!@""'`\/#"
-- DROP ROLE IF EXISTS "Role2_$%{}[]()&*^!@""'`\/#";
CREATE ROLE "Role2_$%{}[]()&*^!@""'`\/#" WITH
NOLOGIN
SUPERUSER
INHERIT
CREATEDB
NOCREATEROLE
NOREPLICATION
NOBYPASSRLS
CONNECTION LIMIT 100
ENCRYPTED PASSWORD '<PASSWORD>'
VALID UNTIL '2050-01-01 00:00:00+05:30';
GRANT test_rolemembership_1 TO "Role2_$%{}[]()&*^!@""'`\/#";
GRANT test_rolemembership_2 TO "Role2_$%{}[]()&*^!@""'`\/#" WITH ADMIN OPTION, INHERIT OPTION, SET OPTION;
ALTER ROLE "Role2_$%{}[]()&*^!@""'`\/#" IN DATABASE postgres SET application_name TO 'pg4';
COMMENT ON ROLE "Role2_$%{}[]()&*^!@""'`\/#" IS 'This is detailed description';

View File

@@ -0,0 +1,3 @@
REVOKE test_rolemembership_1 FROM "Role2_$%{}[]()&*^!@""'`\/#";
REVOKE "Role2_$%{}[]()&*^!@""'`\/#" FROM test_rolemembership_3;

View File

@@ -0,0 +1,20 @@
-- Role: "Role2_$%{}[]()&*^!@""'`\/#"
-- DROP ROLE IF EXISTS "Role2_$%{}[]()&*^!@""'`\/#";
CREATE ROLE "Role2_$%{}[]()&*^!@""'`\/#" WITH
NOLOGIN
SUPERUSER
INHERIT
CREATEDB
NOCREATEROLE
NOREPLICATION
NOBYPASSRLS
CONNECTION LIMIT 100
ENCRYPTED PASSWORD '<PASSWORD>'
VALID UNTIL '2050-01-01 00:00:00+05:30';
GRANT test_rolemembership_2 TO "Role2_$%{}[]()&*^!@""'`\/#" WITH ADMIN OPTION, INHERIT OPTION, SET OPTION;
ALTER ROLE "Role2_$%{}[]()&*^!@""'`\/#" IN DATABASE postgres SET application_name TO 'pg4';
COMMENT ON ROLE "Role2_$%{}[]()&*^!@""'`\/#" IS 'This is detailed description';

View File

@@ -0,0 +1,7 @@
GRANT test_rolemembership_1 TO "Role2_$%{}[]()&*^!@""'`\/#" WITH ADMIN True, INHERIT True, SET True;
GRANT test_rolemembership_2 TO "Role2_$%{}[]()&*^!@""'`\/#" WITH ADMIN False, INHERIT False, SET False;
GRANT "Role2_$%{}[]()&*^!@""'`\/#" TO test_rolemembership_3 WITH ADMIN True, INHERIT True, SET True;
GRANT "Role2_$%{}[]()&*^!@""'`\/#" TO test_rolemembership_4 WITH ADMIN False, INHERIT False, SET False;

View File

@@ -0,0 +1,21 @@
-- Role: "Role2_$%{}[]()&*^!@""'`\/#"
-- DROP ROLE IF EXISTS "Role2_$%{}[]()&*^!@""'`\/#";
CREATE ROLE "Role2_$%{}[]()&*^!@""'`\/#" WITH
NOLOGIN
SUPERUSER
INHERIT
CREATEDB
NOCREATEROLE
NOREPLICATION
NOBYPASSRLS
CONNECTION LIMIT 100
ENCRYPTED PASSWORD '<PASSWORD>'
VALID UNTIL '2050-01-01 00:00:00+05:30';
GRANT test_rolemembership_2 TO "Role2_$%{}[]()&*^!@""'`\/#";
GRANT test_rolemembership_1 TO "Role2_$%{}[]()&*^!@""'`\/#" WITH ADMIN OPTION, INHERIT OPTION, SET OPTION;
ALTER ROLE "Role2_$%{}[]()&*^!@""'`\/#" IN DATABASE postgres SET application_name TO 'pg4';
COMMENT ON ROLE "Role2_$%{}[]()&*^!@""'`\/#" IS 'This is detailed description';

View File

@@ -0,0 +1,9 @@
CREATE ROLE "Role1_$%{}[]()&*^!@""'`\/#" WITH
LOGIN
SUPERUSER
CREATEDB
CREATEROLE
INHERIT
REPLICATION
BYPASSRLS
CONNECTION LIMIT -1;

View File

@@ -0,0 +1,11 @@
-- Role: "Role1_$%{}[]()&*^!@""'`\/#"
-- DROP ROLE IF EXISTS "Role1_$%{}[]()&*^!@""'`\/#";
CREATE ROLE "Role1_$%{}[]()&*^!@""'`\/#" WITH
LOGIN
SUPERUSER
INHERIT
CREATEDB
CREATEROLE
REPLICATION
BYPASSRLS;

View File

@@ -0,0 +1,9 @@
CREATE ROLE "Role1_$%{}[]()&*^!@""'`\/#" WITH
NOLOGIN
NOSUPERUSER
NOCREATEDB
NOCREATEROLE
INHERIT
NOREPLICATION
NOBYPASSRLS
CONNECTION LIMIT -1;

View File

@@ -0,0 +1,11 @@
-- Role: "Role1_$%{}[]()&*^!@""'`\/#"
-- DROP ROLE IF EXISTS "Role1_$%{}[]()&*^!@""'`\/#";
CREATE ROLE "Role1_$%{}[]()&*^!@""'`\/#" WITH
NOLOGIN
NOSUPERUSER
INHERIT
NOCREATEDB
NOCREATEROLE
NOREPLICATION
NOBYPASSRLS;

View File

@@ -0,0 +1,299 @@
{
"scenarios": [
{
"type": "create",
"name": "Create Role 1 for testing rolemembership",
"endpoint": "NODE-role.obj",
"sql_endpoint": "NODE-role.sql_id",
"data": {
"rolname": "test_rolemembership_1",
"rolcanlogin": false,
"rolpassword": null,
"rolconnlimit": -1,
"rolsuper": false,
"rolcreaterole": false,
"rolcreatedb": false,
"rolinherit": true,
"rolreplication": false,
"rolmembership": [],
"seclabels": [],
"variables": []
},
"store_object_id": true
},
{
"type": "create",
"name": "Create Role 2 for testing rolemembership",
"endpoint": "NODE-role.obj",
"sql_endpoint": "NODE-role.sql_id",
"data": {
"rolname": "test_rolemembership_2",
"rolcanlogin": false,
"rolpassword": null,
"rolconnlimit": -1,
"rolsuper": false,
"rolcreaterole": false,
"rolcreatedb": false,
"rolinherit": true,
"rolreplication": false,
"rolmembership": [],
"seclabels": [],
"variables": []
},
"store_object_id": true
},
{
"type": "create",
"name": "Create Role 3 for testing rolemembership",
"endpoint": "NODE-role.obj",
"sql_endpoint": "NODE-role.sql_id",
"data": {
"rolname": "test_rolemembership_3",
"rolcanlogin": false,
"rolpassword": null,
"rolconnlimit": -1,
"rolsuper": false,
"rolcreaterole": false,
"rolcreatedb": false,
"rolinherit": true,
"rolreplication": false,
"rolmembership": [],
"seclabels": [],
"variables": []
},
"store_object_id": true
},
{
"type": "create",
"name": "Create Role 4 for testing rolemembership",
"endpoint": "NODE-role.obj",
"sql_endpoint": "NODE-role.sql_id",
"data": {
"rolname": "test_rolemembership_4",
"rolcanlogin": false,
"rolpassword": null,
"rolconnlimit": -1,
"rolsuper": false,
"rolcreaterole": false,
"rolcreatedb": false,
"rolinherit": true,
"rolreplication": false,
"rolmembership": [],
"seclabels": [],
"variables": []
},
"store_object_id": true
},
{
"type": "create",
"name": "Create Role",
"endpoint": "NODE-role.obj",
"sql_endpoint": "NODE-role.sql_id",
"msql_endpoint": "NODE-role.msql",
"data": {
"rolname": "Role1_$%{}[]()&*^!@\"'`\\/#",
"rolcanlogin": false,
"rolpassword": null,
"rolconnlimit": -1,
"rolsuper": false,
"rolcreaterole": false,
"rolcreatedb": false,
"rolinherit": true,
"rolreplication": false,
"rolmembership": [],
"seclabels": [],
"variables": []
},
"expected_sql_file": "create_role.sql",
"expected_msql_file": "create_role.msql"
},
{
"type": "alter",
"name": "Alter Role description",
"endpoint": "NODE-role.obj_id",
"sql_endpoint": "NODE-role.sql_id",
"msql_endpoint": "NODE-role.msql_id",
"data": {
"description": "This is detailed description"
},
"expected_sql_file": "alter_role_description.sql",
"expected_msql_file": "alter_role_description.msql"
},
{
"type": "alter",
"name": "Alter Role name",
"endpoint": "NODE-role.obj_id",
"sql_endpoint": "NODE-role.sql_id",
"msql_endpoint": "NODE-role.msql_id",
"data": {
"rolname": "Role2_$%{}[]()&*^!@\"'`\\/#"
},
"expected_sql_file": "alter_role_name.sql",
"expected_msql_file": "alter_role_name.msql"
},
{
"type": "alter",
"name": "Alter Role options 1",
"endpoint": "NODE-role.obj_id",
"sql_endpoint": "NODE-role.sql_id",
"msql_endpoint": "NODE-role.msql_id",
"data": {
"rolsuper": true,
"rolcreatedb": true,
"rolreplication": false,
"rolpassword": "abc123",
"rolconnlimit": 100,
"rolvaliduntil": "2050-01-01 00:00:00 +05:30",
"variables": { "added": [{"name":"application_name","value":"pg4","database":"postgres"}] },
"rolmembership": { "added": [{"role": "test_rolemembership_1", "admin": true, "inherit": true, "set": true}, {"role": "test_rolemembership_2", "admin": false, "inherit": false, "set": false}] },
"rolmembers": { "added": [{"role": "test_rolemembership_3", "admin": true, "inherit": true, "set": true}, {"role": "test_rolemembership_4", "admin": false, "inherit": false, "set": false}] }
},
"expected_sql_file": "alter_role_options1.sql",
"expected_msql_file": "alter_role_options1.msql",
"convert_timestamp_columns": ["rolvaliduntil"],
"replace_password": true
},
{
"type": "alter",
"name": "Alter Role options 2",
"endpoint": "NODE-role.obj_id",
"sql_endpoint": "NODE-role.sql_id",
"msql_endpoint": "NODE-role.msql_id",
"data": {
"rolmembership": { "changed": [{"role": "test_rolemembership_1", "admin": false, "inherit": false, "set": false}, {"role": "test_rolemembership_2", "admin": true, "inherit": true, "set": true}] },
"rolmembers": { "changed": [{"role": "test_rolemembership_3", "admin": false, "inherit": false, "set": false}, {"role": "test_rolemembership_4", "admin": true, "inherit": true, "set": true}] }
},
"expected_sql_file": "alter_role_options2.sql",
"expected_msql_file": "alter_role_options2.msql",
"convert_timestamp_columns": ["rolvaliduntil"],
"replace_password": true,
"replace_regex_pattern": ["VALID UNTIL '[0-9\\-T:+ ]*'"]
},
{
"type": "alter",
"name": "Alter Role options 3",
"endpoint": "NODE-role.obj_id",
"sql_endpoint": "NODE-role.sql_id",
"msql_endpoint": "NODE-role.msql_id",
"data": {
"rolmembership": { "deleted": [{"role": "test_rolemembership_1"}] },
"rolmembers": { "deleted": [{"role": "test_rolemembership_3"}] }
},
"expected_sql_file": "alter_role_options3.sql",
"expected_msql_file": "alter_role_options3.msql",
"convert_timestamp_columns": ["rolvaliduntil"],
"replace_password": true,
"replace_regex_pattern": ["VALID UNTIL '[0-9\\-T:+ ]*'"]
},
{
"type": "alter",
"name": "Alter Role options 4",
"endpoint": "NODE-role.obj_id",
"sql_endpoint": "NODE-role.sql_id",
"msql_endpoint": "NODE-role.msql_id",
"data": {
"rolmembership": {
"added": [{"role": "test_rolemembership_1", "admin": true, "inherit": true, "set": true}],
"changed": [{"role": "test_rolemembership_2", "admin": false, "inherit": false, "set": false}]
},
"rolmembers": {
"added": [{"role": "test_rolemembership_3", "admin": true, "inherit": true, "set": true}],
"changed": [{"role": "test_rolemembership_4", "admin": false, "inherit": false, "set": false}]
}
},
"expected_sql_file": "alter_role_options4.sql",
"expected_msql_file": "alter_role_options4.msql",
"convert_timestamp_columns": ["rolvaliduntil"],
"replace_password": true,
"replace_regex_pattern": ["VALID UNTIL '[0-9\\-T:+ ]*'"]
},
{
"type": "delete",
"name": "Drop Role",
"endpoint": "NODE-role.obj_id",
"data": {}
},
{
"type": "delete",
"name": "Drop Role",
"endpoint": "NODE-role.obj",
"data": {"ids": ["<test_rolemembership_1>", "<test_rolemembership_2>", "<test_rolemembership_3>", "<test_rolemembership_4>"]},
"preprocess_data": true
},
{
"type": "create",
"name": "Create Login Role",
"endpoint": "NODE-role.obj",
"sql_endpoint": "NODE-role.sql_id",
"msql_endpoint": "NODE-role.msql",
"data": {
"rolname": "Role1_$%{}[]()&*^!@\"'`\\/#",
"rolcanlogin": true,
"rolpassword": null,
"rolconnlimit": -1,
"rolsuper": true,
"rolcreaterole": true,
"rolcreatedb": true,
"rolinherit": true,
"rolreplication": true,
"rolbypassrls": true,
"rolmembership": [],
"seclabels": [],
"variables": []
},
"expected_sql_file": "create_login_role.sql",
"expected_msql_file": "create_login_role.msql"
},
{
"type": "alter",
"name": "Alter Login Role description",
"endpoint": "NODE-role.obj_id",
"sql_endpoint": "NODE-role.sql_id",
"msql_endpoint": "NODE-role.msql_id",
"data": {
"description": "This is detailed description"
},
"expected_sql_file": "alter_login_role_description.sql",
"expected_msql_file": "alter_login_role_description.msql"
},
{
"type": "alter",
"name": "Alter Login Role name",
"endpoint": "NODE-role.obj_id",
"sql_endpoint": "NODE-role.sql_id",
"msql_endpoint": "NODE-role.msql_id",
"data": {
"rolname": "Role2_$%{}[]()&*^!@\"'`\\/#"
},
"expected_sql_file": "alter_login_role_name.sql",
"expected_msql_file": "alter_login_role_name.msql"
},
{
"type": "alter",
"name": "Alter Login Role options",
"endpoint": "NODE-role.obj_id",
"sql_endpoint": "NODE-role.sql_id",
"msql_endpoint": "NODE-role.msql_id",
"data": {
"rolsuper": false,
"rolcreatedb": false,
"rolreplication": false,
"rolbypassrls": false,
"rolpassword": "abc123",
"rolconnlimit": 100,
"rolvaliduntil": "2050-01-01 00:00:00 +05:30",
"variables": { "added": [{"name":"application_name","value":"pg4","database":"postgres"}] }
},
"expected_sql_file": "alter_login_role_options.sql",
"expected_msql_file": "alter_login_role_options.msql",
"convert_timestamp_columns": ["rolvaliduntil"],
"replace_password": true
},
{
"type": "delete",
"name": "Drop Login Role",
"endpoint": "NODE-role.obj_id",
"data": {}
}
]
}

View File

@@ -8,6 +8,12 @@ ALTER ROLE "Role2_$%{}[]()&*^!@""'`\/#"
PASSWORD 'xxxxxx';
GRANT test_rolemembership_1 TO "Role2_$%{}[]()&*^!@""'`\/#" WITH ADMIN OPTION;
GRANT test_rolemembership_2 TO "Role2_$%{}[]()&*^!@""'`\/#";
ALTER ROLE "Role2_$%{}[]()&*^!@""'`\/#" IN DATABASE postgres
SET application_name TO 'pg4';
GRANT "Role2_$%{}[]()&*^!@""'`\/#" TO test_rolemembership_3 WITH ADMIN OPTION;
GRANT "Role2_$%{}[]()&*^!@""'`\/#" TO test_rolemembership_4;

View File

@@ -1,2 +1,7 @@
REVOKE ADMIN OPTION FOR test_rolemembership_1 FROM "Role2_$%{}[]()&*^!@""'`\/#";
GRANT test_rolemembership_2 TO "Role2_$%{}[]()&*^!@""'`\/#" WITH ADMIN OPTION;
REVOKE ADMIN OPTION FOR test_rolemembership_1 FROM "Role2_$%{}[]()&*^!@""'`\/#";
GRANT "Role2_$%{}[]()&*^!@""'`\/#" TO test_rolemembership_4 WITH ADMIN OPTION;
REVOKE ADMIN OPTION FOR "Role2_$%{}[]()&*^!@""'`\/#" FROM test_rolemembership_3;

View File

@@ -1 +1,3 @@
REVOKE test_rolemembership_1 FROM "Role2_$%{}[]()&*^!@""'`\/#";
REVOKE "Role2_$%{}[]()&*^!@""'`\/#" FROM test_rolemembership_3;

View File

@@ -1 +1,7 @@
GRANT test_rolemembership_1, test_rolemembership_2 TO "Role2_$%{}[]()&*^!@""'`\/#" WITH ADMIN OPTION;
GRANT test_rolemembership_1 TO "Role2_$%{}[]()&*^!@""'`\/#" WITH ADMIN OPTION;
REVOKE ADMIN OPTION FOR test_rolemembership_2 FROM "Role2_$%{}[]()&*^!@""'`\/#";
GRANT "Role2_$%{}[]()&*^!@""'`\/#" TO test_rolemembership_3 WITH ADMIN OPTION;
REVOKE ADMIN OPTION FOR "Role2_$%{}[]()&*^!@""'`\/#" FROM test_rolemembership_4;

View File

@@ -13,7 +13,8 @@ CREATE ROLE "Role2_$%{}[]()&*^!@""'`\/#" WITH
ENCRYPTED PASSWORD '<PASSWORD>'
VALID UNTIL '2050-01-01 00:00:00+05:30';
GRANT test_rolemembership_1, test_rolemembership_2 TO "Role2_$%{}[]()&*^!@""'`\/#" WITH ADMIN OPTION;
GRANT test_rolemembership_2 TO "Role2_$%{}[]()&*^!@""'`\/#";
GRANT test_rolemembership_1 TO "Role2_$%{}[]()&*^!@""'`\/#" WITH ADMIN OPTION;
ALTER ROLE "Role2_$%{}[]()&*^!@""'`\/#" IN DATABASE postgres SET application_name TO 'pg4';

View File

@@ -42,6 +42,48 @@
},
"store_object_id": true
},
{
"type": "create",
"name": "Create Role 3 for testing rolemembership",
"endpoint": "NODE-role.obj",
"sql_endpoint": "NODE-role.sql_id",
"data": {
"rolname": "test_rolemembership_3",
"rolcanlogin": false,
"rolpassword": null,
"rolconnlimit": -1,
"rolsuper": false,
"rolcreaterole": false,
"rolcreatedb": false,
"rolinherit": true,
"rolreplication": false,
"rolmembership": [],
"seclabels": [],
"variables": []
},
"store_object_id": true
},
{
"type": "create",
"name": "Create Role 4 for testing rolemembership",
"endpoint": "NODE-role.obj",
"sql_endpoint": "NODE-role.sql_id",
"data": {
"rolname": "test_rolemembership_4",
"rolcanlogin": false,
"rolpassword": null,
"rolconnlimit": -1,
"rolsuper": false,
"rolcreaterole": false,
"rolcreatedb": false,
"rolinherit": true,
"rolreplication": false,
"rolmembership": [],
"seclabels": [],
"variables": []
},
"store_object_id": true
},
{
"type": "create",
"name": "Create Role",
@@ -103,7 +145,8 @@
"rolconnlimit": 100,
"rolvaliduntil": "2050-01-01 00:00:00 +05:30",
"variables": { "added": [{"name":"application_name","value":"pg4","database":"postgres"}] },
"rolmembership": { "added": [{"role": "test_rolemembership_1", "admin": true}, {"role": "test_rolemembership_2", "admin": false}] }
"rolmembership": { "added": [{"role": "test_rolemembership_1", "admin": true}, {"role": "test_rolemembership_2", "admin": false}] },
"rolmembers": { "added": [{"role": "test_rolemembership_3", "admin": true}, {"role": "test_rolemembership_4", "admin": false}] }
},
"expected_sql_file": "alter_role_options1.sql",
"expected_msql_file": "alter_role_options1.msql",
@@ -117,7 +160,8 @@
"sql_endpoint": "NODE-role.sql_id",
"msql_endpoint": "NODE-role.msql_id",
"data": {
"rolmembership": { "changed": [{"role": "test_rolemembership_1", "admin": false}, {"role": "test_rolemembership_2", "admin": true}] }
"rolmembership": { "changed": [{"role": "test_rolemembership_1", "admin": false}, {"role": "test_rolemembership_2", "admin": true}] },
"rolmembers": { "changed": [{"role": "test_rolemembership_3", "admin": false}, {"role": "test_rolemembership_4", "admin": true}] }
},
"expected_sql_file": "alter_role_options2.sql",
"expected_msql_file": "alter_role_options2.msql",
@@ -132,7 +176,8 @@
"sql_endpoint": "NODE-role.sql_id",
"msql_endpoint": "NODE-role.msql_id",
"data": {
"rolmembership": { "deleted": [{"role": "test_rolemembership_1"}] }
"rolmembership": { "deleted": [{"role": "test_rolemembership_1"}] },
"rolmembers": { "deleted": [{"role": "test_rolemembership_3"}] }
},
"expected_sql_file": "alter_role_options3.sql",
"expected_msql_file": "alter_role_options3.msql",
@@ -149,7 +194,11 @@
"data": {
"rolmembership": {
"added": [{"role": "test_rolemembership_1", "admin": true}],
"changed": [{"role": "test_rolemembership_2", "admin": true}]
"changed": [{"role": "test_rolemembership_2", "admin": false}]
},
"rolmembers": {
"added": [{"role": "test_rolemembership_3", "admin": true}],
"changed": [{"role": "test_rolemembership_4", "admin": false}]
}
},
"expected_sql_file": "alter_role_options4.sql",
@@ -168,7 +217,7 @@
"type": "delete",
"name": "Drop Role",
"endpoint": "NODE-role.obj",
"data": {"ids": ["<test_rolemembership_1>", "<test_rolemembership_2>"]},
"data": {"ids": ["<test_rolemembership_1>", "<test_rolemembership_2>", "<test_rolemembership_3>", "<test_rolemembership_4>"]},
"preprocess_data": true
},
{

View File

@@ -15,15 +15,18 @@ import { getNodeListByName } from '../../../../static/js/node_ajax';
export function getMembershipSchema(nodeObj, treeNodeInfo, itemNodeData) {
return new MembershipSchema(
()=>getNodeListByName('role', treeNodeInfo, itemNodeData, {}, ()=>true),
treeNodeInfo.server
);
}
export default class MembershipSchema extends BaseUISchema {
constructor(roleMembersOptions) {
constructor(roleMembersOptions, node_info={}) {
super({
role: undefined,
admin: undefined
admin: (node_info) && node_info.version >= 160000 ? false : undefined,
inherit: undefined,
set: (node_info) && node_info.version >= 160000 ? true : undefined,
});
this.roleMembersOptions = roleMembersOptions;
}
@@ -43,18 +46,38 @@ export default class MembershipSchema extends BaseUISchema {
return !obj.isNew(state);
},
noEmpty: true,
minWidth: 300
width: 150
},
{
id: 'admin', label: gettext('WITH ADMIN'),
cell: 'checkbox', type: 'checkbox',
minWidth: 300,
minWidth: 100,
deps: ['role'],
depChange: (state) => {
if(_.isUndefined(state.admin)) {
state.admin = false;
}
}
},{
id: 'inherit', label: gettext('WITH INHERIT'),
cell: 'checkbox', type: 'checkbox',
minWidth: 100, min_version: 160000,
deps: ['role'],
depChange: (state) => {
if(_.isUndefined(state.inherit)) {
state.inherit = false;
}
}
},{
id: 'set', label: gettext('WITH SET'),
cell: 'checkbox', type: 'checkbox',
minWidth: 100, min_version: 160000,
deps: ['role'],
depChange: (state) => {
if(_.isUndefined(state.set)) {
state.set = true;
}
}
},
];
}

View File

@@ -8,7 +8,7 @@
//////////////////////////////////////////////////////////////
import { isModeSupportedByField } from 'sources/SchemaView/common';
import { isModeSupportedByField, isFieldSupportedByPgVersion } from 'sources/SchemaView/common';
import { getMappedCell } from '../mappedCell';
@@ -49,7 +49,7 @@ export function createGridColumns({schema, field, viewHelperProps}) {
);
columnVisibility[field.id] = isModeSupportedByField(
field, viewHelperProps
);
) && isFieldSupportedByPgVersion(field, viewHelperProps);
return {
header: field.label||<>&nbsp;</>,

View File

@@ -16,6 +16,22 @@ export const isModeSupportedByField = (field, helperProps) => (
!field.mode || field.mode.indexOf(helperProps.mode) > -1
);
export const isFieldSupportedByPgVersion = (field, helperProps) => {
return (
// serverInfo not found
_.isUndefined(helperProps.serverInfo) ||
// serverInfo found and it's within range
(
_.isUndefined(field.server_type) ? true :
(helperProps.serverInfo.type in field.server_type)
) && (
_.isUndefined(field.min_version) ? true :
(helperProps.serverInfo.version >= field.min_version)
) && (
_.isUndefined(field.max_version) ? true :
(helperProps.serverInfo.version <= field.max_version)
));
};
/*
* Compare the sessData with schema.origData.

View File

@@ -15,6 +15,10 @@ import {
evalInNonPropertyMode,
FIELD_OPTIONS
} from './common';
import {
isFieldSupportedByPgVersion,
isModeSupportedByField
} from '../common';
import {
evaluateFieldOptions,
evaluateFieldsOption,
@@ -45,23 +49,9 @@ registerOptionEvaluator(
VISIBLE,
// Evaluator
({schema, field, value, viewHelperProps}) => (
(
!field.mode || field.mode.indexOf(viewHelperProps.mode) > -1
) && (
// serverInfo not found
_.isUndefined(viewHelperProps.serverInfo) ||
// serverInfo found and it's within range
((
_.isUndefined(field.server_type) ? true :
(viewHelperProps.serverInfo.type in field.server_type)
) && (
_.isUndefined(field.min_version) ? true :
(viewHelperProps.serverInfo.version >= field.min_version)
) && (
_.isUndefined(field.max_version) ? true :
(viewHelperProps.serverInfo.version <= field.max_version)
))
) && (
isModeSupportedByField(field, viewHelperProps)
&& isFieldSupportedByPgVersion(field, viewHelperProps)
&& (
_.isUndefined(field[VISIBLE]) ? true :
Boolean(evalFunc(schema, field[VISIBLE], value))
)),