Implement --set-bucket and --delete-bucket in Cyad
[platform/core/security/cynara.git] / src / cyad / CommandlineParser / CyadCommandlineParser.cpp
index 845f1ef..713b506 100644 (file)
@@ -24,6 +24,9 @@
 #include <getopt.h>
 #include <map>
 #include <sstream>
+#include <string>
+
+#include <cyad/CommandlineParser/PolicyParsingException.h>
 
 #include "CyadCommandlineParser.h"
 
@@ -32,12 +35,29 @@ namespace Cynara {
 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)
@@ -49,33 +69,124 @@ std::shared_ptr<CyadCommand> CyadCommandlineParser::parseMain(void) {
     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 */