backend/wbpublic/grtdb/editor_user_role.cpp (341 lines of code) (raw):
/*
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2.0,
* as published by the Free Software Foundation.
*
* This program is designed to work with certain software (including
* but not limited to OpenSSL) that is licensed under separate terms, as
* designated in a particular file or component or in included license
* documentation. The authors of MySQL hereby grant you an additional
* permission to link the program and your derivative works with the
* separately licensed software that they have either included with
* the program or referenced in the documentation.
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License, version 2.0, for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "editor_user_role.h"
#include "db_object_helpers.h"
#include "base/string_utilities.h"
using namespace grt;
using namespace bec;
using namespace base;
RolePrivilegeListBE::RolePrivilegeListBE(RoleEditorBE *owner) : _owner(owner) {
}
size_t RolePrivilegeListBE::count() {
if (_privileges.is_valid())
return _privileges.count();
return 0;
}
void RolePrivilegeListBE::refresh() {
_role_privilege = _owner->get_object_list()->get_selected_object_info();
_privileges = grt::StringListRef();
if (_role_privilege.is_valid()) {
grt::ListRef<db_mgmt_PrivilegeMapping> mappings(_owner->get_rdbms()->privilegeNames());
for (size_t c = mappings.count(), i = 0; i < c; i++) {
if (_role_privilege->databaseObject().is_valid()) {
if (_role_privilege->databaseObject().is_instance(mappings[i]->structName())) {
_privileges = mappings[i]->privileges();
break;
}
} else if (!_role_privilege->databaseObjectType().empty()) {
std::string objectType;
if (_role_privilege->databaseObjectType() == "SCHEMA")
objectType = "db.mysql.Schema";
else if (_role_privilege->databaseObjectType() == "TABLE")
objectType = "db.mysql.Table";
else if (_role_privilege->databaseObjectType() == "ROUTINE")
objectType = "db.mysql.Routine";
else if (_role_privilege->databaseObjectType() == "FUNCTION")
objectType = "db.mysql.Routine";
else if (_role_privilege->databaseObjectType() == "PROCEDURE")
objectType = "db.mysql.Routine";
if (objectType == *mappings[i]->structName()) {
_privileges = mappings[i]->privileges();
break;
}
}
}
}
}
bool RolePrivilegeListBE::get_field_grt(const NodeId &node, ColumnId column, grt::ValueRef &value) {
if (node[0] >= count() || !_role_privilege.is_valid())
return false;
switch ((Columns)column) {
case Enabled:
if (_role_privilege->privileges().get_index(_privileges.get(node[0])) == BaseListRef::npos)
value = grt::IntegerRef(0);
else
value = grt::IntegerRef(1);
return true;
case Name:
value = _privileges.get(node[0]);
return true;
}
return false;
}
bool RolePrivilegeListBE::set_field(const NodeId &node, ColumnId column, ssize_t value) {
size_t index;
if (node[0] >= count() || !_role_privilege.is_valid())
return false;
switch ((Columns)column) {
case Enabled:
if ((index = _role_privilege->privileges().get_index(_privileges.get(node[0]))) == BaseListRef::npos) {
if (value) {
// grt::AutoUndo undo;
AutoUndoEdit undo(_owner);
_role_privilege->privileges().insert(_privileges.get(node[0]));
undo.end(strfmt(_("Add Object Privilege to Role '%s'"), _owner->get_name().c_str()));
}
} else {
if (!value) {
// grt::AutoUndo undo;
AutoUndoEdit undo(_owner);
_role_privilege->privileges().remove(index);
undo.end(strfmt(_("Remove Object Privilege to Role '%s'"), _owner->get_name().c_str()));
}
}
return true;
case Name:
return false;
}
return false;
}
void RolePrivilegeListBE::add_all() {
if (_role_privilege.is_valid()) {
AutoUndoEdit undo(_owner);
for (size_t c = _privileges.count(), i = 0; i < c; i++)
_role_privilege->privileges().insert(_privileges[i]);
undo.end(
strfmt(_("Add All Privileges for '%s' to Role '%s'"),
_role_privilege->databaseObject().is_valid() ? _role_privilege->databaseObject()->name().c_str() : "*",
_owner->get_name().c_str()));
}
}
void RolePrivilegeListBE::remove_all() {
if (_role_privilege.is_valid()) {
// grt::AutoUndo undo;
AutoUndoEdit undo(_owner);
_role_privilege->privileges().remove_all();
undo.end(
strfmt(_("Remove Privileges for '%s' from Role '%s'"),
_role_privilege->databaseObject().is_valid() ? _role_privilege->databaseObject()->name().c_str() : "*",
_owner->get_name().c_str()));
}
}
//-------------------------------------------------------------------------------------------
RoleObjectListBE::RoleObjectListBE(RoleEditorBE *owner) : _owner(owner) {
}
void RoleObjectListBE::set_selected_node(const NodeId &node) {
_selection = node;
_owner->get_privilege_list()->refresh();
}
db_RolePrivilegeRef RoleObjectListBE::get_selected_object_info() {
if (_selection.is_valid() && _selection[0] < count())
return _owner->get_role()->privileges().get(_selection[0]);
return db_RolePrivilegeRef();
}
size_t RoleObjectListBE::count() {
if (_owner->get_role().is_valid())
return _owner->get_role()->privileges().count();
return 0;
}
MenuItemList RoleObjectListBE::get_popup_items_for_nodes(const std::vector<NodeId> &nodes) {
MenuItemList items;
MenuItem item;
item.enabled = true;
item.type = MenuAction;
db_RoleRef role(_owner->get_role());
if (role.is_valid() && role->owner().is_valid()) {
db_CatalogRef catalog(db_CatalogRef::cast_from(role->owner()));
GRTLIST_FOREACH(db_Schema, catalog->schemata(), schema) {
item.caption = base::strfmt(_("Add Schema '%s'"), (*schema)->name().c_str());
item.internalName = std::string("adds:") + (*schema)->name().c_str();
item.accessibilityName = (*schema)->name();
items.push_back(item);
item.caption = base::strfmt(_("Add Tables Wildcard for '%s.*'"), (*schema)->name().c_str());
item.internalName = std::string("addt:") + (*schema)->name().c_str();
item.accessibilityName = (*schema)->name();
items.push_back(item);
item.caption = base::strfmt(_("Add All Tables in '%s'"), (*schema)->name().c_str());
item.internalName = std::string("allt:") + (*schema)->name().c_str();
item.accessibilityName = (*schema)->name();
items.push_back(item);
}
}
item.caption = "";
item.internalName = "sep";
item.accessibilityName = "Separator";
item.type = MenuSeparator;
items.push_back(item);
item.type = MenuAction;
item.caption = _("Delete Selected");
item.internalName = "deleteObject";
item.accessibilityName = "Delete Object";
item.enabled = nodes.size() > 0;
items.push_back(item);
return items;
}
bool RoleObjectListBE::activate_popup_item_for_nodes(const std::string &name, const std::vector<NodeId> &nodes) {
if (name == "deleteObject") {
for (std::vector<NodeId>::const_reverse_iterator node = nodes.rbegin(); node != nodes.rend(); ++node)
_owner->remove_object(*node);
} else if (name.substr(0, 5) == "adds:")
_owner->add_object("SCHEMA", name.substr(5) + ".*");
else if (name.substr(0, 5) == "addt:")
_owner->add_object("TABLE", name.substr(5) + ".*");
else if (name.substr(0, 5) == "allt:") {
db_RoleRef role(_owner->get_role());
if (role.is_valid() && role->owner().is_valid()) {
db_CatalogRef catalog(db_CatalogRef::cast_from(role->owner()));
std::string wanted_schema = name.substr(5);
db_SchemaRef schema = grt::find_named_object_in_list(catalog->schemata(), wanted_schema);
if (schema.is_valid()) {
GRTLIST_FOREACH(db_Table, schema->tables(), table)
_owner->add_object(*table);
}
}
} else
return false;
return true;
}
bool RoleObjectListBE::get_field_grt(const NodeId &node, ColumnId column, grt::ValueRef &value) {
if (node[0] >= count())
return false;
switch ((Columns)column) {
case Name:
db_RolePrivilegeRef priv(_owner->get_role()->privileges().get(node[0]));
if (priv.is_valid() && priv->databaseObject().is_valid())
value = priv->databaseObject()->name();
else
value = grt::StringRef(base::strfmt("%s", priv->databaseObjectName().c_str()));
return true;
}
return false;
}
IconId RoleObjectListBE::get_field_icon(const NodeId &node, ColumnId column, IconSize size) {
db_RolePrivilegeRef priv(_owner->get_role()->privileges().get(node[0]));
if (priv.is_valid()) {
if (priv->databaseObject().is_valid())
return IconManager::get_instance()->get_icon_id(priv->databaseObject());
else if (priv->databaseObjectType().is_valid()) {
if (priv->databaseObjectType() == "TABLE")
return IconManager::get_instance()->get_icon_id("db.Table.many.$.png", Icon16, "");
if (priv->databaseObjectType() == "SCHEMA")
return IconManager::get_instance()->get_icon_id("db.Schema.$.png", Icon16, "");
if (priv->databaseObjectType() == "ROUTINE")
return IconManager::get_instance()->get_icon_id("db.Routine.many.$.png", Icon16, "");
if (priv->databaseObjectType() == "VIEW")
return IconManager::get_instance()->get_icon_id("db.View.many.$.png", Icon16, "");
return 0;
} else
return 0;
} else
return 0;
}
//-------------------------------------------------------------------------------------------
RoleEditorBE::RoleEditorBE(const db_RoleRef &role, const db_mgmt_RdbmsRef &rdbms)
: BaseEditor(role),
_role(role),
_rdbms(rdbms),
_tree(db_CatalogRef::cast_from(role->owner())),
_privilege_list(this),
_object_list(this) {
}
void RoleEditorBE::set_name(const std::string &name) {
if (get_name() != name) {
AutoUndoEdit undo(this, get_role(), "name");
std::string name_ = base::trim_right(name);
get_role()->name(name_);
undo.end(strfmt(_("Rename Role to '%s'"), name_.c_str()));
}
}
std::string RoleEditorBE::get_name() {
return get_role()->name();
}
std::string RoleEditorBE::get_title() {
return strfmt("%s - Role", get_name().c_str());
}
void RoleEditorBE::set_parent_role(const std::string &name) {
if (name != get_parent_role()) {
grt::ListRef<db_Role> roles(db_CatalogRef::cast_from(get_role()->owner())->roles());
db_RoleRef new_parent_role(grt::find_named_object_in_list(roles, name));
if (!name.empty()) {
db_RoleRef some_parent_role(new_parent_role);
// check for a role loop
while (some_parent_role.is_valid()) {
// if the new parent somehow reaches back to this role, then there's a loop
if (some_parent_role == get_role())
throw std::runtime_error("Cannot set the parent role to a sub-role.");
some_parent_role = some_parent_role->parentRole();
}
}
AutoUndoEdit undo(this);
if (name.empty())
get_role()->parentRole(db_RoleRef());
else {
grt::ListRef<db_Role> roles(db_CatalogRef::cast_from(get_role()->owner())->roles());
get_role()->parentRole(new_parent_role);
}
get_role_tree()->refresh();
undo.end(strfmt(_("Set Parent Role of '%s'"), get_name().c_str()));
}
}
std::string RoleEditorBE::get_parent_role() {
if (get_role()->parentRole().is_valid())
return *get_role()->parentRole()->name();
return "";
}
std::vector<std::string> RoleEditorBE::get_role_list() {
grt::ListRef<db_Role> roles(db_CatalogRef::cast_from(get_role()->owner())->roles());
std::vector<std::string> names;
names.push_back("");
for (grt::ListRef<db_Role>::const_iterator iter = roles.begin(); iter != roles.end(); ++iter) {
db_RoleRef role((*iter));
// do not include the role itself or descendants of ourselves
while (role.is_valid()) {
if (role == get_role())
break;
role = role->parentRole();
}
if (role != get_role())
names.push_back((*iter)->name().c_str());
}
return names;
}
bool RoleEditorBE::add_dropped_objectdata(const std::string &data) {
std::list<db_DatabaseObjectRef> objects;
bool flag = false;
objects = bec::CatalogHelper::dragdata_to_dbobject_list(db_CatalogRef::cast_from(get_role()->owner()), data);
for (std::list<db_DatabaseObjectRef>::const_iterator iter = objects.begin(); iter != objects.end(); ++iter) {
if (add_object(*iter))
flag = true;
}
return flag;
}
bool RoleEditorBE::add_object(const std::string &type, const std::string &name) {
db_RolePrivilegeRef priv(grt::Initialized);
priv->databaseObjectType(type);
priv->databaseObjectName(name);
priv->owner(get_role());
AutoUndoEdit undo(this);
get_role()->privileges().insert(priv);
undo.end(strfmt(_("Add Object %s '%s' to Role '%s'"), type.c_str(), name.c_str(), get_name().c_str()));
return true;
}
bool RoleEditorBE::add_object(db_DatabaseObjectRef object) {
grt::ListRef<db_mgmt_PrivilegeMapping> mappings(get_rdbms()->privilegeNames());
bool ok = false;
for (size_t c = mappings.count(), i = 0; i < c; i++) {
if (object.is_instance(*mappings[i]->structName())) {
ok = true;
break;
}
}
if (!ok)
return false;
// check if already in list
for (size_t c = get_role()->privileges().count(), i = 0; i < c; i++) {
if (get_role()->privileges().get(i)->databaseObject() == object) {
ok = false;
break;
}
}
if (ok) {
db_RolePrivilegeRef priv(grt::Initialized);
priv->databaseObject(object);
priv->owner(get_role());
AutoUndoEdit undo(this);
get_role()->privileges().insert(priv);
undo.end(strfmt(_("Add Object '%s' to Role '%s'"), object->name().c_str(), get_name().c_str()));
}
return true;
}
//!
//! Removes object with index object_node_id from the Role's object list.
//! As it is hard to get to the db_DatabaseObjectRef to remove
//! via
//!
void RoleEditorBE::remove_object(const bec::NodeId &object_node_id) {
// object_node_id is an id of the object in the role
size_t object_idx = -1;
try {
object_idx = object_node_id.end();
} catch (const std::logic_error &e) {
throw std::logic_error(std::string("RoleEditorBE: while removing object from role") + e.what());
}
if (object_idx < get_role()->privileges().count()) {
AutoUndoEdit undo(this);
get_role()->privileges().remove(object_idx);
undo.end(strfmt(_("Remove object from Role '%s'"), get_name().c_str()));
}
}