mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-20 11:48:31 -06:00
Add a field to the Server Dialogue allowing users to specify a subset of databases they'd like to see in the treeview. Fixes #1918
This commit is contained in:
parent
acaa79cf6b
commit
70418144cf
Binary file not shown.
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 84 KiB |
@ -44,4 +44,5 @@ Click the *Advanced* tab to continue.
|
|||||||
|
|
||||||
Use the fields in the *Advanced* tab to configure a connection:
|
Use the fields in the *Advanced* tab to configure a connection:
|
||||||
|
|
||||||
* Specify the IP address of the server host. Using this field to specify the host IP address will avoid a DNS lookup on connection, however it may be useful to specify both a host name and address when using Kerberos, GSSAPI, or SSPI authentication methods, as well as for verify-full SSL certificate verification
|
* Specify the IP address of the server host. Using this field to specify the host IP address will avoid a DNS lookup on connection, however it may be useful to specify both a host name and address when using Kerberos, GSSAPI, or SSPI authentication methods, as well as for verify-full SSL certificate verification
|
||||||
|
* The DB restriction field allows you to enter an SQL restriction that will be used against the pg_database table to limit the databases that you see. For example, you might enter: *live_db test_db* so that only live_db and test_db are shown in the pgAdmin browser. Separate entries with a comma or tab as you type.
|
28
web/migrations/versions/d85a62333272_.py
Normal file
28
web/migrations/versions/d85a62333272_.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: d85a62333272
|
||||||
|
Revises: 3c1e4b6eda55
|
||||||
|
Create Date: 2017-07-07 16:03:23.842734
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from pgadmin.model import db
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'd85a62333272'
|
||||||
|
down_revision = 'f195f9a4923d'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
db.engine.execute(
|
||||||
|
'ALTER TABLE server ADD COLUMN db_res TEXT'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
pass
|
@ -380,7 +380,8 @@ class ServerNode(PGChildNodeView):
|
|||||||
'sslmode': 'ssl_mode',
|
'sslmode': 'ssl_mode',
|
||||||
'gid': 'servergroup_id',
|
'gid': 'servergroup_id',
|
||||||
'comment': 'comment',
|
'comment': 'comment',
|
||||||
'role': 'role'
|
'role': 'role',
|
||||||
|
'db_res': 'db_res'
|
||||||
}
|
}
|
||||||
|
|
||||||
disp_lbl = {
|
disp_lbl = {
|
||||||
@ -398,6 +399,8 @@ class ServerNode(PGChildNodeView):
|
|||||||
data = request.form if request.form else json.loads(
|
data = request.form if request.form else json.loads(
|
||||||
request.data, encoding='utf-8'
|
request.data, encoding='utf-8'
|
||||||
)
|
)
|
||||||
|
if 'db_res' in data:
|
||||||
|
data['db_res'] = ','.join(data['db_res'])
|
||||||
|
|
||||||
if 'hostaddr' in data and data['hostaddr'] != '':
|
if 'hostaddr' in data and data['hostaddr'] != '':
|
||||||
if not self.pat4.match(data['hostaddr']):
|
if not self.pat4.match(data['hostaddr']):
|
||||||
@ -497,7 +500,8 @@ class ServerNode(PGChildNodeView):
|
|||||||
'role': server.role,
|
'role': server.role,
|
||||||
'connected': connected,
|
'connected': connected,
|
||||||
'version': manager.ver,
|
'version': manager.ver,
|
||||||
'server_type': manager.server_type if connected else 'pg'
|
'server_type': manager.server_type if connected else 'pg',
|
||||||
|
'db_res': server.db_res.split(',') if server.db_res else None
|
||||||
})
|
})
|
||||||
|
|
||||||
return ajax_response(
|
return ajax_response(
|
||||||
@ -544,7 +548,8 @@ class ServerNode(PGChildNodeView):
|
|||||||
'connected': connected,
|
'connected': connected,
|
||||||
'version': manager.ver,
|
'version': manager.ver,
|
||||||
'sslmode': server.ssl_mode,
|
'sslmode': server.ssl_mode,
|
||||||
'server_type': manager.server_type if connected else 'pg'
|
'server_type': manager.server_type if connected else 'pg',
|
||||||
|
'db_res': server.db_res.split(',') if server.db_res else None
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -597,7 +602,8 @@ class ServerNode(PGChildNodeView):
|
|||||||
username=data[u'username'],
|
username=data[u'username'],
|
||||||
ssl_mode=data[u'sslmode'],
|
ssl_mode=data[u'sslmode'],
|
||||||
comment=data[u'comment'] if u'comment' in data else None,
|
comment=data[u'comment'] if u'comment' in data else None,
|
||||||
role=data[u'role'] if u'role' in data else None
|
role=data[u'role'] if u'role' in data else None,
|
||||||
|
db_res=','.join(data[u'db_res']) if u'db_res' in data else None
|
||||||
)
|
)
|
||||||
db.session.add(server)
|
db.session.add(server)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
@ -28,7 +28,9 @@ from pgadmin.utils.ajax import gone
|
|||||||
from pgadmin.utils.driver import get_driver
|
from pgadmin.utils.driver import get_driver
|
||||||
|
|
||||||
from config import PG_DEFAULT_DRIVER
|
from config import PG_DEFAULT_DRIVER
|
||||||
|
from pgadmin.browser.server_groups.servers import ServerNode
|
||||||
|
from flask_security import current_user
|
||||||
|
from pgadmin.model import Server
|
||||||
|
|
||||||
class DatabaseModule(CollectionNodeModule):
|
class DatabaseModule(CollectionNodeModule):
|
||||||
NODE_TYPE = 'database'
|
NODE_TYPE = 'database'
|
||||||
@ -166,11 +168,18 @@ class DatabaseView(PGChildNodeView):
|
|||||||
(self.manager.db_info[self.manager.did])['datlastsysoid'] \
|
(self.manager.db_info[self.manager.did])['datlastsysoid'] \
|
||||||
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
|
||||||
|
|
||||||
|
db_disp_res = None
|
||||||
|
params = None
|
||||||
|
if self.manager and self.manager.db_res:
|
||||||
|
db_disp_res = ", ".join(['%s'] * len(self.manager.db_res.split(',')))
|
||||||
|
params = tuple(self.manager.db_res.split(','))
|
||||||
|
|
||||||
SQL = render_template(
|
SQL = render_template(
|
||||||
"/".join([self.template_path, 'properties.sql']),
|
"/".join([self.template_path, 'properties.sql']),
|
||||||
conn=self.conn, last_system_oid=last_system_oid
|
conn=self.conn, last_system_oid=last_system_oid, db_restrictions=db_disp_res
|
||||||
)
|
)
|
||||||
status, res = self.conn.execute_dict(SQL)
|
status, res = self.conn.execute_dict(SQL, params)
|
||||||
|
|
||||||
if not status:
|
if not status:
|
||||||
return internal_server_error(errormsg=res)
|
return internal_server_error(errormsg=res)
|
||||||
@ -188,12 +197,19 @@ 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
|
||||||
)
|
)
|
||||||
|
server_node_res = self.manager
|
||||||
|
|
||||||
|
db_disp_res = None
|
||||||
|
params = None
|
||||||
|
if server_node_res and server_node_res.db_res:
|
||||||
|
db_disp_res = ", ".join(['%s']*len(server_node_res.db_res.split(',')))
|
||||||
|
params = tuple(server_node_res.db_res.split(','))
|
||||||
SQL = render_template(
|
SQL = render_template(
|
||||||
"/".join([self.template_path, 'nodes.sql']),
|
"/".join([self.template_path, 'nodes.sql']),
|
||||||
last_system_oid=last_system_oid
|
last_system_oid=last_system_oid,
|
||||||
|
db_restrictions=db_disp_res
|
||||||
)
|
)
|
||||||
status, rset = self.conn.execute_dict(SQL)
|
status, rset = self.conn.execute_dict(SQL, params)
|
||||||
|
|
||||||
if not status:
|
if not status:
|
||||||
return internal_server_error(errormsg=rset)
|
return internal_server_error(errormsg=rset)
|
||||||
@ -851,12 +867,17 @@ 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
|
||||||
|
|
||||||
|
db_disp_res = None
|
||||||
|
params = None
|
||||||
|
if self.manager and self.manager.db_res:
|
||||||
|
db_disp_res = ", ".join(['%s'] * len(self.manager.db_res.split(',')))
|
||||||
|
params = tuple(self.manager.db_res.split(','))
|
||||||
|
|
||||||
conn = self.manager.connection()
|
conn = self.manager.connection()
|
||||||
status, res = conn.execute_dict(
|
status, res = conn.execute_dict(render_template(
|
||||||
render_template(
|
"/".join([self.template_path, 'stats.sql']),
|
||||||
"/".join([self.template_path, 'stats.sql']),
|
did=did, conn=conn, last_system_oid=last_system_oid, db_restrictions=db_disp_res
|
||||||
did=did, conn=conn, last_system_oid=last_system_oid
|
),params
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if not status:
|
if not status:
|
||||||
|
@ -41,5 +41,10 @@ db.oid = {{ did|qtLiteral }}::OID{% else %}{% if name %}
|
|||||||
db.datname = {{ name|qtLiteral }}::text{% else %}
|
db.datname = {{ name|qtLiteral }}::text{% else %}
|
||||||
db.oid > {{ last_system_oid|qtLiteral }}::OID
|
db.oid > {{ last_system_oid|qtLiteral }}::OID
|
||||||
{% endif %}{% endif %}
|
{% endif %}{% endif %}
|
||||||
|
{% if db_restrictions %}
|
||||||
|
|
||||||
|
AND
|
||||||
|
db.datname in ({{db_restrictions}})
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
ORDER BY datname;
|
ORDER BY datname;
|
@ -29,5 +29,10 @@ WHERE {% if did %}
|
|||||||
db.datid = {{ did|qtLiteral }}::OID{% else %}
|
db.datid = {{ did|qtLiteral }}::OID{% else %}
|
||||||
db.datid > {{ last_system_oid|qtLiteral }}::OID
|
db.datid > {{ last_system_oid|qtLiteral }}::OID
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if db_restrictions %}
|
||||||
|
|
||||||
|
AND
|
||||||
|
db.datname in ({{db_restrictions}})
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
ORDER BY db.datname;
|
ORDER BY db.datname;
|
||||||
|
@ -8,5 +8,10 @@ WHERE {% if did %}
|
|||||||
db.oid = {{ did|qtLiteral }}::OID{% else %}
|
db.oid = {{ did|qtLiteral }}::OID{% else %}
|
||||||
db.oid > {{ last_system_oid }}::OID
|
db.oid > {{ last_system_oid }}::OID
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if db_restrictions %}
|
||||||
|
|
||||||
|
AND
|
||||||
|
db.datname in ({{db_restrictions}})
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
ORDER BY datname;
|
ORDER BY datname;
|
||||||
|
@ -34,5 +34,10 @@ db.oid = {{ did|qtLiteral }}::OID{% else %}{% if name %}
|
|||||||
db.datname = {{ name|qtLiteral }}::text{% else %}
|
db.datname = {{ name|qtLiteral }}::text{% else %}
|
||||||
db.oid > {{ last_system_oid|qtLiteral }}::OID
|
db.oid > {{ last_system_oid|qtLiteral }}::OID
|
||||||
{% endif %}{% endif %}
|
{% endif %}{% endif %}
|
||||||
|
{% if db_restrictions %}
|
||||||
|
|
||||||
|
AND
|
||||||
|
db.datname in ({{db_restrictions}})
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
ORDER BY datname;
|
ORDER BY datname;
|
||||||
|
@ -24,5 +24,10 @@ WHERE {% if did %}
|
|||||||
db.datid = {{ did|qtLiteral }}::OID{% else %}
|
db.datid = {{ did|qtLiteral }}::OID{% else %}
|
||||||
db.datid > {{ last_system_oid|qtLiteral }}::OID
|
db.datid > {{ last_system_oid|qtLiteral }}::OID
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if db_restrictions %}
|
||||||
|
|
||||||
|
AND
|
||||||
|
db.datname in ({{db_restrictions}})
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
ORDER BY db.datname;
|
ORDER BY db.datname;
|
||||||
|
@ -624,7 +624,8 @@ define('pgadmin.node.server', [
|
|||||||
role: null,
|
role: null,
|
||||||
connect_now: true,
|
connect_now: true,
|
||||||
password: undefined,
|
password: undefined,
|
||||||
save_password: false
|
save_password: false,
|
||||||
|
db_res: ''
|
||||||
},
|
},
|
||||||
// Default values!
|
// Default values!
|
||||||
initialize: function(attrs, args) {
|
initialize: function(attrs, args) {
|
||||||
@ -669,6 +670,10 @@ define('pgadmin.node.server', [
|
|||||||
},{
|
},{
|
||||||
id: 'hostaddr', label: gettext('Host address'), type: 'text', group: gettext('Advanced'),
|
id: 'hostaddr', label: gettext('Host address'), type: 'text', group: gettext('Advanced'),
|
||||||
mode: ['properties', 'edit', 'create'], disabled: 'isConnected'
|
mode: ['properties', 'edit', 'create'], disabled: 'isConnected'
|
||||||
|
},{
|
||||||
|
id: 'db_res', label: gettext('DB restriction'), type: 'select2', group: gettext('Advanced'),
|
||||||
|
mode: ['properties', 'edit', 'create'], disabled: 'isConnected', select2: {multiple: true, allowClear: false,
|
||||||
|
tags: true, tokenSeparators: [','], first_empty: false, selectOnClose: true, emptyOptions: true}
|
||||||
},{
|
},{
|
||||||
id: 'port', label: gettext('Port'), type: 'int', group: gettext('Connection'),
|
id: 'port', label: gettext('Port'), type: 'int', group: gettext('Connection'),
|
||||||
mode: ['properties', 'edit', 'create'], disabled: 'isConnected', min: 1024, max: 65535
|
mode: ['properties', 'edit', 'create'], disabled: 'isConnected', min: 1024, max: 65535
|
||||||
|
@ -128,6 +128,8 @@ class Server(db.Model):
|
|||||||
servers = db.relationship('ServerGroup',
|
servers = db.relationship('ServerGroup',
|
||||||
backref=db.backref('server', cascade="all, delete-orphan"),
|
backref=db.backref('server', cascade="all, delete-orphan"),
|
||||||
lazy='joined')
|
lazy='joined')
|
||||||
|
db_res = db.Column(db.Text(), nullable=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1707,7 +1707,8 @@
|
|||||||
defaults: _.extend({}, Backform.SelectControl.prototype.defaults, {
|
defaults: _.extend({}, Backform.SelectControl.prototype.defaults, {
|
||||||
select2: {
|
select2: {
|
||||||
first_empty: true,
|
first_empty: true,
|
||||||
multiple: false
|
multiple: false,
|
||||||
|
emptyOptions: false
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
formatter: Select2Formatter,
|
formatter: Select2Formatter,
|
||||||
@ -1761,7 +1762,8 @@
|
|||||||
data.select2 = data.select2 || {};
|
data.select2 = data.select2 || {};
|
||||||
_.defaults(data.select2, this.defaults.select2, {
|
_.defaults(data.select2, this.defaults.select2, {
|
||||||
first_empty: true,
|
first_empty: true,
|
||||||
multiple: false
|
multiple: false,
|
||||||
|
emptyOptions: false
|
||||||
});
|
});
|
||||||
|
|
||||||
// Evaluate the disabled, visible, and required option
|
// Evaluate the disabled, visible, and required option
|
||||||
@ -1807,8 +1809,29 @@
|
|||||||
* Add empty option as Select2 requires any empty '<option><option>' for
|
* Add empty option as Select2 requires any empty '<option><option>' for
|
||||||
* some of its functionality to work and initialize select2 control.
|
* some of its functionality to work and initialize select2 control.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if (data.select2.tags && data.select2.emptyOptions) {
|
||||||
|
select2Opts.data = data.rawValue;
|
||||||
|
}
|
||||||
|
|
||||||
this.$sel = this.$el.find("select").select2(select2Opts);
|
this.$sel = this.$el.find("select").select2(select2Opts);
|
||||||
|
|
||||||
|
// Add or remove tags from select2 control
|
||||||
|
if (data.select2.tags && data.select2.emptyOptions) {
|
||||||
|
this.$sel.val(data.rawValue);
|
||||||
|
this.$sel.trigger('change.select2');
|
||||||
|
this.$sel.on('select2:unselect', function(evt) {
|
||||||
|
|
||||||
|
$(this).find('option[value="'+evt.params.data.text.replace("'","\\'").replace('"','\\"')+'"]').remove();
|
||||||
|
$(this).trigger('change.select2');
|
||||||
|
if ($(this).val() == null) {
|
||||||
|
$(this).empty();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Select the highlighted item on Tab press.
|
// Select the highlighted item on Tab press.
|
||||||
if (this.$sel) {
|
if (this.$sel) {
|
||||||
this.$sel.data('select2').on("keypress", function(ev) {
|
this.$sel.data('select2').on("keypress", function(ev) {
|
||||||
|
@ -1615,6 +1615,7 @@ class ServerManager(object):
|
|||||||
self.pinged = datetime.datetime.now()
|
self.pinged = datetime.datetime.now()
|
||||||
self.db_info = dict()
|
self.db_info = dict()
|
||||||
self.server_types = None
|
self.server_types = None
|
||||||
|
self.db_res = server.db_res
|
||||||
|
|
||||||
for con in self.connections:
|
for con in self.connections:
|
||||||
self.connections[con]._release()
|
self.connections[con]._release()
|
||||||
|
Loading…
Reference in New Issue
Block a user