Skip to content

Commit e2bf606

Browse files
committed
Add new options like INHERIT and SET to the Role's membership tab. #6451
1 parent e0ba1dd commit e2bf606

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1204
-132
lines changed
14.4 KB
Loading

docs/en_US/images/role_sql.png

3.86 KB
Loading

docs/en_US/role_dialog.rst

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,26 @@ Use the *Privileges* tab to grant privileges to the role.
6565
* Move the *Bypass RLS?* switch to the *Yes* position to control whether a
6666
role can bypasses every row-level security (RLS) policy. The default value is *No*.
6767

68+
Click the *Membership* tab to continue.
69+
6870
.. image:: images/role_membership.png
6971
:alt: Role dialog membership tab
7072
:align: center
7173

72-
* Specify member of the role in the *Member of* field and specify the members in the *Member* field.
73-
Confirm each selection by checking the checkbox to the right of the role name;
74-
delete a selection by clicking the *x* to the left of the role name.
75-
Membership conveys the privileges granted to the specified role to each of
76-
its members.
74+
Use the *Membership* tab to define role memberships. A role can be a member of
75+
other roles and can have other roles as members.
76+
77+
* Use *Member of* section to specify roles of which the current role
78+
is a member. To assign *Admin Option* for a selected role, click on
79+
the appropriate checkbox.
80+
* Use *Members* section to specify roles that are members of the current
81+
role. To assign *Admin Option* for a selected role, click on the appropriate checkbox.
82+
83+
Click the *Add* icon (+) to add more roles; to discard a
84+
role, click the trash icon to the left of the row and confirm the deletion
85+
in the *Delete Row* popup.
86+
87+
**Note:** Apart from *Admin Option*, *Inherit Option* and *Set Option* are available for both *Member of* section and *Members* section from PostgreSQL version >= 16.
7788

7889
Click the *Parameters* tab to continue.
7990

web/pgadmin/browser/server_groups/servers/roles/__init__.py

Lines changed: 124 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -207,80 +207,65 @@ def _process_rolemembership(self, id, data):
207207
:param id: id of role
208208
:param data: input role data
209209
"""
210-
def _part_dict_list(dict_list, condition, list_key=None):
210+
def _part_dict_list(dict_list, condition):
211211
ret_val = []
212212
for d in dict_list:
213213
if condition(d):
214-
ret_val.append(d[list_key])
214+
ret_val.append(d)
215215

216216
return ret_val
217217

218218
if id == -1:
219-
data['members'] = []
220-
data['admins'] = []
221-
222-
data['admins'] = _part_dict_list(
223-
data['rolmembership'], lambda d: d['admin'], 'role')
224-
data['members'] = _part_dict_list(
225-
data['rolmembership'], lambda d: not d['admin'], 'role')
219+
data['rolmembership_list'] = data['rolmembership']
226220
else:
227-
data['admins'] = _part_dict_list(
228-
data['rolmembership'].get('added', []),
229-
lambda d: d['admin'], 'role')
230-
data['members'] = _part_dict_list(
231-
data['rolmembership'].get('added', []),
232-
lambda d: not d['admin'], 'role')
233-
234-
data['admins'].extend(_part_dict_list(
235-
data['rolmembership'].get('changed', []),
236-
lambda d: d['admin'], 'role'))
237-
data['revoked_admins'] = _part_dict_list(
238-
data['rolmembership'].get('changed', []),
239-
lambda d: not d['admin'], 'role')
240-
241-
data['revoked'] = _part_dict_list(
242-
data['rolmembership'].get('deleted', []),
243-
lambda _: True, 'role')
221+
data['rolmembership_list'] = data['rolmembership'].get('added', [])
222+
223+
if self.manager.version < 160000:
224+
data['rolmembership_list'].extend(_part_dict_list(
225+
data['rolmembership'].get('changed', []),
226+
lambda d: d['admin']))
227+
data['rolmembership_revoked_admins'] = _part_dict_list(
228+
data['rolmembership'].get('changed', []),
229+
lambda d: not d['admin'])
230+
else:
231+
data['rolmembership_list'].extend(
232+
data['rolmembership'].get('changed', []))
233+
234+
data['rolmembership_revoked_list'] = (
235+
data['rolmembership'].get('deleted', []))
244236

245237
def _process_rolmembers(self, id, data):
246238
"""
247239
Parser role members.
248240
:param id:
249241
:param data:
250242
"""
251-
def _part_dict_list(dict_list, condition, list_key=None):
243+
def _part_dict_list(dict_list, condition):
252244
ret_val = []
253245
for d in dict_list:
254246
if condition(d):
255-
ret_val.append(d[list_key])
247+
ret_val.append(d)
256248

257249
return ret_val
258250
if id == -1:
259-
data['rol_members'] = []
260-
data['rol_admins'] = []
251+
data['rol_members_list'] = data['rolmembers']
261252

262-
data['rol_admins'] = _part_dict_list(
263-
data['rolmembers'], lambda d: d['admin'], 'role')
264-
data['rol_members'] = _part_dict_list(
265-
data['rolmembers'], lambda d: not d['admin'], 'role')
266253
else:
267-
data['rol_admins'] = _part_dict_list(
268-
data['rolmembers'].get('added', []),
269-
lambda d: d['admin'], 'role')
270-
data['rol_members'] = _part_dict_list(
271-
data['rolmembers'].get('added', []),
272-
lambda d: not d['admin'], 'role')
273-
274-
data['rol_admins'].extend(_part_dict_list(
275-
data['rolmembers'].get('changed', []),
276-
lambda d: d['admin'], 'role'))
277-
data['rol_revoked_admins'] = _part_dict_list(
278-
data['rolmembers'].get('changed', []),
279-
lambda d: not d['admin'], 'role')
280-
281-
data['rol_revoked'] = _part_dict_list(
282-
data['rolmembers'].get('deleted', []),
283-
lambda _: True, 'role')
254+
data['rol_members_list'] = data['rolmembers'].get('added', [])
255+
256+
if self.manager.version < 160000:
257+
data['rol_members_list'].extend(_part_dict_list(
258+
data['rolmembers'].get('changed', []),
259+
lambda d: d['admin']))
260+
data['rol_members_revoked_admins'] = _part_dict_list(
261+
data['rolmembers'].get('changed', []),
262+
lambda d: not d['admin'])
263+
else:
264+
data['rol_members_list'].extend(
265+
data['rolmembers'].get('changed', []))
266+
267+
data['rol_members_revoked_list'] = (
268+
data['rolmembers'].get('deleted', []))
284269

285270
def _validate_rolemembers(self, id, data):
286271
"""
@@ -298,13 +283,21 @@ def _validate_rolemembers(self, id, data):
298283
299284
rolmembers:[{
300285
role: [rolename],
301-
admin: True/False
286+
admin: True/False,
287+
inherit: True/False,
288+
set: True/False,
302289
},
303290
...
304291
]""")
305292

306-
if not self._validate_input_dict_for_new(data['rolmembers'],
307-
['role', 'admin']):
293+
if (self.manager.version < 160000 and
294+
not self._validate_input_dict_for_new(
295+
data['rolmembers'], ['role', 'admin'])):
296+
return msg
297+
elif (self.manager.version >= 160000 and
298+
not self._validate_input_dict_for_new(
299+
data['rolmembers'],
300+
['role', 'admin', 'inherit', 'set'])):
308301
return msg
309302

310303
self._process_rolmembers(id, data)
@@ -316,26 +309,38 @@ def _validate_rolemembers(self, id, data):
316309
rolmembers:{
317310
'added': [{
318311
role: [rolename],
319-
admin: True/False
312+
admin: True/False,
313+
inherit: True/False,
314+
set: True/False,
320315
},
321316
...
322317
],
323318
'deleted': [{
324319
role: [rolename],
325-
admin: True/False
320+
admin: True/False,
321+
inherit: True/False,
322+
set: True/False,
326323
},
327324
...
328325
],
329326
'updated': [{
330327
role: [rolename],
331-
admin: True/False
328+
admin: True/False,
329+
inherit: True/False,
330+
set: True/False,
332331
},
333332
...
334333
]
335334
""")
336-
if not self._validate_input_dict_for_update(data['rolmembers'],
337-
['role', 'admin'],
338-
['role']):
335+
if (self.manager.version < 160000 and
336+
not self._validate_input_dict_for_update(
337+
data['rolmembers'], ['role', 'admin'], ['role'])):
338+
return msg
339+
elif (self.manager.version >= 160000 and
340+
not self._validate_input_dict_for_update(
341+
data['rolmembers'],
342+
['role', 'admin', 'inherit', 'set'],
343+
['role'])):
339344
return msg
340345

341346
self._process_rolmembers(id, data)
@@ -357,13 +362,21 @@ def _validate_rolemembership(self, id, data):
357362
358363
rolmembership:[{
359364
role: [rolename],
360-
admin: True/False
365+
admin: True/False,
366+
inherit: True/False,
367+
set: True/False,
361368
},
362369
...
363370
]""")
364371

365-
if not self._validate_input_dict_for_new(
366-
data['rolmembership'], ['role', 'admin']):
372+
if (self.manager.version < 160000 and
373+
not self._validate_input_dict_for_new(
374+
data['rolmembership'], ['role', 'admin'])):
375+
return msg
376+
elif (self.manager.version >= 160000 and
377+
not self._validate_input_dict_for_new(
378+
data['rolmembership'],
379+
['role', 'admin', 'inherit', 'set'])):
367380
return msg
368381

369382
self._process_rolemembership(id, data)
@@ -375,25 +388,38 @@ def _validate_rolemembership(self, id, data):
375388
rolmembership:{
376389
'added': [{
377390
role: [rolename],
378-
admin: True/False
391+
admin: True/False,
392+
inherit: True/False,
393+
set: True/False,
379394
},
380395
...
381396
],
382397
'deleted': [{
383398
role: [rolename],
384-
admin: True/False
399+
admin: True/False,
400+
inherit: True/False,
401+
set: True/False,
385402
},
386403
...
387404
],
388405
'updated': [{
389406
role: [rolename],
390-
admin: True/False
407+
admin: True/False,
408+
inherit: True/False,
409+
set: True/False,
391410
},
392411
...
393412
]
394413
""")
395-
if not self._validate_input_dict_for_update(
396-
data['rolmembership'], ['role', 'admin'], ['role']):
414+
if (self.manager.version < 160000 and
415+
not self._validate_input_dict_for_update(
416+
data['rolmembership'], ['role', 'admin'], ['role'])):
417+
return msg
418+
elif (self.manager.version >= 160000 and
419+
not self._validate_input_dict_for_update(
420+
data['rolmembership'],
421+
['role', 'admin', 'inherit', 'set'],
422+
['role'])):
397423
return msg
398424

399425
self._process_rolemembership(id, data)
@@ -792,16 +818,25 @@ def _set_seclabels(self, row):
792818
})
793819
row['seclabels'] = res
794820

795-
def _set_rolemembership(self, row):
821+
def _set_rolemembers(self, row):
796822

797823
if 'rolmembers' in row and row['rolmembers'] is not None:
798824
rolmembers = []
799825
for role in row['rolmembers']:
800-
role = re.search(r'([01])(.+)', role)
801-
rolmembers.append({
802-
'role': role.group(2),
803-
'admin': True if role.group(1) == '1' else False
804-
})
826+
if self.manager.version < 160000:
827+
role = re.search(r'([01])(.+)', role)
828+
rolmembers.append({
829+
'role': role.group(2),
830+
'admin': True if role.group(1) == '1' else False
831+
})
832+
else:
833+
role = re.search(r'([01])([01])([01])(.+)', role)
834+
rolmembers.append({
835+
'role': role.group(4),
836+
'admin': True if role.group(1) == '1' else False,
837+
'inherit': True if role.group(2) == '1' else False,
838+
'set': True if role.group(3) == '1' else False
839+
})
805840
row['rolmembers'] = rolmembers
806841

807842
def transform(self, rset):
@@ -810,14 +845,23 @@ def transform(self, rset):
810845
roles = row['rolmembership']
811846
row['rolpassword'] = ''
812847
for role in roles:
813-
role = re.search(r'([01])(.+)', role)
814-
res.append({
815-
'role': role.group(2),
816-
'admin': True if role.group(1) == '1' else False
817-
})
848+
if self.manager.version < 160000:
849+
role = re.search(r'([01])(.+)', role)
850+
res.append({
851+
'role': role.group(2),
852+
'admin': True if role.group(1) == '1' else False
853+
})
854+
else:
855+
role = re.search(r'([01])([01])([01])(.+)', role)
856+
res.append({
857+
'role': role.group(4),
858+
'admin': True if role.group(1) == '1' else False,
859+
'inherit': True if role.group(2) == '1' else False,
860+
'set': True if role.group(3) == '1' else False
861+
})
818862
row['rolmembership'] = res
819863
self._set_seclabels(row)
820-
self._set_rolemembership(row)
864+
self._set_rolemembers(row)
821865

822866
@check_precondition(action='properties')
823867
def properties(self, gid, sid, rid):

web/pgadmin/browser/server_groups/servers/roles/static/js/role.ui.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,12 @@ export default class RoleSchema extends BaseUISchema {
5858
memberDataFormatter(rawData) {
5959
let members = '';
6060
if(_.isObject(rawData)) {
61+
const serverVersion = this.nodeInfo && this.nodeInfo.server && this.nodeInfo.server.version || 0;
6162
rawData.forEach(member => {
62-
let withAdmin = '';
63-
if(member.admin) { withAdmin = ' [WITH ADMIN]';}
63+
let badges = serverVersion >= 160000 ? ` [WITH ADMIN ${member.admin.toString().toUpperCase()}, INHERIT ${member.inherit.toString().toUpperCase()}, SET ${member.set.toString().toUpperCase()}]` : member.admin ? ' [WITH ADMIN OPTION]' : '';
6464

6565
if (members.length > 0) { members += ', '; }
66-
members = members + (member.role + withAdmin);
66+
members = members + (member.role + badges);
6767
});
6868
}
6969
return members;
@@ -177,7 +177,7 @@ export default class RoleSchema extends BaseUISchema {
177177
type: 'text',
178178
controlProps: {
179179
formatter: {
180-
fromRaw: obj.memberDataFormatter,
180+
fromRaw: (raw) => obj.memberDataFormatter(raw),
181181
},
182182
}
183183
},
@@ -198,7 +198,7 @@ export default class RoleSchema extends BaseUISchema {
198198
type: 'text',
199199
controlProps: {
200200
formatter: {
201-
fromRaw: obj.memberDataFormatter,
201+
fromRaw: (raw) => obj.memberDataFormatter(raw),
202202
},
203203
}
204204
},

0 commit comments

Comments
 (0)