#include <getopt.h>
#include <map>
#include <sstream>
+#include <string>
+
+#include <cyad/CommandlineParser/PolicyParsingException.h>
#include "CyadCommandlineParser.h"
namespace CyadCmdlineArgs {
const char HELP = 'h';
const char * const HELP_LONG = "help";
+
+ const char SET_BUCKET = 'b';
+ const char * const SET_BUCKET_LONG = "set-bucket";
+
+ const char DELETE_BUCKET = 'd';
+ const char * const DELETE_BUCKET_LONG = "delete-bucket";
+
+ const char POLICY = 'p';
+ const char * const POLICY_LONG = "policy";
+
+ const char METADATA = 'm';
+ const char * const METADATA_LONG = "metadata";
}
namespace CyadCmdlineErrors {
const char * const UNKNOWN_ERROR = "Unknown error";
const char * const NO_OPTION = "No option specified";
const char * const UNKNOWN_OPTION = "Unknown option";
+ const char * const UNKNOWN_OPTION_SET_BUCKET = "Unknown option in --set-bucket";
+ const char * const UNKNOWN_OPTION_DELETE_BUCKET = "Unknown option in --delete-bucket";
+ const char * const NO_POLICY = "No --policy specified";
+ const char * const NO_BUCKET = "No bucket specified";
+ const char * const INVALID_POLICY = "Invalid --policy option";
}
CyadCommandlineParser::CyadCommandlineParser(int argc, char * const *argv)
namespace Args = CyadCmdlineArgs;
const struct option long_options[] = {
- { Args::HELP_LONG, no_argument, nullptr, Args::HELP },
+ { Args::HELP_LONG, no_argument, nullptr, Args::HELP },
+ { Args::SET_BUCKET_LONG, required_argument, nullptr, Args::SET_BUCKET },
+ { Args::DELETE_BUCKET_LONG, required_argument, nullptr, Args::DELETE_BUCKET },
{ nullptr, 0, nullptr, 0 }
};
optind = 0; // On entry to `getopt', zero means this is the first call; initialize.
int opt;
std::stringstream optstr;
- optstr << ":" << Args::HELP;
+ optstr << ":" << Args::HELP
+ << Args::SET_BUCKET << ":"
+ << Args::DELETE_BUCKET << ":";
while ((opt = getopt_long(m_argc, m_argv, optstr.str().c_str(), long_options, nullptr)) != -1) {
switch (opt) {
- case Args::HELP:
- return std::make_shared<HelpCyadCommand>();
+ case Args::HELP:
+ return std::make_shared<HelpCyadCommand>();
- case '?': // Unknown option
- return std::make_shared<ErrorCyadCommand>(CyadCmdlineErrors::UNKNOWN_OPTION);
+ case Args::SET_BUCKET:
+ return parseSetBucket(optarg);
- case ':': // Missing argument
- // Shall never happen, but let's just make compiler happy.
- return std::make_shared<ErrorCyadCommand>(CyadCmdlineErrors::UNKNOWN_ERROR);
+ case Args::DELETE_BUCKET:
+ return parseDeleteBucket(optarg);
- default:
- return std::make_shared<ErrorCyadCommand>(CyadCmdlineErrors::UNKNOWN_OPTION);
+ case '?': // Unknown option
+ return std::make_shared<ErrorCyadCommand>(CyadCmdlineErrors::UNKNOWN_OPTION);
+
+ case ':': // Missing argument
+ switch (optopt) {
+ case Args::SET_BUCKET:
+ case Args::DELETE_BUCKET:
+ return std::make_shared<ErrorCyadCommand>(CyadCmdlineErrors::NO_BUCKET);
+ }
+ // Shall never happen, but let's just make compiler happy.
+ return std::make_shared<ErrorCyadCommand>(CyadCmdlineErrors::UNKNOWN_ERROR);
+
+ default:
+ return std::make_shared<ErrorCyadCommand>(CyadCmdlineErrors::UNKNOWN_OPTION);
}
}
return std::make_shared<ErrorCyadCommand>(CyadCmdlineErrors::NO_OPTION);
}
+std::shared_ptr<CyadCommand> CyadCommandlineParser::parseSetBucket(const std::string &bucketId) {
+ namespace Args = CyadCmdlineArgs;
+ namespace Errors = CyadCmdlineErrors;
+
+ const struct option long_options[] = {
+ { Args::POLICY_LONG, required_argument, nullptr, Args::POLICY },
+ { Args::METADATA_LONG, required_argument, nullptr, Args::METADATA },
+ { nullptr, 0, nullptr, 0 }
+ };
+
+ std::string policy;
+ std::string metadata;
+
+ int opt;
+ std::stringstream optstr;
+ optstr << ":"
+ << Args::POLICY << ":"
+ << Args::METADATA << ":";
+
+ while ((opt = getopt_long(m_argc, m_argv, optstr.str().c_str(), long_options, nullptr)) != -1) {
+ switch(opt) {
+ case Args::POLICY:
+ policy = optarg;
+ break;
+ case Args::METADATA:
+ metadata = optarg;
+ break;
+ default:
+ return std::make_shared<ErrorCyadCommand>(Errors::UNKNOWN_OPTION_SET_BUCKET);
+ }
+ }
+
+ if (policy.empty())
+ return std::make_shared<ErrorCyadCommand>(Errors::NO_POLICY);
+
+ try {
+ auto policyType = parsePolicyType(policy);
+ return std::make_shared<SetBucketCyadCommand>(bucketId, PolicyResult(policyType, metadata));
+ } catch (const PolicyParsingException &) {
+ return std::make_shared<ErrorCyadCommand>(Errors::INVALID_POLICY);
+ }
+}
+
+std::shared_ptr<CyadCommand> CyadCommandlineParser::parseDeleteBucket(const std::string &bucketId) {
+ namespace Errors = CyadCmdlineErrors;
+
+ // Expect no additional options
+ const struct option long_options[] = {
+ { nullptr, 0, nullptr, 0 }
+ };
+
+ if (getopt_long(m_argc, m_argv, ":", long_options, nullptr) == -1) {
+ return std::make_shared<DeleteBucketCyadCommand>(bucketId);
+ } else {
+ return std::make_shared<ErrorCyadCommand>(Errors::UNKNOWN_OPTION_DELETE_BUCKET);
+ }
+}
+
+PolicyType CyadCommandlineParser::parsePolicyType(const std::string &rawPolicy) {
+ if (rawPolicy == "DENY")
+ return CYNARA_ADMIN_DENY;
+ if (rawPolicy == "NONE")
+ return CYNARA_ADMIN_NONE;
+ if (rawPolicy == "BUCKET")
+ return CYNARA_ADMIN_BUCKET;
+ if (rawPolicy == "ALLOW")
+ return CYNARA_ADMIN_ALLOW;
+
+ // If base for std::stoi is set to 0, it detects base by itself from the format of the sequence
+ try {
+ return std::stoi(rawPolicy, nullptr, 0);
+ } catch (const std::logic_error &) {
+ throw PolicyParsingException();
+ }
+}
+
} /* namespace Cynara */
namespace CyadCmdlineArgs {
extern const char HELP;
extern const char * const HELP_LONG;
+
+ extern const char SET_BUCKET;
+ extern const char * const SET_BUCKET_LONG;
+
+ extern const char DELETE_BUCKET;
+ extern const char * const DELETE_BUCKET_LONG;
+
+ extern const char POLICY;
+ extern const char * const POLICY_LONG;
+
+ extern const char METADATA;
+ extern const char * const METADATA_LONG;
}
namespace CyadCmdlineErrors {
extern const char * const UNKNOWN_ERROR;
extern const char * const NO_OPTION;
extern const char * const UNKNOWN_OPTION;
+ extern const char * const UNKNOWN_OPTION_SET_BUCKET;
+ extern const char * const UNKNOWN_OPTION_DELETE_BUCKET;
+ extern const char * const NO_POLICY;
+ extern const char * const NO_BUCKET;
+ extern const char * const INVALID_POLICY;
}
class CyadCommandlineParser {
virtual ~CyadCommandlineParser();
std::shared_ptr<CyadCommand> parseMain(void);
+ static PolicyType parsePolicyType(const std::string &rawPolicy);
+
+protected:
+ std::shared_ptr<CyadCommand> parseSetBucket(const std::string &bucketId);
+ std::shared_ptr<CyadCommand> parseDeleteBucket(const std::string &bucketId);
private:
int m_argc;
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @file src/cyad/CommandlineParser/PolicyParsingException.h
+ * @author Aleksander Zdyb <a.zdyb@samsung.com>
+ * @version 1.0
+ * @brief PolicyParsingException
+ */
+
+#ifndef SRC_CYAD_COMMANDLINEPARSER_POLICYPARSINGEXCEPTION_H_
+#define SRC_CYAD_COMMANDLINEPARSER_POLICYPARSINGEXCEPTION_H_
+
+#include <exceptions/Exception.h>
+
+namespace Cynara {
+
+class PolicyParsingException : public Exception {
+public:
+ PolicyParsingException() {
+ m_message = "Invalid policy";
+ }
+
+ virtual const std::string &message(void) const {
+ return m_message;
+ }
+
+private:
+ std::string m_message;
+};
+
+} /* namespace Cynara */
+
+#endif /* SRC_CYAD_COMMANDLINEPARSER_POLICYPARSINGEXCEPTION_H_ */
auto result = std::dynamic_pointer_cast<Cynara::HelpCyadCommand>(parser.parseMain());
ASSERT_NE(nullptr, result);
}
+
+TEST_F(CyadCommandlineTest, deleteBucket) {
+ prepare_argv({ "./cyad", "--delete-bucket=bucket" });
+ Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+
+ auto result = std::dynamic_pointer_cast<Cynara::DeleteBucketCyadCommand>(parser.parseMain());
+ ASSERT_NE(nullptr, result);
+ ASSERT_EQ("bucket", result->bucketId());
+}
+
+TEST_F(CyadCommandlineTest, setBucket) {
+ prepare_argv({ "./cyad", "--set-bucket=bucket", "--policy=42" });
+ Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+
+ auto result = std::dynamic_pointer_cast<Cynara::SetBucketCyadCommand>(parser.parseMain());
+ ASSERT_NE(nullptr, result);
+ ASSERT_EQ("bucket", result->bucketId());
+ ASSERT_EQ(42, result->policyResult().policyType());
+ ASSERT_TRUE(result->policyResult().metadata().empty());
+}
+
+TEST_F(CyadCommandlineTest, setBucketWithMetadata) {
+ const std::string ultimateAnswer = "Answer to The Ultimate Question of Life,"
+ " the Universe, and Everything";
+
+ prepare_argv({ "./cyad", "--set-bucket=adams", "--policy=42", "--metadata=" + ultimateAnswer });
+ Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+
+ auto result = std::dynamic_pointer_cast<Cynara::SetBucketCyadCommand>(parser.parseMain());
+ ASSERT_NE(nullptr, result);
+ ASSERT_EQ("adams", result->bucketId());
+ ASSERT_EQ(42, result->policyResult().policyType());
+ ASSERT_EQ(ultimateAnswer, result->policyResult().metadata());
+}
+
+TEST_F(CyadCommandlineTest, parsePolicyTypeBase10) {
+ auto parsePolicyType = [] (const char *rawPolicy) -> Cynara::PolicyType {
+ return Cynara::CyadCommandlineParser::parsePolicyType(rawPolicy);
+ };
+
+ ASSERT_EQ(CYNARA_ADMIN_DENY, parsePolicyType("0"));
+ ASSERT_EQ(CYNARA_ADMIN_NONE, parsePolicyType("1"));
+ ASSERT_EQ(CYNARA_ADMIN_BUCKET, parsePolicyType("65534"));
+ ASSERT_EQ(CYNARA_ADMIN_ALLOW, parsePolicyType("65535"));
+}
+
+TEST_F(CyadCommandlineTest, parsePolicyTypeBase16) {
+ auto parsePolicyType = [] (const char *rawPolicy) -> Cynara::PolicyType {
+ return Cynara::CyadCommandlineParser::parsePolicyType(rawPolicy);
+ };
+
+ ASSERT_EQ(CYNARA_ADMIN_DENY, parsePolicyType("0x0"));
+ ASSERT_EQ(CYNARA_ADMIN_NONE, parsePolicyType("0x1"));
+ ASSERT_EQ(CYNARA_ADMIN_BUCKET, parsePolicyType("0xFFFE"));
+ ASSERT_EQ(CYNARA_ADMIN_ALLOW, parsePolicyType("0xFFFF"));
+}
+
+TEST_F(CyadCommandlineTest, parsePolicyTypeHuman) {
+ auto parsePolicyType = [] (const char *rawPolicy) -> Cynara::PolicyType {
+ return Cynara::CyadCommandlineParser::parsePolicyType(rawPolicy);
+ };
+
+ ASSERT_EQ(CYNARA_ADMIN_DENY, parsePolicyType("DENY"));
+ ASSERT_EQ(CYNARA_ADMIN_NONE, parsePolicyType("NONE"));
+ ASSERT_EQ(CYNARA_ADMIN_BUCKET, parsePolicyType("BUCKET"));
+ ASSERT_EQ(CYNARA_ADMIN_ALLOW, parsePolicyType("ALLOW"));
+}
Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::UNKNOWN_OPTION, parser.parseMain());
}
+
+TEST_F(CyadCommandlineTest, deleteBucketNoBucket) {
+ prepare_argv({ "./cyad", "--delete-bucket" });
+ Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+ ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::NO_BUCKET, parser.parseMain());
+}
+
+TEST_F(CyadCommandlineTest, deleteBucketUnknownOption) {
+ prepare_argv({ "./cyad", "--delete-bucket=bucket", "--unknown" });
+ Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+ ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::UNKNOWN_OPTION_DELETE_BUCKET, parser.parseMain());
+}
+
+TEST_F(CyadCommandlineTest, setBucketNoBucket) {
+ prepare_argv({ "./cyad", "--set-bucket" });
+ Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+ ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::NO_BUCKET, parser.parseMain());
+}
+
+TEST_F(CyadCommandlineTest, setBucketNoPolicy) {
+ prepare_argv({ "./cyad", "--set-bucket=bucket" });
+ Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+ ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::NO_POLICY, parser.parseMain());
+}
+
+TEST_F(CyadCommandlineTest, setBucketInvalidPolicy) {
+ prepare_argv({ "./cyad", "--set-bucket=bucket", "--policy=NaN" });
+ Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+ ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::INVALID_POLICY, parser.parseMain());
+}
+
+TEST_F(CyadCommandlineTest, setBucketUnknownOption) {
+ prepare_argv({ "./cyad", "--set-bucket=bucket", "--unknown", "--policy=42" });
+ Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+ ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::UNKNOWN_OPTION_SET_BUCKET, parser.parseMain());
+}
+
+TEST_F(CyadCommandlineTest, setBucketMetadataNoPolicy) {
+ prepare_argv({ "./cyad", "--set-bucket=bucket", "--metadata=some-meta" });
+ Cynara::CyadCommandlineParser parser(this->argc(), this->argv());
+ ASSERT_ERROR_MSG(Cynara::CyadCmdlineErrors::NO_POLICY, parser.parseMain());
+}