backend/wbpublic/grtdb/role_tree_model.cpp (204 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 "role_tree_model.h"
#include "base/string_utilities.h"
#include "grtpp_undo_manager.h"
using namespace bec;
using namespace base;
RoleTreeBE::RoleTreeBE(const db_CatalogRef &catalog) : _catalog(catalog), _root(0) {
refresh();
}
RoleTreeBE::~RoleTreeBE() {
delete _root;
}
void RoleTreeBE::set_object(const db_DatabaseObjectRef &object) {
_object_id = object.id();
}
void RoleTreeBE::add_role_children_to_node(Node *parent_node) {
if (!parent_node->role->childRoles().is_valid())
return;
grt::ListRef<db_Role> roles(parent_node->role->childRoles());
for (size_t c = roles.count(), i = 0; i < c; i++) {
Node *n = new Node;
n->role = roles.get(i);
n->parent = parent_node;
parent_node->children.push_back(n);
add_role_children_to_node(n);
}
}
void RoleTreeBE::refresh() {
/*
//delete _root;
_root= new Node;
grt::ListRef<db_Role> roles(_catalog.roles());
_root->role= db_Role(_catalog.grt());
_root->role.childRoles(grt::ListRef<db_Role>(_catalog.grt()));
for (size_t c= roles.count(), i= 0; i < c; i++)
{
//if (!roles[i]->parentRole().is_valid()) // top-level role
{
Node *n= new Node;
n->role= roles[i];
n->parent= _root;
_root->children.push_back(n);
_root->role.childRoles().insert(n->role, -1);
add_role_children_to_node(n);
}
}
*/
std::map<std::string, Node *> nodes;
delete _root;
_root = new Node;
grt::ListRef<db_Role> roles(_catalog->roles());
for (size_t c = roles.count(), i = 0; i < c; i++) {
Node *n = new Node;
n->role = roles[i];
nodes[n->role.id()] = n;
}
for (size_t c = roles.count(), i = 0; i < c; i++) {
if (roles[i]->parentRole().is_valid()) {
if (nodes.find(roles[i]->parentRole().id()) == nodes.end()) {
Node *next_node = nodes[roles[i]->id()];
_root->children.push_back(next_node);
next_node->parent = _root;
} else {
Node *parent = nodes[roles[i]->parentRole().id()];
Node *next_node = nodes[roles[i]->id()];
parent->children.push_back(next_node);
next_node->parent = parent;
}
} else {
Node *next_node = nodes[roles[i]->id()];
_root->children.push_back(nodes[roles[i]->id()]);
next_node->parent = _root;
}
}
}
size_t RoleTreeBE::count_children(const NodeId &parent) {
Node *node = get_node_with_id(parent);
if (node)
return (int)node->children.size();
return 0;
}
NodeId RoleTreeBE::get_child(const NodeId &parent, size_t index) {
Node *n = get_node_with_id(parent);
if (n && index < n->children.size())
return NodeId(parent).append(index);
if (n)
throw std::logic_error("invalid index");
return NodeId();
}
bool RoleTreeBE::set_field(const NodeId &node, ColumnId column, const std::string &value) {
Node *n;
switch ((Columns)column) {
case Enabled:
return false;
case Name:
n = get_node_with_id(node);
if (n) {
// Switched to AutoUndoEdit allow for Live editors to not track undo, but
// RoleTree is not used by live editors, so it's ok to keep AutoUndo here.
grt::AutoUndo undo;
// AutoUndoEdit undo(this);
n->role->name(value);
undo.end(strfmt(_("Rename Role to '%s'"), value.c_str()));
return true;
}
return false;
}
return false;
}
grt::Type RoleTreeBE::get_field_type(const NodeId &node, ColumnId column) {
switch ((Columns)column) {
case Enabled:
return grt::IntegerType;
case Name:
return grt::StringType;
}
throw std::logic_error("Invalid column");
}
bool RoleTreeBE::get_field_grt(const NodeId &node, ColumnId column, grt::ValueRef &value) {
Node *n;
switch ((Columns)column) {
case Enabled:
n = get_node_with_id(node);
if (n) {
if (_object_id.empty()) { // returns whether there is anything in the privs list
value = grt::IntegerRef(n->role->privileges().count() > 0 ? 1 : 0);
} else {
// returns whether the object is in the privs list of the role
bool flag = false;
for (size_t c = n->role->privileges().count(), i = 0; i < c; i++) {
db_DatabaseObjectRef obj(n->role->privileges().get(i)->databaseObject());
if (obj.is_valid() && obj.id() == _object_id) {
flag = true;
break;
}
}
value = grt::IntegerRef(flag ? 1 : 0);
}
return true;
}
return false;
case Name:
n = get_node_with_id(node);
if (n) {
value = n->role->name();
return true;
}
return false;
}
return false;
}
RoleTreeBE::Node *RoleTreeBE::get_node_with_id(const NodeId &node) {
Node *n = _root;
if (!n)
return 0;
if (node.depth() == 0)
return n;
for (size_t i = 0; i < node.depth(); i++) {
if (node[i] >= n->children.size())
throw std::logic_error("Invalid node id");
n = n->children[node[i]];
}
return n;
}
bool RoleTreeBE::find_role(const RoleTreeBE::Node *node, const db_RoleRef &role, bec::NodeId &path) {
int i = 0;
if (node->role == role)
return true;
for (std::vector<RoleTreeBE::Node *>::const_iterator r = node->children.begin(); r != node->children.end();
++r, i++) {
if (find_role(*r, role, path)) {
path.prepend(i);
return true;
}
}
return false;
}
NodeId RoleTreeBE::node_id_for_role(const db_RoleRef &role) {
NodeId node;
if (find_role(_root, role, node))
return node;
return NodeId();
}
void RoleTreeBE::erase_node(const NodeId &node) {
Node *n = get_node_with_id(node);
if (!n)
return;
Node *parent = n->parent;
if (!parent)
return;
parent->erase_child(n);
}
bool RoleTreeBE::is_parent_child(Node *parent, Node *child) {
for (; child; child = child->parent) {
if (child->parent == parent)
return true;
}
return false;
}
void RoleTreeBE::append_child(const NodeId &parent, const NodeId &child) {
Node *p = get_node_with_id(parent);
Node *c = get_node_with_id(child);
if (!p || !c || is_parent_child(c, p))
return;
erase_node(child);
p->append_child(c);
}
void RoleTreeBE::insert_node_after(const NodeId &after, const NodeId &node) {
Node *n = get_node_with_id(node);
Node *a = get_node_with_id(after);
if (!n || !a)
return;
erase_node(node);
a->parent->insert_child_after(a, n);
}
void RoleTreeBE::insert_node_before(const NodeId &before, const NodeId &node) {
Node *n = get_node_with_id(node);
Node *b = get_node_with_id(before);
if (!n || !b)
return;
erase_node(node);
b->parent->insert_child_before(b, n);
}
void RoleTreeBE::move_to_top_level(const NodeId &node) {
Node *n = get_node_with_id(node);
if (n != NULL)
n->role->parentRole(db_RoleRef());
}