Treat databases with datallowconn=false appropriately. Fixes #1801

This commit is contained in:
Khushboo Vashi
2016-12-09 11:59:13 +00:00
committed by Dave Page
parent 6ff2fe64b8
commit 81841cdb3c
25 changed files with 308 additions and 157 deletions

View File

@@ -214,7 +214,8 @@ class DatabaseView(PGChildNodeView):
allowConn=row['datallowconn'],
canCreate=row['cancreate'],
canDisconn=canDisConn,
canDrop = canDrop
canDrop=canDrop,
inode=True if row['datallowconn'] else False
)
)
@@ -276,11 +277,13 @@ class DatabaseView(PGChildNodeView):
@check_precondition(action="properties")
def properties(self, gid, sid, did):
conn = self.manager.connection()
SQL = render_template(
"/".join([self.template_path, 'properties.sql']),
did=did, conn=self.conn, last_system_oid=0
did=did, conn=conn, last_system_oid=0
)
status, res = self.conn.execute_dict(SQL)
status, res = conn.execute_dict(SQL)
if len(res['rows']) == 0:
return gone(
@@ -292,9 +295,9 @@ class DatabaseView(PGChildNodeView):
SQL = render_template(
"/".join([self.template_path, 'acl.sql']),
did=did, conn=self.conn
did=did, conn=conn
)
status, dataclres = self.conn.execute_dict(SQL)
status, dataclres = conn.execute_dict(SQL)
if not status:
return internal_server_error(errormsg=res)
@@ -302,9 +305,9 @@ class DatabaseView(PGChildNodeView):
SQL = render_template(
"/".join([self.template_path, 'defacl.sql']),
did=did, conn=self.conn
did=did, conn=conn
)
status, defaclres = self.conn.execute_dict(SQL)
status, defaclres = conn.execute_dict(SQL)
if not status:
return internal_server_error(errormsg=res)
@@ -314,10 +317,10 @@ class DatabaseView(PGChildNodeView):
# Fetching variable for database
SQL = render_template(
"/".join([self.template_path, 'get_variables.sql']),
did=did, conn=self.conn
did=did, conn=conn
)
status, res1 = self.conn.execute_dict(SQL)
status, res1 = conn.execute_dict(SQL)
if not status:
return internal_server_error(errormsg=res1)
@@ -535,12 +538,13 @@ class DatabaseView(PGChildNodeView):
request.data, encoding='utf-8'
)
conn = self.manager.connection()
if did is not None:
# Fetch the name of database for comparison
status, rset = self.conn.execute_dict(
status, rset = conn.execute_dict(
render_template(
"/".join([self.template_path, 'nodes.sql']),
did=did, conn=self.conn, last_system_oid=0
did=did, conn=conn, last_system_oid=0
)
)
if not status:
@@ -556,7 +560,6 @@ class DatabaseView(PGChildNodeView):
data['name'] = data['old_name']
status = self.manager.release(did=did)
conn = self.manager.connection()
for action in ["rename_database", "tablespace"]:
SQL = self.get_offline_sql(gid, sid, data, did, action)
SQL = SQL.strip('\n').strip(' ')
@@ -565,6 +568,18 @@ class DatabaseView(PGChildNodeView):
if not status:
return internal_server_error(errormsg=msg)
if not self.manager.db_info[did]['datallowconn']:
return jsonify(
node=self.blueprint.generate_browser_node(
did,
sid,
data['name'],
"icon-database-not-connected",
connected=False,
allowConn=False
)
)
self.conn = self.manager.connection(database=data['name'], auto_reconnect=True)
status, errmsg = self.conn.connect()
@@ -655,10 +670,11 @@ class DatabaseView(PGChildNodeView):
SQL = ''
if did is not None:
# Fetch the name of database for comparison
status, rset = self.conn.execute_dict(
conn = self.manager.connection()
status, rset = conn.execute_dict(
render_template(
"/".join([self.template_path, 'nodes.sql']),
did=did, conn=self.conn, last_system_oid=0
did=did, conn=conn, last_system_oid=0
)
)
if not status:
@@ -677,7 +693,8 @@ class DatabaseView(PGChildNodeView):
for action in ["rename_database", "tablespace"]:
SQL += self.get_offline_sql(gid, sid, data, did, action)
SQL += self.get_online_sql(gid, sid, data, did)
if rset['rows'][0]['datallowconn']:
SQL += self.get_online_sql(gid, sid, data, did)
else:
SQL += self.get_new_sql(gid, sid, data, did)
@@ -696,31 +713,37 @@ class DatabaseView(PGChildNodeView):
return _(" -- definition incomplete")
acls = []
try:
acls = render_template(
"/".join([self.template_path, 'allowed_privs.json'])
)
acls = json.loads(acls, encoding='utf-8')
except Exception as e:
current_app.logger.exception(e)
SQL_acl = ''
# Privileges
for aclcol in acls:
if aclcol in data:
allowedacl = acls[aclcol]
data[aclcol] = parse_priv_to_db(
data[aclcol], allowedacl['acl']
if data['datallowconn']:
try:
acls = render_template(
"/".join([self.template_path, 'allowed_privs.json'])
)
acls = json.loads(acls, encoding='utf-8')
except Exception as e:
current_app.logger.exception(e)
# Privileges
for aclcol in acls:
if aclcol in data:
allowedacl = acls[aclcol]
data[aclcol] = parse_priv_to_db(
data[aclcol], allowedacl['acl']
)
SQL_acl = render_template(
"/".join([self.template_path, 'grant.sql']),
data=data, conn=self.conn
)
conn = self.manager.connection()
SQL = render_template(
"/".join([self.template_path, 'create.sql']),
data=data, conn=self.conn
data=data, conn=conn
)
SQL += "\n"
SQL += render_template(
"/".join([self.template_path, 'grant.sql']),
data=data, conn=self.conn
)
SQL += SQL_acl
return SQL
def get_online_sql(self, gid, sid, data, did=None):
@@ -792,10 +815,11 @@ class DatabaseView(PGChildNodeView):
if self.manager.db_info is not None and \
self.manager.did in self.manager.db_info else 0
status, res = self.conn.execute_dict(
conn = self.manager.connection()
status, res = conn.execute_dict(
render_template(
"/".join([self.template_path, 'stats.sql']),
did=did, conn=self.conn, last_system_oid=last_system_oid
did=did, conn=conn, last_system_oid=last_system_oid
)
)
@@ -812,52 +836,56 @@ class DatabaseView(PGChildNodeView):
"""
This function will generate sql for sql panel
"""
conn = self.manager.connection()
SQL = render_template(
"/".join([self.template_path, 'properties.sql']),
did=did, conn=self.conn, last_system_oid=0
did=did, conn=conn, last_system_oid=0
)
status, res = self.conn.execute_dict(SQL)
status, res = conn.execute_dict(SQL)
if not status:
return internal_server_error(errormsg=res)
SQL = render_template(
"/".join([self.template_path, 'acl.sql']),
did=did, conn=self.conn
)
status, dataclres = self.conn.execute_dict(SQL)
if not status:
return internal_server_error(errormsg=res)
res = self.formatdbacl(res, dataclres['rows'])
if res['rows'][0]['datallowconn']:
SQL = render_template(
"/".join([self.template_path, 'acl.sql']),
did=did, conn=self.conn
)
status, dataclres = self.conn.execute_dict(SQL)
if not status:
return internal_server_error(errormsg=dataclres)
res = self.formatdbacl(res, dataclres['rows'])
SQL = render_template(
"/".join([self.template_path, 'defacl.sql']),
did=did, conn=self.conn
)
status, defaclres = self.conn.execute_dict(SQL)
if not status:
return internal_server_error(errormsg=res)
SQL = render_template(
"/".join([self.template_path, 'defacl.sql']),
did=did, conn=self.conn
)
status, defaclres = self.conn.execute_dict(SQL)
if not status:
return internal_server_error(errormsg=defaclres)
res = self.formatdbacl(res, defaclres['rows'])
res = self.formatdbacl(res, defaclres['rows'])
result = res['rows'][0]
SQL = render_template(
"/".join([self.template_path, 'get_variables.sql']),
did=did, conn=self.conn
)
status, res1 = self.conn.execute_dict(SQL)
if not status:
return internal_server_error(errormsg=res1)
if result['datallowconn']:
SQL = render_template(
"/".join([self.template_path, 'get_variables.sql']),
did=did, conn=self.conn
)
status, res1 = self.conn.execute_dict(SQL)
if not status:
return internal_server_error(errormsg=res1)
# Get Formatted Security Labels
if 'seclabels' in result:
# Security Labels is not available for PostgreSQL <= 9.1
frmtd_sec_labels = parse_sec_labels_from_db(result['seclabels'])
result.update(frmtd_sec_labels)
# Get Formatted Security Labels
if 'seclabels' in result:
# Security Labels is not available for PostgreSQL <= 9.1
frmtd_sec_labels = parse_sec_labels_from_db(result['seclabels'])
result.update(frmtd_sec_labels)
# Get Formatted Variables
frmtd_variables = parse_variables_from_db(res1['rows'])
result.update(frmtd_variables)
# Get Formatted Variables
frmtd_variables = parse_variables_from_db(res1['rows'])
result.update(frmtd_variables)
sql_header = "-- Database: {0}\n\n-- ".format(result['name'])
if hasattr(str, 'decode'):
@@ -865,7 +893,7 @@ class DatabaseView(PGChildNodeView):
sql_header += render_template(
"/".join([self.template_path, 'delete.sql']),
datname=result['name'], conn=self.conn
datname=result['name'], conn=conn
)
SQL = self.get_new_sql(gid, sid, result, did)
@@ -886,7 +914,8 @@ class DatabaseView(PGChildNodeView):
sid: Server ID
did: Database ID
"""
dependents_result = self.get_dependents(self.conn, did)
dependents_result = self.get_dependents(self.conn, did) if\
self.conn.connected() else []
return ajax_response(
response=dependents_result,
status=200
@@ -903,7 +932,8 @@ class DatabaseView(PGChildNodeView):
sid: Server ID
did: Database ID
"""
dependencies_result = self.get_dependencies(self.conn, did)
dependencies_result = self.get_dependencies(self.conn, did) if\
self.conn.connected() else []
return ajax_response(
response=dependencies_result,
status=200

View File

@@ -39,7 +39,8 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
name: 'create_cast_on_database', node: 'database', module: this,
applies: ['object', 'context'], callback: 'show_obj_properties',
category: 'create', priority: 4, label: '{{ _('Cast...') }}',
icon: 'wcTabIcon icon-cast', data: {action: 'create'}
icon: 'wcTabIcon icon-cast', data: {action: 'create'},
enable: pgBrowser.Nodes['database'].is_conn_allow
},{
name: 'create_cast_on_coll', node: 'coll-cast', module: this,
applies: ['object', 'context'], callback: 'show_obj_properties',

View File

@@ -46,7 +46,8 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
name: 'create_event_trigger', node: 'database', module: this,
applies: ['object', 'context'], callback: 'show_obj_properties',
category: 'create', priority: 4, label: '{{ _('Event Trigger...') }}',
icon: 'wcTabIcon icon-event_trigger', data: {action: 'create'}
icon: 'wcTabIcon icon-event_trigger', data: {action: 'create'},
enable: pgBrowser.Nodes['database'].is_conn_allow
}
]);
},

View File

@@ -72,7 +72,8 @@ function($, _, S, pgAdmin, pgBrowser) {
name: 'create_extension', node: 'database', module: this,
applies: ['object', 'context'], callback: 'show_obj_properties',
category: 'create', priority: 4, label: '{{ _('Extension...') }}',
icon: 'wcTabIcon icon-extension', data: {action: 'create'}
icon: 'wcTabIcon icon-extension', data: {action: 'create'},
enable: pgBrowser.Nodes['database'].is_conn_allow
}
]);
},

View File

@@ -12,7 +12,7 @@
import simplejson as json
from functools import wraps
import pgadmin.browser.server_groups.servers as servers
import pgadmin.browser.server_groups.servers.databases as databases
from flask import render_template, make_response, request, jsonify
from flask_babel import gettext
from pgadmin.browser.collection import CollectionNodeModule
@@ -79,9 +79,9 @@ class ForeignDataWrapperModule(CollectionNodeModule):
"""
Load the module script for foreign data wrapper, when any of the database node is initialized.
Returns: node type of the server module.
Returns: node type of the databse module.
"""
return servers.ServerModule.NODE_TYPE
return databases.DatabaseModule.NODE_TYPE
blueprint = ForeignDataWrapperModule(__name__)

View File

@@ -86,7 +86,8 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
name: 'create_foreign_data_wrapper', node: 'database', module: this,
applies: ['object', 'context'], callback: 'show_obj_properties',
category: 'create', priority: 4, label: '{{ _('Foreign Data Wrapper...') }}',
icon: 'wcTabIcon icon-foreign_data_wrapper', data: {action: 'create'}
icon: 'wcTabIcon icon-foreign_data_wrapper', data: {action: 'create'},
enable: pgBrowser.Nodes['database'].is_conn_allow
}
]);
},

View File

@@ -40,7 +40,8 @@ define(
name: 'create_language_on_database', node: 'database', module: this,
applies: ['object', 'context'], callback: 'show_obj_properties',
category: 'create', priority: 4, label: '{{ _('Language...') }}',
icon: 'wcTabIcon icon-language', data: {action: 'create'}
icon: 'wcTabIcon icon-language', data: {action: 'create'},
enable: pgBrowser.Nodes['database'].is_conn_allow
},{
name: 'create_language_on_coll', node: 'coll-language', module: this,
applies: ['object', 'context'], callback: 'show_obj_properties',

View File

@@ -88,7 +88,7 @@ class SchemaModule(CollectionNodeModule):
@property
def script_load(self):
"""
Load the module script for server, when any of the server-group node is
Load the module script for schema, when any of the server node is
initialized.
"""
return servers.ServerModule.NODE_TYPE

View File

@@ -310,10 +310,14 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
name: 'create_schema', node: 'database', module: this,
applies: ['object', 'context'], callback: 'show_obj_properties',
category: 'create', priority: 4, label: '{{ _('Schema...') }}',
icon: 'wcTabIcon icon-schema', data: {action: 'create'}
icon: 'wcTabIcon icon-schema', data: {action: 'create'},
enable: 'can_create_schema'
}
]);
},
can_create_schema: function(node, item) {
return pgBrowser.Nodes['database'].is_conn_allow.call(this, node);
},
model: pgBrowser.Node.Model.extend({
defaults: {
name: undefined,

View File

@@ -82,11 +82,14 @@ function($, _, S, pgAdmin, pgBrowser, Alertify) {
return server.connected && server.user.can_create_db;
},
is_not_connected: function(node) {
return (node && node.connected != true);
return (node && node.connected != true && node.allowConn == true);
},
is_connected: function(node) {
return (node && node.connected == true && node.canDisconn == true);
},
is_conn_allow: function(node) {
return (node && node.allowConn == true)
},
connection_lost: function(i, resp, server_connected) {
if (pgBrowser.tree) {
var t = pgBrowser.tree,
@@ -102,6 +105,7 @@ function($, _, S, pgAdmin, pgBrowser, Alertify) {
}
if (i && d) {
if (!d.allowConn) return false;
if (_.isUndefined(d.is_connecting) || !d.is_connecting) {
d.is_connecting = true;
@@ -229,7 +233,7 @@ function($, _, S, pgAdmin, pgBrowser, Alertify) {
}
pgBrowser.tree.addIcon(item, {icon: data.icon});
if (!data.connected) {
if (!data.connected && data.allowConn) {
connect_to_database(this, data, pgBrowser.tree, item, true);
return false;
}
@@ -237,18 +241,28 @@ function($, _, S, pgAdmin, pgBrowser, Alertify) {
},
selected: function(item, data) {
if(!data || data._type != 'database' || data.label == "template0") {
if(!data || data._type != 'database') {
return false;
}
pgBrowser.tree.addIcon(item, {icon: data.icon});
if (!data.connected) {
if (!data.connected && data.allowConn) {
connect_to_database(this, data, pgBrowser.tree, item, false);
return false;
}
return pgBrowser.Node.callbacks.selected.apply(this, arguments);
},
refresh: function(cmd, i) {
var self = this,
t = pgBrowser.tree,
item = i || t.selected(),
d = t.itemData(item);
if (!d.allowConn) return;
pgBrowser.Node.callbacks.refresh.apply(this, arguments);
}
},
model: pgBrowser.Node.Model.extend({
defaults: {

View File

@@ -1,6 +1,20 @@
{% if data %}
{% if action == "rename_database" and data.old_name != data.name %}
{% if action == "rename_database" %} {% if data.old_name != data.name %}
ALTER DATABASE {{ conn|qtIdent(data.old_name) }} RENAME TO {{ conn|qtIdent(data.name) }};
{% endif %}
{# Change the owner #}
{% if data.datowner %}
ALTER DATABASE {{ conn|qtIdent(data.name) }} OWNER TO {{ conn|qtIdent(data.datowner) }};
{% endif %}
{# Change the comments/description #}
{% if data.comments is defined %}
COMMENT ON DATABASE {{ conn|qtIdent(data.name) }}
IS {{ data.comments|qtLiteral }};
{% endif %}
{# Change the connection limit #}
{% if data.datconnlimit %}
ALTER DATABASE {{ conn|qtIdent(data.name) }} WITH CONNECTION LIMIT = {{ data.datconnlimit }};
{% endif %}
{% endif %}{% if action == "tablespace" and data.spcname %}
ALTER DATABASE {{ conn|qtIdent(data.name) }} SET TABLESPACE {{ conn|qtIdent(data.spcname) }};

View File

@@ -3,19 +3,6 @@
{% import 'macros/privilege.macros' as PRIVILEGE %}
{% import 'macros/default_privilege.macros' as DEFAULT_PRIVILEGE %}
{% if data %}
{# Change the owner #}
{% if data.datowner %}
ALTER DATABASE {{ conn|qtIdent(data.name) }} OWNER TO {{ conn|qtIdent(data.datowner) }};
{% endif %}
{# Change the comments/description #}
{% if data.comments is defined %}
COMMENT ON DATABASE {{ conn|qtIdent(data.name) }}
IS {{ data.comments|qtLiteral }};
{% endif %}
{# Change the connection limit #}
{% if data.datconnlimit %}
ALTER DATABASE {{ conn|qtIdent(data.name) }} WITH CONNECTION LIMIT = {{ data.datconnlimit }};
{% endif %}
{# Change the variables/options #}
{% if data.variables and data.variables|length > 0 %}
{% set variables = data.variables %}

View File

@@ -1,6 +1,20 @@
{% if data %}
{% if action == "rename_database" and data.old_name != data.name %}
{% if action == "rename_database" %} {% if data.old_name != data.name %}
ALTER DATABASE {{ conn|qtIdent(data.old_name) }} RENAME TO {{ conn|qtIdent(data.name) }};
{% endif %}
{# Change the owner #}
{% if data.datowner %}
ALTER DATABASE {{ conn|qtIdent(data.name) }} OWNER TO {{ conn|qtIdent(data.datowner) }};
{% endif %}
{# Change the comments/description #}
{% if data.comments is defined %}
COMMENT ON DATABASE {{ conn|qtIdent(data.name) }}
IS {{ data.comments|qtLiteral }};
{% endif %}
{# Change the connection limit #}
{% if data.datconnlimit %}
ALTER DATABASE {{ conn|qtIdent(data.name) }} WITH CONNECTION LIMIT = {{ data.datconnlimit }};
{% endif %}
{% endif %}{% if action == "tablespace" and data.spcname %}
ALTER DATABASE {{ conn|qtIdent(data.name) }} SET TABLESPACE {{ conn|qtIdent(data.spcname) }};

View File

@@ -3,19 +3,6 @@
{% import 'macros/privilege.macros' as PRIVILEGE %}
{% import 'macros/default_privilege.macros' as DEFAULT_PRIVILEGE %}
{% if data %}
{# Change the owner #}
{% if data.datowner %}
ALTER DATABASE {{ conn|qtIdent(data.name) }} OWNER TO {{ conn|qtIdent(data.datowner) }};
{% endif %}
{# Change the comments/description #}
{% if data.comments is defined %}
COMMENT ON DATABASE {{ conn|qtIdent(data.name) }}
IS {{ data.comments|qtLiteral }};
{% endif %}
{# Change the connection limit #}
{% if data.datconnlimit %}
ALTER DATABASE {{ conn|qtIdent(data.name) }} WITH CONNECTION LIMIT = {{ data.datconnlimit }};
{% endif %}
{# Change the security labels #}
{% if data.seclabels and data.seclabels|length > 0 %}
{% set seclabels = data.seclabels %}

View File

@@ -1,6 +1,20 @@
{% if data %}
{% if action == "rename_database" and data.old_name != data.name %}
{% if action == "rename_database" %} {% if data.old_name != data.name %}
ALTER DATABASE {{ conn|qtIdent(data.old_name) }} RENAME TO {{ conn|qtIdent(data.name) }};
{% endif %}
{# Change the owner #}
{% if data.datowner %}
ALTER DATABASE {{ conn|qtIdent(data.name) }} OWNER TO {{ conn|qtIdent(data.datowner) }};
{% endif %}
{# Change the comments/description #}
{% if data.comments is defined %}
COMMENT ON DATABASE {{ conn|qtIdent(data.name) }}
IS {{ data.comments|qtLiteral }};
{% endif %}
{# Change the connection limit #}
{% if data.datconnlimit %}
ALTER DATABASE {{ conn|qtIdent(data.name) }} WITH CONNECTION LIMIT = {{ data.datconnlimit }};
{% endif %}
{% endif %}{% if action == "tablespace" and data.spcname %}
ALTER DATABASE {{ conn|qtIdent(data.name) }} SET TABLESPACE {{ conn|qtIdent(data.spcname) }};

View File

@@ -3,19 +3,6 @@
{% import 'macros/privilege.macros' as PRIVILEGE %}
{% import 'macros/default_privilege.macros' as DEFAULT_PRIVILEGE %}
{% if data %}
{# Change the owner #}
{% if data.datowner %}
ALTER DATABASE {{ conn|qtIdent(data.name) }} OWNER TO {{ conn|qtIdent(data.datowner) }};
{% endif %}
{# Change the comments/description #}
{% if data.comments is defined %}
COMMENT ON DATABASE {{ conn|qtIdent(data.name) }}
IS {{ data.comments|qtLiteral }};
{% endif %}
{# Change the connection limit #}
{% if data.datconnlimit %}
ALTER DATABASE {{ conn|qtIdent(data.name) }} WITH CONNECTION LIMIT = {{ data.datconnlimit }};
{% endif %}
{# Change the security labels #}
{% if data.seclabels and data.seclabels|length > 0 %}
{% set seclabels = data.seclabels %}