Allow setting custom username for shared servers, with default as username of server being shared. #6229
parent
4450145d31
commit
fc411bfc49
Binary file not shown.
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 67 KiB |
|
@ -44,6 +44,9 @@ Use the fields in the *General* tab to identify the server:
|
|||
Please note that once the server is shared, it's icon is changed in the
|
||||
object explorer.
|
||||
|
||||
* Use the *Shared Username* field to fill the username of the shared server
|
||||
connection. By default, it will take the username of the server being shared.
|
||||
|
||||
* Provide a comment about the server in the *Comments* field.
|
||||
|
||||
Click the *Connection* tab to continue.
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2023, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
""" Add the new column for shared server username and change
|
||||
autoincrement in server table
|
||||
Revision ID: 9426ad06a63b
|
||||
Revises: f656e56dfdc8
|
||||
Create Date: 2023-10-09 15:09:50.773035
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '9426ad06a63b'
|
||||
down_revision = 'f656e56dfdc8'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# Added sqlite_autoincrement to force sqlite use auto increment instead of
|
||||
# last row id for next record. For future server table changes, we need to
|
||||
# add table_kwargs={'sqlite_autoincrement': True} as a param to
|
||||
# batch_alter_table
|
||||
with op.batch_alter_table(
|
||||
"server", table_kwargs={'sqlite_autoincrement': True}) as batch_op:
|
||||
batch_op.alter_column('id', autoincrement=True)
|
||||
batch_op.add_column(sa.Column('shared_username', sa.String(64), nullable=True))
|
||||
|
||||
|
||||
|
||||
def downgrade():
|
||||
# pgAdmin only upgrades, downgrade not implemented.
|
||||
pass
|
|
@ -376,7 +376,7 @@ class ServerModule(sg.ServerGroupPluginModule):
|
|||
host=data.host,
|
||||
port=data.port,
|
||||
maintenance_db=data.maintenance_db,
|
||||
username=None,
|
||||
username=data.shared_username,
|
||||
save_password=0,
|
||||
comment=None,
|
||||
role=data.role,
|
||||
|
@ -814,6 +814,7 @@ class ServerNode(PGChildNodeView):
|
|||
'tunnel_authentication': 'tunnel_authentication',
|
||||
'tunnel_identity_file': 'tunnel_identity_file',
|
||||
'shared': 'shared',
|
||||
'shared_username': 'shared_username',
|
||||
'kerberos_conn': 'kerberos_conn',
|
||||
'connection_params': 'connection_params'
|
||||
}
|
||||
|
@ -850,6 +851,10 @@ class ServerNode(PGChildNodeView):
|
|||
errormsg=gettext('Not a valid Host address')
|
||||
)
|
||||
|
||||
# remove the shared username if shared is updated to False
|
||||
if 'shared' in data and data['shared'] is False:
|
||||
data['shared_username'] = ''
|
||||
|
||||
manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid)
|
||||
conn = manager.connection()
|
||||
connected = conn.connected()
|
||||
|
@ -1073,6 +1078,8 @@ class ServerNode(PGChildNodeView):
|
|||
'port': server.port,
|
||||
'db': server.maintenance_db,
|
||||
'shared': server.shared if config.SERVER_MODE else None,
|
||||
'shared_username': server.shared_username
|
||||
if config.SERVER_MODE else None,
|
||||
'username': server.username,
|
||||
'gid': str(server.servergroup_id),
|
||||
'group-name': sg.name if (sg and sg.name) else gettext('Servers'),
|
||||
|
|
|
@ -36,6 +36,7 @@ export default class ServerSchema extends BaseUISchema {
|
|||
passexec: undefined,
|
||||
passexec_expiration: undefined,
|
||||
service: undefined,
|
||||
shared_username: '',
|
||||
use_ssh_tunnel: false,
|
||||
tunnel_host: undefined,
|
||||
tunnel_port: 22,
|
||||
|
@ -130,6 +131,34 @@ export default class ServerSchema extends BaseUISchema {
|
|||
return current_user.is_admin && pgAdmin.server_mode == 'True';
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'shared_username', label: gettext('Shared Username'), type: 'text',
|
||||
controlProps: { maxLength: 64},
|
||||
mode: ['properties', 'create', 'edit'], deps: ['shared', 'username'],
|
||||
readonly: (s)=>{
|
||||
if(!this.origData.shared && s.shared) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}, visible: (s)=>!obj.isShared(s),
|
||||
depChange: (state, source, _topState, actionObj)=>{
|
||||
let ret = {};
|
||||
if(this.origData.shared) {
|
||||
return ret;
|
||||
}
|
||||
if(source == 'username' && actionObj.oldState.username == state.shared_username) {
|
||||
ret['shared_username'] = state.username;
|
||||
}
|
||||
if(source == 'shared') {
|
||||
if(state.shared) {
|
||||
ret['shared_username'] = state.username;
|
||||
} else {
|
||||
ret['shared_username'] = '';
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'comment', label: gettext('Comments'), type: 'multiline', group: null,
|
||||
mode: ['properties', 'edit', 'create'],
|
||||
|
|
|
@ -33,7 +33,7 @@ import config
|
|||
#
|
||||
##########################################################################
|
||||
|
||||
SCHEMA_VERSION = 35
|
||||
SCHEMA_VERSION = 36
|
||||
|
||||
##########################################################################
|
||||
#
|
||||
|
@ -202,42 +202,11 @@ class Server(db.Model):
|
|||
tunnel_identity_file = db.Column(db.String(64), nullable=True)
|
||||
tunnel_password = db.Column(PgAdminDbBinaryString())
|
||||
shared = db.Column(db.Boolean(), nullable=False)
|
||||
shared_username = db.Column(db.String(64), nullable=True)
|
||||
kerberos_conn = db.Column(db.Boolean(), nullable=False, default=0)
|
||||
cloud_status = db.Column(db.Integer(), nullable=False, default=0)
|
||||
connection_params = db.Column(MutableDict.as_mutable(types.JSON))
|
||||
|
||||
@property
|
||||
def serialize(self):
|
||||
"""Return object data in easily serializable format"""
|
||||
return {
|
||||
"id": self.id,
|
||||
"user_id": self.user_id,
|
||||
"servergroup_id": self.servergroup_id,
|
||||
"name": self.name,
|
||||
"host": self.host,
|
||||
"port": self.port,
|
||||
"maintenance_db": self.maintenance_db,
|
||||
"username": self.username,
|
||||
"password": self.password,
|
||||
"save_password": self.save_password,
|
||||
"role": self.role,
|
||||
"comment": self.comment,
|
||||
"discovery_id": self.discovery_id,
|
||||
"db_res": self.db_res,
|
||||
"passexec_cmd": self.passexec_cmd,
|
||||
"passexec_expiration": self.passexec_expiration,
|
||||
"bgcolor": self.bgcolor,
|
||||
"fgcolor": self.fgcolor,
|
||||
"service": self.service,
|
||||
"use_ssh_tunnel": self.use_ssh_tunnel,
|
||||
"tunnel_host": self.tunnel_host,
|
||||
"tunnel_port": self.tunnel_port,
|
||||
"tunnel_authentication": self.tunnel_authentication,
|
||||
"tunnel_identity_file": self.tunnel_identity_file,
|
||||
"tunnel_password": self.tunnel_password,
|
||||
"connection_params": self.connection_params
|
||||
}
|
||||
|
||||
|
||||
class ModulePreference(db.Model):
|
||||
"""Define a preferences table for any modules."""
|
||||
|
|
|
@ -59,7 +59,8 @@ export default class DepListener {
|
|||
if(actionObj.listener?.callback) {
|
||||
state = this._getListenerData(state, actionObj.listener, actionObj);
|
||||
} else {
|
||||
let allListeners = _.filter(this._depListeners, (entry)=>_.join(currPath, '|').startsWith(_.join(entry.source, '|')));
|
||||
// adding a extra item in path to avoid incorrect matching like shared and shared_username
|
||||
let allListeners = _.filter(this._depListeners, (entry)=>_.join(currPath.concat(['']), '|').startsWith(_.join(entry.source.concat(['']), '|')));
|
||||
if(allListeners) {
|
||||
for(const listener of allListeners) {
|
||||
state = this._getListenerData(state, listener, actionObj);
|
||||
|
|
|
@ -130,7 +130,8 @@ def load_servers():
|
|||
data = json.loads(j.read())
|
||||
|
||||
# Validate the json file and data
|
||||
errmsg = validate_json_data(data, False)
|
||||
errmsg = validate_json_data(
|
||||
data, current_user.has_role("Administrator"))
|
||||
if errmsg is not None:
|
||||
return internal_server_error(errmsg)
|
||||
|
||||
|
|
|
@ -493,6 +493,7 @@ def dump_database_servers(output_file, selected_servers,
|
|||
add_value(attr_dict, "Role", server.role)
|
||||
add_value(attr_dict, "Comment", server.comment)
|
||||
add_value(attr_dict, "Shared", server.shared)
|
||||
add_value(attr_dict, "SharedUsername", server.shared_username)
|
||||
add_value(attr_dict, "DBRestriction", server.db_res)
|
||||
add_value(attr_dict, "BGColor", server.bgcolor)
|
||||
add_value(attr_dict, "FGColor", server.fgcolor)
|
||||
|
@ -738,6 +739,8 @@ def load_database_servers(input_file, selected_servers,
|
|||
|
||||
new_server.shared = obj.get("Shared", None)
|
||||
|
||||
new_server.shared_username = obj.get("SharedUsername", None)
|
||||
|
||||
new_server.kerberos_conn = obj.get("KerberosAuthentication", None)
|
||||
|
||||
# if desktop mode
|
||||
|
|
Loading…
Reference in New Issue