| 75 | } |
| 76 | |
| 77 | static CoTryTask<Dispatcher::OutputTable> handle(IEnv &ienv, |
| 78 | const argparse::ArgumentParser &parser, |
| 79 | const Dispatcher::Args &args) { |
| 80 | auto &env = dynamic_cast<AdminEnv &>(ienv); |
| 81 | ENSURE_USAGE(args.empty()); |
| 82 | Dispatcher::OutputTable output; |
| 83 | |
| 84 | auto uid = Uid(parser.get<uint32_t>("uid")); |
| 85 | auto name = parser.get<std::string>("name"); |
| 86 | auto isRootUser = parser.get<bool>("--root"); |
| 87 | auto isAdmin = parser.get<bool>("--admin"); |
| 88 | auto token = parser.present<String>("--token").value_or(""); |
| 89 | auto gids = splitAndTransform(parser.present<String>("--groups").value_or(""), boost::is_any_of(","), [](auto s) { |
| 90 | return flat::Gid(folly::to<uint32_t>(s)); |
| 91 | }); |
| 92 | |
| 93 | core::UserStore store; |
| 94 | auto handler = [&](kv::IReadWriteTransaction &txn) -> CoTryTask<flat::UserAttr> { |
| 95 | auto userList = co_await store.listUsers(txn); |
| 96 | CO_RETURN_ON_ERROR(userList); |
| 97 | if (userList->empty()) { |
| 98 | if (!isAdmin) { |
| 99 | co_return makeError(StatusCode::kInvalidArg, "The first user must be admin"); |
| 100 | } |
| 101 | } else { |
| 102 | CO_RETURN_ON_ERROR(co_await ensureAdmin(txn, store, env.userInfo.token)); |
| 103 | } |
| 104 | co_return co_await store.addUser(txn, uid, name, gids, isRootUser, isAdmin, token); |
| 105 | }; |
| 106 | auto commitRes = co_await kv::WithTransaction(getRetryStrategy()) |
| 107 | .run(env.kvEngineGetter()->createReadWriteTransaction(), std::move(handler)); |
| 108 | CO_RETURN_ON_ERROR(commitRes); |
| 109 | printUserAttr(output, uid, *commitRes); |
| 110 | co_return output; |
| 111 | } |
| 112 | }; |
| 113 | |
| 114 | struct UserRemoveHandler { |
nothing calls this directly
no test coverage detected