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

@ -66,7 +66,7 @@ class CollectionNodeModule(PgAdminModule, PGChildModule):
"id": "%s/%s" % (self.node_type, node_id), "id": "%s/%s" % (self.node_type, node_id),
"label": label, "label": label,
"icon": self.node_icon if not icon else icon, "icon": self.node_icon if not icon else icon,
"inode": self.node_inode, "inode": self.node_inode if 'inode' not in kwargs else kwargs['inode'],
"_type": self.node_type, "_type": self.node_type,
"_id": node_id, "_id": node_id,
"_pid": parent_id, "_pid": parent_id,

View File

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

View File

@ -39,7 +39,8 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
name: 'create_cast_on_database', node: 'database', module: this, name: 'create_cast_on_database', node: 'database', module: this,
applies: ['object', 'context'], callback: 'show_obj_properties', applies: ['object', 'context'], callback: 'show_obj_properties',
category: 'create', priority: 4, label: '{{ _('Cast...') }}', 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, name: 'create_cast_on_coll', node: 'coll-cast', module: this,
applies: ['object', 'context'], callback: 'show_obj_properties', 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, name: 'create_event_trigger', node: 'database', module: this,
applies: ['object', 'context'], callback: 'show_obj_properties', applies: ['object', 'context'], callback: 'show_obj_properties',
category: 'create', priority: 4, label: '{{ _('Event Trigger...') }}', 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, name: 'create_extension', node: 'database', module: this,
applies: ['object', 'context'], callback: 'show_obj_properties', applies: ['object', 'context'], callback: 'show_obj_properties',
category: 'create', priority: 4, label: '{{ _('Extension...') }}', 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 import simplejson as json
from functools import wraps 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 import render_template, make_response, request, jsonify
from flask_babel import gettext from flask_babel import gettext
from pgadmin.browser.collection import CollectionNodeModule 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. 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__) blueprint = ForeignDataWrapperModule(__name__)

View File

@ -86,7 +86,8 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
name: 'create_foreign_data_wrapper', node: 'database', module: this, name: 'create_foreign_data_wrapper', node: 'database', module: this,
applies: ['object', 'context'], callback: 'show_obj_properties', applies: ['object', 'context'], callback: 'show_obj_properties',
category: 'create', priority: 4, label: '{{ _('Foreign Data Wrapper...') }}', 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, name: 'create_language_on_database', node: 'database', module: this,
applies: ['object', 'context'], callback: 'show_obj_properties', applies: ['object', 'context'], callback: 'show_obj_properties',
category: 'create', priority: 4, label: '{{ _('Language...') }}', 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, name: 'create_language_on_coll', node: 'coll-language', module: this,
applies: ['object', 'context'], callback: 'show_obj_properties', applies: ['object', 'context'], callback: 'show_obj_properties',

View File

@ -88,7 +88,7 @@ class SchemaModule(CollectionNodeModule):
@property @property
def script_load(self): 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. initialized.
""" """
return servers.ServerModule.NODE_TYPE return servers.ServerModule.NODE_TYPE

View File

@ -310,10 +310,14 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
name: 'create_schema', node: 'database', module: this, name: 'create_schema', node: 'database', module: this,
applies: ['object', 'context'], callback: 'show_obj_properties', applies: ['object', 'context'], callback: 'show_obj_properties',
category: 'create', priority: 4, label: '{{ _('Schema...') }}', 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({ model: pgBrowser.Node.Model.extend({
defaults: { defaults: {
name: undefined, name: undefined,

View File

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

View File

@ -1,6 +1,20 @@
{% if data %} {% 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) }}; 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 %} {% endif %}{% if action == "tablespace" and data.spcname %}
ALTER DATABASE {{ conn|qtIdent(data.name) }} SET TABLESPACE {{ conn|qtIdent(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/privilege.macros' as PRIVILEGE %}
{% import 'macros/default_privilege.macros' as DEFAULT_PRIVILEGE %} {% import 'macros/default_privilege.macros' as DEFAULT_PRIVILEGE %}
{% if data %} {% 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 #} {# Change the variables/options #}
{% if data.variables and data.variables|length > 0 %} {% if data.variables and data.variables|length > 0 %}
{% set variables = data.variables %} {% set variables = data.variables %}

View File

@ -1,6 +1,20 @@
{% if data %} {% 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) }}; 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 %} {% endif %}{% if action == "tablespace" and data.spcname %}
ALTER DATABASE {{ conn|qtIdent(data.name) }} SET TABLESPACE {{ conn|qtIdent(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/privilege.macros' as PRIVILEGE %}
{% import 'macros/default_privilege.macros' as DEFAULT_PRIVILEGE %} {% import 'macros/default_privilege.macros' as DEFAULT_PRIVILEGE %}
{% if data %} {% 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 #} {# Change the security labels #}
{% if data.seclabels and data.seclabels|length > 0 %} {% if data.seclabels and data.seclabels|length > 0 %}
{% set seclabels = data.seclabels %} {% set seclabels = data.seclabels %}

View File

@ -1,6 +1,20 @@
{% if data %} {% 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) }}; 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 %} {% endif %}{% if action == "tablespace" and data.spcname %}
ALTER DATABASE {{ conn|qtIdent(data.name) }} SET TABLESPACE {{ conn|qtIdent(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/privilege.macros' as PRIVILEGE %}
{% import 'macros/default_privilege.macros' as DEFAULT_PRIVILEGE %} {% import 'macros/default_privilege.macros' as DEFAULT_PRIVILEGE %}
{% if data %} {% 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 #} {# Change the security labels #}
{% if data.seclabels and data.seclabels|length > 0 %} {% if data.seclabels and data.seclabels|length > 0 %}
{% set seclabels = data.seclabels %} {% set seclabels = data.seclabels %}

View File

@ -126,7 +126,15 @@ function($, _, S, pgAdmin, Menu, Backbone, Alertify, pgBrowser, Backform) {
name: 'show_query_tool', node: self.type, module: self, name: 'show_query_tool', node: self.type, module: self,
applies: ['context'], callback: 'show_query_tool', applies: ['context'], callback: 'show_query_tool',
priority: 998, label: '{{ _("Query Tool...") }}', priority: 998, label: '{{ _("Query Tool...") }}',
icon: 'fa fa-bolt' icon: 'fa fa-bolt',
enable: function(itemData, item, data) {
if (itemData._type == 'database' && itemData.allowConn)
return true;
else if(itemData._type != 'database')
return true;
else
return false;
}
}]); }]);
} }
} }
@ -164,6 +172,11 @@ function($, _, S, pgAdmin, Menu, Backbone, Alertify, pgBrowser, Backform) {
if (itemData._type == 'server-group' || itemData._type == 'server') { if (itemData._type == 'server-group' || itemData._type == 'server') {
return false; return false;
} }
// Do not display the menu if the database connection is not allowed
if (itemData._type == 'database' && !itemData.allowConn)
return false;
var node = pgBrowser.Nodes[itemData._type], var node = pgBrowser.Nodes[itemData._type],
parentData = node.getTreeNodeHierarchy(item); parentData = node.getTreeNodeHierarchy(item);
if ( _.indexOf(['create','insert','update', 'delete'], data.script) != -1) { if ( _.indexOf(['create','insert','update', 'delete'], data.script) != -1) {

View File

@ -16,7 +16,8 @@ from flask import render_template, url_for, Response, g
from flask_babel import gettext from flask_babel import gettext
from flask_security import login_required from flask_security import login_required
from pgadmin.utils import PgAdminModule from pgadmin.utils import PgAdminModule
from pgadmin.utils.ajax import make_response as ajax_response, internal_server_error from pgadmin.utils.ajax import make_response as ajax_response,\
internal_server_error
from pgadmin.utils.ajax import precondition_required from pgadmin.utils.ajax import precondition_required
from pgadmin.utils.driver import get_driver from pgadmin.utils.driver import get_driver
from pgadmin.utils.menu import Panel from pgadmin.utils.menu import Panel
@ -68,7 +69,8 @@ class DashboardModule(PgAdminModule):
Register preferences for this module. Register preferences for this module.
""" """
# Register options for the PG and PPAS help paths # Register options for the PG and PPAS help paths
self.dashboard_preference = Preferences('dashboards', gettext('Dashboards')) self.dashboard_preference = Preferences('dashboards',
gettext('Dashboards'))
self.session_stats_refresh = self.dashboard_preference.register( self.session_stats_refresh = self.dashboard_preference.register(
'dashboards', 'session_stats_refresh', 'dashboards', 'session_stats_refresh',
@ -133,9 +135,31 @@ def check_precondition(f):
# If DB not connected then return error to browser # If DB not connected then return error to browser
if not g.conn.connected(): if not g.conn.connected():
return precondition_required( if f.__name__ in ['activity', 'prepared', 'locks', 'config']:
gettext("Connection to the server has been lost.") return precondition_required(
) gettext("Please connect to the selected server"
" to view the table.")
)
else:
return precondition_required(
gettext("Please connect to the selected server"
" to view the graph.")
)
if 'did' in kwargs:
db_conn = g.manager.connection(did=kwargs['did'])
# If the selected DB not connected then return error to browser
if not db_conn.connected():
if f.__name__ in ['activity', 'prepared', 'locks', 'config']:
return precondition_required(
gettext("Please connect to the selected database"
" to view the table.")
)
else:
return precondition_required(
gettext("Please connect to the selected database to"
" view the graph.")
)
# Set template path for sql scripts # Set template path for sql scripts
g.server_type = g.manager.server_type g.server_type = g.manager.server_type
@ -155,7 +179,8 @@ def check_precondition(f):
@login_required @login_required
def script(): def script():
"""render the required javascript""" """render the required javascript"""
return Response(response=render_template("dashboard/js/dashboard.js", _=gettext), return Response(response=render_template("dashboard/js/dashboard.js",
_=gettext),
status=200, status=200,
mimetype="application/javascript") mimetype="application/javascript")
@ -204,9 +229,16 @@ def index(sid=None, did=None):
if sid is None and did is None: if sid is None and did is None:
return render_template('/dashboard/welcome_dashboard.html') return render_template('/dashboard/welcome_dashboard.html')
if did is None: if did is None:
return render_template('/dashboard/server_dashboard.html', sid=sid, rates=rates, version=g.version) return render_template('/dashboard/server_dashboard.html',
sid=sid,
rates=rates,
version=g.version)
else: else:
return render_template('/dashboard/database_dashboard.html', sid=sid, did=did, rates=rates, version=g.version) return render_template('/dashboard/database_dashboard.html',
sid=sid,
did=did,
rates=rates,
version=g.version)
def get_data(sid, did, template): def get_data(sid, did, template):

View File

@ -217,9 +217,13 @@ function(r, $, pgAdmin, _, Backbone) {
pgAdmin.Dashboard.render_chart(container, data, dataset, sid, did, url, options, counter, refresh); pgAdmin.Dashboard.render_chart(container, data, dataset, sid, did, url, options, counter, refresh);
}, },
error: function (xhr, status, msg) { error: function (xhr, status, msg) {
var err = $.parseJSON(xhr.responseText),
msg = err.errormsg
// If we get a 428, it means the server isn't connected // If we get a 428, it means the server isn't connected
if (xhr.status == 428) { if (xhr.status == 428) {
msg = '{{ gettext('Please connect to the selected server to view the graph.') }}'; if (_.isUndefined(msg) || _.isNull(msg)) {
msg = '{{ gettext('Please connect to the selected server to view the graph.') }}';
}
cls = 'info'; cls = 'info';
} else { } else {
msg = '{{ gettext('An error occurred whilst rendering the graph.') }}'; msg = '{{ gettext('An error occurred whilst rendering the graph.') }}';
@ -325,9 +329,13 @@ function(r, $, pgAdmin, _, Backbone) {
filter.search(); filter.search();
}, },
error: function(model, xhr, options) { error: function(model, xhr, options) {
var err = $.parseJSON(xhr.responseText),
msg = err.errormsg
// If we get a 428, it means the server isn't connected // If we get a 428, it means the server isn't connected
if (xhr.status == 428) { if (xhr.status == 428) {
msg = '{{ gettext('Please connect to the selected server to view the table.') }}'; if (_.isUndefined(msg) || _.isNull(msg)) {
msg = '{{ gettext('Please connect to the selected server to view the table.') }}';
}
cls = 'info'; cls = 'info';
} else { } else {
msg = '{{ gettext('An error occurred whilst rendering the table.') }}'; msg = '{{ gettext('An error occurred whilst rendering the table.') }}';

View File

@ -285,11 +285,19 @@ TODO LIST FOR BACKUP:
var t = pgBrowser.tree, i = item, d = itemData; var t = pgBrowser.tree, i = item, d = itemData;
var parent_item = t.hasParent(i) ? t.parent(i): null, var parent_item = t.hasParent(i) ? t.parent(i): null,
parent_data = parent_item ? t.itemData(parent_item) : null; parent_data = parent_item ? t.itemData(parent_item) : null;
if(!_.isUndefined(d) && !_.isNull(d) && !_.isNull(parent_data)) if(!_.isUndefined(d) && !_.isNull(d) && !_.isNull(parent_data)) {
return ( if (_.indexOf(backup_supported_nodes, d._type) !== -1 &&
(_.indexOf(backup_supported_nodes, d._type) !== -1 && parent_data._type != 'catalog') {
parent_data._type != 'catalog') ? true: false if (d._type == 'database' && d.allowConn)
); return true;
else if(d._type != 'database')
return true;
else
return false;
}
else
return false;
}
else else
return false; return false;
}; };

View File

@ -56,7 +56,14 @@ define(
*/ */
query_tool_menu_enabled = function(obj) { query_tool_menu_enabled = function(obj) {
if(!_.isUndefined(obj) && !_.isNull(obj)) if(!_.isUndefined(obj) && !_.isNull(obj))
return (_.indexOf(unsupported_nodes, obj._type) !== -1 ? false: true); if(_.indexOf(unsupported_nodes, obj._type) == -1) {
if (obj._type == 'database' && obj.allowConn)
return true;
else if(obj._type != 'database')
return true;
else
return false;
}
else else
return false; return false;
}; };

View File

@ -155,8 +155,19 @@ define([
var t = pgBrowser.tree, i = item, d = itemData; var t = pgBrowser.tree, i = item, d = itemData;
var parent_item = t.hasParent(i) ? t.parent(i): null, var parent_item = t.hasParent(i) ? t.parent(i): null,
parent_data = parent_item ? t.itemData(parent_item) : null; parent_data = parent_item ? t.itemData(parent_item) : null;
if(!_.isUndefined(d) && !_.isNull(d) && !_.isNull(parent_data)) if(!_.isUndefined(d) && !_.isNull(d) && !_.isNull(parent_data)) {
return ((_.indexOf(supported_nodes, d._type) !== -1 && parent_data._type != 'catalog') ? true: false); if (_.indexOf(supported_nodes, d._type) !== -1 &&
parent_data._type != 'catalog') {
if (d._type == 'database' && d.allowConn)
return true;
else if(d._type != 'database')
return true;
else
return false;
}
else
return false;
}
else else
return false; return false;
}; };

View File

@ -154,11 +154,19 @@ define(
var t = pgBrowser.tree, i = item, d = itemData; var t = pgBrowser.tree, i = item, d = itemData;
var parent_item = t.hasParent(i) ? t.parent(i): null, var parent_item = t.hasParent(i) ? t.parent(i): null,
parent_data = parent_item ? t.itemData(parent_item) : null; parent_data = parent_item ? t.itemData(parent_item) : null;
if(!_.isUndefined(d) && !_.isNull(d) && !_.isNull(parent_data)) if(!_.isUndefined(d) && !_.isNull(d) && !_.isNull(parent_data)) {
return ( if (_.indexOf(maintenance_supported_nodes, d._type) !== -1 &&
(_.indexOf(maintenance_supported_nodes, d._type) !== -1 && parent_data._type != 'catalog') {
parent_data._type != 'catalog') ? true: false if (d._type == 'database' && d.allowConn)
); return true;
else if(d._type != 'database')
return true;
else
return false;
}
else
return false;
}
else else
return false; return false;
}; };

View File

@ -240,11 +240,19 @@ define([
var t = pgBrowser.tree, i = item, d = itemData; var t = pgBrowser.tree, i = item, d = itemData;
var parent_item = t.hasParent(i) ? t.parent(i): null, var parent_item = t.hasParent(i) ? t.parent(i): null,
parent_data = parent_item ? t.itemData(parent_item) : null; parent_data = parent_item ? t.itemData(parent_item) : null;
if(!_.isUndefined(d) && !_.isNull(d) && !_.isNull(parent_data)) if(!_.isUndefined(d) && !_.isNull(d) && !_.isNull(parent_data)) {
return ( if (_.indexOf(restore_supported_nodes, d._type) !== -1 &&
(_.indexOf(restore_supported_nodes, d._type) !== -1 && is_parent_catalog(itemData, item, data) ) {
is_parent_catalog(itemData, item, data) ) ? true: false if (d._type == 'database' && d.allowConn)
); return true;
else if(d._type != 'database')
return true;
else
return false;
}
else
return false;
}
else else
return false; return false;
}; };