///////////////////////////////////////////////////////////// // // pgAdmin 4 - PostgreSQL Tools // // Copyright (C) 2013 - 2021, The pgAdmin Development Team // This software is released under the PostgreSQL Licence // ////////////////////////////////////////////////////////////// import axios from 'axios/index'; import gettext from '../../../../static/js/gettext'; import url_for from '../../../../static/js/url_for'; import _ from 'underscore'; import {DialogWrapper} from '../../../../static/js/alertify/dialog_wrapper'; import {fetch_ticket_lifetime} from '../../../../authenticate/static/js/kerberos'; import userInfo from 'pgadmin.user_management.current_user'; import pgConst from 'pgadmin.browser.constants'; export class BackupDialogWrapper extends DialogWrapper { constructor(dialogContainerSelector, dialogTitle, typeOfDialog, jquery, pgBrowser, alertify, dialogModel, backform) { super(dialogContainerSelector, dialogTitle, jquery, pgBrowser, alertify, dialogModel, backform); this.typeOfDialog = typeOfDialog; } main(title) { this.set('title', title); } setup() { let get_help_file = function (dialog_type) { if (dialog_type == 'globals') { return 'backup_globals_dialog.html'; } else if (dialog_type == 'server') { return 'backup_server_dialog.html'; } return 'backup_dialog.html'; }; return { buttons: [{ text: '', className: 'btn btn-primary-icon pull-left fa fa-info pg-alertify-icon-button', attrs: { name: 'object_help', type: 'button', url: 'backup.html', label: gettext('Backup'), 'aria-label': gettext('Backup'), }, }, { text: '', key: 112, className: 'btn btn-primary-icon pull-left fa fa-question pg-alertify-icon-button', attrs: { name: 'dialog_help', type: 'button', label: gettext('Help'), 'aria-label': gettext('Help'), url: url_for('help.static', { 'filename': get_help_file(this.typeOfDialog), }), }, }, { text: gettext('Cancel'), key: 27, className: 'btn btn-secondary fa fa-lg fa-times pg-alertify-button', 'data-btn-name': 'cancel', }, { text: gettext('Backup'), key: 13, className: 'btn btn-primary fa fa-lg fa-save pg-alertify-button', 'data-btn-name': 'backup', }], // Set options for dialog options: { title: this.dialogTitle, //disable both padding and overflow control. padding: !1, overflow: !1, model: 0, resizable: true, maximizable: true, pinnable: false, closableByDimmer: false, modal: false, }, }; } prepare() { this.disableBackupButton(); const $container = this.jquery(this.dialogContainerSelector); const selectedTreeNode = this.getSelectedNode(); const selectedTreeNodeData = this.getSelectedNodeData(selectedTreeNode); if (!selectedTreeNodeData) { return; } const node = this.pgBrowser.Nodes[selectedTreeNodeData._type]; if (this.dialogTitle === null) { let title = gettext('Backup (%s: %s)', node.label, selectedTreeNodeData.label); this.main(title); } const treeInfo = this.pgBrowser.tree.getTreeNodeHierarchy(selectedTreeNode); const dialog = this.createDialog(node, treeInfo, this.typeOfDialog, $container); this.addAlertifyClassToBackupNodeChildNodes(); dialog.render(); const statusBar = this.jquery( '
').appendTo($container); this.elements.content.appendChild($container.get(0)); this.focusOnDialog(this); this.setListenersForFilenameChanges(statusBar); } callback(event) { const selectedTreeNode = this.getSelectedNode(); const selectedTreeNodeData = this.getSelectedNodeData(selectedTreeNode); const node = selectedTreeNodeData && this.pgBrowser.Nodes[selectedTreeNodeData._type]; if (this.wasHelpButtonPressed(event)) { event.cancel = true; this.pgBrowser.showHelp( event.button.element.name, event.button.element.getAttribute('url'), node, selectedTreeNode.getHtmlIdentifier() ); return; } if (this.wasBackupButtonPressed(event)) { if (!selectedTreeNodeData) return; const serverIdentifier = this.retrieveServerIdentifier(node, selectedTreeNode); const dialog = this; let urlShortcut = 'backup.create_server_job'; if (this.typeOfDialog === 'backup_objects') { urlShortcut = 'backup.create_object_job'; } const baseUrl = url_for(urlShortcut, { 'sid': serverIdentifier, }); const treeInfo = this.pgBrowser.tree.getTreeNodeHierarchy(selectedTreeNode); this.setExtraParameters(selectedTreeNode, treeInfo); let backupDate = this.view.model.toJSON(); if(userInfo['current_auth_source'] == pgConst['KERBEROS'] && treeInfo.server.gss_authenticated && (backupDate.type == 'globals' || backupDate.type == 'server')) { let newPromise = fetch_ticket_lifetime(); newPromise.then( function(lifetime) { if (lifetime < 1800 && lifetime > 0) { dialog.alertify.warning( 'You have '+ (Math.round(parseInt(lifetime)/60)).toString() +' minutes left on your ticket - if the dump takes longer than that, it may fail."' ); } }, function() { dialog.alertify.warning( gettext('Please renew your kerberos ticket, it has been expired.') ); } ); } axios.post( baseUrl, backupDate ).then(function (res) { if (res.data.success) { dialog.alertify.success(gettext('Backup job created.'), 5); dialog.pgBrowser.Events.trigger('pgadmin-bgprocess:created', dialog); } else { dialog.alertify.alert( gettext('Backup job creation failed.'), res.data.errormsg ); } }).catch(function (error) { try { const err = error.response.data; dialog.alertify.alert( gettext('Backup job failed.'), err.errormsg ); } catch (e) { console.warn(e.stack || e); } }); } } addAlertifyClassToBackupNodeChildNodes() { this.jquery(this.elements.body.childNodes[0]).addClass( 'alertify_tools_dialog_properties obj_properties' ); } getSelectedNode() { const tree = this.pgBrowser.tree; const selectedNode = tree.selected(); if (selectedNode) { return tree.findNodeByDomElement(selectedNode); } else { return undefined; } } disableBackupButton() { this.__internal.buttons[3].element.disabled = true; } enableBackupButton() { this.__internal.buttons[3].element.disabled = false; } createDialog(node, treeInfo, typeOfDialog, $container) { let attributes = {}; if (typeOfDialog !== 'backup_objects') { attributes['type'] = typeOfDialog; } // Instance of backbone model const newModel = new this.dialogModel(attributes, { node_info: treeInfo, }); const fields = this.backform.generateViewSchema( treeInfo, newModel, 'create', node, treeInfo.server, true ); return this.view = new this.backform.Dialog({ el: $container, model: newModel, schema: fields, }); } retrieveServerIdentifier(node, selectedTreeNode) { const treeInfo = this.pgBrowser.tree.getTreeNodeHierarchy(selectedTreeNode); return treeInfo.server._id; } setListenersForFilenameChanges(statusBar) { const self = this; this.view.model.on('change', function () { const ctx = this; var errmsg; const showError = function(errorField, errormsg) { ctx.errorModel.set(errorField, errormsg); statusBar.removeClass('d-none'); statusBar.find('.alert-text').html(errormsg); self.elements.dialog.querySelector('.close-error').addEventListener('click', ()=>{ statusBar.addClass('d-none'); ctx.errorModel.set(errorField, errormsg); }); }; if (!_.isUndefined(this.get('file')) && this.get('file') !== '') { this.errorModel.clear(); statusBar.addClass('d-none'); self.enableBackupButton(); } else { self.disableBackupButton(); errmsg = gettext('Please provide a filename'); showError('file', errmsg); } }); } setExtraParameters(selectedTreeNode, treeInfo) { if (this.typeOfDialog === 'backup_objects') { this.view.model.set('database', treeInfo.database._label); const nodeData = selectedTreeNode.getData(); if (nodeData._type === 'schema') { this.view.model.set('schemas', [nodeData._label]); } if (nodeData._type === 'table' || nodeData._type === 'partition') { this.view.model.set('tables', [ [treeInfo.schema._label, nodeData._label], ]); } if (_.isEmpty(this.view.model.get('ratio'))) { this.view.model.unset('ratio'); } } } wasBackupButtonPressed(event) { return event.button['data-btn-name'] === 'backup'; } }