mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Adding the Login/Group Role Node.
Also - includes: * Added 'parent_id' in the 'generate_browser_node' function of the Nodes to allow them to move around the parents objects (specially through update/save functionality). * Handles the issue related to adding the older object back to the collection (DataModel). Author: Ashesh Vashi Reviewed by: Neel Patel, and Akshay Joshi.
This commit is contained in:
@@ -201,7 +201,7 @@ class BrowserPluginModule(PgAdminModule):
|
|||||||
return scripts
|
return scripts
|
||||||
|
|
||||||
def generate_browser_node(
|
def generate_browser_node(
|
||||||
self, node_id, label, icon, inode, node_type, **kwargs
|
self, node_id, parent_id, label, icon, inode, node_type, **kwargs
|
||||||
):
|
):
|
||||||
obj = {
|
obj = {
|
||||||
"id": "%s/%s" % (node_type, node_id),
|
"id": "%s/%s" % (node_type, node_id),
|
||||||
@@ -210,6 +210,7 @@ class BrowserPluginModule(PgAdminModule):
|
|||||||
"inode": inode,
|
"inode": inode,
|
||||||
"_type": node_type,
|
"_type": node_type,
|
||||||
"_id": node_id,
|
"_id": node_id,
|
||||||
|
"_pid": parent_id,
|
||||||
"module": 'pgadmin.node.%s' % node_type
|
"module": 'pgadmin.node.%s' % node_type
|
||||||
}
|
}
|
||||||
for key in kwargs:
|
for key in kwargs:
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ class CollectionNodeModule(PgAdminModule, PGChildModule):
|
|||||||
return scripts
|
return scripts
|
||||||
|
|
||||||
def generate_browser_node(
|
def generate_browser_node(
|
||||||
self, node_id, label, icon, **kwargs
|
self, node_id, parent_id, label, icon, **kwargs
|
||||||
):
|
):
|
||||||
obj = {
|
obj = {
|
||||||
"id": "%s/%s" % (self.node_type, node_id),
|
"id": "%s/%s" % (self.node_type, node_id),
|
||||||
@@ -62,20 +62,22 @@ class CollectionNodeModule(PgAdminModule, PGChildModule):
|
|||||||
"inode": self.node_inode,
|
"inode": self.node_inode,
|
||||||
"_type": self.node_type,
|
"_type": self.node_type,
|
||||||
"_id": node_id,
|
"_id": node_id,
|
||||||
|
"_pid": parent_id,
|
||||||
"module": 'pgadmin.node.%s' % self.node_type
|
"module": 'pgadmin.node.%s' % self.node_type
|
||||||
}
|
}
|
||||||
for key in kwargs:
|
for key in kwargs:
|
||||||
obj.setdefault(key, kwargs[key])
|
obj.setdefault(key, kwargs[key])
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def generate_browser_collection_node(self, sid, **kwargs):
|
def generate_browser_collection_node(self, parent_id, **kwargs):
|
||||||
obj = {
|
obj = {
|
||||||
"id": "coll-%s/%d" % (self.node_type, sid),
|
"id": "coll-%s/%d" % (self.node_type, parent_id),
|
||||||
"label": self.collection_label,
|
"label": self.collection_label,
|
||||||
"icon": self.collection_icon,
|
"icon": self.collection_icon,
|
||||||
"inode": True,
|
"inode": True,
|
||||||
"_type": 'coll-%s' % (self.node_type),
|
"_type": 'coll-%s' % (self.node_type),
|
||||||
"_id": sid,
|
"_id": parent_id,
|
||||||
|
"_pid": parent_id,
|
||||||
"module": 'pgadmin.node.%s' % self.node_type
|
"module": 'pgadmin.node.%s' % self.node_type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class ServerGroupModule(BrowserPluginModule):
|
|||||||
groups = ServerGroup.query.filter_by(user_id=current_user.id)
|
groups = ServerGroup.query.filter_by(user_id=current_user.id)
|
||||||
for group in groups:
|
for group in groups:
|
||||||
yield self.generate_browser_node(
|
yield self.generate_browser_node(
|
||||||
"%d" % (group.id),
|
"%d" % (group.id), None,
|
||||||
group.name,
|
group.name,
|
||||||
"icon-%s" % self.node_type,
|
"icon-%s" % self.node_type,
|
||||||
True,
|
True,
|
||||||
@@ -184,7 +184,7 @@ class ServerGroupView(NodeView):
|
|||||||
|
|
||||||
return jsonify(
|
return jsonify(
|
||||||
node=self.blueprint.generate_browser_node(
|
node=self.blueprint.generate_browser_node(
|
||||||
"%d" % (sg.id),
|
"%d" % (sg.id), None,
|
||||||
sg.name,
|
sg.name,
|
||||||
"icon-%s" % self.node_type,
|
"icon-%s" % self.node_type,
|
||||||
True,
|
True,
|
||||||
@@ -241,7 +241,7 @@ class ServerGroupView(NodeView):
|
|||||||
for group in groups:
|
for group in groups:
|
||||||
nodes.append(
|
nodes.append(
|
||||||
self.generate_browser_node(
|
self.generate_browser_node(
|
||||||
"%d" % (group.id),
|
"%d" % (group.id), None,
|
||||||
group.name,
|
group.name,
|
||||||
"icon-%s" % self.node_type,
|
"icon-%s" % self.node_type,
|
||||||
True,
|
True,
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ class ServerModule(sg.ServerGroupPluginModule):
|
|||||||
|
|
||||||
yield self.generate_browser_node(
|
yield self.generate_browser_node(
|
||||||
"%d" % (server.id),
|
"%d" % (server.id),
|
||||||
|
gid,
|
||||||
server.name,
|
server.name,
|
||||||
"icon-server-not-connected" if not connected else
|
"icon-server-not-connected" if not connected else
|
||||||
"icon-{0}".format(manager.server_type),
|
"icon-{0}".format(manager.server_type),
|
||||||
@@ -196,6 +197,7 @@ class ServerNode(PGChildNodeView):
|
|||||||
res.append(
|
res.append(
|
||||||
self.blueprint.generate_browser_node(
|
self.blueprint.generate_browser_node(
|
||||||
"%d" % (server.id),
|
"%d" % (server.id),
|
||||||
|
gid,
|
||||||
server.name,
|
server.name,
|
||||||
"icon-server-not-connected" if not connected else
|
"icon-server-not-connected" if not connected else
|
||||||
"icon-{0}".format(manager.server_type),
|
"icon-{0}".format(manager.server_type),
|
||||||
@@ -236,6 +238,7 @@ class ServerNode(PGChildNodeView):
|
|||||||
return make_json_response(
|
return make_json_response(
|
||||||
result=self.blueprint.generate_browser_node(
|
result=self.blueprint.generate_browser_node(
|
||||||
"%d" % (server.id),
|
"%d" % (server.id),
|
||||||
|
gid,
|
||||||
server.name,
|
server.name,
|
||||||
"icon-server-not-connected" if not connected else
|
"icon-server-not-connected" if not connected else
|
||||||
"icon-{0}".format(manager.server_type),
|
"icon-{0}".format(manager.server_type),
|
||||||
@@ -490,7 +493,7 @@ class ServerNode(PGChildNodeView):
|
|||||||
|
|
||||||
return jsonify(
|
return jsonify(
|
||||||
node=self.blueprint.generate_browser_node(
|
node=self.blueprint.generate_browser_node(
|
||||||
"%d" % (server.id),
|
"%d" % (server.id), gid,
|
||||||
server.name,
|
server.name,
|
||||||
"icon-server-not-connected",
|
"icon-server-not-connected",
|
||||||
True,
|
True,
|
||||||
|
|||||||
908
web/pgadmin/browser/server_groups/servers/roles/__init__.py
Normal file
908
web/pgadmin/browser/server_groups/servers/roles/__init__.py
Normal file
@@ -0,0 +1,908 @@
|
|||||||
|
##########################################################################
|
||||||
|
#
|
||||||
|
# pgAdmin 4 - PostgreSQL Tools
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013 - 2016, The pgAdmin Development Team
|
||||||
|
# This software is released under the PostgreSQL Licence
|
||||||
|
#
|
||||||
|
##########################################################################
|
||||||
|
from flask import render_template, request, current_app, jsonify
|
||||||
|
from flask.ext.babel import gettext as _
|
||||||
|
from pgadmin.utils.ajax import make_json_response, \
|
||||||
|
make_response as ajax_response, precondition_required, \
|
||||||
|
internal_server_error, forbidden, \
|
||||||
|
not_implemented, success_return
|
||||||
|
from pgadmin.browser.utils import NodeView
|
||||||
|
from pgadmin.browser.collection import CollectionNodeModule
|
||||||
|
import pgadmin.browser.server_groups as sg
|
||||||
|
from pgadmin.utils.driver import get_driver
|
||||||
|
from config import PG_DEFAULT_DRIVER
|
||||||
|
import re
|
||||||
|
import datetime
|
||||||
|
from functools import wraps
|
||||||
|
import simplejson as json
|
||||||
|
|
||||||
|
|
||||||
|
class RoleModule(CollectionNodeModule):
|
||||||
|
NODE_TYPE = 'role'
|
||||||
|
COLLECTION_LABEL = _("Login/Group Roles")
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
self.min_ver = None
|
||||||
|
self.max_ver = None
|
||||||
|
|
||||||
|
super(RoleModule, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def get_nodes(self, gid, sid):
|
||||||
|
"""
|
||||||
|
Generate the collection node
|
||||||
|
"""
|
||||||
|
|
||||||
|
yield self.generate_browser_collection_node(sid)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def node_inode(self):
|
||||||
|
"""
|
||||||
|
Override this property to make the node as leaf node.
|
||||||
|
"""
|
||||||
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def script_load(self):
|
||||||
|
"""
|
||||||
|
Load the module script for server, when any of the server-group node is
|
||||||
|
initialized.
|
||||||
|
"""
|
||||||
|
return sg.ServerGroupModule.NODE_TYPE
|
||||||
|
|
||||||
|
@property
|
||||||
|
def csssnippets(self):
|
||||||
|
"""
|
||||||
|
Returns a snippet of css to include in the page
|
||||||
|
"""
|
||||||
|
snippets = [
|
||||||
|
render_template(
|
||||||
|
"browser/css/collection.css",
|
||||||
|
node_type=self.node_type
|
||||||
|
),
|
||||||
|
render_template("role/css/role.css")]
|
||||||
|
|
||||||
|
for submodule in self.submodules:
|
||||||
|
snippets.extend(submodule.csssnippets)
|
||||||
|
|
||||||
|
return snippets
|
||||||
|
|
||||||
|
|
||||||
|
blueprint = RoleModule(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class RoleView(NodeView):
|
||||||
|
node_type = 'role'
|
||||||
|
|
||||||
|
parent_ids = [
|
||||||
|
{'type': 'int', 'id': 'gid'},
|
||||||
|
{'type': 'int', 'id': 'sid'}
|
||||||
|
]
|
||||||
|
ids = [
|
||||||
|
{'type': 'int', 'id': 'rid'}
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = dict({
|
||||||
|
'obj': [
|
||||||
|
{'get': 'properties', 'delete': 'drop', 'put': 'update'},
|
||||||
|
{'get': 'list', 'post': 'create'}
|
||||||
|
],
|
||||||
|
'nodes': [{'get': 'node'}, {'get': 'nodes'}],
|
||||||
|
'sql': [{'get': 'sql'}],
|
||||||
|
'msql': [{'get': 'msql'}, {'get': 'msql'}],
|
||||||
|
'dependency': [{'get': 'dependencies'}],
|
||||||
|
'dependent': [{'get': 'dependents'}],
|
||||||
|
'children': [{'get': 'children'}],
|
||||||
|
'module.js': [{}, {}, {'get': 'module_js'}],
|
||||||
|
'vopts': [{}, {'get': 'voptions'}],
|
||||||
|
'variables': [{'get': 'variables'}],
|
||||||
|
})
|
||||||
|
|
||||||
|
def validate_request(f):
|
||||||
|
@wraps(f)
|
||||||
|
def wrap(self, **kwargs):
|
||||||
|
|
||||||
|
data = None
|
||||||
|
if request.data:
|
||||||
|
data = json.loads(request.data)
|
||||||
|
else:
|
||||||
|
data = dict()
|
||||||
|
req = request.args or request.form
|
||||||
|
|
||||||
|
for key in req:
|
||||||
|
|
||||||
|
val = req[key]
|
||||||
|
if key in [
|
||||||
|
u'rolcanlogin', u'rolsuper', u'rolcreatedb',
|
||||||
|
u'rolcreaterole', u'rolinherit', u'rolreplication',
|
||||||
|
u'rolcatupdate', u'variables', u'rolmembership',
|
||||||
|
u'seclabels'
|
||||||
|
]:
|
||||||
|
data[key] = json.loads(val)
|
||||||
|
else:
|
||||||
|
data[key] = val
|
||||||
|
|
||||||
|
if u'rid' not in kwargs or kwargs['rid'] == -1:
|
||||||
|
if u'rolname' not in data:
|
||||||
|
return precondition_required(
|
||||||
|
_("Name is not provided!")
|
||||||
|
)
|
||||||
|
|
||||||
|
if u'rolconnlimit' in data:
|
||||||
|
if data[u'rolconnlimit'] is not None:
|
||||||
|
data[u'rolconnlimit'] = int(data[u'rolconnlimit'])
|
||||||
|
if type(data[u'rolconnlimit']) != int or data[u'rolconnlimit'] < -1:
|
||||||
|
return precondition_required(
|
||||||
|
_("Connection limit must be an integer value or equals to -1!")
|
||||||
|
)
|
||||||
|
|
||||||
|
if u'rolmembership' in data:
|
||||||
|
if u'rid' not in kwargs or kwargs['rid'] == -1:
|
||||||
|
msg = _("""
|
||||||
|
Role membership information must be passed as an array of JSON object in the
|
||||||
|
following format:
|
||||||
|
|
||||||
|
rolmembership:[{
|
||||||
|
role: [rolename],
|
||||||
|
admin: True/False
|
||||||
|
},
|
||||||
|
...
|
||||||
|
]""")
|
||||||
|
if type(data[u'rolmembership']) != list:
|
||||||
|
return precondition_required(msg)
|
||||||
|
|
||||||
|
data[u'members'] = []
|
||||||
|
data[u'admins'] = []
|
||||||
|
|
||||||
|
for r in data[u'rolmembership']:
|
||||||
|
if type(r) != dict or u'role' not in r or u'admin' not in r:
|
||||||
|
return precondition_required(msg)
|
||||||
|
else:
|
||||||
|
if r[u'admin']:
|
||||||
|
data[u'admins'].append(r[u'role'])
|
||||||
|
else:
|
||||||
|
data[u'members'].append(r[u'role'])
|
||||||
|
else:
|
||||||
|
msg = _("""
|
||||||
|
Role membership information must be passed a string representing an array of
|
||||||
|
JSON object in the following format:
|
||||||
|
rolmembership:{
|
||||||
|
'added': [{
|
||||||
|
role: [rolename],
|
||||||
|
admin: True/False
|
||||||
|
},
|
||||||
|
...
|
||||||
|
],
|
||||||
|
'deleted': [{
|
||||||
|
role: [rolename],
|
||||||
|
admin: True/False
|
||||||
|
},
|
||||||
|
...
|
||||||
|
],
|
||||||
|
'updated': [{
|
||||||
|
role: [rolename],
|
||||||
|
admin: True/False
|
||||||
|
},
|
||||||
|
...
|
||||||
|
]
|
||||||
|
""")
|
||||||
|
if type(data[u'rolmembership']) != dict:
|
||||||
|
return precondition_required(msg)
|
||||||
|
|
||||||
|
data[u'members'] = []
|
||||||
|
data[u'admins'] = []
|
||||||
|
data[u'revoked_admins'] = []
|
||||||
|
data[u'revoked'] = []
|
||||||
|
|
||||||
|
if u'added' in data[u'rolmembership']:
|
||||||
|
roles = (data[u'rolmembership'])[u'added']
|
||||||
|
|
||||||
|
if type(roles) != list:
|
||||||
|
return precondition_required(msg)
|
||||||
|
|
||||||
|
for r in roles:
|
||||||
|
if (type(r) != dict or u'role' not in r or
|
||||||
|
u'admin' not in r):
|
||||||
|
return precondition_required(msg)
|
||||||
|
|
||||||
|
if r[u'admin']:
|
||||||
|
data[u'admins'].append(r[u'role'])
|
||||||
|
else:
|
||||||
|
data[u'members'].append(r[u'role'])
|
||||||
|
|
||||||
|
if u'deleted' in data[u'rolmembership']:
|
||||||
|
roles = (data[u'rolmembership'])[u'deleted']
|
||||||
|
|
||||||
|
if type(roles) != list:
|
||||||
|
return precondition_required(msg)
|
||||||
|
|
||||||
|
for r in roles:
|
||||||
|
if type(r) != dict or u'role' not in r:
|
||||||
|
return precondition_required(msg)
|
||||||
|
|
||||||
|
data[u'revoked'].append(r[u'role'])
|
||||||
|
|
||||||
|
if u'changed' in data[u'rolmembership']:
|
||||||
|
roles = (data[u'rolmembership'])[u'changed']
|
||||||
|
|
||||||
|
if type(roles) != list:
|
||||||
|
return precondition_required(msg)
|
||||||
|
|
||||||
|
for r in roles:
|
||||||
|
if (type(r) != dict or u'role' not in r or
|
||||||
|
u'admin' not in r):
|
||||||
|
return precondition_required(msg)
|
||||||
|
|
||||||
|
if not r[u'admin']:
|
||||||
|
data[u'revoked_admins'].append(r[u'role'])
|
||||||
|
else:
|
||||||
|
data[u'admins'].append(r[u'role'])
|
||||||
|
|
||||||
|
if self.manager.version >= 90200:
|
||||||
|
if u'seclabels' in data:
|
||||||
|
if u'rid' not in kwargs or kwargs['rid'] == -1:
|
||||||
|
msg = _("""
|
||||||
|
Security Label must be passed as an array of JSON object in the following
|
||||||
|
format:
|
||||||
|
seclabels:[{
|
||||||
|
provider: <provider>,
|
||||||
|
label: <label>
|
||||||
|
},
|
||||||
|
...
|
||||||
|
]""")
|
||||||
|
if type(data[u'seclabels']) != list:
|
||||||
|
return precondition_required(msg)
|
||||||
|
|
||||||
|
for s in data[u'seclabels']:
|
||||||
|
if (type(s) != dict or u'provider' not in s or
|
||||||
|
u'label' not in s):
|
||||||
|
return precondition_required(msg)
|
||||||
|
else:
|
||||||
|
msg = _("""
|
||||||
|
Security Label must be passed as an array of JSON object in the following
|
||||||
|
format:
|
||||||
|
seclabels:{
|
||||||
|
'added': [{
|
||||||
|
provider: <provider>,
|
||||||
|
label: <label>
|
||||||
|
},
|
||||||
|
...
|
||||||
|
],
|
||||||
|
'deleted': [{
|
||||||
|
provider: <provider>,
|
||||||
|
label: <label>
|
||||||
|
},
|
||||||
|
...
|
||||||
|
],
|
||||||
|
'updated': [{
|
||||||
|
provider: <provider>,
|
||||||
|
label: <label>
|
||||||
|
},
|
||||||
|
...
|
||||||
|
]
|
||||||
|
""")
|
||||||
|
seclabels = data[u'seclabels']
|
||||||
|
if type(seclabels) != dict:
|
||||||
|
return precondition_required(msg)
|
||||||
|
|
||||||
|
if u'added' in seclabels:
|
||||||
|
new_seclabels = seclabels[u'added']
|
||||||
|
|
||||||
|
|
||||||
|
if type(new_seclabels) != list:
|
||||||
|
return precondition_required(msg)
|
||||||
|
|
||||||
|
for s in new_seclabels:
|
||||||
|
if (type(s) != dict or u'provider' not in s or
|
||||||
|
u'label' not in s):
|
||||||
|
return precondition_required(msg)
|
||||||
|
|
||||||
|
if u'deleted' in seclabels:
|
||||||
|
removed_seclabels = seclabels[u'deleted']
|
||||||
|
|
||||||
|
if type(removed_seclabels) != list:
|
||||||
|
return precondition_required(msg)
|
||||||
|
|
||||||
|
for s in removed_seclabels:
|
||||||
|
if (type(s) != dict or u'provider' not in s):
|
||||||
|
return precondition_required(msg)
|
||||||
|
|
||||||
|
if u'changed' in seclabels:
|
||||||
|
changed_seclabels = seclabels[u'deleted']
|
||||||
|
|
||||||
|
if type(changed_seclabels) != list:
|
||||||
|
return precondition_required(msg)
|
||||||
|
|
||||||
|
for s in changed_seclabels:
|
||||||
|
if (type(s) != dict or u'provider' not in s
|
||||||
|
and u'label' not in s):
|
||||||
|
return precondition_required(msg)
|
||||||
|
|
||||||
|
if u'variables' in data:
|
||||||
|
if u'rid' not in kwargs or kwargs['rid'] == -1:
|
||||||
|
msg = _("""
|
||||||
|
Configuration parameters/variables must be passed as an array of JSON object in
|
||||||
|
the following format (create mode):
|
||||||
|
variables:[{
|
||||||
|
database: <database> or null,
|
||||||
|
name: <configuration>,
|
||||||
|
value: <value>
|
||||||
|
},
|
||||||
|
...
|
||||||
|
]""")
|
||||||
|
if type(data[u'variables']) != list:
|
||||||
|
return precondition_required(msg)
|
||||||
|
|
||||||
|
for r in data[u'variables']:
|
||||||
|
if (type(r) != dict or
|
||||||
|
u'name' not in r or
|
||||||
|
u'value' not in r):
|
||||||
|
return precondition_required(msg)
|
||||||
|
else:
|
||||||
|
msg = _("""
|
||||||
|
Configuration parameters/variables must be passed as an array of JSON object in
|
||||||
|
the following format (update mode):
|
||||||
|
rolmembership:{
|
||||||
|
'added': [{
|
||||||
|
database: <database> or null,
|
||||||
|
name: <configuration>,
|
||||||
|
value: <value>
|
||||||
|
},
|
||||||
|
...
|
||||||
|
],
|
||||||
|
'deleted': [{
|
||||||
|
database: <database> or null,
|
||||||
|
name: <configuration>,
|
||||||
|
value: <value>
|
||||||
|
},
|
||||||
|
...
|
||||||
|
],
|
||||||
|
'updated': [{
|
||||||
|
database: <database> or null,
|
||||||
|
name: <configuration>,
|
||||||
|
value: <value>
|
||||||
|
},
|
||||||
|
...
|
||||||
|
]
|
||||||
|
""")
|
||||||
|
variables = data[u'variables']
|
||||||
|
if type(variables) != dict:
|
||||||
|
return precondition_required(msg)
|
||||||
|
|
||||||
|
if u'added' in variables:
|
||||||
|
new_vars = variables[u'added']
|
||||||
|
|
||||||
|
if type(new_vars) != list:
|
||||||
|
return precondition_required(msg)
|
||||||
|
|
||||||
|
for v in new_vars:
|
||||||
|
if (type(v) != dict or u'name' not in v or
|
||||||
|
u'value' not in v):
|
||||||
|
return precondition_required(msg)
|
||||||
|
|
||||||
|
if u'deleted' in variables:
|
||||||
|
delete_vars = variables[u'deleted']
|
||||||
|
|
||||||
|
if type(delete_vars) != list:
|
||||||
|
return precondition_required(msg)
|
||||||
|
|
||||||
|
for v in delete_vars:
|
||||||
|
if type(v) != dict or u'name' not in v:
|
||||||
|
return precondition_required(msg)
|
||||||
|
|
||||||
|
if u'changed' in variables:
|
||||||
|
new_vars = variables[u'changed']
|
||||||
|
|
||||||
|
if type(new_vars) != list:
|
||||||
|
return precondition_required(msg)
|
||||||
|
|
||||||
|
for v in new_vars:
|
||||||
|
if (type(v) != dict or u'name' not in v or
|
||||||
|
u'value' not in v):
|
||||||
|
return precondition_required(msg)
|
||||||
|
|
||||||
|
self.request = data
|
||||||
|
|
||||||
|
return f(self, **kwargs)
|
||||||
|
return wrap
|
||||||
|
|
||||||
|
def check_precondition(action=None):
|
||||||
|
"""
|
||||||
|
This function will behave as a decorator which will checks the status
|
||||||
|
of the database connection for the maintainance database of the server,
|
||||||
|
beforeexecuting rest of the operation for the wrapped function. It will
|
||||||
|
also attach manager, conn (maintenance connection for the server) as
|
||||||
|
properties of the instance.
|
||||||
|
"""
|
||||||
|
def wrap(f):
|
||||||
|
@wraps(f)
|
||||||
|
def wrapped(self, **kwargs):
|
||||||
|
self.manager = get_driver(
|
||||||
|
PG_DEFAULT_DRIVER
|
||||||
|
).connection_manager(
|
||||||
|
kwargs['sid']
|
||||||
|
)
|
||||||
|
self.conn = self.manager.connection()
|
||||||
|
|
||||||
|
if not self.conn.connected():
|
||||||
|
return precondition_required(
|
||||||
|
_("Connection to the server has been lost!")
|
||||||
|
)
|
||||||
|
|
||||||
|
ver = self.manager.version
|
||||||
|
|
||||||
|
self.sql_path = 'role/sql/{0}/'.format(
|
||||||
|
'post9_4' if ver >= 90500 else \
|
||||||
|
'post9_1' if ver >= 90200 else \
|
||||||
|
'post9_0' if ver >= 90100 else \
|
||||||
|
'post8_4'
|
||||||
|
)
|
||||||
|
|
||||||
|
self.alterKeys = [
|
||||||
|
u'rolcanlogin', u'rolsuper', u'rolcreatedb',
|
||||||
|
u'rolcreaterole', u'rolinherit', u'rolreplication',
|
||||||
|
u'rolconnlimit', u'rolvaliduntil', u'rolpassword'
|
||||||
|
] if ver >= 90200 else [
|
||||||
|
u'rolcanlogin', u'rolsuper', u'rolcreatedb',
|
||||||
|
u'rolcreaterole', u'rolinherit', u'rolconnlimit',
|
||||||
|
u'rolvaliduntil', u'rolpassword'
|
||||||
|
]
|
||||||
|
|
||||||
|
auth_tbl=False
|
||||||
|
check_permission=False
|
||||||
|
fetch_name=False
|
||||||
|
forbidden_msg = None
|
||||||
|
|
||||||
|
if action in ['list', 'properties']:
|
||||||
|
auth_tbl = True
|
||||||
|
elif action in ['drop', 'update']:
|
||||||
|
check_permission = True
|
||||||
|
fetch_name = True
|
||||||
|
if action == 'drop':
|
||||||
|
forbidden_msg = _(
|
||||||
|
"The current user does not have permission to drop the role!"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
forbidden_msg = _(
|
||||||
|
"The current user does not have permission to update the role!"
|
||||||
|
)
|
||||||
|
elif action == 'create':
|
||||||
|
check_permission = True
|
||||||
|
forbidden_msg = _(
|
||||||
|
"The current user does not have permission to create the role!"
|
||||||
|
)
|
||||||
|
elif (action == 'msql' and
|
||||||
|
'rid' in kwargs and kwargs['rid'] != -1):
|
||||||
|
fetch_name = True
|
||||||
|
|
||||||
|
if auth_tbl:
|
||||||
|
status, res = self.conn.execute_scalar(
|
||||||
|
"SELECT has_table_privilege('pg_authid', 'SELECT')"
|
||||||
|
)
|
||||||
|
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(
|
||||||
|
_(
|
||||||
|
"Error checking the permission to the pg_authid!\n{0}"
|
||||||
|
).format(res)
|
||||||
|
)
|
||||||
|
self.role_tbl = 'pg_authid' if res else 'pg_roles'
|
||||||
|
else:
|
||||||
|
self.role_tbl = 'pg_roles'
|
||||||
|
|
||||||
|
if check_permission:
|
||||||
|
user = self.manager.user_info
|
||||||
|
|
||||||
|
if not user['is_superuser'] and not user['can_create_role']:
|
||||||
|
if (action != 'update' or
|
||||||
|
'rid' in kwargs and kwargs['rid'] != -1 and
|
||||||
|
user['id'] != rid):
|
||||||
|
return forbidden(forbidden_msg)
|
||||||
|
|
||||||
|
if fetch_name:
|
||||||
|
|
||||||
|
status, res = self.conn.execute_dict(
|
||||||
|
render_template(
|
||||||
|
self.sql_path + 'permission.sql',
|
||||||
|
rid=kwargs['rid'],
|
||||||
|
conn=self.conn
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(
|
||||||
|
_(
|
||||||
|
"ERROR: fetching the role information!\n{0}"
|
||||||
|
).format(res)
|
||||||
|
)
|
||||||
|
|
||||||
|
if len(res['rows']) == 0:
|
||||||
|
return gone(
|
||||||
|
_("Couldn't find the specific role in the database server!")
|
||||||
|
)
|
||||||
|
|
||||||
|
row = res['rows'][0]
|
||||||
|
|
||||||
|
self.role = row['rolname']
|
||||||
|
self.rolCanLogin = row['rolcanlogin']
|
||||||
|
self.rolCatUpdate = row['rolcatupdate']
|
||||||
|
self.rolSuper = row['rolsuper']
|
||||||
|
|
||||||
|
return f(self, **kwargs)
|
||||||
|
return wrapped
|
||||||
|
return wrap
|
||||||
|
|
||||||
|
@check_precondition(action='list')
|
||||||
|
def list(self, gid, sid):
|
||||||
|
status, res = self.conn.execute_dict(
|
||||||
|
render_template(self.sql_path + 'properties.sql',
|
||||||
|
role_tbl=self.role_tbl
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(
|
||||||
|
_(
|
||||||
|
"Error fetching the roles from the database server!\n{0}"
|
||||||
|
).format(res)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.transform(res)
|
||||||
|
|
||||||
|
return ajax_response(
|
||||||
|
response=res['rows'],
|
||||||
|
status=200
|
||||||
|
)
|
||||||
|
|
||||||
|
@check_precondition(action='nodes')
|
||||||
|
def nodes(self, gid, sid):
|
||||||
|
|
||||||
|
status, rset = self.conn.execute_2darray(
|
||||||
|
render_template(self.sql_path + 'nodes.sql',
|
||||||
|
role_tbl=self.role_tbl
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(
|
||||||
|
_(
|
||||||
|
"Error fetching the roles information from the database server!\n{0}"
|
||||||
|
).format(res)
|
||||||
|
)
|
||||||
|
|
||||||
|
res = []
|
||||||
|
for row in rset['rows']:
|
||||||
|
res.append(
|
||||||
|
self.blueprint.generate_browser_node(
|
||||||
|
row['oid'], sid,
|
||||||
|
row['rolname'],
|
||||||
|
'icon-role' if row['rolcanlogin'] else 'icon-group',
|
||||||
|
can_login=row['rolcanlogin'],
|
||||||
|
is_superuser=row['rolsuper']
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return make_json_response(
|
||||||
|
data=res,
|
||||||
|
status=200
|
||||||
|
)
|
||||||
|
|
||||||
|
@check_precondition(action='node')
|
||||||
|
def node(self, gid, sid, rid):
|
||||||
|
|
||||||
|
status, rset = self.conn.execute_2darray(
|
||||||
|
render_template(self.sql_path + 'nodes.sql',
|
||||||
|
rid=rid,
|
||||||
|
role_tbl=self.role_tbl
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(
|
||||||
|
_(
|
||||||
|
"Error fetching the roles information from the database server!\n{0}"
|
||||||
|
).format(res)
|
||||||
|
)
|
||||||
|
|
||||||
|
for row in rset['rows']:
|
||||||
|
return make_json_response(
|
||||||
|
data=self.blueprint.generate_browser_node(
|
||||||
|
row['oid'], sid,
|
||||||
|
row['rolname'],
|
||||||
|
'icon-role' if row['rolcanlogin'] else 'icon-group',
|
||||||
|
can_login=row['rolcanlogin'],
|
||||||
|
is_superuser=row['rolsuper']
|
||||||
|
),
|
||||||
|
status=200
|
||||||
|
)
|
||||||
|
|
||||||
|
return gone(_("Couldn't find the role information!"))
|
||||||
|
|
||||||
|
def transform(self, rset):
|
||||||
|
for row in rset['rows']:
|
||||||
|
res = []
|
||||||
|
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
|
||||||
|
})
|
||||||
|
row['rolmembership'] = res
|
||||||
|
row['rolvaliduntil'] = row['rolvaliduntil'].isoformat() \
|
||||||
|
if isinstance(
|
||||||
|
row['rolvaliduntil'],
|
||||||
|
(datetime.date, datetime.datetime)
|
||||||
|
) else None
|
||||||
|
if 'seclabels' in row and row['seclabels'] is not None:
|
||||||
|
res = []
|
||||||
|
for sec in row['seclabels']:
|
||||||
|
sec = re.search(r'([^=]+)=(.*$)', sec)
|
||||||
|
res.append({
|
||||||
|
'provider': sec.group(1),
|
||||||
|
'label': sec.group(2)
|
||||||
|
})
|
||||||
|
|
||||||
|
@check_precondition(action='properties')
|
||||||
|
def properties(self, gid, sid, rid):
|
||||||
|
|
||||||
|
status, res = self.conn.execute_dict(
|
||||||
|
render_template(self.sql_path + 'properties.sql',
|
||||||
|
role_tbl=self.role_tbl,
|
||||||
|
rid=rid
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(
|
||||||
|
_(
|
||||||
|
"Error fetching the roles from the database server!\n{0}"
|
||||||
|
).format(res)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.transform(res)
|
||||||
|
if len(res['rows']) == 0:
|
||||||
|
return gone(_("Couldn't find the role information!"))
|
||||||
|
|
||||||
|
return ajax_response(
|
||||||
|
response=res['rows'][0],
|
||||||
|
status=200
|
||||||
|
)
|
||||||
|
|
||||||
|
@check_precondition(action='drop')
|
||||||
|
def drop(self, gid, sid, rid):
|
||||||
|
|
||||||
|
status, res = self.conn.execute_2darray(
|
||||||
|
"DROP ROLE {0};".format(self.role)
|
||||||
|
)
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(
|
||||||
|
_("ERROR: Couldn't drop the user!\n{0}").format(res)
|
||||||
|
)
|
||||||
|
|
||||||
|
return success_return()
|
||||||
|
|
||||||
|
@check_precondition()
|
||||||
|
def sql(self, gid, sid, rid):
|
||||||
|
status, res = self.conn.execute_scalar(
|
||||||
|
render_template(
|
||||||
|
self.sql_path + 'sql.sql',
|
||||||
|
role_tbl=self.role_tbl
|
||||||
|
),
|
||||||
|
dict({'rid':rid})
|
||||||
|
)
|
||||||
|
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(
|
||||||
|
_("ERROR: Couldn't generate reversed engineered Query for the role/user!\n{0}").format(
|
||||||
|
res
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if res is None:
|
||||||
|
return gone(
|
||||||
|
_("ERROR: Couldn't generate reversed engineered Query for the role/user!")
|
||||||
|
)
|
||||||
|
|
||||||
|
return ajax_response(response=res)
|
||||||
|
|
||||||
|
@check_precondition(action='create')
|
||||||
|
@validate_request
|
||||||
|
def create(self, gid, sid):
|
||||||
|
|
||||||
|
sql = render_template(
|
||||||
|
self.sql_path + 'create.sql',
|
||||||
|
data=self.request,
|
||||||
|
dummy=False,
|
||||||
|
conn=self.conn
|
||||||
|
)
|
||||||
|
|
||||||
|
status, msg = self.conn.execute_dict(sql)
|
||||||
|
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(
|
||||||
|
_("ERROR: Couldn't create the role!\n{0}").format(msg)
|
||||||
|
)
|
||||||
|
|
||||||
|
status, rid = self.conn.execute_scalar(
|
||||||
|
"SELECT oid FROM {0} WHERE rolname = %(rolname)s".format(
|
||||||
|
self.role_tbl
|
||||||
|
),
|
||||||
|
{'rolname': self.request[u'rolname']}
|
||||||
|
)
|
||||||
|
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(
|
||||||
|
_("ERROR: Couldn't fetch the role information!\n{0}").format(msg)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
status, rset = self.conn.execute_dict(
|
||||||
|
render_template(self.sql_path + 'nodes.sql',
|
||||||
|
rid=rid,
|
||||||
|
role_tbl=self.role_tbl
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(
|
||||||
|
_(
|
||||||
|
"Error fetching the roles information from the database server!\n{0}"
|
||||||
|
).format(res)
|
||||||
|
)
|
||||||
|
for row in rset['rows']:
|
||||||
|
return jsonify(
|
||||||
|
node=self.blueprint.generate_browser_node(
|
||||||
|
rid, sid,
|
||||||
|
row['rolname'],
|
||||||
|
'icon-role' if row['rolcanlogin'] else 'icon-group',
|
||||||
|
can_login=row['rolcanlogin']
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return gone(_("Couldn't find the role information!"))
|
||||||
|
|
||||||
|
@check_precondition(action='update')
|
||||||
|
@validate_request
|
||||||
|
def update(self, gid, sid, rid):
|
||||||
|
|
||||||
|
sql = render_template(
|
||||||
|
self.sql_path + 'update.sql',
|
||||||
|
data=self.request,
|
||||||
|
dummy=False,
|
||||||
|
conn=self.conn,
|
||||||
|
role=self.role,
|
||||||
|
rolCanLogin=self.rolCanLogin,
|
||||||
|
rolCatUpdate=self.rolCatUpdate,
|
||||||
|
rolSuper=self.rolSuper,
|
||||||
|
alterKeys=self.alterKeys
|
||||||
|
)
|
||||||
|
|
||||||
|
status, msg = self.conn.execute_dict(sql)
|
||||||
|
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(
|
||||||
|
_("ERROR: Couldn't create the role!\n{0}").format(msg)
|
||||||
|
)
|
||||||
|
|
||||||
|
status, rset = self.conn.execute_dict(
|
||||||
|
render_template(self.sql_path + 'nodes.sql',
|
||||||
|
rid=rid,
|
||||||
|
role_tbl=self.role_tbl
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(
|
||||||
|
_(
|
||||||
|
"Error fetching the roles information from the database server!\n{0}"
|
||||||
|
).format(res)
|
||||||
|
)
|
||||||
|
|
||||||
|
for row in rset['rows']:
|
||||||
|
return jsonify(
|
||||||
|
node=self.blueprint.generate_browser_node(
|
||||||
|
rid, sid,
|
||||||
|
row['rolname'],
|
||||||
|
'icon-role' if row['rolcanlogin'] else 'icon-group',
|
||||||
|
can_login=row['rolcanlogin'],
|
||||||
|
is_superuser=row['rolsuper']
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return gone(_("Couldn't find the role information!"))
|
||||||
|
|
||||||
|
@check_precondition(action='msql')
|
||||||
|
@validate_request
|
||||||
|
def msql(self, gid, sid, rid=-1):
|
||||||
|
if rid == -1:
|
||||||
|
return make_json_response(
|
||||||
|
data=render_template(
|
||||||
|
self.sql_path + 'create.sql',
|
||||||
|
data=self.request,
|
||||||
|
dummy=True,
|
||||||
|
conn=self.conn
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return make_json_response(
|
||||||
|
data=render_template(
|
||||||
|
self.sql_path + 'update.sql',
|
||||||
|
data=self.request,
|
||||||
|
dummy=True,
|
||||||
|
conn=self.conn,
|
||||||
|
role=self.role,
|
||||||
|
rolCanLogin=self.rolCanLogin,
|
||||||
|
rolCatUpdate=self.rolCatUpdate,
|
||||||
|
rolSuper=self.rolSuper,
|
||||||
|
alterKeys=self.alterKeys
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
@check_precondition()
|
||||||
|
def dependencies(self, gid, sid, rid):
|
||||||
|
return not_implemented()
|
||||||
|
|
||||||
|
@check_precondition()
|
||||||
|
def dependents(self, gid, sid, rid):
|
||||||
|
return not_implemented()
|
||||||
|
|
||||||
|
@check_precondition()
|
||||||
|
def variables(self, gid, sid, rid):
|
||||||
|
|
||||||
|
status, rset = self.conn.execute_dict(
|
||||||
|
render_template(self.sql_path + 'variables.sql',
|
||||||
|
rid=rid
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(
|
||||||
|
_(
|
||||||
|
"Error fetching the variable information for the given role!\n{0}"
|
||||||
|
).format(rset)
|
||||||
|
)
|
||||||
|
|
||||||
|
return make_json_response(
|
||||||
|
data=rset['rows']
|
||||||
|
)
|
||||||
|
|
||||||
|
@check_precondition()
|
||||||
|
def voptions(self, gid, sid):
|
||||||
|
|
||||||
|
status, res = self.conn.execute_dict(
|
||||||
|
"""
|
||||||
|
SELECT
|
||||||
|
name, vartype, min_val, max_val, enumvals
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
'role'::text AS name, 'string'::text AS vartype,
|
||||||
|
NULL AS min_val, NULL AS max_val, NULL::text[] AS enumvals
|
||||||
|
UNION ALL
|
||||||
|
SELECT
|
||||||
|
name, vartype, min_val::numeric AS min_val, max_val::numeric AS max_val, enumvals
|
||||||
|
FROM
|
||||||
|
pg_settings
|
||||||
|
WHERE
|
||||||
|
context in ('user', 'superuser')
|
||||||
|
) a""")
|
||||||
|
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(
|
||||||
|
_(
|
||||||
|
"Error fetching the variable options for role!\n{0}"
|
||||||
|
).format(res)
|
||||||
|
)
|
||||||
|
return make_json_response(
|
||||||
|
data=res['rows']
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
RoleView.register_node_view(blueprint)
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 472 B |
Binary file not shown.
|
After Width: | Height: | Size: 804 B |
Binary file not shown.
|
After Width: | Height: | Size: 557 B |
@@ -0,0 +1,27 @@
|
|||||||
|
.icon-role {
|
||||||
|
background-image: url('{{ url_for('NODE-role.static', filename='img/role.png')}}') !important;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
align-content: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
height: 1.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-group {
|
||||||
|
background-image: url('{{ url_for('NODE-role.static', filename='img/group.png')}}') !important;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
align-content: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
height: 1.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pgadmin-node-select option[node="role"] {
|
||||||
|
background-image: url('{{ url_for('NODE-role.static', filename='img/role.png')}}') !important;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pgadmin-node-select option[node="group"] {
|
||||||
|
background-image: url('{{ url_for('NODE-role.static', filename='img/group.png')}}') !important;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center left;
|
||||||
|
}
|
||||||
@@ -0,0 +1,512 @@
|
|||||||
|
define(
|
||||||
|
[
|
||||||
|
'jquery', 'underscore', 'underscore.string', 'pgadmin', 'pgadmin.browser',
|
||||||
|
'alertify', 'pgadmin.backform', 'select2', 'pgadmin.browser.collection',
|
||||||
|
'pgadmin.browser.node.ui', 'pgadmin.browser.server.variable'
|
||||||
|
],
|
||||||
|
function($, _, S, pgAdmin, pgBrowser, alertify, Backform) {
|
||||||
|
|
||||||
|
if (!pgBrowser.Nodes['coll-role']) {
|
||||||
|
var role = pgAdmin.Browser.Nodes['coll-role'] =
|
||||||
|
pgAdmin.Browser.Collection.extend({
|
||||||
|
node: 'role',
|
||||||
|
type: 'coll-role',
|
||||||
|
columns: [
|
||||||
|
'rolname', 'rolvaliduntil', 'rolconnlimit', 'rolcanlogin',
|
||||||
|
'rolsuper', 'rolcreaterole', 'rolcreatedb', 'rolcatupdate',
|
||||||
|
'rolinherit', 'rolreplication'
|
||||||
|
]
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var SecurityModel = pgAdmin.Browser.SecurityModel =
|
||||||
|
pgAdmin.Browser.SecurityModel || pgAdmin.Browser.Node.Model.extend({
|
||||||
|
defaults: {
|
||||||
|
provider: null,
|
||||||
|
label: null
|
||||||
|
},
|
||||||
|
schema: [{
|
||||||
|
id: 'provider', label: '{{ _('Provider') }}',
|
||||||
|
type: 'text', disabled: false
|
||||||
|
},{
|
||||||
|
id: 'label', label: '{{ _('Security Label') }}',
|
||||||
|
type: 'text', disabled: false
|
||||||
|
}],
|
||||||
|
validate: function() {
|
||||||
|
var err = {},
|
||||||
|
errmsg = null,
|
||||||
|
data = this.toJSON();
|
||||||
|
|
||||||
|
if (_.isUndefined(data.provider) ||
|
||||||
|
_.isNull(data.provider) ||
|
||||||
|
String(data.provider).replace(/^\s+|\s+$/g, '') == '') {
|
||||||
|
var msg = '{{ _('Please specify the value for all the security providers.') }}';
|
||||||
|
|
||||||
|
this.errorModel.set('provider', msg);
|
||||||
|
return msg;
|
||||||
|
} else {
|
||||||
|
this.errorModel.unset('provider');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_.isUndefined(data.label) ||
|
||||||
|
_.isNull(data.label) ||
|
||||||
|
String(data.label).replace(/^\s+|\s+$/g, '') == '') {
|
||||||
|
var msg = '{{ _('Please specify the value for all the security providers.') }}' ;
|
||||||
|
|
||||||
|
this.errorModel.set('label', msg);
|
||||||
|
return msg;
|
||||||
|
} else {
|
||||||
|
this.errorModel.unset('label');
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var switchOptions = {
|
||||||
|
'onText': 'Yes', 'offText': 'No',
|
||||||
|
'onColor': 'warning', 'offColor': 'primary',
|
||||||
|
'size': 'mini'
|
||||||
|
};
|
||||||
|
|
||||||
|
var RoleMembersControl = Backform.Control.extend({
|
||||||
|
defaults: _.defaults(
|
||||||
|
{extraClasses: ['col-xs-12 col-sm-12 col-md-12']},
|
||||||
|
Backform.NodeListByNameControl.prototype.defaults
|
||||||
|
),
|
||||||
|
initialize: function() {
|
||||||
|
Backform.NodeListByNameControl.prototype.initialize.apply(this, arguments);
|
||||||
|
},
|
||||||
|
formatter: {
|
||||||
|
fromRaw: function (rawData, model) {
|
||||||
|
var res = _.isObject(rawData) ? rawData : JSON.parse(rawData);
|
||||||
|
|
||||||
|
return _.pluck(res, 'role');
|
||||||
|
},
|
||||||
|
toRaw: function (formattedData, model) {
|
||||||
|
return formattedData;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
template: _.template([
|
||||||
|
'<label class="control-label col-xs-12"><%=label%></label>',
|
||||||
|
'<div class="pgadmin-controls col-xs-12">',
|
||||||
|
' <select multiple="multiple" style="width:100%;" class="pgadmin-controls <%=extraClasses.join(\' \')%>" name="<%=name%>" value="<%-JSON.stringify(value)%>" <%=disabled ? "disabled" : ""%> <%=required ? "required" : ""%>>',
|
||||||
|
' <% for (var i=0; i < options.length; i++) { %>',
|
||||||
|
' <% var option = options[i]; %>',
|
||||||
|
' <option value=<%-option.value%> data-icon=<%-option.image%> <%=value != null && _.indexOf(value, option.value) != -1 ? "selected" : ""%> <%=option.disabled ? "disabled=\'disabled\'" : ""%>><%-option.label%></option>',
|
||||||
|
' <% } %>',
|
||||||
|
' </select>',
|
||||||
|
'</div>',
|
||||||
|
'<div class="note <%=Backform.helpMessageClassName%> col-xs-12"></div>',
|
||||||
|
].join("\n")),
|
||||||
|
selectionTemplate: _.template([
|
||||||
|
'<span>',
|
||||||
|
' <span class="wcTabIcon <%= optimage %>"></span>',
|
||||||
|
' <span><%= opttext %><span>',
|
||||||
|
' <% if (checkbox) { %>',
|
||||||
|
' <input type="checkbox" <%=disabled ? "disabled=\'disabled\'" : ""%>/>',
|
||||||
|
' <% } %>',
|
||||||
|
'</span>'
|
||||||
|
].join("\n")),
|
||||||
|
events: {"change select": "onChange"},
|
||||||
|
getValueFromDOM: function() {
|
||||||
|
var res = [];
|
||||||
|
|
||||||
|
this.$el.find("select").find(':selected').each(function() {
|
||||||
|
res.push($(this).attr('value'));
|
||||||
|
});
|
||||||
|
|
||||||
|
return res;
|
||||||
|
},
|
||||||
|
render: function() {
|
||||||
|
var field = _.defaults(this.field.toJSON(), this.defaults),
|
||||||
|
attributes = this.model.toJSON(),
|
||||||
|
attrArr = field.name.split('.'),
|
||||||
|
name = attrArr.shift(),
|
||||||
|
path = attrArr.join('.'),
|
||||||
|
rawValue = this.keyPathAccessor(attributes[name], path),
|
||||||
|
data = _.extend(field, {
|
||||||
|
rawValue: rawValue,
|
||||||
|
value: this.formatter.fromRaw(rawValue, this.model),
|
||||||
|
attributes: attributes,
|
||||||
|
formatter: this.formatter
|
||||||
|
}),
|
||||||
|
evalF = function(f, d, m) {
|
||||||
|
return (_.isFunction(f) ? !!f.apply(d, [m]) : !!f);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Evaluate the disabled, visible, and required option
|
||||||
|
_.extend(data, {
|
||||||
|
disabled: evalF(data.disabled, data, this.model),
|
||||||
|
visible: evalF(data.visible, data, this.model),
|
||||||
|
required: evalF(data.required, data, this.model)
|
||||||
|
});
|
||||||
|
// Evaluation the options
|
||||||
|
if (_.isFunction(data.options)) {
|
||||||
|
try {
|
||||||
|
data.options = data.options.apply(this)
|
||||||
|
} catch(e) {
|
||||||
|
// Do nothing
|
||||||
|
data.options = []
|
||||||
|
this.model.trigger('pgadmin-view:transform:error', m, self.field, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up first
|
||||||
|
this.$el.removeClass(Backform.hiddenClassname);
|
||||||
|
|
||||||
|
if (!data.visible)
|
||||||
|
this.$el.addClass(Backform.hiddenClassname);
|
||||||
|
|
||||||
|
this.$el.html(this.template(data)).addClass(field.name);
|
||||||
|
this.updateInvalid();
|
||||||
|
|
||||||
|
var self = this,
|
||||||
|
collection = this.model.get(this.field.get('name')),
|
||||||
|
formatState = function(opt) {
|
||||||
|
if (!opt.id) {
|
||||||
|
return opt.text;
|
||||||
|
}
|
||||||
|
|
||||||
|
var optimage = $(opt.element).data('icon');
|
||||||
|
|
||||||
|
if(!optimage){
|
||||||
|
return opt.text;
|
||||||
|
} else {
|
||||||
|
var d = _.extend(
|
||||||
|
{}, data, {
|
||||||
|
'opttext': opt.text,
|
||||||
|
'optimage': optimage,
|
||||||
|
'checkbox': false
|
||||||
|
});
|
||||||
|
return $(self.selectionTemplate(d));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
formatSelection = function (opt) {
|
||||||
|
|
||||||
|
if (!opt.id) {
|
||||||
|
return opt.text;
|
||||||
|
}
|
||||||
|
|
||||||
|
var optimage = $(opt.element).data('icon'),
|
||||||
|
grantUpdate = function(ev) {
|
||||||
|
|
||||||
|
_.each(collection.where({role: opt.id}), function(m) {
|
||||||
|
m.set('admin', $(ev.target).is(":checked"));
|
||||||
|
});
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
if(!optimage){
|
||||||
|
return opt.text;
|
||||||
|
} else {
|
||||||
|
var d = _.extend(
|
||||||
|
{}, data, {
|
||||||
|
'opttext': opt.text,
|
||||||
|
'optimage': optimage,
|
||||||
|
'checkbox': true
|
||||||
|
}),
|
||||||
|
j = $(self.selectionTemplate(d));
|
||||||
|
|
||||||
|
// Update the checkbox lazy
|
||||||
|
setTimeout(
|
||||||
|
function() {
|
||||||
|
_.each(collection.where({role: opt.id}), function(m) {
|
||||||
|
j.find('input').prop('checked', m.get('admin'));
|
||||||
|
});
|
||||||
|
}, 200);
|
||||||
|
|
||||||
|
(j.find('input')).on('change', grantUpdate);
|
||||||
|
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$el.find('select').select2({
|
||||||
|
templateResult: formatState,
|
||||||
|
templateSelection: formatSelection,
|
||||||
|
multiple: true,
|
||||||
|
tags: true,
|
||||||
|
allowClear: true,
|
||||||
|
placeholder: "Select members",
|
||||||
|
width: 'style'
|
||||||
|
}).on("change", function(e) {
|
||||||
|
$(e.target).find(':selected').each(function() {
|
||||||
|
});
|
||||||
|
});
|
||||||
|
var msg = '{{ _('Selection of checkbox represents the permission to give grant to other roles.') }}';
|
||||||
|
|
||||||
|
this.$el.find('div.note').html("<span>NOTE:<br/>" + msg + "</span>");
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
onChange: function(e) {
|
||||||
|
var model = this.model,
|
||||||
|
$el = $(e.target),
|
||||||
|
attrArr = this.field.get("name").split('.'),
|
||||||
|
name = attrArr.shift(),
|
||||||
|
path = attrArr.join('.'),
|
||||||
|
vals = this.getValueFromDOM(),
|
||||||
|
collection = model.get(name),
|
||||||
|
removed = [];
|
||||||
|
|
||||||
|
this.stopListening(this.model, "change:" + name, this.render);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iterate through all the values, and find out how many are already
|
||||||
|
* present in the collection.
|
||||||
|
*/
|
||||||
|
collection.each(function(m) {
|
||||||
|
var role = m.get('role'),
|
||||||
|
idx = _.indexOf(vals, role);
|
||||||
|
|
||||||
|
if (idx > -1) {
|
||||||
|
vals.splice(idx, 1);
|
||||||
|
} else {
|
||||||
|
removed.push(role);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adding new values
|
||||||
|
*/
|
||||||
|
_.each(vals, function(v) {
|
||||||
|
collection.add({role: v});
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Removing unwanted!
|
||||||
|
*/
|
||||||
|
_.each(removed, function(v) {
|
||||||
|
collection.remove(collection.where({role: v}));
|
||||||
|
});
|
||||||
|
|
||||||
|
this.listenTo(this.model, "change:" + name, this.render);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!pgBrowser.Nodes['role']) {
|
||||||
|
var role = pgAdmin.Browser.Nodes['role'] = pgAdmin.Browser.Node.extend({
|
||||||
|
parent_type: 'server',
|
||||||
|
type: 'role',
|
||||||
|
label: '{{ _('Login/Group Role') }}',
|
||||||
|
hasSQL: true,
|
||||||
|
canDrop: true,
|
||||||
|
node_label: function(r) {
|
||||||
|
if (!r.can_login) {
|
||||||
|
return r.label + '(GROUP)';
|
||||||
|
}
|
||||||
|
return r.label;
|
||||||
|
},
|
||||||
|
node_image: function(r) {
|
||||||
|
return (r.can_login ? 'icon-role' : 'icon-group');
|
||||||
|
},
|
||||||
|
title: function(d) {
|
||||||
|
if (!d) {
|
||||||
|
return this.label;
|
||||||
|
}
|
||||||
|
if (d.can_login) {
|
||||||
|
return '{{ _('Login Role') }}' + ' - ' + d.label;
|
||||||
|
}
|
||||||
|
return '{{ _('Group Role') }}' + ' - ' + d.label;
|
||||||
|
},
|
||||||
|
Init: function() {
|
||||||
|
/* Avoid mulitple registration of menus */
|
||||||
|
if (this.initialized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.initialized = true;
|
||||||
|
|
||||||
|
pgBrowser.add_menus([{
|
||||||
|
name: 'create_role_on_server', node: 'server', module: this,
|
||||||
|
applies: ['object', 'context'], callback: 'show_obj_properties',
|
||||||
|
category: 'create', priority: 4, label: '{{ _('Login/Group Role...') }}',
|
||||||
|
icon: 'wcTabIcon icon-role', data: {action: 'create'},
|
||||||
|
enable: 'can_create_role'
|
||||||
|
},{
|
||||||
|
name: 'create_role_on_roles', node: 'coll-role', module: this,
|
||||||
|
applies: ['object', 'context'], callback: 'show_obj_properties',
|
||||||
|
category: 'create', priority: 4, label: '{{ _('Login/Group Role...') }}',
|
||||||
|
icon: 'wcTabIcon icon-role', data: {action: 'create'},
|
||||||
|
enable: 'can_create_role'
|
||||||
|
},{
|
||||||
|
name: 'create_role', node: 'role', module: this,
|
||||||
|
applies: ['object', 'context'], callback: 'show_obj_properties',
|
||||||
|
category: 'create', priority: 4, label: '{{ _('Login/Group Role...') }}',
|
||||||
|
icon: 'wcTabIcon icon-role', data: {action: 'create'},
|
||||||
|
enable: 'can_create_role'
|
||||||
|
}]);
|
||||||
|
},
|
||||||
|
can_create_role: function(node, item) {
|
||||||
|
var treeData = this.getTreeNodeHierarchy(item),
|
||||||
|
server = treeData['server'];
|
||||||
|
|
||||||
|
return server.connected && server.user.can_create_role;
|
||||||
|
},
|
||||||
|
model: pgAdmin.Browser.Node.Model.extend({
|
||||||
|
idAttribute: 'oid',
|
||||||
|
defaults: {
|
||||||
|
oid: null,
|
||||||
|
rolname: undefined,
|
||||||
|
rolcanlogin: false,
|
||||||
|
rolpassword: null,
|
||||||
|
rolconnlimit: -1,
|
||||||
|
rolsuper: false,
|
||||||
|
rolcreaterole: false,
|
||||||
|
rolcreatedb: false,
|
||||||
|
rolinherit: true,
|
||||||
|
rolcatupdate: false,
|
||||||
|
rolreplication: false,
|
||||||
|
rolmembership: [],
|
||||||
|
rolvaliduntil: null,
|
||||||
|
seclabels: [],
|
||||||
|
variables: []
|
||||||
|
},
|
||||||
|
schema: [{
|
||||||
|
id: 'rolname', label: '{{ _('Name') }}', type: 'text',
|
||||||
|
disabled: 'readonly'
|
||||||
|
},{
|
||||||
|
id: 'oid', label:'{{ _('Role ID') }}', cell: 'string',
|
||||||
|
editable: false, type: 'text', visible: true, disabled: true
|
||||||
|
},{
|
||||||
|
id: 'rolpassword', label: '{{ _('Password') }}', type: 'password',
|
||||||
|
group: '{{ _('Definition') }}', mode: ['edit', 'create'],
|
||||||
|
control: 'input', deps: ['rolcanlogin'], retype: true,
|
||||||
|
cell: 'string', disabled: function(m) {
|
||||||
|
if (!m.isNew()) {
|
||||||
|
var user = this.node_info.server.user;
|
||||||
|
|
||||||
|
return (!(user.is_superuser || user.can_create_role) &&
|
||||||
|
user.id != m.get('oid'));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},{
|
||||||
|
id: 'rolvaliduntil', disabled: 'readonly', type: 'date',
|
||||||
|
group: '{{ _('Definition') }}', label: '{{ _('Account Expires') }}',
|
||||||
|
cell: 'string', mode: ['properties', 'edit', 'create'], retype: true,
|
||||||
|
deps: ['rolcanlogin'], options: {}
|
||||||
|
},{
|
||||||
|
id: 'rolconnlimit', type: 'int', group: '{{ _('Definition') }}',
|
||||||
|
label: '{{ _('Connection Limit') }}', cell: 'number',
|
||||||
|
mode: ['properties', 'edit', 'create'], disabled: 'readonly'
|
||||||
|
},{
|
||||||
|
id: 'rolcanlogin', label:'{{ _('Can login?') }}', type: 'switch',
|
||||||
|
group: '{{ _('Role Privileges') }}', options: switchOptions,
|
||||||
|
disabled: 'readonly'
|
||||||
|
},{
|
||||||
|
id: 'rolsuper', label:'{{ _('Superuser') }}', type: 'switch',
|
||||||
|
group: '{{ _('Role Privileges') }}', options: switchOptions,
|
||||||
|
control: Backform.SwitchControl.extend({
|
||||||
|
onChange: function() {
|
||||||
|
Backform.SwitchControl.prototype.onChange.apply(this, arguments);
|
||||||
|
|
||||||
|
this.model.set('rolcatupdate', this.model.get('rolsuper'));
|
||||||
|
this.model.set('rolcreaterole', this.model.get('rolsuper'));
|
||||||
|
this.model.set('rolcreatedb', this.model.get('rolsuper'));
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
disabled: 'readonly'
|
||||||
|
},{
|
||||||
|
id: 'rolcreaterole', label:'{{ _('Create roles?') }}',
|
||||||
|
group: '{{ _('Role Privileges') }}', type: 'switch',
|
||||||
|
options: switchOptions, disabled: 'readonly'
|
||||||
|
},{
|
||||||
|
id: 'description', label:'{{ _('Comments') }}', type: 'multiline',
|
||||||
|
group: null, mode: ['properties', 'edit', 'create'],
|
||||||
|
options: switchOptions, disabled: 'readonly'
|
||||||
|
},{
|
||||||
|
id: 'rolcreatedb', label:'{{ _('Create databases?') }}',
|
||||||
|
group: '{{ _('Role Privileges') }}', type: 'switch',
|
||||||
|
options: switchOptions, disabled: 'readonly'
|
||||||
|
},{
|
||||||
|
id: 'rolcatupdate', label:'{{ _('Update Catalog?') }}',
|
||||||
|
type: 'switch', max_version: 90500, options: switchOptions,
|
||||||
|
group: '{{ _('Role Privileges') }}', disabled: function(m) {
|
||||||
|
return (m.get('read_only') || (!m.get('rolsuper')));
|
||||||
|
}
|
||||||
|
},{
|
||||||
|
id: 'rolinherit', group: '{{ _('Role Privileges') }}',
|
||||||
|
label:'{{ _('Inherit rights from the parent roles?') }}',
|
||||||
|
type: 'switch', options: switchOptions, disabled: 'readonly'
|
||||||
|
},{
|
||||||
|
id: 'rolreplication', group: '{{ _('Role Privileges') }}',
|
||||||
|
label:'{{ _('Can initiate streaming replication and backups?') }}',
|
||||||
|
type: 'switch', min_version: 90100, options: switchOptions,
|
||||||
|
disabled: 'readonly'
|
||||||
|
},{
|
||||||
|
id: 'rolmembership', label: '{{ _('Role Membership') }}',
|
||||||
|
group: '{{ _('Role Privileges') }}', type: 'collection',
|
||||||
|
cell: 'string', disabled: 'readonly',
|
||||||
|
mode: ['properties', 'edit', 'create'],
|
||||||
|
control: RoleMembersControl, model: pgBrowser.Node.Model.extend({
|
||||||
|
keys: ['role'],
|
||||||
|
defaults: {
|
||||||
|
role: undefined,
|
||||||
|
admin: false
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
filter: function(d) {
|
||||||
|
return this.model.isNew() || (this.model.get('rolname') != d.label);
|
||||||
|
}
|
||||||
|
},{
|
||||||
|
id: 'variables', label: '{{ _('Variables') }}', type: 'collection',
|
||||||
|
group: '{{ _('Security') }}', hasDatabase: true, url: 'variables',
|
||||||
|
model: pgBrowser.Node.VariableModel, control: 'variable-collection',
|
||||||
|
mode: [ 'edit', 'create'], canAdd: true, canDelete: true,
|
||||||
|
url: "variables", disabled: 'readonly'
|
||||||
|
},{
|
||||||
|
id: 'seclabels', label: '{{ _('Security Labels') }}',
|
||||||
|
model: SecurityModel, editable: false, type: 'collection',
|
||||||
|
group: '{{ _('Security') }}', mode: ['edit', 'create'],
|
||||||
|
min_version: 90200, disabled: 'readonly', canAdd: true,
|
||||||
|
canEdit: false, canDelete: true, control: 'unique-col-collection'
|
||||||
|
}],
|
||||||
|
readonly: function(m) {
|
||||||
|
if (!m.has('read_only')) {
|
||||||
|
var user = this.node_info.server.user;
|
||||||
|
|
||||||
|
m.set('read_only', !(user.is_superuser || user.can_create_role));
|
||||||
|
}
|
||||||
|
|
||||||
|
return m.get('read_only');
|
||||||
|
},
|
||||||
|
validate: function()
|
||||||
|
{
|
||||||
|
var err = {},
|
||||||
|
errmsg,
|
||||||
|
seclabels = this.get('seclabels');
|
||||||
|
|
||||||
|
if (_.isUndefined(this.get('rolname')) || String(this.get('rolname')).replace(/^\s+|\s+$/g, '') == '') {
|
||||||
|
err['name'] = '{{ _('Name can not be empty!') }}';
|
||||||
|
errmsg = errmsg || err['name'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (seclabels) {
|
||||||
|
var secLabelsErr;
|
||||||
|
for (var i = 0; i < seclabels.models.length && !secLabelsErr; i++) {
|
||||||
|
secLabelsErr = (seclabels.models[i]).validate.apply(seclabels.models[i]);
|
||||||
|
if (secLabelsErr) {
|
||||||
|
err['seclabels'] = secLabelsErr;
|
||||||
|
errmsg = errmsg || secLabelsErr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.errorModel.clear().set(err);
|
||||||
|
|
||||||
|
if (_.size(err)) {
|
||||||
|
this.trigger('on-status', {msg: errmsg});
|
||||||
|
return errmsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
sg = pgBrowser.Nodes['server-group'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return pgBrowser.Nodes['role'];
|
||||||
|
});
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
{% import 'macros/security.macros' as SECLABLE %}
|
||||||
|
{% import 'macros/variable.macros' as VARIABLE %}
|
||||||
|
CREATE {% if data.rolcanlogin %}USER{% else %}ROLE{% endif %} {{ 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 '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 }} {% endif %}{% if data.rolpassword %}
|
||||||
|
|
||||||
|
PASSWORD {% if data.rolpassword is none %}NULL{% else %}{% if dummy %}'xxxxxx'{% else %} {{ data.rolpassword | qtLiteral }}{% endif %}{% endif %}{% endif %};{% if data.rolsuper and data.rolcatupdate is sameas false %}
|
||||||
|
|
||||||
|
|
||||||
|
UPDATE pg_authid SET rolcatupdate=false WHERE rolname = {{ data.rolname|qtLiteral }};{% 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.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 }};
|
||||||
|
{% endif %}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
SELECT
|
||||||
|
r.oid, r.rolname, r.rolcanlogin, r.rolsuper
|
||||||
|
FROM
|
||||||
|
{{ role_tbl }} r
|
||||||
|
{% if rid %}
|
||||||
|
WHERE r.oid = {{ rid }}::int
|
||||||
|
{% endif %}
|
||||||
|
ORDER BY r.rolcanlogin, r.rolname
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
SELECT
|
||||||
|
rolname, rolcanlogin, rolcatupdate, rolsuper
|
||||||
|
FROM
|
||||||
|
pg_roles
|
||||||
|
WHERE oid = {{ rid }}::OID
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
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 || rm.rolname
|
||||||
|
FROM
|
||||||
|
(SELECT * FROM pg_auth_members WHERE member = r.oid) am
|
||||||
|
LEFT JOIN pg_catalog.pg_roles rm ON (rm.oid = am.roleid)
|
||||||
|
) rolmembership
|
||||||
|
FROM
|
||||||
|
{{ role_tbl }} r
|
||||||
|
{% if rid %}
|
||||||
|
WHERE r.oid = {{ rid }}::int
|
||||||
|
{% endif %}
|
||||||
|
ORDER BY r.rolcanlogin, r.rolname
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
SELECT
|
||||||
|
array_to_string(array_agg(sql), E'\n\n')
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
CASE WHEN rolcanlogin THEN '-- User: ' ELSE '-- Role: ' END ||
|
||||||
|
pg_catalog.quote_ident(rolname) ||
|
||||||
|
E'\n-- DROP ' || CASE WHEN rolcanlogin THEN 'USER ' ELSE 'ROLE ' END ||
|
||||||
|
pg_catalog.quote_ident(rolname) || E';\n\nCREATE ' ||
|
||||||
|
CASE WHEN rolcanlogin THEN 'USER ' ELSE 'ROLE ' END ||
|
||||||
|
pg_catalog.quote_ident(rolname) || E' WITH\n ' ||
|
||||||
|
CASE WHEN rolcanlogin THEN 'LOGIN' ELSE 'NOLOGIN' END || E'\n ' ||
|
||||||
|
CASE WHEN rolcanlogin AND rolpassword LIKE 'md5%%' THEN 'ENCRYPTED PASSWORD ' || quote_literal(rolpassword) || E'\n ' ELSE '' END ||
|
||||||
|
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 ' ||
|
||||||
|
CASE WHEN rolconnlimit > 0 THEN E'\n CONNECTION LIMIT ' || rolconnlimit ELSE '' END ||
|
||||||
|
CASE WHEN rolvaliduntil IS NOT NULL THEN E'\n VALID UNTIL ' || quote_literal(rolvaliduntil::text) ELSE ';' END ||
|
||||||
|
-- PostgreSQL < 9.5
|
||||||
|
CASE WHEN rolsuper AND NOT rolcatupdate THEN E'\n\nUPDATE pg_authid SET rolcatupdate=false WHERE rolname=' || pg_catalog.quote_literal(rolname) || ';' ELSE '' END AS sql
|
||||||
|
FROM
|
||||||
|
{{ role_tbl }} r
|
||||||
|
WHERE
|
||||||
|
r.oid=%(rid)s::OID
|
||||||
|
UNION ALL
|
||||||
|
(SELECT
|
||||||
|
array_to_string(array_agg(sql), E'\n')
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
'GRANT ' || array_to_string(array_agg(rolname), ', ') || ' TO ' || pg_catalog.quote_ident(pg_get_userbyid(%(rid)s::OID)) ||
|
||||||
|
CASE WHEN admin_option THEN ' WITH ADMIN OPTION;' ELSE ';' END sql
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
quote_ident(r.rolname) AS rolname, m.admin_option AS admin_option
|
||||||
|
FROM
|
||||||
|
pg_auth_members m
|
||||||
|
LEFT JOIN pg_roles r ON (m.roleid = r.oid)
|
||||||
|
WHERE
|
||||||
|
m.member=%(rid)s::OID
|
||||||
|
ORDER BY
|
||||||
|
r.rolname
|
||||||
|
) a
|
||||||
|
GROUP BY admin_option) s)
|
||||||
|
UNION ALL
|
||||||
|
(SELECT
|
||||||
|
array_to_string(array_agg(sql), E'\n') sql
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
'ALTER ' || CASE WHEN rolcanlogin THEN 'USER ' ELSE 'ROLE ' END || pg_catalog.quote_ident(rolname) || ' SET ' || param || ' TO ' || CASE WHEN param IN ('search_path', 'temp_tablespaces') THEN value ELSE quote_literal(value) END || ';' AS sql
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
rolcanlogin, rolname, split_part(rolconfig, '=', 1) AS param, replace(rolconfig, split_part(rolconfig, '=', 1) || '=', '') AS value
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
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
|
||||||
|
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 quote_literal(value)
|
||||||
|
END || ';' AS sql
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
datname, split_part(rolconfig, '=', 1) AS param, replace(rolconfig, split_part(rolconfig, '=', 1) || '=', '') AS value
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
d.datname, 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)) AS a
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
{% import 'macros/variable.macros' as VARIABLE %}
|
||||||
|
{% if 'rolname' in data %}
|
||||||
|
{% set rolname=data.rolname %}
|
||||||
|
ALTER{% if rolCanLogin %} USER {% else %} ROLE {% endif %}{{ conn|qtIdent(role) }}
|
||||||
|
RENAME TO {{ conn|qtIdent(rolname) }};
|
||||||
|
|
||||||
|
{% else %}
|
||||||
|
{% set rolname=role %}
|
||||||
|
{% endif %}
|
||||||
|
{% if data|hasAny(alterKeys) %}
|
||||||
|
ALTER {% if rolCanLogin %}USER{% else %}ROLE{% endif %} {{ 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 'rolconnlimit' in data and data.rolconnlimit is number and data.rolconnlimit >= -1 %}
|
||||||
|
|
||||||
|
CONNECTION LIMIT {{ data.rolconnlimit }}
|
||||||
|
{% endif %}{% if 'rolvaliduntil' in data and data.rolvaliduntil %}
|
||||||
|
|
||||||
|
VALID UNTIL {% if data.rolvaliduntil is not none %}{{ data.rolvaliduntil|qtLiteral }}{% else %}'infinity'
|
||||||
|
{% endif %}{% endif %}{% if 'rolpassword' in data %}
|
||||||
|
|
||||||
|
PASSWORD{% if data.rolpassword is none %} NULL{% else %}{% if dummy %} 'xxxxxx'{% else %} {{ data.rolpassword|qtLiteral }}{% endif %}{% endif %}{% endif %};{% endif %}
|
||||||
|
|
||||||
|
{% if
|
||||||
|
not rolSuper and
|
||||||
|
'rolsuper' in data and
|
||||||
|
'rolcatupdate' not in data and
|
||||||
|
data.rolsuper %}
|
||||||
|
|
||||||
|
|
||||||
|
UPDATE pg_authid SET rolcatupdate=false WHERE rolname = {{ rolname|qtLiteral }};
|
||||||
|
|
||||||
|
{% elif
|
||||||
|
rolSuper and
|
||||||
|
'rolsuper' not in data and
|
||||||
|
'rolcatupdate' in data %}
|
||||||
|
{% if data.rolcatupdate %}
|
||||||
|
|
||||||
|
|
||||||
|
UPDATE pg_authid SET rolcatupdate=true WHERE rolname = {{ rolname|qtLiteral }};
|
||||||
|
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
|
||||||
|
UPDATE pg_authid SET rolcatupdate=false WHERE rolname = {{ rolname|qtLiteral }};
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% if 'revoked_admins' in data and
|
||||||
|
data.revoked_admins|length > 0
|
||||||
|
%}
|
||||||
|
|
||||||
|
-- Revoked the admin options from the members
|
||||||
|
REVOKE ADMIN OPTION FOR {{ conn|qtIdent(data.revoked_admins)|join(', ') }} FROM {{ conn|qtIdent(rolname) }};{% endif %}{% if 'revoked' in data and data.revoked|length > 0 %}
|
||||||
|
|
||||||
|
|
||||||
|
-- Following are no more the members
|
||||||
|
REVOKE {{ conn|qtIdent(data.revoked)|join(', ') }} FROM {{ conn|qtIdent(rolname) }};{% endif %}{% if data.admins and data.admins|length > 0 %}
|
||||||
|
|
||||||
|
-- Following are the new admins (or, existing members made admins)
|
||||||
|
GRANT {{ conn|qtIdent(data.admins)|join(', ') }} TO {{ conn|qtIdent(rolname) }} WITH ADMIN OPTION;{% endif %}{% if data.members and data.members|length > 0 %}
|
||||||
|
|
||||||
|
|
||||||
|
-- Following are the new members
|
||||||
|
GRANT {{ conn|qtIdent(data.members)|join(', ') }} TO {{ conn|qtIdent(rolname) }};{% 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 }};
|
||||||
|
{% endif %}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
SELECT
|
||||||
|
split_part(rolconfig, '=', 1) AS name, replace(rolconfig, split_part(rolconfig, '=', 1) || '=', '') AS value, NULL::text AS database
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
unnest(rolconfig) AS rolconfig, rolcanlogin, rolname
|
||||||
|
FROM
|
||||||
|
pg_catalog.pg_roles
|
||||||
|
WHERE
|
||||||
|
oid={{ rid|qtLiteral }}::OID
|
||||||
|
) r
|
||||||
|
|
||||||
|
UNION ALL
|
||||||
|
SELECT
|
||||||
|
split_part(rolconfig, '=', 1) AS name, replace(rolconfig, split_part(rolconfig, '=', 1) || '=', '') AS value, datname AS database
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
d.datname, unnest(c.setconfig) AS rolconfig
|
||||||
|
FROM
|
||||||
|
(SELECT *
|
||||||
|
FROM pg_catalog.pg_db_role_setting dr
|
||||||
|
WHERE
|
||||||
|
dr.setrole={{ rid|qtLiteral }}::OID AND dr.setdatabase!=0
|
||||||
|
) c
|
||||||
|
LEFT JOIN pg_catalog.pg_database d ON (d.oid = c.setdatabase)
|
||||||
|
) a;
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
{% import 'macros/security.macros' as SECLABLE %}
|
||||||
|
{% import 'macros/variable.macros' as VARIABLE %}
|
||||||
|
CREATE {% if data.rolcanlogin %}USER{% else %}ROLE{% endif %} {{ 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 '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 }} {% endif %}{% if data.rolpassword %}
|
||||||
|
|
||||||
|
PASSWORD {% if data.rolpassword is none %}NULL{% else %}{% if dummy %}'xxxxxx'{% else %} {{ data.rolpassword | qtLiteral }}{% endif %}{% endif %}{% endif %};{% if data.rolsuper and data.rolcatupdate is sameas false %}
|
||||||
|
|
||||||
|
|
||||||
|
UPDATE pg_authid SET rolcatupdate=false WHERE rolname = {{ data.rolname|qtLiteral }};{% 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.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 }};
|
||||||
|
{% endif %}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
SELECT
|
||||||
|
r.oid, r.rolname, r.rolcanlogin, r.rolsuper
|
||||||
|
FROM
|
||||||
|
{{ role_tbl }} r
|
||||||
|
{% if rid %}
|
||||||
|
WHERE r.oid = {{ rid }}::int
|
||||||
|
{% endif %}
|
||||||
|
ORDER BY r.rolcanlogin, r.rolname
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
SELECT
|
||||||
|
rolname, rolcanlogin, rolcatupdate, rolsuper
|
||||||
|
FROM
|
||||||
|
pg_roles
|
||||||
|
WHERE oid = {{ rid }}::OID
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
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 || rm.rolname
|
||||||
|
FROM
|
||||||
|
(SELECT * FROM pg_auth_members WHERE member = r.oid) am
|
||||||
|
LEFT JOIN pg_catalog.pg_roles rm ON (rm.oid = am.roleid)
|
||||||
|
) rolmembership
|
||||||
|
FROM
|
||||||
|
{{ role_tbl }} r
|
||||||
|
{% if rid %}
|
||||||
|
WHERE r.oid = {{ rid }}::int
|
||||||
|
{% endif %}
|
||||||
|
ORDER BY r.rolcanlogin, r.rolname
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
SELECT
|
||||||
|
array_to_string(array_agg(sql), E'\n\n')
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
CASE WHEN rolcanlogin THEN '-- User: ' ELSE '-- Role: ' END ||
|
||||||
|
pg_catalog.quote_ident(rolname) ||
|
||||||
|
E'\n-- DROP ' || CASE WHEN rolcanlogin THEN 'USER ' ELSE 'ROLE ' END ||
|
||||||
|
pg_catalog.quote_ident(rolname) || E';\n\nCREATE ' ||
|
||||||
|
CASE WHEN rolcanlogin THEN 'USER ' ELSE 'ROLE ' END ||
|
||||||
|
pg_catalog.quote_ident(rolname) || E' WITH\n ' ||
|
||||||
|
CASE WHEN rolcanlogin THEN 'LOGIN' ELSE 'NOLOGIN' END || E'\n ' ||
|
||||||
|
CASE WHEN rolcanlogin AND rolpassword LIKE 'md5%%' THEN 'ENCRYPTED PASSWORD ' || quote_literal(rolpassword) || E'\n ' ELSE '' END ||
|
||||||
|
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 ' ||
|
||||||
|
CASE WHEN rolconnlimit > 0 THEN E'\n CONNECTION LIMIT ' || rolconnlimit ELSE '' END ||
|
||||||
|
CASE WHEN rolvaliduntil IS NOT NULL THEN E'\n VALID UNTIL ' || quote_literal(rolvaliduntil::text) ELSE ';' END ||
|
||||||
|
-- PostgreSQL < 9.5
|
||||||
|
CASE WHEN rolsuper AND NOT rolcatupdate THEN E'\n\nUPDATE pg_authid SET rolcatupdate=false WHERE rolname=' || pg_catalog.quote_literal(rolname) || ';' ELSE '' END AS sql
|
||||||
|
FROM
|
||||||
|
{{ role_tbl }} r
|
||||||
|
WHERE
|
||||||
|
r.oid=%(rid)s::OID
|
||||||
|
UNION ALL
|
||||||
|
(SELECT
|
||||||
|
array_to_string(array_agg(sql), E'\n')
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
'GRANT ' || array_to_string(array_agg(rolname), ', ') || ' TO ' || pg_catalog.quote_ident(pg_get_userbyid(%(rid)s::OID)) ||
|
||||||
|
CASE WHEN admin_option THEN ' WITH ADMIN OPTION;' ELSE ';' END sql
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
quote_ident(r.rolname) AS rolname, m.admin_option AS admin_option
|
||||||
|
FROM
|
||||||
|
pg_auth_members m
|
||||||
|
LEFT JOIN pg_roles r ON (m.roleid = r.oid)
|
||||||
|
WHERE
|
||||||
|
m.member=%(rid)s::OID
|
||||||
|
ORDER BY
|
||||||
|
r.rolname
|
||||||
|
) a
|
||||||
|
GROUP BY admin_option) s)
|
||||||
|
UNION ALL
|
||||||
|
(SELECT
|
||||||
|
array_to_string(array_agg(sql), E'\n') sql
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
'ALTER ' || CASE WHEN rolcanlogin THEN 'USER ' ELSE 'ROLE ' END || pg_catalog.quote_ident(rolname) || ' SET ' || param || ' TO ' || CASE WHEN param IN ('search_path', 'temp_tablespaces') THEN value ELSE quote_literal(value) END || ';' AS sql
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
rolcanlogin, rolname, split_part(rolconfig, '=', 1) AS param, replace(rolconfig, split_part(rolconfig, '=', 1) || '=', '') AS value
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
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
|
||||||
|
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 quote_literal(value)
|
||||||
|
END || ';' AS sql
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
datname, split_part(rolconfig, '=', 1) AS param, replace(rolconfig, split_part(rolconfig, '=', 1) || '=', '') AS value
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
d.datname, 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)) AS a
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
{% import 'macros/variable.macros' as VARIABLE %}
|
||||||
|
{% if 'rolname' in data %}
|
||||||
|
{% set rolname=data.rolname %}
|
||||||
|
ALTER{% if rolCanLogin %} USER {% else %} ROLE {% endif %}{{ conn|qtIdent(role) }}
|
||||||
|
RENAME TO {{ conn|qtIdent(rolname) }};
|
||||||
|
|
||||||
|
{% else %}
|
||||||
|
{% set rolname=role %}
|
||||||
|
{% endif %}
|
||||||
|
{% if data|hasAny(alterKeys) %}
|
||||||
|
ALTER {% if rolCanLogin %}USER{% else %}ROLE{% endif %} {{ 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 'rolconnlimit' in data and data.rolconnlimit is number and data.rolconnlimit >= -1 %}
|
||||||
|
|
||||||
|
CONNECTION LIMIT {{ data.rolconnlimit }}
|
||||||
|
{% endif %}{% if 'rolvaliduntil' in data and data.rolvaliduntil %}
|
||||||
|
|
||||||
|
VALID UNTIL {% if data.rolvaliduntil is not none %}{{ data.rolvaliduntil|qtLiteral }}{% else %}'infinity'
|
||||||
|
{% endif %}{% endif %}{% if 'rolpassword' in data %}
|
||||||
|
|
||||||
|
PASSWORD{% if data.rolpassword is none %} NULL{% else %}{% if dummy %} 'xxxxxx'{% else %} {{ data.rolpassword|qtLiteral }}{% endif %}{% endif %}{% endif %};{% endif %}
|
||||||
|
|
||||||
|
{% if
|
||||||
|
not rolSuper and
|
||||||
|
'rolsuper' in data and
|
||||||
|
'rolcatupdate' not in data and
|
||||||
|
data.rolsuper %}
|
||||||
|
|
||||||
|
|
||||||
|
UPDATE pg_authid SET rolcatupdate=false WHERE rolname = {{ rolname|qtLiteral }};
|
||||||
|
|
||||||
|
{% elif
|
||||||
|
rolSuper and
|
||||||
|
'rolsuper' not in data and
|
||||||
|
'rolcatupdate' in data %}
|
||||||
|
{% if data.rolcatupdate %}
|
||||||
|
|
||||||
|
|
||||||
|
UPDATE pg_authid SET rolcatupdate=true WHERE rolname = {{ rolname|qtLiteral }};
|
||||||
|
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
|
||||||
|
UPDATE pg_authid SET rolcatupdate=false WHERE rolname = {{ rolname|qtLiteral }};
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% if 'revoked_admins' in data and
|
||||||
|
data.revoked_admins|length > 0
|
||||||
|
%}
|
||||||
|
|
||||||
|
-- Revoked the admin options from the members
|
||||||
|
REVOKE ADMIN OPTION FOR {{ conn|qtIdent(data.revoked_admins)|join(', ') }} FROM {{ conn|qtIdent(rolname) }};{% endif %}{% if 'revoked' in data and data.revoked|length > 0 %}
|
||||||
|
|
||||||
|
|
||||||
|
-- Following are no more the members
|
||||||
|
REVOKE {{ conn|qtIdent(data.revoked)|join(', ') }} FROM {{ conn|qtIdent(rolname) }};{% endif %}{% if data.admins and data.admins|length > 0 %}
|
||||||
|
|
||||||
|
-- Following are the new admins (or, existing members made admins)
|
||||||
|
GRANT {{ conn|qtIdent(data.admins)|join(', ') }} TO {{ conn|qtIdent(rolname) }} WITH ADMIN OPTION;{% endif %}{% if data.members and data.members|length > 0 %}
|
||||||
|
|
||||||
|
|
||||||
|
-- Following are the new members
|
||||||
|
GRANT {{ conn|qtIdent(data.members)|join(', ') }} TO {{ conn|qtIdent(rolname) }};{% 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 }};
|
||||||
|
{% endif %}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
SELECT
|
||||||
|
split_part(rolconfig, '=', 1) AS name, replace(rolconfig, split_part(rolconfig, '=', 1) || '=', '') AS value, NULL::text AS database
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
unnest(rolconfig) AS rolconfig, rolcanlogin, rolname
|
||||||
|
FROM
|
||||||
|
pg_catalog.pg_roles
|
||||||
|
WHERE
|
||||||
|
oid={{ rid|qtLiteral }}::OID
|
||||||
|
) r
|
||||||
|
|
||||||
|
UNION ALL
|
||||||
|
SELECT
|
||||||
|
split_part(rolconfig, '=', 1) AS name, replace(rolconfig, split_part(rolconfig, '=', 1) || '=', '') AS value, datname AS database
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
d.datname, unnest(c.setconfig) AS rolconfig
|
||||||
|
FROM
|
||||||
|
(SELECT *
|
||||||
|
FROM pg_catalog.pg_db_role_setting dr
|
||||||
|
WHERE
|
||||||
|
dr.setrole={{ rid|qtLiteral }}::OID AND dr.setdatabase!=0
|
||||||
|
) c
|
||||||
|
LEFT JOIN pg_catalog.pg_database d ON (d.oid = c.setdatabase)
|
||||||
|
) a;
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
{% import 'macros/security.macros' as SECLABLE %}
|
||||||
|
{% import 'macros/variable.macros' as VARIABLE %}
|
||||||
|
CREATE {% if data.rolcanlogin %}USER{% else %}ROLE{% endif %} {{ 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 '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 }} {% endif %}{% if data.rolpassword %}
|
||||||
|
|
||||||
|
PASSWORD {% if data.rolpassword is none %}NULL{% else %}{% if dummy %}'xxxxxx'{% else %} {{ data.rolpassword | qtLiteral }}{% endif %}{% endif %}{% endif %};{% if data.rolsuper and data.rolcatupdate is sameas false %}
|
||||||
|
|
||||||
|
|
||||||
|
UPDATE pg_authid SET rolcatupdate=false WHERE rolname = {{ data.rolname|qtLiteral }};{% 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 %}
|
||||||
|
|
||||||
|
{% for r in data.seclabels %}
|
||||||
|
|
||||||
|
{{ SECLABLE.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 }};
|
||||||
|
{% endif %}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
SELECT
|
||||||
|
r.oid, r.rolname, r.rolcanlogin, r.rolsuper
|
||||||
|
FROM
|
||||||
|
{{ role_tbl }} r
|
||||||
|
{% if rid %}
|
||||||
|
WHERE r.oid = {{ rid }}::int
|
||||||
|
{% endif %}
|
||||||
|
ORDER BY r.rolcanlogin, r.rolname
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
SELECT
|
||||||
|
rolname, rolcanlogin, rolcatupdate, rolsuper
|
||||||
|
FROM
|
||||||
|
pg_roles
|
||||||
|
WHERE oid = {{ rid }}::OID
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
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 || rm.rolname
|
||||||
|
FROM
|
||||||
|
(SELECT * FROM pg_auth_members WHERE member = r.oid) am
|
||||||
|
LEFT JOIN pg_catalog.pg_roles rm ON (rm.oid = am.roleid)
|
||||||
|
) rolmembership,
|
||||||
|
(SELECT array_agg(provider || '=' || label) FROM pg_shseclabel sl1 WHERE sl1.objoid=r.oid) AS seclabels
|
||||||
|
FROM
|
||||||
|
{{ role_tbl }} r
|
||||||
|
{% if rid %}
|
||||||
|
WHERE r.oid = {{ rid }}::int
|
||||||
|
{% endif %}
|
||||||
|
ORDER BY r.rolcanlogin, r.rolname
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
SELECT
|
||||||
|
array_to_string(array_agg(sql), E'\n\n')
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
CASE WHEN rolcanlogin THEN '-- User: ' ELSE '-- Role: ' END ||
|
||||||
|
pg_catalog.quote_ident(rolname) ||
|
||||||
|
E'\n-- DROP ' || CASE WHEN rolcanlogin THEN 'USER ' ELSE 'ROLE ' END ||
|
||||||
|
pg_catalog.quote_ident(rolname) || E';\n\nCREATE ' ||
|
||||||
|
CASE WHEN rolcanlogin THEN 'USER ' ELSE 'ROLE ' END ||
|
||||||
|
pg_catalog.quote_ident(rolname) || E' WITH\n ' ||
|
||||||
|
CASE WHEN rolcanlogin THEN 'LOGIN' ELSE 'NOLOGIN' END || E'\n ' ||
|
||||||
|
CASE WHEN rolcanlogin AND rolpassword LIKE 'md5%%' THEN 'ENCRYPTED PASSWORD ' || quote_literal(rolpassword) || E'\n ' ELSE '' END ||
|
||||||
|
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 ||
|
||||||
|
CASE WHEN rolconnlimit > 0 THEN E'\n CONNECTION LIMIT ' || rolconnlimit ELSE '' END ||
|
||||||
|
CASE WHEN rolvaliduntil IS NOT NULL THEN E'\n VALID UNTIL ' || quote_literal(rolvaliduntil::text) ELSE ';' END ||
|
||||||
|
-- PostgreSQL < 9.5
|
||||||
|
CASE WHEN rolsuper AND NOT rolcatupdate THEN E'\n\nUPDATE pg_authid SET rolcatupdate=false WHERE rolname=' || pg_catalog.quote_literal(rolname) || ';' ELSE '' END AS sql
|
||||||
|
FROM
|
||||||
|
{{ role_tbl }} r
|
||||||
|
WHERE
|
||||||
|
r.oid=%(rid)s::OID
|
||||||
|
UNION ALL
|
||||||
|
(SELECT
|
||||||
|
array_to_string(array_agg(sql), E'\n')
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
'GRANT ' || array_to_string(array_agg(rolname), ', ') || ' TO ' || pg_catalog.quote_ident(pg_get_userbyid(%(rid)s::OID)) ||
|
||||||
|
CASE WHEN admin_option THEN ' WITH ADMIN OPTION;' ELSE ';' END sql
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
quote_ident(r.rolname) AS rolname, m.admin_option AS admin_option
|
||||||
|
FROM
|
||||||
|
pg_auth_members m
|
||||||
|
LEFT JOIN pg_roles r ON (m.roleid = r.oid)
|
||||||
|
WHERE
|
||||||
|
m.member=%(rid)s::OID
|
||||||
|
ORDER BY
|
||||||
|
r.rolname
|
||||||
|
) a
|
||||||
|
GROUP BY admin_option) s)
|
||||||
|
UNION ALL
|
||||||
|
(SELECT
|
||||||
|
array_to_string(array_agg(sql), E'\n') sql
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
'ALTER ' || CASE WHEN rolcanlogin THEN 'USER ' ELSE 'ROLE ' END || pg_catalog.quote_ident(rolname) || ' SET ' || param || ' TO ' || CASE WHEN param IN ('search_path', 'temp_tablespaces') THEN value ELSE quote_literal(value) END || ';' AS sql
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
rolcanlogin, rolname, split_part(rolconfig, '=', 1) AS param, replace(rolconfig, split_part(rolconfig, '=', 1) || '=', '') AS value
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
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
|
||||||
|
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 quote_literal(value)
|
||||||
|
END || ';' AS sql
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
datname, split_part(rolconfig, '=', 1) AS param, replace(rolconfig, split_part(rolconfig, '=', 1) || '=', '') AS value
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
d.datname, 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
|
||||||
|
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_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
|
||||||
@@ -0,0 +1,132 @@
|
|||||||
|
{% import 'macros/security.macros' as SECLABLE %}
|
||||||
|
{% import 'macros/variable.macros' as VARIABLE %}
|
||||||
|
{% if 'rolname' in data %}
|
||||||
|
{% set rolname=data.rolname %}
|
||||||
|
ALTER{% if rolCanLogin %} USER {% else %} ROLE {% endif %}{{ conn|qtIdent(role) }}
|
||||||
|
RENAME TO {{ conn|qtIdent(rolname) }};
|
||||||
|
|
||||||
|
{% else %}
|
||||||
|
{% set rolname=role %}
|
||||||
|
{% endif %}
|
||||||
|
{% if data|hasAny(alterKeys) %}
|
||||||
|
ALTER {% if rolCanLogin %}USER{% else %}ROLE{% endif %} {{ 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 'rolconnlimit' in data and data.rolconnlimit is number and data.rolconnlimit >= -1 %}
|
||||||
|
|
||||||
|
CONNECTION LIMIT {{ data.rolconnlimit }}
|
||||||
|
{% endif %}{% if 'rolvaliduntil' in data and data.rolvaliduntil %}
|
||||||
|
|
||||||
|
VALID UNTIL {% if data.rolvaliduntil is not none %}{{ data.rolvaliduntil|qtLiteral }}{% else %}'infinity'
|
||||||
|
{% endif %}{% endif %}{% if 'rolpassword' in data %}
|
||||||
|
|
||||||
|
PASSWORD{% if data.rolpassword is none %} NULL{% else %}{% if dummy %} 'xxxxxx'{% else %} {{ data.rolpassword|qtLiteral }}{% endif %}{% endif %}{% endif %};{% endif %}
|
||||||
|
|
||||||
|
{% if
|
||||||
|
not rolSuper and
|
||||||
|
'rolsuper' in data and
|
||||||
|
'rolcatupdate' not in data and
|
||||||
|
data.rolsuper %}
|
||||||
|
|
||||||
|
|
||||||
|
UPDATE pg_authid SET rolcatupdate=false WHERE rolname = {{ rolname|qtLiteral }};
|
||||||
|
|
||||||
|
{% elif
|
||||||
|
rolSuper and
|
||||||
|
'rolsuper' not in data and
|
||||||
|
'rolcatupdate' in data %}
|
||||||
|
{% if data.rolcatupdate %}
|
||||||
|
|
||||||
|
|
||||||
|
UPDATE pg_authid SET rolcatupdate=true WHERE rolname = {{ rolname|qtLiteral }};
|
||||||
|
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
|
||||||
|
UPDATE pg_authid SET rolcatupdate=false WHERE rolname = {{ rolname|qtLiteral }};
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% if 'revoked_admins' in data and
|
||||||
|
data.revoked_admins|length > 0
|
||||||
|
%}
|
||||||
|
|
||||||
|
-- Revoked the admin options from the members
|
||||||
|
REVOKE ADMIN OPTION FOR {{ conn|qtIdent(data.revoked_admins)|join(', ') }} FROM {{ conn|qtIdent(rolname) }};{% endif %}{% if 'revoked' in data and data.revoked|length > 0 %}
|
||||||
|
|
||||||
|
|
||||||
|
-- Following are no more the members
|
||||||
|
REVOKE {{ conn|qtIdent(data.revoked)|join(', ') }} FROM {{ conn|qtIdent(rolname) }};{% endif %}{% if data.admins and data.admins|length > 0 %}
|
||||||
|
|
||||||
|
-- Following are the new admins (or, existing members made admins)
|
||||||
|
GRANT {{ conn|qtIdent(data.admins)|join(', ') }} TO {{ conn|qtIdent(rolname) }} WITH ADMIN OPTION;{% endif %}{% if data.members and data.members|length > 0 %}
|
||||||
|
|
||||||
|
|
||||||
|
-- Following are the new members
|
||||||
|
GRANT {{ conn|qtIdent(data.members)|join(', ') }} TO {{ conn|qtIdent(rolname) }};{% 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 %}
|
||||||
|
{{ SECLABLE.DROP(conn, 'ROLE', data.rolname, r.provider) }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% if 'added' in seclabels and seclabels.added|length > 0 %}
|
||||||
|
|
||||||
|
{% for r in seclabels.added %}
|
||||||
|
{{ SECLABLE.APPLY(conn, 'ROLE', data.rolname, r.provider, r.label) }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
|
||||||
|
|
||||||
|
{% for r in seclabels.changed %}
|
||||||
|
{{ SECLABLE.APPLY(conn, 'ROLE', data.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 }};
|
||||||
|
{% endif %}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
SELECT
|
||||||
|
split_part(rolconfig, '=', 1) AS name, replace(rolconfig, split_part(rolconfig, '=', 1) || '=', '') AS value, NULL::text AS database
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
unnest(rolconfig) AS rolconfig, rolcanlogin, rolname
|
||||||
|
FROM
|
||||||
|
pg_catalog.pg_roles
|
||||||
|
WHERE
|
||||||
|
oid={{ rid|qtLiteral }}::OID
|
||||||
|
) r
|
||||||
|
|
||||||
|
UNION ALL
|
||||||
|
SELECT
|
||||||
|
split_part(rolconfig, '=', 1) AS name, replace(rolconfig, split_part(rolconfig, '=', 1) || '=', '') AS value, datname AS database
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
d.datname, unnest(c.setconfig) AS rolconfig
|
||||||
|
FROM
|
||||||
|
(SELECT *
|
||||||
|
FROM pg_catalog.pg_db_role_setting dr
|
||||||
|
WHERE
|
||||||
|
dr.setrole={{ rid|qtLiteral }}::OID AND dr.setdatabase!=0
|
||||||
|
) c
|
||||||
|
LEFT JOIN pg_catalog.pg_database d ON (d.oid = c.setdatabase)
|
||||||
|
) a;
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
{% import 'macros/security.macros' as SECLABLE %}
|
||||||
|
{% import 'macros/variable.macros' as VARIABLE %}
|
||||||
|
CREATE {% if data.rolcanlogin %}USER{% else %}ROLE{% endif %} {{ 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 '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 }} {% endif %}{% if data.rolpassword %}
|
||||||
|
|
||||||
|
PASSWORD {% if data.rolpassword is none %}NULL{% else %}{% if dummy %}'xxxxxx'{% else %} {{ data.rolpassword | qtLiteral }}{% 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 %}
|
||||||
|
|
||||||
|
{% for r in data.seclabels %}
|
||||||
|
|
||||||
|
{{ SECLABLE.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 }};
|
||||||
|
{% endif %}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
SELECT
|
||||||
|
r.oid, r.rolname, r.rolcanlogin, r.rolsuper
|
||||||
|
FROM
|
||||||
|
{{ role_tbl }} r
|
||||||
|
{% if rid %}
|
||||||
|
WHERE r.oid = {{ rid }}::int
|
||||||
|
{% endif %}
|
||||||
|
ORDER BY r.rolcanlogin, r.rolname
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
SELECT
|
||||||
|
rolname, rolcanlogin, rolsuper AS rolcatupdate, rolsuper
|
||||||
|
FROM
|
||||||
|
pg_roles
|
||||||
|
WHERE oid = {{ rid }}::OID
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
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 || rm.rolname
|
||||||
|
FROM
|
||||||
|
(SELECT * FROM pg_auth_members WHERE member = r.oid) am
|
||||||
|
LEFT JOIN pg_catalog.pg_roles rm ON (rm.oid = am.roleid)
|
||||||
|
) rolmembership,
|
||||||
|
(SELECT array_agg(provider || '=' || label) FROM pg_shseclabel sl1 WHERE sl1.objoid=r.oid) AS seclabels
|
||||||
|
FROM
|
||||||
|
{{ role_tbl }} r
|
||||||
|
{% if rid %}
|
||||||
|
WHERE r.oid = {{ rid }}::int
|
||||||
|
{% endif %}
|
||||||
|
ORDER BY r.rolcanlogin, r.rolname
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
SELECT
|
||||||
|
array_to_string(array_agg(sql), E'\n\n')
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
CASE WHEN rolcanlogin THEN '-- User: ' ELSE '-- Role: ' END ||
|
||||||
|
pg_catalog.quote_ident(rolname) ||
|
||||||
|
E'\n-- DROP ' || CASE WHEN rolcanlogin THEN 'USER ' ELSE 'ROLE ' END ||
|
||||||
|
pg_catalog.quote_ident(rolname) || E';\n\nCREATE ' ||
|
||||||
|
CASE WHEN rolcanlogin THEN 'USER ' ELSE 'ROLE ' END ||
|
||||||
|
pg_catalog.quote_ident(rolname) || E' WITH\n ' ||
|
||||||
|
CASE WHEN rolcanlogin THEN 'LOGIN' ELSE 'NOLOGIN' END || E'\n ' ||
|
||||||
|
CASE WHEN rolcanlogin AND rolpassword LIKE 'md5%%' THEN 'ENCRYPTED PASSWORD ' || quote_literal(rolpassword) || E'\n ' ELSE '' END ||
|
||||||
|
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 ||
|
||||||
|
CASE WHEN rolconnlimit > 0 THEN E'\n CONNECTION LIMIT ' || rolconnlimit ELSE '' END ||
|
||||||
|
CASE WHEN rolvaliduntil IS NOT NULL THEN E'\n VALID UNTIL ' || quote_literal(rolvaliduntil::text) ELSE ';' END AS sql
|
||||||
|
FROM
|
||||||
|
{{ role_tbl }} r
|
||||||
|
WHERE
|
||||||
|
r.oid=%(rid)s::OID
|
||||||
|
UNION ALL
|
||||||
|
(SELECT
|
||||||
|
array_to_string(array_agg(sql), E'\n')
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
'GRANT ' || array_to_string(array_agg(rolname), ', ') || ' TO ' || pg_catalog.quote_ident(pg_get_userbyid(%(rid)s::OID)) ||
|
||||||
|
CASE WHEN admin_option THEN ' WITH ADMIN OPTION;' ELSE ';' END sql
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
quote_ident(r.rolname) AS rolname, m.admin_option AS admin_option
|
||||||
|
FROM
|
||||||
|
pg_auth_members m
|
||||||
|
LEFT JOIN pg_roles r ON (m.roleid = r.oid)
|
||||||
|
WHERE
|
||||||
|
m.member=%(rid)s::OID
|
||||||
|
ORDER BY
|
||||||
|
r.rolname
|
||||||
|
) a
|
||||||
|
GROUP BY admin_option) s)
|
||||||
|
UNION ALL
|
||||||
|
(SELECT
|
||||||
|
array_to_string(array_agg(sql), E'\n') sql
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
'ALTER ' || CASE WHEN rolcanlogin THEN 'USER ' ELSE 'ROLE ' END || pg_catalog.quote_ident(rolname) || ' SET ' || param || ' TO ' || CASE WHEN param IN ('search_path', 'temp_tablespaces') THEN value ELSE quote_literal(value) END || ';' AS sql
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
rolcanlogin, rolname, split_part(rolconfig, '=', 1) AS param, replace(rolconfig, split_part(rolconfig, '=', 1) || '=', '') AS value
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
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
|
||||||
|
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 quote_literal(value)
|
||||||
|
END || ';' AS sql
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
datname, split_part(rolconfig, '=', 1) AS param, replace(rolconfig, split_part(rolconfig, '=', 1) || '=', '') AS value
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
d.datname, 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
|
||||||
|
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_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
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
{% import 'macros/security.macros' as SECLABLE %}
|
||||||
|
{% import 'macros/variable.macros' as VARIABLE %}
|
||||||
|
{% if 'rolname' in data %}
|
||||||
|
{% set rolname=data.rolname %}
|
||||||
|
ALTER{% if rolCanLogin %} USER {% else %} ROLE {% endif %}{{ conn|qtIdent(role) }}
|
||||||
|
RENAME TO {{ conn|qtIdent(rolname) }};
|
||||||
|
|
||||||
|
{% else %}
|
||||||
|
{% set rolname=role %}
|
||||||
|
{% endif %}
|
||||||
|
{% if data|hasAny(alterKeys) %}
|
||||||
|
ALTER {% if rolCanLogin %}USER{% else %}ROLE{% endif %} {{ 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 'rolconnlimit' in data and data.rolconnlimit is number and data.rolconnlimit >= -1 %}
|
||||||
|
|
||||||
|
CONNECTION LIMIT {{ data.rolconnlimit }}
|
||||||
|
{% endif %}{% if 'rolvaliduntil' in data and data.rolvaliduntil %}
|
||||||
|
|
||||||
|
VALID UNTIL {% if data.rolvaliduntil is not none %}{{ data.rolvaliduntil|qtLiteral }}{% else %}'infinity'
|
||||||
|
{% endif %}{% endif %}{% if 'rolpassword' in data %}
|
||||||
|
|
||||||
|
PASSWORD{% if data.rolpassword is none %} NULL{% else %}{% if dummy %} 'xxxxxx'{% else %} {{ data.rolpassword|qtLiteral }}{% endif %}{% endif %}{% endif %};{% endif %}
|
||||||
|
|
||||||
|
{% if 'revoked_admins' in data and
|
||||||
|
data.revoked_admins|length > 0
|
||||||
|
%}
|
||||||
|
|
||||||
|
-- Revoked the admin options from the members
|
||||||
|
REVOKE ADMIN OPTION FOR {{ conn|qtIdent(data.revoked_admins)|join(', ') }} FROM {{ conn|qtIdent(rolname) }};{% endif %}{% if 'revoked' in data and data.revoked|length > 0 %}
|
||||||
|
|
||||||
|
|
||||||
|
-- Following are no more the members
|
||||||
|
REVOKE {{ conn|qtIdent(data.revoked)|join(', ') }} FROM {{ conn|qtIdent(rolname) }};{% endif %}{% if data.admins and data.admins|length > 0 %}
|
||||||
|
|
||||||
|
-- Following are the new admins (or, existing members made admins)
|
||||||
|
GRANT {{ conn|qtIdent(data.admins)|join(', ') }} TO {{ conn|qtIdent(rolname) }} WITH ADMIN OPTION;{% endif %}{% if data.members and data.members|length > 0 %}
|
||||||
|
|
||||||
|
|
||||||
|
-- Following are the new members
|
||||||
|
GRANT {{ conn|qtIdent(data.members)|join(', ') }} TO {{ conn|qtIdent(rolname) }};{% 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 %}
|
||||||
|
{{ SECLABLE.DROP(conn, 'ROLE', data.rolname, r.provider) }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% if 'added' in seclabels and seclabels.added|length > 0 %}
|
||||||
|
|
||||||
|
{% for r in seclabels.added %}
|
||||||
|
{{ SECLABLE.APPLY(conn, 'ROLE', data.rolname, r.provider, r.label) }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
|
||||||
|
|
||||||
|
{% for r in seclabels.changed %}
|
||||||
|
{{ SECLABLE.APPLY(conn, 'ROLE', data.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 }};
|
||||||
|
{% endif %}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
SELECT
|
||||||
|
split_part(rolconfig, '=', 1) AS name, replace(rolconfig, split_part(rolconfig, '=', 1) || '=', '') AS value, NULL::text AS database
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
unnest(rolconfig) AS rolconfig, rolcanlogin, rolname
|
||||||
|
FROM
|
||||||
|
pg_catalog.pg_roles
|
||||||
|
WHERE
|
||||||
|
oid={{ rid|qtLiteral }}::OID
|
||||||
|
) r
|
||||||
|
|
||||||
|
UNION ALL
|
||||||
|
SELECT
|
||||||
|
split_part(rolconfig, '=', 1) AS name, replace(rolconfig, split_part(rolconfig, '=', 1) || '=', '') AS value, datname AS database
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
d.datname, unnest(c.setconfig) AS rolconfig
|
||||||
|
FROM
|
||||||
|
(SELECT *
|
||||||
|
FROM pg_catalog.pg_db_role_setting dr
|
||||||
|
WHERE
|
||||||
|
dr.setrole={{ rid|qtLiteral }}::OID AND dr.setdatabase!=0
|
||||||
|
) c
|
||||||
|
LEFT JOIN pg_catalog.pg_database d ON (d.oid = c.setdatabase)
|
||||||
|
) a;
|
||||||
@@ -218,7 +218,12 @@ function(_, pgAdmin, $, Backbone) {
|
|||||||
set: function(key, val, options) {
|
set: function(key, val, options) {
|
||||||
var opts = _.isObject(key) ? val : options;
|
var opts = _.isObject(key) ? val : options;
|
||||||
|
|
||||||
|
this._changing = true;
|
||||||
|
this._previousAttributes = _.clone(this.attributes);
|
||||||
|
this.changed = {};
|
||||||
|
|
||||||
var res = Backbone.Model.prototype.set.call(this, key, val, options);
|
var res = Backbone.Model.prototype.set.call(this, key, val, options);
|
||||||
|
this._changing = false;
|
||||||
|
|
||||||
if ((opts&& opts.intenal) || !this.trackChanges) {
|
if ((opts&& opts.intenal) || !this.trackChanges) {
|
||||||
return true;
|
return true;
|
||||||
@@ -233,7 +238,7 @@ function(_, pgAdmin, $, Backbone) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
attrs[k] = v;
|
attrs[k] = v;
|
||||||
if (self.origSessAttrs[k] == v) {
|
if (_.isEqual(self.origSessAttrs[k], v)) {
|
||||||
delete self.sessAttrs[k];
|
delete self.sessAttrs[k];
|
||||||
} else {
|
} else {
|
||||||
self.sessAttrs[k] = v;
|
self.sessAttrs[k] = v;
|
||||||
@@ -248,7 +253,9 @@ function(_, pgAdmin, $, Backbone) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.trigger('pgadmin-session:set', self, attrs);
|
self.trigger('pgadmin-session:set', self, attrs);
|
||||||
|
if (!options || !options.silent) {
|
||||||
|
self.trigger('change', self, options);
|
||||||
|
}
|
||||||
if ('validate' in self && typeof(self['validate']) === 'function') {
|
if ('validate' in self && typeof(self['validate']) === 'function') {
|
||||||
|
|
||||||
var msg = self.validate(_.keys(attrs));
|
var msg = self.validate(_.keys(attrs));
|
||||||
@@ -770,17 +777,15 @@ function(_, pgAdmin, $, Backbone) {
|
|||||||
isAlreadyInvalid = (_.size(self.sessAttrs['invalid']) != 0),
|
isAlreadyInvalid = (_.size(self.sessAttrs['invalid']) != 0),
|
||||||
idx = self.objFindInSession(obj, 'deleted');
|
idx = self.objFindInSession(obj, 'deleted');
|
||||||
|
|
||||||
if ('validate' in obj && typeof(obj.validate) === 'function') {
|
|
||||||
msg = obj.validate();
|
|
||||||
|
|
||||||
if (msg) {
|
|
||||||
self.sessAttrs['invalid'].push(obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hmm.. - it was originally deleted from this collection, we should
|
// Hmm.. - it was originally deleted from this collection, we should
|
||||||
// remove it from the 'deleted' list.
|
// remove it from the 'deleted' list.
|
||||||
if (idx >= 0) {
|
if (idx >= 0) {
|
||||||
|
var origObj = self.sessAttrs['deleted'][idx];
|
||||||
|
|
||||||
|
obj.origSessAttrs = _.clone(origObj.origSessAttrs);
|
||||||
|
obj.attributes = _.extend(obj.attributes, origObj.attributes);
|
||||||
|
obj.sessAttrs = _.clone(origObj.sessAttrs);
|
||||||
|
|
||||||
self.sessAttrs['deleted'].splice(idx, 1);
|
self.sessAttrs['deleted'].splice(idx, 1);
|
||||||
|
|
||||||
// It has been changed originally!
|
// It has been changed originally!
|
||||||
@@ -790,6 +795,14 @@ function(_, pgAdmin, $, Backbone) {
|
|||||||
|
|
||||||
(self.handler || self).trigger('pgadmin-session:added', self, obj);
|
(self.handler || self).trigger('pgadmin-session:added', self, obj);
|
||||||
|
|
||||||
|
if ('validate' in obj && typeof(obj.validate) === 'function') {
|
||||||
|
msg = obj.validate();
|
||||||
|
|
||||||
|
if (msg) {
|
||||||
|
self.sessAttrs['invalid'].push(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the collection was already invalid, we don't need to inform the
|
* If the collection was already invalid, we don't need to inform the
|
||||||
* parent, or raise the event for the invalid status.
|
* parent, or raise the event for the invalid status.
|
||||||
@@ -804,6 +817,13 @@ function(_, pgAdmin, $, Backbone) {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if ('validate' in obj && typeof(obj.validate) === 'function') {
|
||||||
|
msg = obj.validate();
|
||||||
|
|
||||||
|
if (msg) {
|
||||||
|
self.sessAttrs['invalid'].push(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
self.sessAttrs['added'].push(obj);
|
self.sessAttrs['added'].push(obj);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -840,6 +860,7 @@ function(_, pgAdmin, $, Backbone) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
idx = self.objFindInSession(obj, 'added');
|
idx = self.objFindInSession(obj, 'added');
|
||||||
|
|
||||||
// Hmm - it was newly added, we can safely remove it.
|
// Hmm - it was newly added, we can safely remove it.
|
||||||
if (idx >= 0) {
|
if (idx >= 0) {
|
||||||
self.sessAttrs['added'].splice(idx, 1);
|
self.sessAttrs['added'].splice(idx, 1);
|
||||||
|
|||||||
Reference in New Issue
Block a user