diff --git a/web/pgadmin/browser/server_groups/__init__.py b/web/pgadmin/browser/server_groups/__init__.py index 476a4e66..56177263 100644 --- a/web/pgadmin/browser/server_groups/__init__.py +++ b/web/pgadmin/browser/server_groups/__init__.py @@ -177,6 +177,17 @@ class ServerGroupView(NodeView): # if server group id is 1 we won't delete it. sg = groups.first() + shared_servers = Server.query.filter_by(servergroup_id=sg.id, + shared=True).all() + if shared_servers: + return make_json_response( + status=417, + success=0, + errormsg=gettext( + 'The specified server group cannot be deleted.' + ) + ) + if sg.id == gid: return make_json_response( status=417, diff --git a/web/pgadmin/static/js/sqleditor/new_connection_dialog_model.js b/web/pgadmin/static/js/sqleditor/new_connection_dialog_model.js index de1d0f21..4f282da8 100644 --- a/web/pgadmin/static/js/sqleditor/new_connection_dialog_model.js +++ b/web/pgadmin/static/js/sqleditor/new_connection_dialog_model.js @@ -100,352 +100,353 @@ export default function newConnectionDialogModel(response, sgid, sid, handler, c server_name: server_name, database_name: database_name, }, - schema: [{ - id: 'server', - name: 'server', - label: gettext('Server'), - type: 'text', - editable: true, - disabled: false, - select2: { - allowClear: false, - width: 'style', - templateResult: formatNode, - templateSelection: formatNode, - }, - events: { - 'focus select': 'clearInvalid', - 'keydown :input': 'processTab', - 'select2:select': 'onSelect', - 'select2:selecting': 'beforeSelect', - 'select2:clear': 'onChange', - }, - transform: function(data) { - let group_template_options = []; - for (let key in data) { - if (data.hasOwnProperty(key)) { - group_template_options.push({'group': key, 'optval': data[key]}); - } - } - return group_template_options; - }, - control: Backform.Select2Control.extend({ - template: _.template([ - '<% if(label == false) {} else {%>', - ' ', - '<% }%>', - '
', - ' ', - ' <% if (helpMessage && helpMessage.length) { %>', - ' <%=helpMessage%>', - ' <% } %>', - '
', - ].join('\n')), - beforeSelect: function() { - var selVal = arguments[0].params.args.data.id; - - if(this.field.get('connect') && this.$el.find('option[value="'+selVal+'"]').attr('data-connected') !== 'connected') { - this.field.get('connect').apply(this, [selVal, this.changeIcon.bind(this)]); - } else { - $(this.$sel).trigger('change'); - setTimeout(function(){ this.onChange.apply(this); }.bind(this), 200); + schema: [ + { + id: 'server', + name: 'server', + label: gettext('Server'), + type: 'text', + editable: true, + disabled: false, + select2: { + allowClear: false, + width: 'style', + templateResult: formatNode, + templateSelection: formatNode, + }, + events: { + 'focus select': 'clearInvalid', + 'keydown :input': 'processTab', + 'select2:select': 'onSelect', + 'select2:selecting': 'beforeSelect', + 'select2:clear': 'onChange', + }, + transform: function(data) { + let group_template_options = []; + for (let key in data) { + if (data.hasOwnProperty(key)) { + group_template_options.push({'group': key, 'optval': data[key]}); + } } + return group_template_options; }, - changeIcon: function(data) { - let span = this.$el.find('.select2-selection .select2-selection__rendered span.wcTabIcon'), - selSpan = this.$el.find('option:selected'); + control: Backform.Select2Control.extend({ + template: _.template([ + '<% if(label == false) {} else {%>', + ' ', + '<% }%>', + '
', + ' ', + ' <% if (helpMessage && helpMessage.length) { %>', + ' <%=helpMessage%>', + ' <% } %>', + '
', + ].join('\n')), + beforeSelect: function() { + var selVal = arguments[0].params.args.data.id; - if (span.hasClass('icon-server-not-connected') || span.hasClass('icon-shared-server-not-connected')) { - let icon = (data.icon) ? data.icon : 'icon-pg'; - span.removeClass('icon-server-not-connected'); - span.addClass(icon); - span.attr('data-connected', 'connected'); + if(this.field.get('connect') && this.$el.find('option[value="'+selVal+'"]').attr('data-connected') !== 'connected') { + this.field.get('connect').apply(this, [selVal, this.changeIcon.bind(this)]); + } else { + $(this.$sel).trigger('change'); + setTimeout(function(){ this.onChange.apply(this); }.bind(this), 200); + } + }, + changeIcon: function(data) { + let span = this.$el.find('.select2-selection .select2-selection__rendered span.wcTabIcon'), + selSpan = this.$el.find('option:selected'); - selSpan.data().image = icon; - selSpan.attr('data-connected', 'connected'); - alertify.connectServer().destroy(); - this.onChange.apply(this); - } - else if (span.hasClass('icon-database-not-connected')) { - let icon = (data.icon) ? data.icon : 'pg-icon-database'; + if (span.hasClass('icon-server-not-connected') || span.hasClass('icon-shared-server-not-connected')) { + let icon = (data.icon) ? data.icon : 'icon-pg'; + span.removeClass('icon-server-not-connected'); + span.addClass(icon); + span.attr('data-connected', 'connected'); - span.removeClass('icon-database-not-connected'); - span.addClass(icon); - span.attr('data-connected', 'connected'); + selSpan.data().image = icon; + selSpan.attr('data-connected', 'connected'); + alertify.connectServer().destroy(); + this.onChange.apply(this); + } + else if (span.hasClass('icon-database-not-connected')) { + let icon = (data.icon) ? data.icon : 'pg-icon-database'; - selSpan.removeClass('icon-database-not-connected'); - selSpan.data().image = icon; - selSpan.attr('data-connected', 'connected'); - alertify.connectServer().destroy(); - this.onChange.apply(this); - } - }, - connect: function(self) { - let local_self = self; + span.removeClass('icon-database-not-connected'); + span.addClass(icon); + span.attr('data-connected', 'connected'); - if(alertify.connectServer) { - delete alertify.connectServer; - } + selSpan.removeClass('icon-database-not-connected'); + selSpan.data().image = icon; + selSpan.attr('data-connected', 'connected'); + alertify.connectServer().destroy(); + this.onChange.apply(this); + } + }, + connect: function(self) { + let local_self = self; - alertify.dialog('connectServer', function factory() { - return { - main: function( - title, message, server_id, submit_password=true, connect_server=null, - ) { - this.set('title', title); - this.message = message; - this.server_id = server_id; - this.submit_password = submit_password; - this.connect_server = connect_server; - }, - setup:function() { - return { - buttons:[{ - text: gettext('Cancel'), className: 'btn btn-secondary fa fa-times pg-alertify-button', - key: 27, - },{ - text: gettext('OK'), key: 13, className: 'btn btn-primary fa fa-check pg-alertify-button', - }], - focus: {element: '#password', select: true}, - options: { - modal: 0, resizable: false, maximizable: false, pinnable: false, - }, - }; - }, - build:function() { - }, - prepare:function() { - this.setContent(this.message); - }, - callback: function(closeEvent) { - var loadingDiv = $('#show_filter_progress'); - if (closeEvent.button.text == gettext('OK')) { - if(this.submit_password) { - var _url = url_for('sqleditor.connect_server', {'sid': this.server_id}); + if(alertify.connectServer) { + delete alertify.connectServer; + } - loadingDiv.removeClass('d-none'); - $.ajax({ - type: 'POST', - timeout: 30000, - url: _url, - data: $('#frmPassword').serialize(), - }) - .done(function(res) { + alertify.dialog('connectServer', function factory() { + return { + main: function( + title, message, server_id, submit_password=true, connect_server=null, + ) { + this.set('title', title); + this.message = message; + this.server_id = server_id; + this.submit_password = submit_password; + this.connect_server = connect_server; + }, + setup:function() { + return { + buttons:[{ + text: gettext('Cancel'), className: 'btn btn-secondary fa fa-times pg-alertify-button', + key: 27, + },{ + text: gettext('OK'), key: 13, className: 'btn btn-primary fa fa-check pg-alertify-button', + }], + focus: {element: '#password', select: true}, + options: { + modal: 0, resizable: false, maximizable: false, pinnable: false, + }, + }; + }, + build:function() { + }, + prepare:function() { + this.setContent(this.message); + }, + callback: function(closeEvent) { + var loadingDiv = $('#show_filter_progress'); + if (closeEvent.button.text == gettext('OK')) { + if(this.submit_password) { + var _url = url_for('sqleditor.connect_server', {'sid': this.server_id}); - local_self.model.attributes.database = null; - local_self.changeIcon(res.data); - local_self.model.attributes.user = null; - local_self.model.attributes.role = null; - Backform.Select2Control.prototype.onChange.apply(local_self, arguments); - Object.keys(response.server_list).forEach(key => { - response.server_list[key].forEach(option => { - if (option.value == local_self.getValueFromDOM()) { - response.server_name = option.label; - } + loadingDiv.removeClass('d-none'); + $.ajax({ + type: 'POST', + timeout: 30000, + url: _url, + data: $('#frmPassword').serialize(), + }) + .done(function(res) { + + local_self.model.attributes.database = null; + local_self.changeIcon(res.data); + local_self.model.attributes.user = null; + local_self.model.attributes.role = null; + Backform.Select2Control.prototype.onChange.apply(local_self, arguments); + Object.keys(response.server_list).forEach(key => { + response.server_list[key].forEach(option => { + if (option.value == local_self.getValueFromDOM()) { + response.server_name = option.label; + } + }); }); - }); + loadingDiv.addClass('d-none'); + alertify.connectServer().destroy(); + }) + .fail(function(xhr) { + loadingDiv.addClass('d-none'); + alertify.connectServer().destroy(); + alertify.connectServer('Connect to server', xhr.responseJSON.result, local_self.getValueFromDOM()); + }); + } else { + if(Object.keys(this.connect_server).length > 0) { + this.connect_server['password'] = $('#password').val(); + this.connect_server['is_selected'] = false; + handler.gridView.on_change_connection(this.connect_server, conn_self, false); + loadingDiv = $('#fetching_data'); loadingDiv.addClass('d-none'); - alertify.connectServer().destroy(); - }) - .fail(function(xhr) { + } else { + response.password = $('#password').val(); loadingDiv.addClass('d-none'); - alertify.connectServer().destroy(); - alertify.connectServer('Connect to server', xhr.responseJSON.result, local_self.getValueFromDOM()); - }); - } else { - if(Object.keys(this.connect_server).length > 0) { - this.connect_server['password'] = $('#password').val(); - this.connect_server['is_selected'] = false; - handler.gridView.on_change_connection(this.connect_server, conn_self, false); - loadingDiv = $('#fetching_data'); - loadingDiv.addClass('d-none'); - } else { - response.password = $('#password').val(); - loadingDiv.addClass('d-none'); + } } - } - } else { - local_self.model.attributes.database = null; - local_self.model.attributes.user = null; - local_self.model.attributes.role = null; - Backform.Select2Control.prototype.onChange.apply(local_self, arguments); - loadingDiv.addClass('d-none'); - alertify.connectServer().destroy(); + } else { + local_self.model.attributes.database = null; + local_self.model.attributes.user = null; + local_self.model.attributes.role = null; + Backform.Select2Control.prototype.onChange.apply(local_self, arguments); + loadingDiv.addClass('d-none'); + alertify.connectServer().destroy(); - } - closeEvent.close = true; - }, - }; - }); - }, - render: function() { - let self = this; - self.connect(self); - Object.keys(response.server_list).forEach(key => { - response.server_list[key].forEach(option => { - if (option.value == parseInt(sid)) { - response.server_name = option.label; - } + } + closeEvent.close = true; + }, + }; }); - }); - var transform = self.field.get('transform') || self.defaults.transform; - if (transform && _.isFunction(transform)) { - self.field.set('options', transform.bind(self, response.server_list)); - } else { - self.field.set('options', response.server_list); - } - return Backform.Select2Control.prototype.render.apply(self, arguments); - }, - onChange: function() { - this.model.attributes.database = null; - this.model.attributes.user = null; - let self = this; - self.connect(self); - - let url = url_for('sqleditor.connect_server', { - 'sid': self.getValueFromDOM(), - 'usr': self.model.attributes.user, - }); - var loadingDiv = $('#show_filter_progress'); - loadingDiv.removeClass('d-none'); - $.ajax({ - url: url, - type: 'POST', - headers: { - 'Cache-Control' : 'no-cache', - }, - }).done(function () { - Backform.Select2Control.prototype.onChange.apply(self, arguments); + }, + render: function() { + let self = this; + self.connect(self); Object.keys(response.server_list).forEach(key => { response.server_list[key].forEach(option => { - if (option.value == self.getValueFromDOM()) { + if (option.value == parseInt(sid)) { response.server_name = option.label; } }); }); - loadingDiv.addClass('d-none'); - }).fail(function(xhr){ - loadingDiv.addClass('d-none'); - alertify.connectServer('Connect to server', xhr.responseJSON.result, self.getValueFromDOM()); - }); - - }, - }), - }, - { - id: 'database', - name: 'database', - label: gettext('Database'), - type: 'text', - editable: true, - disabled: function(m) { - let self_local = this; - if (!_.isUndefined(m.get('server')) && !_.isNull(m.get('server')) - && m.get('server') !== '') { - setTimeout(function() { - if(self_local.options.length) { - m.set('database', self_local.options[0].value); + var transform = self.field.get('transform') || self.defaults.transform; + if (transform && _.isFunction(transform)) { + self.field.set('options', transform.bind(self, response.server_list)); + } else { + self.field.set('options', response.server_list); } - }, 10); - return false; - } + return Backform.Select2Control.prototype.render.apply(self, arguments); + }, + onChange: function() { + this.model.attributes.database = null; + this.model.attributes.user = null; + let self = this; + self.connect(self); - return true; - }, - deps: ['server'], - url: 'sqleditor.get_new_connection_database', - select2: { - allowClear: false, - width: '100%', - first_empty: true, - select_first: false, - }, - extraClasses:['new-connection-dialog-style'], - control: NewConnectionSelect2Control, - transform: function(data) { - response.database_list = data; - return data; - }, - }, - { - id: 'user', - name: 'user', - label: gettext('User'), - type: 'text', - editable: true, - deps: ['server'], - select2: { - allowClear: false, - width: '100%', + let url = url_for('sqleditor.connect_server', { + 'sid': self.getValueFromDOM(), + 'usr': self.model.attributes.user, + }); + var loadingDiv = $('#show_filter_progress'); + loadingDiv.removeClass('d-none'); + $.ajax({ + url: url, + type: 'POST', + headers: { + 'Cache-Control' : 'no-cache', + }, + }).done(function () { + Backform.Select2Control.prototype.onChange.apply(self, arguments); + Object.keys(response.server_list).forEach(key => { + response.server_list[key].forEach(option => { + if (option.value == self.getValueFromDOM()) { + response.server_name = option.label; + } + }); + }); + loadingDiv.addClass('d-none'); + }).fail(function(xhr){ + loadingDiv.addClass('d-none'); + alertify.connectServer('Connect to server', xhr.responseJSON.result, self.getValueFromDOM()); + }); + + }, + }), }, - control: NewConnectionSelect2Control, - url: 'sqleditor.get_new_connection_user', - disabled: function(m) { - let self_local = this; - if (!_.isUndefined(m.get('server')) && !_.isNull(m.get('server')) + { + id: 'database', + name: 'database', + label: gettext('Database'), + type: 'text', + editable: true, + disabled: function(m) { + let self_local = this; + if (!_.isUndefined(m.get('server')) && !_.isNull(m.get('server')) && m.get('server') !== '') { - setTimeout(function() { - if(self_local.options.length) { - m.set('user', self_local.options[0].value); - } - }, 10); - return false; - } - return true; + setTimeout(function() { + if(self_local.options.length) { + m.set('database', self_local.options[0].value); + } + }, 10); + return false; + } + + return true; + }, + deps: ['server'], + url: 'sqleditor.get_new_connection_database', + select2: { + allowClear: false, + width: '100%', + first_empty: true, + select_first: false, + }, + extraClasses:['new-connection-dialog-style'], + control: NewConnectionSelect2Control, + transform: function(data) { + response.database_list = data; + return data; + }, }, - },{ - id: 'role', - name: 'role', - label: gettext('Role'), - type: 'text', - editable: true, - deps: ['server'], - select2: { - allowClear: false, - width: '100%', - first_empty: true, + { + id: 'user', + name: 'user', + label: gettext('User'), + type: 'text', + editable: true, + deps: ['server'], + select2: { + allowClear: false, + width: '100%', + }, + control: NewConnectionSelect2Control, + url: 'sqleditor.get_new_connection_user', + disabled: function(m) { + let self_local = this; + if (!_.isUndefined(m.get('server')) && !_.isNull(m.get('server')) + && m.get('server') !== '') { + setTimeout(function() { + if(self_local.options.length) { + m.set('user', self_local.options[0].value); + } + }, 10); + return false; + } + return true; + }, + },{ + id: 'role', + name: 'role', + label: gettext('Role'), + type: 'text', + editable: true, + deps: ['server'], + select2: { + allowClear: false, + width: '100%', + first_empty: true, + }, + control: NewConnectionSelect2Control, + url: 'sqleditor.get_new_connection_role', + disabled: false, }, - control: NewConnectionSelect2Control, - url: 'sqleditor.get_new_connection_role', - disabled: false, - }, ], validate: function() { let msg = null; diff --git a/web/pgadmin/tools/user_management/__init__.py b/web/pgadmin/tools/user_management/__init__.py index ce280a3d..f202f898 100644 --- a/web/pgadmin/tools/user_management/__init__.py +++ b/web/pgadmin/tools/user_management/__init__.py @@ -28,7 +28,7 @@ from pgadmin.utils.constants import MIMETYPE_APP_JS, INTERNAL,\ SUPPORTED_AUTH_SOURCES, KERBEROS from pgadmin.utils.validation_utils import validate_email from pgadmin.model import db, Role, User, UserPreference, Server, \ - ServerGroup, Process, Setting + ServerGroup, Process, Setting, roles_users, SharedServer # set template path for sql scripts MODULE_NAME = 'user_management' @@ -78,7 +78,9 @@ class UserManagementModule(PgAdminModule): 'user_management.update_user', 'user_management.delete_user', 'user_management.create_user', 'user_management.users', 'user_management.user', current_app.login_manager.login_view, - 'user_management.auth_sources', 'user_management.auth_sources' + 'user_management.auth_sources', 'user_management.auth_sources', + 'user_management.shared_servers', 'user_management.admin_users', + 'user_management.change_owner', ] @@ -336,6 +338,8 @@ def delete(uid): abort(404) try: + server_groups = ServerGroup.query.filter_by(user_id=uid).all() + sg = [server_group.id for server_group in server_groups] Setting.query.filter_by(user_id=uid).delete() @@ -346,6 +350,11 @@ def delete(uid): ServerGroup.query.filter_by(user_id=uid).delete() Process.query.filter_by(user_id=uid).delete() + # Delete Shared servers for current user. + SharedServer.query.filter_by(user_id=uid).delete() + + SharedServer.query.filter(SharedServer.servergroup_id.in_(sg)).delete( + synchronize_session=False) # Finally delete user db.session.delete(usr) @@ -361,6 +370,174 @@ def delete(uid): return internal_server_error(errormsg=str(e)) +@blueprint.route('/change_owner', methods=['POST'], endpoint='change_owner') +@roles_required('Administrator') +def change_owner(): + """ + + Returns: + + """ + + data = request.form if request.form else json.loads( + request.data, encoding='utf-8' + ) + try: + old_user_servers = Server.query.filter_by(shared=True, user_id=data[ + 'old_owner']).all() + server_group_ids = [server.servergroup_id for server in + old_user_servers] + server_groups = ServerGroup.query.filter( + ServerGroup.id.in_(server_group_ids)).all() + + new_owner_sg = ServerGroup.query.filter_by( + user_id=data['new_owner']).all() + old_owner_sg = ServerGroup.query.filter_by( + user_id=data['old_owner']).all() + sg_data = {sg.name: sg.id for sg in new_owner_sg} + old_sg_data = {sg.id: sg.name for sg in old_owner_sg} + + deleted_sg = [] + # Change server user. + for server in old_user_servers: + if old_sg_data[server.servergroup_id] in sg_data: + sh_servers = SharedServer.query.filter_by( + servergroup_id=server.servergroup_id).all() + for sh in sh_servers: + sh.servergroup_id = sg_data[ + old_sg_data[server.servergroup_id]] + # Update Server user and server group to prevent deleting + # shared server associated with deleting user. + Server.query.filter_by( + servergroup_id=server.servergroup_id, shared=True, + user_id=data['old_owner'] + ).update( + { + 'servergroup_id': sg_data[old_sg_data[ + server.servergroup_id]], + 'user_id': data['new_owner'] + } + ) + ServerGroup.query.filter_by(id=server.servergroup_id).delete() + deleted_sg.append(server.servergroup_id) + else: + server.user_id = data['new_owner'] + + # Change server group user. + for server_group in server_groups: + if server_group.id not in deleted_sg: + server_group.user_id = data['new_owner'] + + db.session.commit() + # Delete old owner records. + delete(data['old_owner']) + + return make_json_response( + success=1, + info=_("Owner changed successfully."), + data={} + ) + except Exception as e: + return internal_server_error( + errormsg='Unable to update shared server owner') + + +@blueprint.route( + '/shared_servers/', methods=['GET'], endpoint='shared_servers' +) +@roles_required('Administrator') +def get_shared_servers(uid): + """ + + Args: + uid: + + Returns: + + """ + usr = User.query.get(uid) + + if not usr: + abort(404) + + try: + shared_servers_count = 0 + admin_role = Role.query.filter_by(name='Administrator')[0] + # Check user has admin role. + for role in usr.roles: + if role.id == admin_role.id: + # get all server created by user. + servers = Server.query.filter_by(user_id=usr.id).all() + for server in servers: + if server.shared: + shared_servers_count += 1 + break + + if shared_servers_count: + return make_json_response( + success=1, + info=_( + "{0} Shared servers are associated with this user." + "".format(shared_servers_count) + ), + data={ + 'shared_servers': shared_servers_count + } + ) + + return make_json_response( + success=1, + info=_("No shared servers found"), + data={'shared_servers': 0} + ) + except Exception as e: + return internal_server_error(errormsg=str(e)) + + +# @blueprint.route( +# '/admin_users', methods=['GET'], endpoint='admin_users' +# ) +@blueprint.route( + '/admin_users/', methods=['GET'], endpoint='admin_users' +) +@roles_required('Administrator') +def admin_users(uid=None): + """ + + Args: + uid: + + Returns: + + """ + admin_role = Role.query.filter_by(name='Administrator')[0] + + admin_users = db.session.query(roles_users).filter_by( + role_id=admin_role.id).all() + + if uid: + admin_users = [user[0] for user in admin_users if user[0] != uid] + else: + admin_users = [user[0] for user in admin_users] + + admin_list = User.query.filter(User.id.in_(admin_users)).all() + + user_list = [{'value': admin.id, 'label': admin.username} for admin in + admin_list] + + return make_json_response( + success=1, + info=_("No shared servers found"), + data={ + 'status': 'success', + 'msg': 'Admin user list', + 'result': { + 'data': user_list, + } + } + ) + + @blueprint.route('/user/', methods=['PUT'], endpoint='update_user') @roles_required('Administrator') def update(uid): diff --git a/web/pgadmin/tools/user_management/static/js/user_management.js b/web/pgadmin/tools/user_management/static/js/user_management.js index c3aca881..531c8c59 100644 --- a/web/pgadmin/tools/user_management/static/js/user_management.js +++ b/web/pgadmin/tools/user_management/static/js/user_management.js @@ -604,7 +604,223 @@ define([ }), gridSchema = Backform.generateGridColumnsFromModel( null, UserModel, 'edit'), + + deleteUserCell = Backgrid.Extension.DeleteCell.extend({ + changeOwnership: function(res, uid) { + let self = this; + + let ownershipSelect2Control = Backform.Select2Control.extend({ + fetchData: function(){ + let self = this; + let url = self.field.get('url'); + + url = url_for(url, {'uid': uid}); + + $.ajax({ + url: url, + headers: { + 'Cache-Control' : 'no-cache', + }, + }).done(function (res) { + var transform = self.field.get('transform'); + if(res.data.status){ + let data = res.data.result.data; + + if (transform && _.isFunction(transform)) { + self.field.set('options', transform.bind(self, data)); + } else { + self.field.set('options', data); + } + } else { + if (transform && _.isFunction(transform)) { + self.field.set('options', transform.bind(self, [])); + } else { + self.field.set('options', []); + } + } + Backform.Select2Control.prototype.render.apply(self, arguments); + }).fail(function(e){ + let msg = ''; + if(e.status == 404) { + msg = 'Unable to find url.'; + } else { + msg = e.responseJSON.errormsg; + } + alertify.error(msg); + }); + }, + render: function() { + this.fetchData(); + return Backform.Select2Control.prototype.render.apply(this, arguments); + }, + onChange: function() { + Backform.Select2Control.prototype.onChange.apply(this, arguments); + }, + }); + + let ownershipModel = pgBrowser.DataModel.extend({ + schema: [ + { + id: 'note_text_ch_owner', + control: Backform.NoteControl, + text: 'Select the user that will take ownership of the shared servers created by ' + self.model.get('username') + '. ' + res['data'].shared_servers + ' shared servers are currently owned by this user.', + group: gettext('General'), + }, + { + id: 'user', + name: 'user', + label: gettext('User'), + type: 'text', + editable: true, + select2: { + allowClear: true, + width: '100%', + first_empty: true, + }, + control: ownershipSelect2Control, + url: 'user_management.admin_users', + helpMessage: gettext('Note: If no user is selected, the shared servers will be deleted.'), + }], + }); + // Change shared server ownership before deleting the admin user + if (!alertify.changeOwnershipDialog) { + alertify.dialog('changeOwnershipDialog', function factory() { + let $container = $('
'); + return { + main: function(message) { + this.msg = message; + }, + build: function() { + this.elements.content.appendChild($container.get(0)); + alertify.pgDialogBuild.apply(this); + }, + setup: function(){ + return { + buttons: [ + { + text: gettext('Cancel'), + key: 27, + className: 'btn btn-secondary fa fa-times pg-alertify-button', + 'data-btn-name': 'cancel', + }, { + text: gettext('OK'), + key: 13, + className: 'btn btn-primary fa fa-check pg-alertify-button', + 'data-btn-name': 'ok', + }, + ], + // Set options for dialog + options: { + title: 'Change ownership', + //disable both padding and overflow control. + padding: !1, + overflow: !1, + model: 0, + resizable: true, + maximizable: false, + pinnable: false, + closableByDimmer: false, + modal: false, + autoReset: false, + closable: true, + }, + }; + }, + prepare: function() { + let self = this; + $container.html(''); + + self.ownershipModel = new ownershipModel(); + let fields = pgBackform.generateViewSchema(null, self.ownershipModel, 'create', null, null, true, null); + + let view = this.view = new pgBackform.Dialog({ + el: '
', + model: self.ownershipModel, + schema: fields, + }); + //Render change ownership dialog. + $container.append(view.render().$el[0]); + }, + callback: function(e) { + if(e.button['data-btn-name'] === 'ok') { + e.cancel = true; // Do not close dialog + let ownershipModel = this.ownershipModel.toJSON(); + if (ownershipModel.user == '' || ownershipModel.user == undefined) { + alertify.confirm( + gettext('Delete user?'), + gettext('The shared servers owned by '+ self.model.get('username') +' will be deleted. Do you wish to continue?'), + function() { + + self.model.destroy({ + wait: true, + success: function() { + alertify.success(gettext('User deleted.')); + alertify.changeOwnershipDialog().destroy(); + alertify.UserManagement().destroy(); + }, + error: function() { + alertify.error( + gettext('Error during deleting user.') + ); + }, + }); + alertify.changeOwnershipDialog().destroy(); + }, + function() { + return true; + } + ); + } else { + self.changeOwner(ownershipModel.user, uid); + } + } else { + alertify.changeOwnershipDialog().destroy(); + } + }, + }; + }); + } + alertify.changeOwnershipDialog('Change ownership').resizeTo(pgBrowser.stdW.md, pgBrowser.stdH.md); + }, + changeOwner: function(user_id, old_user) { + $.ajax({ + url: url_for('user_management.change_owner'), + method: 'POST', + data:{'new_owner': user_id, 'old_owner': old_user}, + }) + .done(function(res) { + alertify.changeOwnershipDialog().destroy(); + alertify.UserManagement().destroy(); + alertify.success(gettext(res.info)); + }) + .fail(function() { + alertify.error(gettext('Unable to change owner.')); + }); + }, + deleteUser: function() { + let self = this; + alertify.confirm( + gettext('Delete user?'), + gettext('Are you sure you wish to delete this user?'), + function() { + self.model.destroy({ + wait: true, + success: function() { + alertify.success(gettext('User deleted.')); + }, + error: function() { + alertify.error( + gettext('Error during deleting user.') + ); + }, + }); + }, + function() { + return true; + } + ); + }, deleteRow: function(e) { var self = this; e.preventDefault(); @@ -629,26 +845,27 @@ define([ if (self.model.isNew()) { self.model.destroy(); } else { - alertify.confirm( - gettext('Delete user?'), - gettext('Are you sure you wish to delete this user?'), - function() { - self.model.destroy({ - wait: true, - success: function() { - alertify.success(gettext('User deleted.')); - }, - error: function() { - alertify.error( - gettext('Error during deleting user.') - ); - }, + if(self.model.get('role') == 1){ + $.ajax({ + url: url_for('user_management.shared_servers', {'uid': self.model.get('id'), + }), + method: 'GET', + async: false, + }) + .done(function(res) { + if(res['data'].shared_servers > 0) { + self.changeOwnership(res, self.model.get('id')); + } else { + self.deleteUser(); + } + }) + .fail(function() { + self.deleteUser(); }); - }, - function() { - return true; - } - ); + } else { + self.deleteUser(); + } + } } else { alertify.alert(