/**
* Copyright (C) 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.
*/
#include "mongo/db/commands/mr.h"
#include
#include
#include "mongo/db/auth/action_set.h"
#include "mongo/db/auth/action_type.h"
#include "mongo/db/auth/privilege.h"
#include "mongo/db/commands.h"
#include "mongo/db/jsobj.h"
#include "mongo/util/mongoutils/str.h"
namespace mongo {
namespace mr {
Config::OutputOptions Config::parseOutputOptions(const std::string& dbname,
const BSONObj& cmdObj) {
Config::OutputOptions outputOptions;
outputOptions.outNonAtomic = false;
if (cmdObj["out"].type() == String) {
outputOptions.collectionName = cmdObj["out"].String();
outputOptions.outType = REPLACE;
}
else if (cmdObj["out"].type() == Object) {
BSONObj o = cmdObj["out"].embeddedObject();
BSONElement e = o.firstElement();
string t = e.fieldName();
if (t == "normal" || t == "replace") {
outputOptions.outType = REPLACE;
outputOptions.collectionName = e.String();
}
else if (t == "merge") {
outputOptions.outType = MERGE;
outputOptions.collectionName = e.String();
}
else if (t == "reduce") {
outputOptions.outType = REDUCE;
outputOptions.collectionName = e.String();
}
else if (t == "inline") {
outputOptions.outType = INMEMORY;
}
else {
uasserted(13522,
mongoutils::str::stream() << "unknown out specifier [" << t << "]");
}
if (o.hasElement("db")) {
outputOptions.outDB = o["db"].String();
}
if (o.hasElement("nonAtomic")) {
outputOptions.outNonAtomic = o["nonAtomic"].Bool();
if (outputOptions.outNonAtomic)
uassert(15895,
"nonAtomic option cannot be used with this output type",
(outputOptions.outType == REDUCE ||
outputOptions.outType == MERGE));
}
}
else {
uasserted(13606 , "'out' has to be a string or an object");
}
if (outputOptions.outType != INMEMORY) {
outputOptions.finalNamespace = mongoutils::str::stream()
<< (outputOptions.outDB.empty() ? dbname : outputOptions.outDB)
<< "." << outputOptions.collectionName;
}
return outputOptions;
}
void addPrivilegesRequiredForMapReduce(Command* commandTemplate,
const std::string& dbname,
const BSONObj& cmdObj,
std::vector* out) {
Config::OutputOptions outputOptions = Config::parseOutputOptions(dbname, cmdObj);
ResourcePattern inputResource(commandTemplate->parseResourcePattern(dbname, cmdObj));
uassert(17142, mongoutils::str::stream() <<
"Invalid input resource " << inputResource.toString(),
inputResource.isExactNamespacePattern());
out->push_back(Privilege(inputResource, ActionType::find));
if (outputOptions.outType != Config::INMEMORY) {
ActionSet outputActions;
outputActions.addAction(ActionType::insert);
if (outputOptions.outType == Config::REPLACE) {
outputActions.addAction(ActionType::remove);
}
else {
outputActions.addAction(ActionType::update);
}
ResourcePattern outputResource(
ResourcePattern::forExactNamespace(
NamespaceString(outputOptions.finalNamespace)));
uassert(17143, mongoutils::str::stream() << "Invalid target namespace " <<
outputResource.ns().ns(),
outputResource.ns().isValid());
// TODO: check if outputNs exists and add createCollection privilege if not
out->push_back(Privilege(outputResource, outputActions));
}
}
}
}