diff --git a/web/pgAdmin4.py b/web/pgAdmin4.py index 10aabe8a9..939c67f8f 100644 --- a/web/pgAdmin4.py +++ b/web/pgAdmin4.py @@ -16,6 +16,9 @@ import sys if sys.version_info < (3, 4): raise RuntimeError('This application must be run under Python 3.4 ' 'or later.') +# Due to https://github.com/eventlet/eventlet/issues/670 +if sys.version_info <= (3, 9): + import select import builtins import os diff --git a/web/pgadmin/misc/cloud/google/__init__.py b/web/pgadmin/misc/cloud/google/__init__.py index 162f58d46..5d0cf3420 100644 --- a/web/pgadmin/misc/cloud/google/__init__.py +++ b/web/pgadmin/misc/cloud/google/__init__.py @@ -71,7 +71,7 @@ def verify_credentials(): data = json.loads(request.data) client_secret_path = data['secret']['client_secret_file'] if \ 'client_secret_file' in data['secret'] else None - status = True + status = False error = None res_data = {} @@ -91,15 +91,14 @@ def verify_credentials(): # get auth url auth_url, error_msg = _google.get_auth_url(request.host_url) if error_msg: - status = False error = error_msg else: + status = True res_data = {'auth_url': auth_url} # save google object - session['google']['client_config'] = client_config - session['google']['google_obj'] = pickle.dumps(_google, -1) + session['google']['client_config'] = client_config + session['google']['google_obj'] = pickle.dumps(_google, -1) else: - status = False error = 'Client secret path not found' return make_json_response(success=status, errormsg=error, data=res_data) diff --git a/web/pgadmin/misc/cloud/static/js/CloudWizard.jsx b/web/pgadmin/misc/cloud/static/js/CloudWizard.jsx index 452cdd984..95921ea43 100644 --- a/web/pgadmin/misc/cloud/static/js/CloudWizard.jsx +++ b/web/pgadmin/misc/cloud/static/js/CloudWizard.jsx @@ -271,6 +271,10 @@ export default function CloudWizard({ nodeInfo, nodeData, onClose, cloudPanel}) if(activeStep == 3 && (cloudProvider == CLOUD_PROVIDERS.AWS || cloudProvider == CLOUD_PROVIDERS.AZURE || cloudProvider == CLOUD_PROVIDERS.GOOGLE)) { resolve(true); } + else if(activeStep == 1 && (cloudProvider == CLOUD_PROVIDERS.AWS || cloudProvider == CLOUD_PROVIDERS.AZURE || cloudProvider == CLOUD_PROVIDERS.GOOGLE)) { + setVerificationIntiated(false); + } + setErrMsg(['', '']); resolve(); }); }; diff --git a/web/pgadmin/misc/cloud/static/js/google.js b/web/pgadmin/misc/cloud/static/js/google.js index 2a14ce610..6cfcf8257 100644 --- a/web/pgadmin/misc/cloud/static/js/google.js +++ b/web/pgadmin/misc/cloud/static/js/google.js @@ -83,7 +83,7 @@ export function GoogleCredentials(props) { child.close(); } resolve(); - } else if (res.data && res.data.success == 0 && (res.data.errormsg == 'Invalid state parameter.' || res.data.errormsg == 'Access denied.' || res.data.errormsg == 'Authentication is failed.')){ + } else if (res.data && res.data.success == 0 && res.data.errormsg ){ _eventBus.fireEvent('SET_ERROR_MESSAGE_FOR_CLOUD_WIZARD',[MESSAGE_TYPE.ERROR, res.data.errormsg]); _eventBus.fireEvent('SET_CRED_VERIFICATION_INITIATED',false); clearInterval(interval); @@ -242,9 +242,12 @@ GoogleDatabaseDetails.propTypes = { // Validation functions export function validateGoogleStep2(cloudInstanceDetails) { let isError = false; - if (isEmptyString(cloudInstanceDetails.name) || - isEmptyString(cloudInstanceDetails.db_version) || isEmptyString(cloudInstanceDetails.instance_type) || - isEmptyString(cloudInstanceDetails.region)|| isEmptyString(cloudInstanceDetails.storage_size) || isEmptyString(cloudInstanceDetails.public_ips)) { + if ((isEmptyString(cloudInstanceDetails.name) || isEmptyString(cloudInstanceDetails.project) || + isEmptyString(cloudInstanceDetails.region) || isEmptyString(cloudInstanceDetails.availability_zone) || + isEmptyString(cloudInstanceDetails.db_version) || isEmptyString(cloudInstanceDetails.instance_type) || + isEmptyString(cloudInstanceDetails.instance_class) || isEmptyString(cloudInstanceDetails.storage_type)|| + isEmptyString(cloudInstanceDetails.storage_size) || isEmptyString(cloudInstanceDetails.public_ips)) || + (cloudInstanceDetails.high_availability && isEmptyString(cloudInstanceDetails.secondary_availability_zone))) { isError = true; } return isError; @@ -274,9 +277,17 @@ function createData(name, value) { // Summary section export function getGoogleSummary(cloud, cloudInstanceDetails, cloudDBDetails) { - let dbVersion = cloudInstanceDetails.db_version; - dbVersion = dbVersion.charAt(0) + dbVersion.slice(1,7).toLowerCase() + 'SQL ' + dbVersion.split('_')[1]; + let db_version = cloudInstanceDetails.db_version; + db_version = db_version.charAt(0) + db_version.slice(1,7).toLowerCase() + 'SQL ' + db_version.split('_')[1]; let storageType = cloudInstanceDetails.storage_type.split('_')[1]; + let instance_class = cloudInstanceDetails.instance_class.charAt(0).toUpperCase() + cloudInstanceDetails.instance_class.slice(1); + let instance_type = cloudInstanceDetails.instance_type; + if (instance_class =='Standard' || instance_class =='Highmem' ){ + instance_type = instance_type.split('-')[2] + ' vCPU ' + Math.round((parseInt(instance_type.split('-')[3]))/1024) + ' GB'; + }else{ + const instance_type_mapping = {'db-f1-micro':'1 vCPU, 0.6 GB', 'db-g1-small': '1 vCPU, 1.7 GB'}; + instance_type = instance_type_mapping[instance_type]; + } const rows1 = [ createData(gettext('Cloud'), cloud), @@ -287,8 +298,9 @@ export function getGoogleSummary(cloud, cloudInstanceDetails, cloudDBDetails) { ]; const rows2 = [ - createData(gettext('PostgreSQL version'), dbVersion), - createData(gettext('Instance type'), cloudInstanceDetails.instance_type), + createData(gettext('PostgreSQL version'), db_version), + createData(gettext('Instance class'), instance_class), + createData(gettext('Instance type'), instance_type), ]; const rows3 = [ diff --git a/web/pgadmin/misc/cloud/static/js/google_schema.ui.js b/web/pgadmin/misc/cloud/static/js/google_schema.ui.js index 1f9182e2d..2d4e35a5f 100644 --- a/web/pgadmin/misc/cloud/static/js/google_schema.ui.js +++ b/web/pgadmin/misc/cloud/static/js/google_schema.ui.js @@ -38,7 +38,7 @@ class GoogleCredSchema extends BaseUISchema{ id: 'client_secret_file', label: gettext('Client secret file'), type: 'file', - helpMessage: gettext('Select a client secrets file containing the client ID, client secret, and other OAuth 2.0 parameters for google authentication. Refer link for creating client secret.'), + helpMessage: gettext('Select a client secrets file containing the client ID, client secret, and other OAuth 2.0 parameters for google authentication. Refer link for creating client secret.'), controlProps: { dialogType: 'select_file', supportedTypes: ['json'], @@ -65,6 +65,7 @@ class GoogleCredSchema extends BaseUISchema{ obj.fieldOptions.authenticateGoogle(state.client_secret_file) .then(()=>{ resolve(()=>({ + is_authenticating: false, })); }) .catch((err)=>{ @@ -81,7 +82,7 @@ class GoogleCredSchema extends BaseUISchema{ deps:['auth_btn'], deferredDepChange: (state, source)=>{ return new Promise((resolve, reject)=>{ - if(source == 'auth_btn' && state.is_authenticating ) { + if(source == 'auth_btn' && state.is_authenticating ) { obj.fieldOptions.verification_ack() .then(()=>{ resolve(); @@ -261,7 +262,7 @@ class GoogleStorageSchema extends BaseUISchema { { id: 'storage_size', label: gettext('Storage capacity'), - type: 'text', + type: 'int', mode: ['create'], noEmpty: true, deps: ['storage_type'], @@ -272,7 +273,7 @@ class GoogleStorageSchema extends BaseUISchema { validate(data, setErrMsg) { if (data.storage_size && (data.storage_size < 9 || data.storage_size > 65536)) { - setErrMsg('storage_size', gettext('Please enter value betwwen 10 and 65,536.')); + setErrMsg('storage_size', gettext('Please enter the value between 10 and 65,536.')); return true; } return false; @@ -350,8 +351,8 @@ class GoogleHighAvailabilitySchema extends BaseUISchema { } validate(data, setErrMsg) { - if (data.high_availability && (isEmptyString(data.secondary_availability_zone))) { - setErrMsg('secondary_availability_zone', gettext('Please select Secondary availability zone.')); + if (data.high_availability && (isEmptyString(data.secondary_availability_zone)) || (data.secondary_availability_zone == data.availability_zone)) { + setErrMsg('secondary_availability_zone', gettext('Please select Secondary availability zone different than primary.')); return true; } return false; @@ -519,6 +520,14 @@ class GoogleClusterSchema extends BaseUISchema { }, ]; } + + validate(data, setErr) { + if ( !isEmptyString(data.name) && (!/^(?=[a-z])[a-z0-9\-]*$/.test(data.name) || data.name.length > 97)) { + setErr('name',gettext('Name must only contain lowercase letters, numbers, and hyphens. Start with a letter.')); + return true; + } + return false; + } } -export {GoogleCredSchema, GoogleClusterSchema, GoogleDatabaseSchema}; \ No newline at end of file +export {GoogleCredSchema, GoogleClusterSchema, GoogleDatabaseSchema};