/* Copyright 2012 10gen Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
* As a special exception, the copyright holders give permission to link the
* code of portions of this program with the OpenSSL library under certain
* conditions as described in each individual source file and distribute
* linked combinations including the program with the OpenSSL library. You
* must comply with the GNU Affero General Public License in all respects
* for all of the code used other than as permitted herein. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you do not
* wish to do so, delete this exception statement from your version. If you
* delete this exception statement from all source files in the program,
* then also delete it in the license file.
*/
#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kAccessControl
#include "mongo/platform/basic.h"
#include "mongo/db/auth/action_set.h"
#include
#include
#include "mongo/base/status.h"
#include "mongo/bson/util/builder.h"
#include "mongo/util/log.h"
#include "mongo/util/mongoutils/str.h"
#include "mongo/util/stringutils.h"
namespace mongo {
ActionSet::ActionSet(std::initializer_list actions) {
for (auto& action : actions) {
addAction(action);
}
}
void ActionSet::addAction(const ActionType& action) {
if (action == ActionType::anyAction) {
addAllActions();
return;
}
_actions.set(action.getIdentifier(), true);
}
void ActionSet::addAllActionsFromSet(const ActionSet& actions) {
if (actions.contains(ActionType::anyAction)) {
addAllActions();
return;
}
_actions |= actions._actions;
}
void ActionSet::addAllActions() {
_actions = ~std::bitset();
}
void ActionSet::removeAction(const ActionType& action) {
_actions.set(action.getIdentifier(), false);
_actions.set(ActionType::anyAction.getIdentifier(), false);
}
void ActionSet::removeAllActionsFromSet(const ActionSet& other) {
_actions &= ~other._actions;
if (!other.empty()) {
_actions.set(ActionType::anyAction.getIdentifier(), false);
}
}
void ActionSet::removeAllActions() {
_actions = std::bitset();
}
bool ActionSet::contains(const ActionType& action) const {
return _actions[action.getIdentifier()];
}
bool ActionSet::isSupersetOf(const ActionSet& other) const {
return (_actions & other._actions) == other._actions;
}
Status ActionSet::parseActionSetFromString(const std::string& actionsString, ActionSet* result) {
std::vector actionsList;
splitStringDelim(actionsString, &actionsList, ',');
std::vector unrecognizedActions;
Status status = parseActionSetFromStringVector(actionsList, result, &unrecognizedActions);
invariantOK(status);
if (unrecognizedActions.empty()) {
return Status::OK();
}
std::string unrecognizedActionsString;
joinStringDelim(unrecognizedActions, &unrecognizedActionsString, ',');
return Status(ErrorCodes::FailedToParse,
str::stream() << "Unrecognized action privilege strings: "
<< unrecognizedActionsString);
}
Status ActionSet::parseActionSetFromStringVector(const std::vector& actionsVector,
ActionSet* result,
std::vector* unrecognizedActions) {
result->removeAllActions();
for (size_t i = 0; i < actionsVector.size(); i++) {
ActionType action;
Status status = ActionType::parseActionFromString(actionsVector[i], &action);
if (status == ErrorCodes::FailedToParse) {
unrecognizedActions->push_back(actionsVector[i]);
} else {
invariantOK(status);
if (action == ActionType::anyAction) {
result->addAllActions();
return Status::OK();
}
result->addAction(action);
}
}
return Status::OK();
}
std::string ActionSet::toString() const {
if (contains(ActionType::anyAction)) {
return ActionType::anyAction.toString();
}
StringBuilder str;
bool addedOne = false;
for (int i = 0; i < ActionType::actionTypeEndValue; i++) {
ActionType action(i);
if (contains(action)) {
if (addedOne) {
str << ",";
}
str << ActionType::actionToString(action);
addedOne = true;
}
}
return str.str();
}
std::vector ActionSet::getActionsAsStrings() const {
std::vector result;
if (contains(ActionType::anyAction)) {
result.push_back(ActionType::anyAction.toString());
return result;
}
for (int i = 0; i < ActionType::actionTypeEndValue; i++) {
ActionType action(i);
if (contains(action)) {
result.push_back(ActionType::actionToString(action));
}
}
return result;
}
} // namespace mongo