Added support for Reassign/Drop Owned for login roles. Fixes #3893

pull/55/head
Rahul Shirsat 2021-06-28 18:54:51 +05:30 committed by Akshay Joshi
parent 5c6d00d545
commit 5fe52b9cfe
11 changed files with 841 additions and 7 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

View File

@ -18,4 +18,5 @@ database, right-click on the *Databases* node, and select *Create Database...*
move_objects
resource_group_dialog
role_dialog
tablespace_dialog
tablespace_dialog
role_reassign_dialog

View File

@ -9,6 +9,7 @@ This release contains a number of bug fixes and new features since the release o
New features
************
| `Issue #3893 <https://redmine.postgresql.org/issues/3893>`_ - Added support for Reassign/Drop Owned for login roles.
| `Issue #3920 <https://redmine.postgresql.org/issues/3920>`_ - Do not block the query editor window when running a query.
| `Issue #6559 <https://redmine.postgresql.org/issues/6559>`_ - Added option to provide maximum width of the column when 'Resize by data? option in the preferences is set to True.

View File

@ -0,0 +1,39 @@
.. _role_reassign_dialog:
**************************************
`Role Reassign/Drop Own Dialog`:index:
**************************************
Use the *Role Reassign/Drop Own* dialog to change the ownership of database objects owned
by a database role. This dialog instructs the system to change the ownership of database
objects owned by any of the *old_roles* to *new_role*.
The *Role Reassign/Drop Own* dialog organizes the Reassign & Drop role through General tab.
.. image:: images/role_reassign_dialog.png
:alt: Role Reassign/Drop Own dialog
:align: center
* Use the *Role operation* field to provide Reassign option.
* Provide a new role in the *Reassign Objects to* field; The ownership of all the objects within the selected database,
and of all shared objects (databases, tablespaces), owned by the *old_role* will be reassigned to *new_role*.
* Provide a database on which the reassignment is to be carried out.
The above example demonstrates reassigning *old_role* to *new_role*.
Removing database objects owned by a database role.
.. image:: images/role_drop_dialog.png
:alt: Role Reassign/Drop Own dialog
:align: center
* Use the *Role operation* field to provide Drop option.
* Use the *Drop with* field to provide CASCADE option, RESTRICT is default.
* Provide a database on which the drop of objects is to be carried out.
The above examples demonstrates drop owned by *role*.
* Click the *Help* button (?) to access online help.
* Click the *OK* button to save work.
* Click the *Cancel* button to exit without saving work.

View File

@ -23,6 +23,9 @@ from pgadmin.utils.driver import get_driver
from pgadmin.utils.constants import ERROR_FETCHING_ROLE_INFORMATION
from config import PG_DEFAULT_DRIVER
from flask_babelex import gettext
_REASSIGN_OWN_SQL = 'reassign_own.sql'
class RoleModule(CollectionNodeModule):
@ -100,7 +103,7 @@ class RoleView(PGChildNodeView):
operations = dict({
'obj': [
{'get': 'properties', 'delete': 'drop', 'put': 'update'},
{'get': 'list', 'post': 'create', 'delete': 'drop'}
{'get': 'list', 'post': 'create', 'delete': 'drop'},
],
'nodes': [{'get': 'node'}, {'get': 'nodes'}],
'sql': [{'get': 'sql'}],
@ -110,6 +113,8 @@ class RoleView(PGChildNodeView):
'children': [{'get': 'children'}],
'vopts': [{}, {'get': 'voptions'}],
'variables': [{'get': 'variables'}],
'reassign': [{'get': 'get_reassign_own_sql',
'post': 'role_reassign_own'}]
})
def _validate_input_dict_for_new(self, data, req_keys):
@ -1274,5 +1279,125 @@ WHERE
data=res['rows']
)
def _execute_role_reassign(self, conn, rid=None, data=None):
"""
This function is used for executing reassign/drop
query
:param conn:
:param rid:
:param data:
:return: status & result object
"""
SQL = render_template(
"/".join([self.sql_path, _REASSIGN_OWN_SQL]),
rid=rid, data=data
)
status, res = conn.execute_scalar(SQL)
if not status:
return status, res
return status, res
@check_precondition()
def role_reassign_own(self, gid, sid, rid):
"""
This function is used to reassign/drop role for the selected database.
Args:
sid: Server ID
rid: Role Id.
Returns: Json object with success/failure status
"""
if request.data:
data = json.loads(request.data, encoding='utf-8')
else:
data = request.args or request.form
did = int(data['did'])
is_already_connected = False
can_disconn = True
try:
# Connect to the database where operation needs to carry out.
from pgadmin.utils.driver import get_driver
manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid)
conn = manager.connection(did=did, auto_reconnect=True)
is_already_connected = conn.connected()
pg_db = self.manager.db_info[self.manager.did]
if did == pg_db['did']:
can_disconn = False
# if database is not connected, try connecting it and get
# the connection object.
if not is_already_connected:
status, errmsg = conn.connect()
if not status:
current_app.logger.error(
"Could not connect to database(#{0}).\nError: {1}"
.format(
did, errmsg
)
)
return internal_server_error(errmsg)
else:
current_app.logger.info(
'Connection Established for Database Id: \
%s' % did
)
status, old_role_name = self._execute_role_reassign(conn, rid)
if not status:
raise Exception(old_role_name)
data['old_role_name'] = old_role_name
is_reassign = True if data['role_op'] == 'reassign' else False
data['is_reassign'] = is_reassign
# check whether role operation is to reassign or drop
if is_reassign \
and (data['new_role_name'] == 'CURRENT_USER' or
data['new_role_name'] == 'SESSION_USER' or
data['new_role_name'] == 'CURRENT_ROLE') is False:
status, new_role_name = \
self._execute_role_reassign(conn, data['new_role_id'])
if not status:
raise Exception(new_role_name)
data['new_role_name'] = new_role_name
status, res = self._execute_role_reassign(conn, None, data)
if not status:
raise Exception(res)
if is_already_connected is False and can_disconn:
manager.release(did=did)
return make_json_response(
success=1,
info=gettext("Reassign owned successfully!") if is_reassign
else gettext("Drop owned successfully!")
)
except Exception as e:
# Release Connection
current_app.logger.exception(e)
if is_already_connected is False and can_disconn:
self.manager.release(did=did)
return internal_server_error(errormsg=str(e))
RoleView.register_node_view(blueprint)

View File

@ -10,9 +10,10 @@
define('pgadmin.node.role', [
'sources/gettext', 'sources/url_for', 'jquery', 'underscore',
'sources/pgadmin', 'pgadmin.browser', 'alertify',
'pgadmin.backform', 'select2', 'pgadmin.browser.collection',
'pgadmin.browser.node.ui', 'pgadmin.browser.server.variable',
], function(gettext, url_for, $, _, pgAdmin, pgBrowser, alertify, Backform) {
'pgadmin.backform', 'axios', 'sources/utils', 'backbone', 'select2',
'pgadmin.browser.collection', 'pgadmin.browser.node.ui',
'pgadmin.browser.server.variable',
], function(gettext, url_for, $, _, pgAdmin, pgBrowser, alertify, Backform, axios, utils, Backbone) {
if (!pgBrowser.Nodes['coll-role']) {
pgAdmin.Browser.Nodes['coll-role'] =
@ -365,6 +366,13 @@ define('pgadmin.node.role', [
category: 'create', priority: 4, label: gettext('Login/Group Role...'),
icon: 'wcTabIcon icon-role', data: {action: 'create'},
enable: 'can_create_role',
}, {
name: 'reassign_role', node: 'role', module: this,
applies: ['object', 'context'], callback: 'reassign_role',
category: 'role', priority: 5,
label: gettext('Reassign/Drop Owned...'),
icon: 'wcTabIcon icon-role',
enable: 'can_reassign_role',
}]);
},
can_create_role: function(node, item) {
@ -373,6 +381,424 @@ define('pgadmin.node.role', [
return server.connected && server.user.can_create_role;
},
can_reassign_role: function(node, item) {
var treeData = this.getTreeNodeHierarchy(item),
server = treeData['server'];
return server.connected && node.can_login;
},
reassign_role: function() {
var tree = pgBrowser.tree,
_i = tree.selected(),
_d = _i && _i.length == 1 ? tree.itemData(_i) : undefined,
obj = this, finalUrl;
//RoleReassign Model (Objects like role, database)
var RoleReassignObjectModel = Backbone.Model.extend({
idAttribute: 'id',
defaults: {
role_op: undefined,
did: undefined,
new_role_id: undefined,
new_role_name: undefined,
drop_with_cascade: false
},
// Default values!
initialize: function() {
// Set default options according to node type selection by user
Backbone.Model.prototype.initialize.apply(this, arguments);
},
schema: [
{
id: 'role_op',
label: gettext('Role operation'),
cell: 'string',
type: 'radioModern',
controlsClassName: 'pgadmin-controls col-12 col-sm-8',
controlLabelClassName: 'control-label col-sm-4 col-12',
group: gettext('General'),
options: [{
'label': 'Reassign',
'value': 'reassign',
},
{
'label': 'Drop',
'value': 'drop',
},
],
helpMessage: gettext('Change the ownership or\ndrop the database objects owned by a database role'),
},
{
id: 'new_role_name',
label: gettext('Reassign objects to'),
controlsClassName: 'pgadmin-controls col-12 col-sm-8',
controlLabelClassName: 'control-label col-sm-4 col-12',
url: 'nodes',
helpMessage: gettext('New owner of the affected objects'),
transform: function(data, cell) {
var res = [],
control = cell || this,
node = control.field.get('schema_node');
// remove the current role from list
let current_label = control.field.attributes.node_info.role.label;
if (data && _.isArray(data)) {
let CURRENT_USER = {
label: 'CURRENT_USER', value: 'CURRENT_USER',
image: 'icon-' + node.type, _id: null,
},
SESSION_USER = {
label: 'SESSION_USER', value: 'SESSION_USER', image: 'icon-' + node.type, _id: null,
};
CURRENT_USER.value = JSON.stringify(CURRENT_USER);
SESSION_USER.value = JSON.stringify(SESSION_USER);
res.push(CURRENT_USER, SESSION_USER);
if(control.field.attributes.node_data.version >= 140000) {
let CURRENT_ROLE = {
label: 'CURRENT_ROLE', value: 'CURRENT_ROLE',
image: 'icon-' + node.type, _id: null,
};
CURRENT_ROLE.value = JSON.stringify(CURRENT_ROLE);
res.push(CURRENT_ROLE);
}
_.each(data, function(d) {
/*
* d contains json data and sets into
* select's option control
*
* We need to stringify data because formatter will
* convert Array Object as [Object] string
*/
if (current_label != d.label)
res.push({label: d.label, image: d.icon, value: JSON.stringify(d)});
});
}
return res;
},
control: Backform.NodeListByIdControl.extend({
getValueFromDOM: function() {
var data = this.formatter.toRaw(
_.unescape(this.$el.find('select').val()), this.model);
/*
* return null if data is empty to prevent it from
* throwing parsing error. Adds check as name can be empty
*/
if (data === '') {
return null;
}
else if (typeof(data) === 'string') {
data=JSON.parse(data);
}
return data.label;
},
/*
* When name is changed, extract value from its select option and
* set attributes values into the model
*/
onChange: function() {
Backform.NodeAjaxOptionsControl.prototype.onChange.apply(
this, arguments
);
var selectedValue = this.$el.find('select').val();
if (selectedValue.trim() != '') {
var d = this.formatter.toRaw(selectedValue, this.model);
if(typeof(d) === 'string')
d=JSON.parse(d);
this.model.set({
'new_role_id' : d._id,
'new_role_name': d.label,
});
}
}
}),
node: 'role',
group: gettext('General'),
select2: {
allowClear: false,
},
disabled: 'isDisabled',
deps: ['role_op'],
filter: function(d) {
// Exclude the currently selected
let tree = pgBrowser.tree,
_i = tree.selected(),
_d = _i && _i.length == 1 ? tree.itemData(_i) : undefined;
if(!_d)
return true;
return d && (d.label != _d.label);
},
},
{
id: 'drop_with_cascade',
label: gettext('Drop with'),
cell: 'string',
type: 'switch',
controlsClassName: 'pgadmin-controls col-12 col-sm-8',
controlLabelClassName: 'control-label col-sm-4 col-12',
disabled: 'isDisabled',
group: gettext('General'),
options: {
'onText': gettext('CASCADE'),
'offText': gettext('RESTRICT'), 'size': 'mini', width: '90'
},
deps: ['role_op'],
helpMessage: gettext('Note: CASCADE will automatically drop objects that depend on the affected objects, and in turn all objects that depend on those objects'),
},
{
id: 'did',
label: gettext('From database'),
controlsClassName: 'pgadmin-controls col-12 col-sm-8',
controlLabelClassName: 'control-label col-sm-4 col-12',
node: 'database',
group: gettext('General'),
disabled: 'isDisabled',
control: Backform.NodeListByIdControl.extend({
onChange: function() {
Backform.NodeListByIdControl.prototype.onChange.apply(
this, arguments
);
let did = this.model.get('did');
this.model.set('did', parseInt(did));
},
}),
select2: {
allowClear: false,
},
events: {
'select2:select': 'onChange'
},
first_empty: false,
helpMessage: gettext('Target database on which the operation will be carried out'),
}
],
validate: function() {
return null;
},
isDisabled: function(m) {
let self_local = this;
switch(this.name) {
case 'new_role_name':
return (m.get('role_op') != 'reassign');
case 'drop_with_cascade':
return (m.get('role_op') != 'drop');
case 'did':
setTimeout(function() {
if(_.isUndefined(m.get('did'))) {
let db = self_local.options[0];
m.set('did', db.value);
}
}, 10);
return false;
default:
return false;
}
},
});
if (!_d)
return;
if (!alertify.roleReassignDialog) {
alertify.dialog('roleReassignDialog', function factory() {
return {
main: function(title) {
this.set('title', title);
},
setup: function() {
return {
buttons:[{
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('Users'),
url: url_for('help.static', {'filename': 'role_reassign_dialog.html'})},
},{
text: gettext('Cancel'),
key: 27,
className: 'btn btn-secondary fa fa-lg fa-times pg-alertify-button',
}, {
text: gettext('OK'),
key: 13,
className: 'btn btn-primary fa fa-lg fa-save pg-alertify-button',
}],
focus: {
element: 0,
},
options: {
//disable both padding and overflow control.
padding : !1,
overflow: !1,
modal: false,
resizable: true,
maximizable: true,
pinnable: false,
closableByDimmer: false,
},
};
},
build: function() {
alertify.pgDialogBuild.apply(this);
},
hooks:{
onclose: function() {
if (this.view) {
// clear our backform model/view
this.view.remove({data: true, internal: true, silent: true});
}
},
},
prepare:function() {
var self = this,
$container = $('<div class=\'role_reassign_own\'></div>');
//Disable Okay button
self.__internal.buttons[2].element.disabled = true;
// Find current/selected node
var tree = pgBrowser.tree,
_i = tree.selected(),
_d = _i && _i.length == 1 ? tree.itemData(_i) : undefined,
node = _d && pgBrowser.Nodes[_d._type];
finalUrl = obj.generate_url(_i, 'reassign' , _d, true);
if (!_d)
return;
// Create treeInfo
var treeInfo = node.getTreeNodeHierarchy.apply(node, [_i]);
// Instance of backbone model
var newModel = new RoleReassignObjectModel({}, {node_info: treeInfo}),
fields = Backform.generateViewSchema(
treeInfo, newModel, 'create', node,
treeInfo.server, true
);
var view = self.view = new Backform.Dialog({
el: $container, model: newModel, schema: fields,
});
// Add our class to alertify
$(self.elements.body.childNodes[0]).addClass(
'alertify_tools_dialog_properties obj_properties'
);
// Render dialog
view.render();
self.elements.content.append($container.get(0));
const statusBar = $(
'<div class=\'pg-prop-status-bar pg-prop-status-bar-absolute pg-el-xs-12 d-none\'>' +
' <div class="error-in-footer"> ' +
' <div class="d-flex px-2 py-1"> ' +
' <div class="pr-2"> ' +
' <i class="fa fa-exclamation-triangle text-danger" aria-hidden="true"></i> ' +
' </div> ' +
' <div class="alert-text" role="alert"></div> ' +
' <div class="ml-auto close-error-bar"> ' +
' <a aria-label="' + gettext('Close error bar') + '" class="close-error fa fa-times text-danger"></a> ' +
' </div> ' +
' </div> ' +
' </div> ' +
'</div>').appendTo($container);
// Listen to model & if filename is provided then enable Backup button
this.view.model.on('change', function() {
const ctx = this;
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);
});
};
statusBar.addClass('d-none');
if ((this.get('role_op') == 'reassign')
&& !_.isUndefined(this.get('new_role_name')
&& this.get('new_role_name') !== '')
) {
this.errorModel.clear();
self.__internal.buttons[2].element.disabled = false;
} else if(this.get('role_op') == 'drop') {
this.errorModel.clear();
this.set({'new_role_name': undefined, silent: true});
this.set({'new_role_id': undefined, silent: true});
self.__internal.buttons[2].element.disabled = false;
} else if(_.isUndefined(this.get('new_role_name'))) {
let errmsg = gettext('Please provide a new role name');
this.errorModel.set('new_role_name', errmsg);
showError('new_role_name', errmsg);
self.__internal.buttons[2].element.disabled = true;
}
else {
self.__internal.buttons[2].element.disabled = true;
}
});
// set default role operation as reassign
this.view.model.set({'role_op': 'reassign'});
},
// Callback functions when click on the buttons of the alertify dialogs
callback: function(e) {
if (e.button.element.name == 'dialog_help') {
e.cancel = true;
pgBrowser.showHelp(e.button.element.name, e.button.element.getAttribute('url'),
null, null);
return;
}
if (e.button.text === gettext('OK')) {
let roleReassignData = this.view.model.toJSON(),
roleOp = roleReassignData.role_op,
confirmBoxTitle = utils.titleize(roleOp);
alertify.confirm(
gettext('%s Objects', confirmBoxTitle),
gettext('Are you sure you wish to %s all the objects owned by the selected role?', roleOp),
function() {
axios.post(
finalUrl,
roleReassignData
).then(function (response) {
if(response.data)
alertify.success(response.data.info);
}).catch(function (error) {
try {
const err = error.response.data;
alertify.alert(
gettext('Role reassign/drop failed.'),
err.errormsg
);
} catch (e) {
console.warn(e.stack || e);
}
});
},
function() { return true; }
).set('labels', {
ok: gettext('Yes'),
cancel: gettext('No'),
});
}
},
};
});
}
alertify.roleReassignDialog(
gettext('Reassign/Drop Owned - \'%s\'', _d.label)
).resizeTo(pgAdmin.Browser.stdW.md, pgAdmin.Browser.stdH.lg);
},
model: pgAdmin.Browser.Node.Model.extend({
idAttribute: 'oid',
defaults: {

View File

@ -0,0 +1,13 @@
{# ============= Get the role name using oid ============= #}
{% if rid %}
SELECT rolname FROM pg_catalog.pg_roles WHERE oid = {{rid}}::oid;
{% else %}
{# ============= Reassign/Drop own the role ============= #}
{% if data %}
{% if data.is_reassign %}
REASSIGN OWNED BY {{ conn|qtIdent(data.old_role_name) }} TO {% if data.new_role_name == "CURRENT_USER" or data.new_role_name == "SESSION_USER" or data.new_role_name == "CURRENT_ROLE" %}{{ data.new_role_name }}{% else %}{{ conn|qtIdent(data.new_role_name) }}{% endif%}
{% else %}
DROP OWNED BY {{ conn|qtIdent(data.old_role_name) }}{% if data.drop_with_cascade %} CASCADE{% endif%}
{% endif %}
{% endif %}
{% endif %}

View File

@ -0,0 +1,127 @@
{
"role_reassign": [
{
"name": "Reassign own role - Internal server error",
"is_positive_test": false,
"test_data": {
"did": null,
"new_role_id": null,
"role_op": "reassign"
},
"mocking_required": true,
"mock_data": {
"function_name": "pgadmin.utils.driver.psycopg2.connection.Connection.connect",
"return_value": "(False, 'Mocked Internal Server Error while checking db connect.')"
},
"expected_data": {
"status_code": 500,
"error_msg": null,
"test_result_data": {}
}
},
{
"name": "Reassign own role",
"is_positive_test": true,
"test_data": {
"did": null,
"new_role_id": null,
"role_op": "reassign",
"new_role_name": null
},
"mocking_required": false,
"mock_data": {},
"expected_data": {
"status_code": 200,
"error_msg": null,
"test_result_data": {}
}
},
{
"name": "Reassign own role (SESSION_USER)",
"is_positive_test": true,
"test_data": {
"did": null,
"new_role_id": null,
"role_op": "reassign",
"new_role_name": "SESSION_USER"
},
"mocking_required": false,
"mock_data": {},
"expected_data": {
"status_code": 200,
"error_msg": null,
"test_result_data": {}
}
},
{
"name": "Reassign own role (CURRENT_USER)",
"is_positive_test": true,
"test_data": {
"did": null,
"new_role_id": null,
"role_op": "reassign",
"new_role_name": "CURRENT_USER"
},
"mocking_required": false,
"mock_data": {},
"expected_data": {
"status_code": 200,
"error_msg": null,
"test_result_data": {}
}
},
{
"name": "Reassign own role (CURRENT_ROLE)",
"is_positive_test": true,
"test_data": {
"did": null,
"new_role_id": null,
"role_op": "reassign",
"new_role_name": "CURRENT_ROLE"
},
"server_min_version": 140000,
"skip_msg": "CURRENT_ROLE are not supported by PPAS/PG 13.0 and below.",
"mocking_required": false,
"mock_data": {},
"expected_data": {
"status_code": 200,
"error_msg": null,
"test_result_data": {}
}
},
{
"name": "Drop own role",
"is_positive_test": true,
"test_data": {
"did": null,
"new_role_id": null,
"role_op": "drop",
"drop_with_cascade": false
},
"mocking_required": false,
"mock_data": {},
"expected_data": {
"status_code": 200,
"error_msg": null,
"test_result_data": {}
}
},
{
"name": "Drop own role (cascade)",
"is_positive_test": true,
"test_data": {
"did": null,
"new_role_id": null,
"role_op": "drop",
"drop_with_cascade": true
},
"mocking_required": false,
"mock_data": {},
"expected_data": {
"status_code": 200,
"error_msg": null,
"test_result_data": {}
}
}
]
}

View File

@ -0,0 +1,99 @@
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2021, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
import uuid
from pgadmin.utils.route import BaseTestGenerator
from regression import parent_node_dict
from regression.python_test_utils import test_utils as utils
from pgadmin.utils import server_utils as server_utils
from . import utils as roles_utils
import json
from unittest.mock import patch
class ReassignRoleTestCase(BaseTestGenerator):
"""This class tests the role reassign/drop scenario"""
url = '/browser/role/reassign/'
# Generates scenarios
scenarios = utils.generate_scenarios("role_reassign",
roles_utils.test_cases)
def setUp(self):
self.server_id = parent_node_dict["server"][-1]["server_id"]
self.data = self.test_data
self.role_name = "role_get_%s" % str(uuid.uuid4())[1:8]
self.role_id = roles_utils.create_role(self.server, self.role_name)
role_dict = {
"server_id": self.server_id,
"role_id": self.role_id,
"role_name": self.role_name,
"new_role_name": None
}
self.data['did'] = parent_node_dict['database'][-1]['db_id']
if self.data["role_op"] == 'reassign':
if hasattr(self, 'server_min_version') and \
self.server_information['server_version'] \
< self.server_min_version:
self.skipTest(self.skip_msg)
self.role_name_1 = "role_get_%s" % str(uuid.uuid4())[1:8]
self.role_id_1 = roles_utils.create_role(self.server,
self.role_name_1)
role_dict["role_id_1"] = self.role_id_1
role_dict["new_role_name"] = self.role_name_1
self.data["new_role_id"] = self.role_id_1
self.data["new_role_name"] = self.role_name_1
utils.write_node_info("lrid", role_dict)
def reassign_post_api(self):
post_response = self.tester.post(
self.url + str(utils.SERVER_GROUP) + '/' +
str(self.server_id) + '/' + str(self.role_id),
data=json.dumps(self.data),
follow_redirects=True)
return post_response
def runTest(self):
"""This function tests role reassign/drop scenario"""
if self.is_positive_test:
post_response = self.reassign_post_api()
elif self.mocking_required:
with patch(self.mock_data["function_name"],
return_value=eval(self.mock_data["return_value"])):
post_response = self.reassign_post_api()
self.assertEqual(post_response.status_code,
self.expected_data['status_code'])
def tearDown(self):
"""This function delete the role from added server"""
connection = utils.get_db_connection(self.server['db'],
self.server['username'],
self.server['db_password'],
self.server['host'],
self.server['port'],
self.server['sslmode'])
role_list = [self.role_name]
if self.data["role_op"] == 'reassign':
role_list.append(self.role_name_1)
roles_utils.delete_role(connection, role_list)

View File

@ -9,16 +9,19 @@
import os
import pickle
import sys
import uuid
import json
from regression.python_test_utils import test_utils as utils
from regression.test_setup import config_data
ROLE_URL = '/browser/role/obj/'
file_name = os.path.basename(__file__)
CURRENT_PATH = os.path.dirname(os.path.realpath(__file__))
with open(CURRENT_PATH + "/role_test_data.json") as data_file:
test_cases = json.load(data_file)
def verify_role(server, role_name):
"""