PageRenderTime 37ms CodeModel.GetById 1ms RepoModel.GetById 0ms app.codeStats 0ms

/src/cyad/CommandlineParser/CyadCommandlineParser.cpp

https://gitlab.com/github-cloud-corporation/cynara
C++ | 418 lines | 322 code | 68 blank | 28 comment | 33 complexity | 4dfd26c286f5a38cd07d959a93b96d37 MD5 | raw file
  1. /*
  2. * Copyright (c) 2014-2015 Samsung Electronics Co., Ltd All Rights Reserved
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /**
  17. * @file src/cyad/CommandlineParser/CyadCommandlineParser.cpp
  18. * @author Aleksander Zdyb <a.zdyb@samsung.com>
  19. * @author Oskar Świtalski <o.switalski@samsung.com>
  20. * @version 1.0
  21. * @brief Commandline parser for Cyad
  22. */
  23. #include <functional>
  24. #include <getopt.h>
  25. #include <memory>
  26. #include <sstream>
  27. #include <string>
  28. #include <unordered_map>
  29. #include <cynara-admin-types.h>
  30. #include <cyad/CommandlineParser/CmdlineErrors.h>
  31. #include <cyad/CommandlineParser/CmdlineOpts.h>
  32. #include <cyad/CommandlineParser/HumanReadableParser.h>
  33. #include <cyad/CommandlineParser/PolicyParsingException.h>
  34. #include "CyadCommandlineParser.h"
  35. namespace Cynara {
  36. CyadCommandlineParser::CyadCommandlineParser(int argc, char * const *argv)
  37. : m_argc(argc), m_argv(argv) {}
  38. CyadCommandlineParser::~CyadCommandlineParser() {}
  39. static std::shared_ptr<ErrorCyadCommand> sharedError(const std::string &message) {
  40. return std::make_shared<ErrorCyadCommand>(message);
  41. }
  42. std::shared_ptr<CyadCommand> CyadCommandlineParser::parseMain(void) {
  43. namespace Opts = CmdlineOpts;
  44. namespace Err = CmdlineErrors;
  45. using CmdlineOpts::CmdlineOpt;
  46. std::vector<CmdlineOpt> opts = {
  47. CmdlineOpt::Help,
  48. CmdlineOpt::SetBucket,
  49. CmdlineOpt::DeleteBucket,
  50. CmdlineOpt::SetPolicy,
  51. CmdlineOpt::Erase,
  52. CmdlineOpt::Check,
  53. CmdlineOpt::ListPolicies,
  54. CmdlineOpt::ListPoliciesDesc
  55. };
  56. const auto longOpts = Opts::makeLongOptions(opts);
  57. const auto shortOpts = Opts::makeShortOptions(opts);
  58. optind = 0; // On entry to `getopt', zero means this is the first call; initialize.
  59. int opt;
  60. while ((opt = getopt_long(m_argc, m_argv, shortOpts.data(), longOpts.data(), nullptr)) != -1) {
  61. switch (opt) {
  62. case CmdlineOpt::Help:
  63. return std::make_shared<HelpCyadCommand>();
  64. case CmdlineOpt::SetBucket:
  65. return parseSetBucket(optarg);
  66. case CmdlineOpt::DeleteBucket:
  67. return parseDeleteBucket(optarg);
  68. case CmdlineOpt::SetPolicy:
  69. return parseSetPolicy();
  70. case CmdlineOpt::Erase:
  71. return parseErase(optarg);
  72. case CmdlineOpt::Check:
  73. return parseCheck();
  74. case CmdlineOpt::ListPolicies:
  75. return parseListPolicies(optarg);
  76. case CmdlineOpt::ListPoliciesDesc:
  77. return std::make_shared<ListPoliciesDescCyadCommand>();
  78. case '?': // Unknown option
  79. return sharedError(Err::unknownOption());
  80. case ':': // Missing argument
  81. switch (optopt) {
  82. case CmdlineOpt::SetBucket:
  83. case CmdlineOpt::DeleteBucket:
  84. case CmdlineOpt::Erase:
  85. case CmdlineOpt::ListPolicies:
  86. return sharedError(Err::noBucket());
  87. }
  88. // Shall never happen, but let's just make compiler happy.
  89. return sharedError(Err::unknownError());
  90. default:
  91. return sharedError(Err::unknownOption());
  92. }
  93. }
  94. return sharedError(Err::noOption());
  95. }
  96. std::shared_ptr<CyadCommand> CyadCommandlineParser::parseSetBucket(const std::string &bucketId) {
  97. namespace Opts = CmdlineOpts;
  98. namespace Err = CmdlineErrors;
  99. using CmdlineOpts::CmdlineOpt;
  100. std::vector<CmdlineOpt> opts = {
  101. CmdlineOpt::Type,
  102. CmdlineOpt::Metadata
  103. };
  104. const auto longOpts = Opts::makeLongOptions(opts);
  105. const auto shortOpts = Opts::makeShortOptions(opts);
  106. std::string policy;
  107. std::string metadata;
  108. int opt;
  109. while ((opt = getopt_long(m_argc, m_argv, shortOpts.data(), longOpts.data(), nullptr)) != -1) {
  110. switch (opt) {
  111. case CmdlineOpt::Type:
  112. policy = optarg;
  113. break;
  114. case CmdlineOpt::Metadata:
  115. metadata = optarg;
  116. break;
  117. default:
  118. return sharedError(Err::unknownOption(CmdlineOpt::SetBucket));
  119. }
  120. }
  121. if (policy.empty())
  122. return sharedError(Err::noType());
  123. return std::make_shared<SetBucketCyadCommand>(bucketId, RawPolicyResult(policy, metadata));
  124. }
  125. std::shared_ptr<CyadCommand> CyadCommandlineParser::parseDeleteBucket(const std::string &bucketId) {
  126. namespace Opts = CmdlineOpts;
  127. namespace Err = CmdlineErrors;
  128. using CmdlineOpts::CmdlineOpt;
  129. // Expect no additional options
  130. std::vector<CmdlineOpt> opts = {};
  131. const auto longOpts = Opts::makeLongOptions(opts);
  132. const auto shortOpts = Opts::makeShortOptions(opts);
  133. if (getopt_long(m_argc, m_argv, shortOpts.data(), longOpts.data(), nullptr) == -1) {
  134. return std::make_shared<DeleteBucketCyadCommand>(bucketId);
  135. } else {
  136. return sharedError(Err::unknownOption(CmdlineOpt::DeleteBucket));
  137. }
  138. }
  139. std::shared_ptr<CyadCommand> CyadCommandlineParser::parseSetPolicy(void) {
  140. namespace Opts = CmdlineOpts;
  141. namespace Err = CmdlineErrors;
  142. using CmdlineOpts::CmdlineOpt;
  143. std::vector<CmdlineOpt> opts = {
  144. CmdlineOpt::Client,
  145. CmdlineOpt::User,
  146. CmdlineOpt::Privilege,
  147. CmdlineOpt::Bucket,
  148. CmdlineOpt::Type,
  149. CmdlineOpt::Metadata,
  150. CmdlineOpt::Bulk
  151. };
  152. const auto longOpts = Opts::makeLongOptions(opts);
  153. const auto shortOpts = Opts::makeShortOptions(opts);
  154. typedef std::unordered_map<char, std::string> OptionsValues;
  155. OptionsValues values = { { CmdlineOpt::Client, std::string() },
  156. { CmdlineOpt::User, std::string() },
  157. { CmdlineOpt::Privilege, std::string() },
  158. { CmdlineOpt::Type, std::string() } };
  159. std::string metadata;
  160. std::string bucket = CYNARA_ADMIN_DEFAULT_BUCKET;
  161. int opt;
  162. while ((opt = getopt_long(m_argc, m_argv, shortOpts.data(), longOpts.data(), nullptr)) != -1) {
  163. switch (opt) {
  164. case CmdlineOpt::Client:
  165. case CmdlineOpt::User:
  166. case CmdlineOpt::Privilege:
  167. case CmdlineOpt::Type:
  168. values[opt] = optarg;
  169. break;
  170. case CmdlineOpt::Bucket:
  171. bucket = optarg;
  172. break;
  173. case CmdlineOpt::Metadata:
  174. metadata = optarg;
  175. break;
  176. case CmdlineOpt::Bulk:
  177. return std::make_shared<SetPolicyBulkCyadCommand>(optarg);
  178. case ':': // Missing argument
  179. return sharedError(Err::argumentMissing(CmdlineOpt::SetPolicy));
  180. default:
  181. return sharedError(Err::unknownOption(CmdlineOpt::SetPolicy));
  182. }
  183. }
  184. for (const auto &val : values) {
  185. if (val.second.empty()) {
  186. // TODO: Identify actual option
  187. return sharedError(Err::optionMissing(CmdlineOpt::SetPolicy));
  188. }
  189. }
  190. auto policyResult = RawPolicyResult(values[CmdlineOpt::Type], metadata);
  191. return std::make_shared<SetPolicyCyadCommand>(bucket, policyResult,
  192. PolicyKey(values[CmdlineOpt::Client],
  193. values[CmdlineOpt::User],
  194. values[CmdlineOpt::Privilege]));
  195. }
  196. std::shared_ptr<CyadCommand> CyadCommandlineParser::parseErase(const std::string &bucketId) {
  197. namespace Opts = CmdlineOpts;
  198. namespace Err = CmdlineErrors;
  199. using CmdlineOpts::CmdlineOpt;
  200. std::vector<CmdlineOpt> opts = {
  201. CmdlineOpt::Recursive,
  202. CmdlineOpt::Client,
  203. CmdlineOpt::User,
  204. CmdlineOpt::Privilege
  205. };
  206. const auto longOpts = Opts::makeLongOptions(opts);
  207. const auto shortOpts = Opts::makeShortOptions(opts);
  208. typedef std::unordered_map<char, std::string> OptionsValues;
  209. OptionsValues values = { { CmdlineOpt::Recursive, std::string() },
  210. { CmdlineOpt::Client, std::string() },
  211. { CmdlineOpt::User, std::string() },
  212. { CmdlineOpt::Privilege, std::string() } };
  213. int opt;
  214. while ((opt = getopt_long(m_argc, m_argv, shortOpts.data(), longOpts.data(), nullptr)) != -1) {
  215. switch (opt) {
  216. case CmdlineOpt::Recursive:
  217. case CmdlineOpt::Client:
  218. case CmdlineOpt::User:
  219. case CmdlineOpt::Privilege:
  220. values[opt] = optarg;
  221. break;
  222. case ':': // Missing argument
  223. return sharedError(Err::argumentMissing(CmdlineOpt::Erase));
  224. default:
  225. return sharedError(Err::unknownOption(CmdlineOpt::Erase));
  226. }
  227. }
  228. for (const auto &val : values) {
  229. if (val.second.empty()) {
  230. // TODO: Identify actual option
  231. return sharedError(Err::optionMissing(CmdlineOpt::Erase));
  232. }
  233. }
  234. auto recursive = HumanReadableParser::isYes(values[CmdlineOpt::Recursive]);
  235. return std::make_shared<EraseCyadCommand>(bucketId, recursive,
  236. PolicyKey(values[CmdlineOpt::Client],
  237. values[CmdlineOpt::User],
  238. values[CmdlineOpt::Privilege]));
  239. }
  240. std::shared_ptr<CyadCommand> CyadCommandlineParser::parseCheck(void) {
  241. namespace Opts = CmdlineOpts;
  242. namespace Err = CmdlineErrors;
  243. using CmdlineOpts::CmdlineOpt;
  244. std::vector<CmdlineOpt> opts = {
  245. CmdlineOpt::Bucket,
  246. CmdlineOpt::Recursive,
  247. CmdlineOpt::Client,
  248. CmdlineOpt::User,
  249. CmdlineOpt::Privilege,
  250. CmdlineOpt::Humanize,
  251. };
  252. const auto longOpts = Opts::makeLongOptions(opts);
  253. const auto shortOpts = Opts::makeShortOptions(opts);
  254. typedef std::unordered_map<char, std::string> OptionsValues;
  255. OptionsValues values = { { CmdlineOpt::Recursive, std::string() },
  256. { CmdlineOpt::Client, std::string() },
  257. { CmdlineOpt::User, std::string() },
  258. { CmdlineOpt::Privilege, std::string() } };
  259. std::string bucketId = CYNARA_ADMIN_DEFAULT_BUCKET;
  260. int opt;
  261. bool humanize = false;
  262. while ((opt = getopt_long(m_argc, m_argv, shortOpts.data(), longOpts.data(), nullptr)) != -1) {
  263. switch (opt) {
  264. case CmdlineOpt::Recursive:
  265. case CmdlineOpt::Client:
  266. case CmdlineOpt::User:
  267. case CmdlineOpt::Privilege:
  268. values[opt] = optarg;
  269. break;
  270. case CmdlineOpt::Bucket:
  271. bucketId = optarg;
  272. break;
  273. case CmdlineOpt::Humanize:
  274. humanize = true;
  275. break;
  276. case ':': // Missing argument
  277. return sharedError(Err::argumentMissing(CmdlineOpt::Check));
  278. default:
  279. return sharedError(Err::unknownOption(CmdlineOpt::Check));
  280. }
  281. }
  282. for (const auto &val : values) {
  283. if (val.second.empty()) {
  284. // TODO: Identify actual option
  285. return sharedError(Err::optionMissing(CmdlineOpt::Check));
  286. }
  287. }
  288. auto recursive = HumanReadableParser::isYes(values[CmdlineOpt::Recursive]);
  289. return std::make_shared<CheckCyadCommand>(bucketId, recursive,
  290. PolicyKey(values[CmdlineOpt::Client],
  291. values[CmdlineOpt::User],
  292. values[CmdlineOpt::Privilege]),
  293. humanize);
  294. }
  295. std::shared_ptr<CyadCommand> CyadCommandlineParser::parseListPolicies(const std::string &bucketId) {
  296. namespace Opts = CmdlineOpts;
  297. namespace Err = CmdlineErrors;
  298. using CmdlineOpts::CmdlineOpt;
  299. std::vector<CmdlineOpt> opts = {
  300. CmdlineOpt::Client,
  301. CmdlineOpt::User,
  302. CmdlineOpt::Privilege,
  303. CmdlineOpt::All,
  304. CmdlineOpt::Humanize,
  305. };
  306. const auto longOpts = Opts::makeLongOptions(opts);
  307. const auto shortOpts = Opts::makeShortOptions(opts);
  308. typedef std::unordered_map<char, std::string> OptionsValues;
  309. OptionsValues values = { { CmdlineOpt::Client, std::string() },
  310. { CmdlineOpt::User, std::string() },
  311. { CmdlineOpt::Privilege, std::string() } };
  312. int opt;
  313. bool listAll = false;
  314. bool humanize = false;
  315. while ((opt = getopt_long(m_argc, m_argv, shortOpts.data(), longOpts.data(), nullptr)) != -1) {
  316. switch (opt) {
  317. case CmdlineOpt::Client:
  318. case CmdlineOpt::User:
  319. case CmdlineOpt::Privilege:
  320. values[opt] = optarg;
  321. break;
  322. case CmdlineOpt::All:
  323. listAll = true;
  324. break;
  325. case CmdlineOpt::Humanize:
  326. humanize = true;
  327. break;
  328. case ':': // Missing argument
  329. return sharedError(Err::argumentMissing(CmdlineOpt::ListPolicies));
  330. default:
  331. return sharedError(Err::unknownOption(CmdlineOpt::ListPolicies));
  332. }
  333. }
  334. for (auto &val : values) {
  335. if (val.second.empty()) {
  336. if (listAll) {
  337. val.second = CYNARA_ADMIN_ANY;
  338. } else {
  339. // TODO: Identify actual option
  340. return sharedError(Err::optionMissing(CmdlineOpt::ListPolicies));
  341. }
  342. }
  343. }
  344. return std::make_shared<ListPoliciesCyadCommand>(bucketId,
  345. PolicyKey(values[CmdlineOpt::Client],
  346. values[CmdlineOpt::User],
  347. values[CmdlineOpt::Privilege]),
  348. humanize);
  349. }
  350. } /* namespace Cynara */