pgadmin4/web/pgadmin/browser/server_groups/servers/static/js/server.ui.js
2023-10-12 16:58:46 +05:30

535 lines
20 KiB
JavaScript

/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2023, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import gettext from 'sources/gettext';
import _ from 'lodash';
import BaseUISchema from 'sources/SchemaView/base_schema.ui';
import pgAdmin from 'sources/pgadmin';
import {default as supportedServers} from 'pgadmin.server.supported_servers';
import current_user from 'pgadmin.user_management.current_user';
import { isEmptyString } from 'sources/validators';
import VariableSchema from './variable.ui';
export default class ServerSchema extends BaseUISchema {
constructor(serverGroupOptions=[], userId=0, initValues={}) {
super({
gid: undefined,
id: undefined,
name: '',
bgcolor: '',
fgcolor: '',
host: '',
port: 5432,
db: 'postgres',
username: current_user.name,
role: null,
connect_now: true,
password: undefined,
save_password: false,
db_res: [],
passexec: undefined,
passexec_expiration: undefined,
service: undefined,
shared_username: '',
use_ssh_tunnel: false,
tunnel_host: undefined,
tunnel_port: 22,
tunnel_username: undefined,
tunnel_identity_file: undefined,
tunnel_password: undefined,
tunnel_authentication: false,
save_tunnel_password: false,
connection_string: undefined,
connection_params: [
{'name': 'sslmode', 'value': 'prefer', 'keyword': 'sslmode'},
{'name': 'connect_timeout', 'value': 10, 'keyword': 'connect_timeout'}],
...initValues,
});
this.serverGroupOptions = serverGroupOptions;
this.paramSchema = new VariableSchema(this.getConnectionParameters(), null, null, ['name', 'keyword', 'value']);
this.userId = userId;
_.bindAll(this, 'isShared');
}
initialise(state) {
this.paramSchema.setAllReadOnly(this.isConnected(state));
}
isShared(state) {
return !this.isNew(state) && this.userId != current_user.id && state.shared;
}
isConnected(state) {
return Boolean(state.connected);
}
get baseFields() {
let obj = this;
return [
{
id: 'id', label: gettext('ID'), type: 'int', group: null,
mode: ['properties'],
},{
id: 'name', label: gettext('Name'), type: 'text', group: null,
mode: ['properties', 'edit', 'create'], noEmpty: true,
disabled: obj.isShared,
},{
id: 'gid', label: gettext('Server group'), type: 'select',
options: obj.serverGroupOptions,
mode: ['create', 'edit'],
controlProps: { allowClear: false },
disabled: obj.isShared,
},
{
id: 'server_owner', label: gettext('Shared Server Owner'), type: 'text', mode: ['properties'],
visible: function(state) {
let serverOwner = obj.userId;
return state.shared && serverOwner != current_user.id && pgAdmin.server_mode == 'True';
},
},
{
id: 'server_type', label: gettext('Server type'), type: 'select',
mode: ['properties'], visible: obj.isConnected,
options: supportedServers,
}, {
id: 'connected', label: gettext('Connected?'), type: 'switch',
mode: ['properties'], group: gettext('Connection'),
}, {
id: 'version', label: gettext('Version'), type: 'text', group: null,
mode: ['properties'], visible: obj.isConnected,
},
{
id: 'bgcolor', label: gettext('Background'), type: 'color',
group: null, mode: ['edit', 'create'],
disabled: obj.isConnected, deps: ['fgcolor'], depChange: (state)=>{
if(!state.bgcolor && state.fgcolor) {
return {'bgcolor': '#ffffff'};
}
}
},{
id: 'fgcolor', label: gettext('Foreground'), type: 'color',
group: null, mode: ['edit', 'create'], disabled: obj.isConnected,
},
{
id: 'connect_now', label: gettext('Connect now?'), type: 'switch',
group: null, mode: ['create'],
},
{
id: 'shared', label: gettext('Shared?'), type: 'switch',
mode: ['properties', 'create', 'edit'],
readonly: function(state){
let serverOwner = obj.userId;
return !obj.isNew(state) && serverOwner != current_user.id;
}, visible: function(){
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)=>{
return !(!this.origData.shared && s.shared);
}, visible: ()=>{
return current_user.is_admin && pgAdmin.server_mode == 'True';
},
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'],
}, {
id: 'connection_string', label: gettext('Connection String'), type: 'multiline',
group: gettext('Connection'), mode: ['properties'], readonly: true,
}, {
id: 'host', label: gettext('Host name/address'), type: 'text', group: gettext('Connection'),
mode: ['properties', 'edit', 'create'], disabled: obj.isShared,
depChange: (state)=>{
if(obj.origData.host != state.host && !obj.isNew(state) && state.connected){
obj.informText = gettext(
'To apply changes to the connection configuration, please disconnect from the server and then reconnect.'
);
} else {
obj.informText = undefined;
}
}
},
{
id: 'port', label: gettext('Port'), type: 'int', group: gettext('Connection'),
mode: ['properties', 'edit', 'create'], min: 1, max: 65535, disabled: obj.isShared,
depChange: (state)=>{
if(obj.origData.port != state.port && !obj.isNew(state) && state.connected){
obj.informText = gettext(
'To apply changes to the connection configuration, please disconnect from the server and then reconnect.'
);
} else {
obj.informText = undefined;
}
}
},{
id: 'db', label: gettext('Maintenance database'), type: 'text', group: gettext('Connection'),
mode: ['properties', 'edit', 'create'], readonly: obj.isConnected, disabled: obj.isShared,
noEmpty: true,
},{
id: 'username', label: gettext('Username'), type: 'text', group: gettext('Connection'),
mode: ['properties', 'edit', 'create'],
depChange: (state)=>{
if(obj.origData.username != state.username && !obj.isNew(state) && state.connected){
obj.informText = gettext(
'To apply changes to the connection configuration, please disconnect from the server and then reconnect.'
);
} else {
obj.informText = undefined;
}
}
},{
id: 'kerberos_conn', label: gettext('Kerberos authentication?'), type: 'switch',
group: gettext('Connection'),
},{
id: 'gss_authenticated', label: gettext('GSS authenticated?'), type: 'switch',
group: gettext('Connection'), mode: ['properties'], visible: obj.isConnected,
},{
id: 'gss_encrypted', label: gettext('GSS encrypted?'), type: 'switch',
group: gettext('Connection'), mode: ['properties'], visible: obj.isConnected,
},{
id: 'password', label: gettext('Password'), type: 'password',
group: gettext('Connection'),
mode: ['create'],
deps: ['connect_now', 'kerberos_conn'],
visible: function(state) {
return state.connect_now && obj.isNew(state);
},
controlProps: {
maxLength: null
},
disabled: function(state) {return state.kerberos_conn;},
},{
id: 'save_password', label: gettext('Save password?'),
type: 'switch', group: gettext('Connection'), mode: ['create'],
deps: ['connect_now', 'kerberos_conn'],
visible: function(state) {
return state.connect_now && obj.isNew(state);
},
disabled: function(state) {
return !current_user.allow_save_password || state.kerberos_conn;
},
},{
id: 'role', label: gettext('Role'), type: 'text', group: gettext('Connection'),
mode: ['properties', 'edit', 'create'], readonly: obj.isConnected,
},{
id: 'service', label: gettext('Service'), type: 'text',
mode: ['properties', 'edit', 'create'], readonly: obj.isConnected,
group: gettext('Connection'),
}, {
id: 'connection_params', label: gettext('Connection Parameters'),
type: 'collection', group: gettext('Parameters'),
schema: this.paramSchema, mode: ['edit', 'create'], uniqueCol: ['name'],
canAdd: (state)=> !obj.isConnected(state), canEdit: false,
canDelete: (state)=> !obj.isConnected(state),
}, {
id: 'use_ssh_tunnel', label: gettext('Use SSH tunneling'), type: 'switch',
mode: ['properties', 'edit', 'create'], group: gettext('SSH Tunnel'),
disabled: function() {
return !pgAdmin.Browser.utils.support_ssh_tunnel;
},
readonly: obj.isConnected,
},{
id: 'tunnel_host', label: gettext('Tunnel host'), type: 'text', group: gettext('SSH Tunnel'),
mode: ['properties', 'edit', 'create'], deps: ['use_ssh_tunnel'],
disabled: function(state) {
return !state.use_ssh_tunnel;
},
readonly: obj.isConnected,
},{
id: 'tunnel_port', label: gettext('Tunnel port'), type: 'int', group: gettext('SSH Tunnel'),
mode: ['properties', 'edit', 'create'], deps: ['use_ssh_tunnel'], max: 65535,
disabled: function(state) {
return !state.use_ssh_tunnel;
},
readonly: obj.isConnected,
},{
id: 'tunnel_username', label: gettext('Username'), type: 'text', group: gettext('SSH Tunnel'),
mode: ['properties', 'edit', 'create'], deps: ['use_ssh_tunnel'],
disabled: function(state) {
return !state.use_ssh_tunnel;
},
readonly: obj.isConnected,
},{
id: 'tunnel_authentication', label: gettext('Authentication'), type: 'toggle',
mode: ['properties', 'edit', 'create'], group: gettext('SSH Tunnel'),
options: [
{'label': gettext('Password'), value: false},
{'label': gettext('Identity file'), value: true},
],
disabled: function(state) {
return !state.use_ssh_tunnel;
},
readonly: obj.isConnected,
},
{
id: 'tunnel_identity_file', label: gettext('Identity file'), type: 'file',
group: gettext('SSH Tunnel'), mode: ['properties', 'edit', 'create'],
controlProps: {
dialogType: 'select_file', supportedTypes: ['*'],
},
deps: ['tunnel_authentication', 'use_ssh_tunnel'],
depChange: (state)=>{
if (!state.tunnel_authentication && state.tunnel_identity_file) {
return {tunnel_identity_file: null};
}
},
disabled: function(state) {
return !state.tunnel_authentication || !state.use_ssh_tunnel;
},
},
{
id: 'tunnel_password', label: gettext('Password'), type: 'password',
group: gettext('SSH Tunnel'), mode: ['create'],
deps: ['use_ssh_tunnel'],
disabled: function(state) {
return !state.use_ssh_tunnel;
},
controlProps: {
maxLength: null
},
readonly: obj.isConnected,
}, {
id: 'save_tunnel_password', label: gettext('Save password?'),
type: 'switch', group: gettext('SSH Tunnel'), mode: ['create'],
deps: ['connect_now', 'use_ssh_tunnel'],
visible: function(state) {
return state.connect_now && obj.isNew(state);
},
disabled: function(state) {
return (!current_user.allow_save_tunnel_password || !state.use_ssh_tunnel);
},
},
{
id: 'db_res', label: gettext('DB restriction'), type: 'select', group: gettext('Advanced'),
options: [],
mode: ['properties', 'edit', 'create'], readonly: obj.isConnected, controlProps: {
multiple: true, allowClear: false, creatable: true, noDropdown: true, placeholder: 'Specify the databases to be restrict...'},
},
{
id: 'passexec_cmd', label: gettext('Password exec command'), type: 'text',
group: gettext('Advanced'),
mode: ['properties', 'edit', 'create'],
disabled: pgAdmin.server_mode == 'True',
},
{
id: 'passexec_expiration', label: gettext('Password exec expiration (seconds)'), type: 'int',
group: gettext('Advanced'),
mode: ['properties', 'edit', 'create'],
disabled: function(state) {
return isEmptyString(state.passexec_cmd);
},
},
{
id: 'prepare_threshold', label: gettext('Prepare threshold'), type: 'int',
group: gettext('Advanced'),
mode: ['properties', 'edit', 'create'],
helpMessageMode: ['edit', 'create'],
helpMessage: gettext('If it is set to 0, every query is prepared the first time it is executed. If it is set to blank, prepared statements are disabled on the connection.')
}
];
}
validate(state, setError) {
let errmsg = null;
if (isEmptyString(state.service)) {
errmsg = gettext('Either Host name or Service must be specified.');
if(isEmptyString(state.host)) {
setError('host', errmsg);
return true;
} else {
setError('host', null);
}
/* Hostname, IP address validate */
if (state.host) {
// Check for leading and trailing spaces.
if (/(^\s)|(\s$)/.test(state.host)){
errmsg = gettext('Host name must be valid hostname or IPv4 or IPv6 address.');
setError('host', errmsg);
return true;
} else {
setError('host', null);
}
}
if(isEmptyString(state.username)) {
errmsg = gettext('Username must be specified.');
setError('username', errmsg);
return true;
} else {
setError('username', null);
}
if(isEmptyString(state.port)) {
errmsg = gettext('Port must be specified.');
setError('port', errmsg);
return true;
} else {
setError('port', null);
}
} else {
_.each(['host', 'db', 'username', 'port'], (item) => {
setError(item, null);
});
}
if (state.use_ssh_tunnel) {
if(isEmptyString(state.tunnel_host)) {
errmsg = gettext('SSH Tunnel host must be specified.');
setError('tunnel_host', errmsg);
return true;
} else {
setError('tunnel_host', null);
}
if(isEmptyString(state.tunnel_port)) {
errmsg = gettext('SSH Tunnel port must be specified.');
setError('tunnel_port', errmsg);
return true;
} else {
setError('tunnel_port', null);
}
if(isEmptyString(state.tunnel_username)) {
errmsg = gettext('SSH Tunnel username must be specified.');
setError('tunnel_username', errmsg);
return true;
} else {
setError('tunnel_username', null);
}
if (state.tunnel_authentication) {
if(isEmptyString(state.tunnel_identity_file)) {
errmsg = gettext('SSH Tunnel identity file must be specified.');
setError('tunnel_identity_file', errmsg);
return true;
} else {
setError('tunnel_identity_file', null);
}
}
}
return false;
}
getConnectionParameters() {
return [{
'value': 'hostaddr', 'label': gettext('Host address'), 'vartype': 'string'
}, {
'value': 'passfile', 'label': gettext('Password file'), 'vartype': 'file'
}, {
'value': 'channel_binding', 'label': gettext('Channel binding'), 'vartype': 'enum',
'enumvals': [gettext('prefer'), gettext('require'), gettext('disable')],
'min_server_version': '13'
}, {
'value': 'connect_timeout', 'label': gettext('Connection timeout (seconds)'), 'vartype': 'integer'
}, {
'value': 'client_encoding', 'label': gettext('Client encoding'), 'vartype': 'string'
}, {
'value': 'options', 'label': gettext('Options'), 'vartype': 'string'
}, {
'value': 'application_name', 'label': gettext('Application name'), 'vartype': 'string'
}, {
'value': 'fallback_application_name', 'label': gettext('Fallback application name'), 'vartype': 'string'
}, {
'value': 'keepalives', 'label': gettext('Keepalives'), 'vartype': 'integer'
}, {
'value': 'keepalives_idle', 'label': gettext('Keepalives idle (seconds)'), 'vartype': 'integer'
}, {
'value': 'keepalives_interval', 'label': gettext('Keepalives interval (seconds)'), 'vartype': 'integer'
}, {
'value': 'keepalives_count', 'label': gettext('Keepalives count'), 'vartype': 'integer'
}, {
'value': 'tcp_user_timeout', 'label': gettext('TCP user timeout (milliseconds)'), 'vartype': 'integer',
'min_server_version': '12'
}, {
'value': 'tty', 'label': gettext('TTY'), 'vartype': 'string',
'max_server_version': '13'
}, {
'value': 'replication', 'label': gettext('Replication'), 'vartype': 'enum',
'enumvals': [gettext('on'), gettext('off'), gettext('database')],
'min_server_version': '11'
}, {
'value': 'gssencmode', 'label': gettext('GSS encmode'), 'vartype': 'enum',
'enumvals': [gettext('prefer'), gettext('require'), gettext('disable')],
'min_server_version': '12'
}, {
'value': 'sslmode', 'label': gettext('SSL mode'), 'vartype': 'enum',
'enumvals': [gettext('allow'), gettext('prefer'), gettext('require'),
gettext('disable'), gettext('verify-ca'), gettext('verify-full')]
}, {
'value': 'sslcompression', 'label': gettext('SSL compression?'), 'vartype': 'bool',
}, {
'value': 'sslcert', 'label': gettext('Client certificate'), 'vartype': 'file'
}, {
'value': 'sslkey', 'label': gettext('Client certificate key'), 'vartype': 'file'
}, {
'value': 'sslpassword', 'label': gettext('SSL password'), 'vartype': 'string',
'min_server_version': '13'
}, {
'value': 'sslrootcert', 'label': gettext('Root certificate'), 'vartype': 'file'
}, {
'value': 'sslcrl', 'label': gettext('Certificate revocation list'), 'vartype': 'file',
}, {
'value': 'sslcrldir', 'label': gettext('Certificate revocation list directory'), 'vartype': 'file',
'min_server_version': '14'
}, {
'value': 'sslsni', 'label': gettext('Server name indication'), 'vartype': 'bool',
'min_server_version': '14'
}, {
'value': 'requirepeer', 'label': gettext('Require peer'), 'vartype': 'string',
}, {
'value': 'ssl_min_protocol_version', 'label': gettext('SSL min protocol version'),
'vartype': 'enum', 'min_server_version': '13',
'enumvals': [gettext('TLSv1'), gettext('TLSv1.1'), gettext('TLSv1.2'),
gettext('TLSv1.3')]
}, {
'value': 'ssl_max_protocol_version', 'label': gettext('SSL max protocol version'),
'vartype': 'enum', 'min_server_version': '13',
'enumvals': [gettext('TLSv1'), gettext('TLSv1.1'), gettext('TLSv1.2'),
gettext('TLSv1.3')]
}, {
'value': 'krbsrvname', 'label': gettext('Kerberos service name'), 'vartype': 'string',
}, {
'value': 'gsslib', 'label': gettext('GSS library'), 'vartype': 'string',
}, {
'value': 'target_session_attrs', 'label': gettext('Target session attribute'),
'vartype': 'enum',
'enumvals': [gettext('any'), gettext('read-write'), gettext('read-only'),
gettext('primary'), gettext('standby'), gettext('prefer-standby')]
}, {
'value': 'load_balance_hosts', 'label': gettext('Load balance hosts'),
'vartype': 'enum', 'min_server_version': '16',
'enumvals': [gettext('disable'), gettext('random')]
}];
}
}