From: Maxim Mamontov <faust.madf@gmail.com> Date: Wed, 28 May 2014 20:01:41 +0000 (+0300) Subject: Implemented --add-admin. X-Git-Url: https://git.stg.codes/stg.git/commitdiff_plain/c00e81f9f50c4fe50ee32b02a689d68c9bc595b6?ds=sidebyside;hp=c1b9be104712ea200385bd4f7d76f185a2d76eb7 Implemented --add-admin. --- diff --git a/include/stg/admin_conf.h b/include/stg/admin_conf.h index 8b1a988e..7fbf4440 100644 --- a/include/stg/admin_conf.h +++ b/include/stg/admin_conf.h @@ -78,6 +78,7 @@ struct ADMIN_CONF //----------------------------------------------------------------------------- struct ADMIN_CONF_RES { + ADMIN_CONF_RES() {} ADMIN_CONF_RES(const ADMIN_CONF & conf) : priv(conf.priv), login(conf.login), diff --git a/projects/sgconf/action.h b/projects/sgconf/action.h index b45ac470..940ea7f6 100644 --- a/projects/sgconf/action.h +++ b/projects/sgconf/action.h @@ -41,7 +41,7 @@ class ACTION virtual std::string ParamDescription() const = 0; virtual std::string DefaultDescription() const = 0; virtual OPTION_BLOCK & Suboptions() = 0; - virtual PARSER_STATE Parse(int argc, char ** argv) = 0; + virtual PARSER_STATE Parse(int argc, char ** argv, void * data = NULL) = 0; virtual void ParseValue(const std::string &) {} class ERROR : public std::runtime_error diff --git a/projects/sgconf/actions.h b/projects/sgconf/actions.h index c47f9776..07bcfb8b 100644 --- a/projects/sgconf/actions.h +++ b/projects/sgconf/actions.h @@ -30,6 +30,8 @@ #include <string> +#include <cassert> + namespace SGCONF { @@ -46,7 +48,7 @@ class FUNC0_ACTION : public ACTION virtual std::string ParamDescription() const { return ""; } virtual std::string DefaultDescription() const { return ""; } virtual OPTION_BLOCK & Suboptions() { return m_suboptions; } - virtual PARSER_STATE Parse(int argc, char ** argv) + virtual PARSER_STATE Parse(int argc, char ** argv, void * /*data*/) { m_func(); return PARSER_STATE(true, argc, argv); @@ -88,7 +90,7 @@ class PARAM_ACTION : public ACTION virtual std::string ParamDescription() const { return m_description; } virtual std::string DefaultDescription() const; virtual OPTION_BLOCK & Suboptions() { return m_suboptions; } - virtual PARSER_STATE Parse(int argc, char ** argv); + virtual PARSER_STATE Parse(int argc, char ** argv, void * /*data*/); virtual void ParseValue(const std::string & value); private: @@ -117,7 +119,7 @@ return m_hasDefault ? " (default: '" + m_defaltValue + "')" template <typename T> inline -PARSER_STATE PARAM_ACTION<T>::Parse(int argc, char ** argv) +PARSER_STATE PARAM_ACTION<T>::Parse(int argc, char ** argv, void * /*data*/) { if (argc == 0 || argv == NULL || @@ -151,7 +153,7 @@ m_param = stringValue; template <> inline -PARSER_STATE PARAM_ACTION<std::string>::Parse(int argc, char ** argv) +PARSER_STATE PARAM_ACTION<std::string>::Parse(int argc, char ** argv, void * /*data*/) { if (argc == 0 || argv == NULL || @@ -182,10 +184,8 @@ class KV_ACTION : public ACTION { public: KV_ACTION(const std::string & name, - std::map<std::string, std::string> & kvs, const std::string & paramDescription) : m_name(name), - m_kvs(kvs), m_description(paramDescription) {} @@ -194,32 +194,32 @@ class KV_ACTION : public ACTION virtual std::string ParamDescription() const { return m_description; } virtual std::string DefaultDescription() const { return ""; } virtual OPTION_BLOCK & Suboptions() { return m_suboptions; } - virtual PARSER_STATE Parse(int argc, char ** argv); + virtual PARSER_STATE Parse(int argc, char ** argv, void * data); private: std::string m_name; - std::map<std::string, std::string> & m_kvs; std::string m_description; OPTION_BLOCK m_suboptions; }; inline -PARSER_STATE KV_ACTION::Parse(int argc, char ** argv) +PARSER_STATE KV_ACTION::Parse(int argc, char ** argv, void * data) { if (argc == 0 || argv == NULL || *argv == NULL) throw ERROR("Missing argument."); -m_kvs[m_name] = *argv; +assert(data != NULL && "Expecting container pointer."); +std::map<std::string, std::string> & kvs = *static_cast<std::map<std::string, std::string>*>(data); +kvs[m_name] = *argv; return PARSER_STATE(false, --argc, ++argv); } inline KV_ACTION * MakeKVAction(const std::string & name, - std::map<std::string, std::string> & kvs, const std::string & paramDescription) { -return new KV_ACTION(name, kvs, paramDescription); +return new KV_ACTION(name, paramDescription); } } // namespace SGCONF diff --git a/projects/sgconf/admins.cpp b/projects/sgconf/admins.cpp index b560f581..6a59fa28 100644 --- a/projects/sgconf/admins.cpp +++ b/projects/sgconf/admins.cpp @@ -3,6 +3,7 @@ #include "api_action.h" #include "options.h" #include "config.h" +#include "utils.h" #include "stg/servconf.h" #include "stg/servconf_types.h" @@ -46,10 +47,28 @@ std::cout << Indent(level, true) << "login: " << info.login << "\n" std::vector<SGCONF::API_ACTION::PARAM> GetAdminParams() { std::vector<SGCONF::API_ACTION::PARAM> params; -params.push_back({"priv", "<priv>", "priviledges"}); +params.push_back(SGCONF::API_ACTION::PARAM("password", "<password>", "password")); +params.push_back(SGCONF::API_ACTION::PARAM("priv", "<priv>", "priviledges")); return params; } +void ConvPriv(const std::string & value, RESETABLE<PRIV> & res) +{ +if (value.length() != 9) + throw SGCONF::ACTION::ERROR("Priviledges value should be a 9-digits length binary number."); +PRIV priv; +priv.corpChg = (value[0] == '0' ? 0 : 1); +priv.serviceChg = (value[1] == '0' ? 0 : 1); +priv.tariffChg = (value[2] == '0' ? 0 : 1); +priv.adminChg = (value[3] == '0' ? 0 : 1); +priv.userAddDel = (value[4] == '0' ? 0 : 1); +priv.userPasswd = (value[5] == '0' ? 0 : 1); +priv.userCash = (value[6] == '0' ? 0 : 1); +priv.userConf = (value[7] == '0' ? 0 : 1); +priv.userStat = (value[8] == '0' ? 0 : 1); +res = priv; +} + void SimpleCallback(bool result, const std::string & reason, void * /*data*/) @@ -133,11 +152,17 @@ return proto.DelAdmin(arg, SimpleCallback, NULL) == STG::st_ok; bool AddAdminFunction(const SGCONF::CONFIG & config, const std::string & arg, - const std::map<std::string, std::string> & /*options*/) + const std::map<std::string, std::string> & options) { // TODO -std::cerr << "Unimplemented.\n"; -return false; +ADMIN_CONF_RES conf; +conf.login = arg; +SGCONF::MaybeSet(options, "priv", conf.priv, ConvPriv); +STG::SERVCONF proto(config.server.data(), + config.port.data(), + config.userName.data(), + config.userPass.data()); +return proto.AddAdmin(arg, conf, SimpleCallback, NULL) == STG::st_ok; } bool ChgAdminFunction(const SGCONF::CONFIG & config, diff --git a/projects/sgconf/api_action.cpp b/projects/sgconf/api_action.cpp index 420f5f0a..d5b1e8e6 100644 --- a/projects/sgconf/api_action.cpp +++ b/projects/sgconf/api_action.cpp @@ -3,7 +3,7 @@ #include "actions.h" #include "parser_state.h" -SGCONF::PARSER_STATE SGCONF::API_ACTION::Parse(int argc, char ** argv) +SGCONF::PARSER_STATE SGCONF::API_ACTION::Parse(int argc, char ** argv, void * /*data*/) { PARSER_STATE state(false, argc, argv); if (!m_argument.empty()) @@ -16,7 +16,7 @@ if (!m_argument.empty()) --state.argc; ++state.argv; } -m_suboptions.Parse(state.argc, state.argv); +state = m_suboptions.Parse(state.argc, state.argv, &m_params); m_commands.Add(m_funPtr, m_argument, m_params); return state; } @@ -34,7 +34,7 @@ SGCONF::API_ACTION::API_ACTION(COMMANDS & commands, std::vector<PARAM>::const_iterator it(params.begin()); while (it != params.end()) { - m_suboptions.Add(it->name, MakeKVAction(it->name, m_params, it->shortDescr), it->longDescr); + m_suboptions.Add(it->name, MakeKVAction(it->name, it->shortDescr), it->longDescr); ++it; } } diff --git a/projects/sgconf/api_action.h b/projects/sgconf/api_action.h index e5f95b2c..f27715ca 100644 --- a/projects/sgconf/api_action.h +++ b/projects/sgconf/api_action.h @@ -63,6 +63,13 @@ class API_ACTION : public ACTION public: struct PARAM { + PARAM(const std::string & n, + const std::string & s, + const std::string & l) + : name(n), + shortDescr(s), + longDescr(l) + {} std::string name; std::string shortDescr; std::string longDescr; @@ -88,7 +95,7 @@ class API_ACTION : public ACTION virtual std::string ParamDescription() const { return m_description; } virtual std::string DefaultDescription() const { return ""; } virtual OPTION_BLOCK & Suboptions() { return m_suboptions; } - virtual PARSER_STATE Parse(int argc, char ** argv); + virtual PARSER_STATE Parse(int argc, char ** argv, void * /*data*/); private: COMMANDS & m_commands; diff --git a/projects/sgconf/corps.cpp b/projects/sgconf/corps.cpp index 97c3add0..82673377 100644 --- a/projects/sgconf/corps.cpp +++ b/projects/sgconf/corps.cpp @@ -32,7 +32,7 @@ std::cout << Indent(level, true) << "name: " << info.name << "\n" std::vector<SGCONF::API_ACTION::PARAM> GetCorpParams() { std::vector<SGCONF::API_ACTION::PARAM> params; -params.push_back({"cash", "<cash>", "\tcorporation's cash"}); +params.push_back(SGCONF::API_ACTION::PARAM("cash", "<cash>", "\tcorporation's cash")); return params; } diff --git a/projects/sgconf/main.cpp b/projects/sgconf/main.cpp index 73917852..22e998f3 100644 --- a/projects/sgconf/main.cpp +++ b/projects/sgconf/main.cpp @@ -163,7 +163,7 @@ class CONFIG_ACTION : public ACTION virtual std::string ParamDescription() const { return m_description; } virtual std::string DefaultDescription() const { return ""; } virtual OPTION_BLOCK & Suboptions() { return m_suboptions; } - virtual PARSER_STATE Parse(int argc, char ** argv); + virtual PARSER_STATE Parse(int argc, char ** argv, void * /*data*/); private: SGCONF::CONFIG & m_config; @@ -175,7 +175,7 @@ class CONFIG_ACTION : public ACTION }; -PARSER_STATE CONFIG_ACTION::Parse(int argc, char ** argv) +PARSER_STATE CONFIG_ACTION::Parse(int argc, char ** argv, void * /*data*/) { if (argc == 0 || argv == NULL || @@ -298,15 +298,15 @@ else } config = configOverride; + +std::cerr << "Config: " << config.Serialize() << std::endl; +return commands.Execute(config) ? 0 : -1; } catch (const std::exception& ex) { std::cerr << ex.what() << "\n"; return -1; } - -std::cerr << "Config: " << config.Serialize() << std::endl; -return commands.Execute(config) ? 0 : -1; } //----------------------------------------------------------------------------- diff --git a/projects/sgconf/options.cpp b/projects/sgconf/options.cpp index f5e423ad..49e04d64 100644 --- a/projects/sgconf/options.cpp +++ b/projects/sgconf/options.cpp @@ -134,18 +134,20 @@ if (*arg++ != '-') return false; if (*arg == '-') +{ return m_longName == arg + 1; +} return m_shortName == arg; } -PARSER_STATE OPTION::Parse(int argc, char ** argv) +PARSER_STATE OPTION::Parse(int argc, char ** argv, void * data) { if (!m_action) throw ERROR("Option is not defined."); try { - return m_action->Parse(argc, argv); + return m_action->Parse(argc, argv, data); } catch (const ACTION::ERROR & ex) { @@ -199,14 +201,16 @@ std::for_each(m_options.begin(), std::bind2nd(std::mem_fun_ref(&OPTION::Help), level + 1)); } -PARSER_STATE OPTION_BLOCK::Parse(int argc, char ** argv) +PARSER_STATE OPTION_BLOCK::Parse(int argc, char ** argv, void * data) { PARSER_STATE state(false, argc, argv); +if (state.argc == 0) + return state; while (state.argc > 0 && !state.stop) { std::vector<OPTION>::iterator it = std::find_if(m_options.begin(), m_options.end(), std::bind2nd(std::mem_fun_ref(&OPTION::Check), *state.argv)); if (it != m_options.end()) - state = it->Parse(--state.argc, ++state.argv); + state = it->Parse(--state.argc, ++state.argv, data); else break; ++it; @@ -243,7 +247,7 @@ PARSER_STATE OPTION_BLOCKS::Parse(int argc, char ** argv) { PARSER_STATE state(false, argc, argv); std::list<OPTION_BLOCK>::iterator it(m_blocks.begin()); -while (!state.stop && it != m_blocks.end()) +while (state.argc > 0 && !state.stop && it != m_blocks.end()) { state = it->Parse(state.argc, state.argv); ++it; diff --git a/projects/sgconf/options.h b/projects/sgconf/options.h index 53875091..c00707bf 100644 --- a/projects/sgconf/options.h +++ b/projects/sgconf/options.h @@ -50,7 +50,7 @@ class OPTION OPTION & operator=(const OPTION & rhs); void Help(size_t level = 0) const; - PARSER_STATE Parse(int argc, char ** argv); + PARSER_STATE Parse(int argc, char ** argv, void * data); void ParseValue(const std::string & value); bool Check(const char * arg) const; const std::string & Name() const { return m_longName; } @@ -85,7 +85,7 @@ class OPTION_BLOCK void Help(size_t level) const; - PARSER_STATE Parse(int argc, char ** argv); + PARSER_STATE Parse(int argc, char ** argv, void * data = NULL); void ParseFile(const std::string & filePath); class ERROR : public std::runtime_error diff --git a/projects/sgconf/services.cpp b/projects/sgconf/services.cpp index 7989de20..f5d73742 100644 --- a/projects/sgconf/services.cpp +++ b/projects/sgconf/services.cpp @@ -34,9 +34,9 @@ std::cout << Indent(level, true) << "name: " << info.name << "\n" std::vector<SGCONF::API_ACTION::PARAM> GetServiceParams() { std::vector<SGCONF::API_ACTION::PARAM> params; -params.push_back({"cost", "<cost>", "\tcost of the service"}); -params.push_back({"pay-day", "<month day>", "payment day"}); -params.push_back({"comment", "<text>", "comment"}); +params.push_back(SGCONF::API_ACTION::PARAM("cost", "<cost>", "\tcost of the service")); +params.push_back(SGCONF::API_ACTION::PARAM("pay-day", "<month day>", "payment day")); +params.push_back(SGCONF::API_ACTION::PARAM("comment", "<text>", "comment")); return params; } diff --git a/projects/sgconf/tariffs.cpp b/projects/sgconf/tariffs.cpp index 75cd169f..3da1001a 100644 --- a/projects/sgconf/tariffs.cpp +++ b/projects/sgconf/tariffs.cpp @@ -94,15 +94,15 @@ for (size_t i = 0; i < info.dirPrice.size(); ++i) std::vector<SGCONF::API_ACTION::PARAM> GetTariffParams() { std::vector<SGCONF::API_ACTION::PARAM> params; -params.push_back({"fee", "<fee>", "\t\ttariff fee"}); -params.push_back({"free", "<free mb>", "\tprepaid traff"}); -params.push_back({"passive-cost", "<cost>", "\tpassive cost"}); -params.push_back({"traff-type", "<type>", "\ttraff type (up, dow, up+down, max)"}); -params.push_back({"period", "<period>", "\ttarification period (daily, monthly)"}); -params.push_back({"times", "<hh:mm-hh:mm, ...>", "coma-separated day time-spans for each direction"}); -params.push_back({"day-prices", "<price/price, ...>", "coma-separated day prices for each direction"}); -params.push_back({"night-prices", "<price/price, ...>", "coma-separated day prices for each direction"}); -params.push_back({"thresholds", "<threshold, ...>", "coma-separated thresholds for each direction"}); +params.push_back(SGCONF::API_ACTION::PARAM("fee", "<fee>", "\t\ttariff fee")); +params.push_back(SGCONF::API_ACTION::PARAM("free", "<free mb>", "\tprepaid traff")); +params.push_back(SGCONF::API_ACTION::PARAM("passive-cost", "<cost>", "\tpassive cost")); +params.push_back(SGCONF::API_ACTION::PARAM("traff-type", "<type>", "\ttraff type (up, dow, up+down, max)")); +params.push_back(SGCONF::API_ACTION::PARAM("period", "<period>", "\ttarification period (daily, monthly)")); +params.push_back(SGCONF::API_ACTION::PARAM("times", "<hh:mm-hh:mm, ...>", "coma-separated day time-spans for each direction")); +params.push_back(SGCONF::API_ACTION::PARAM("day-prices", "<price/price, ...>", "coma-separated day prices for each direction")); +params.push_back(SGCONF::API_ACTION::PARAM("night-prices", "<price/price, ...>", "coma-separated day prices for each direction")); +params.push_back(SGCONF::API_ACTION::PARAM("thresholds", "<threshold, ...>", "coma-separated thresholds for each direction")); return params; } diff --git a/projects/sgconf/users.cpp b/projects/sgconf/users.cpp index 45603199..9c6c30b5 100644 --- a/projects/sgconf/users.cpp +++ b/projects/sgconf/users.cpp @@ -71,42 +71,42 @@ if (!info.authBy.empty()) std::vector<SGCONF::API_ACTION::PARAM> GetUserParams() { std::vector<SGCONF::API_ACTION::PARAM> params; -params.push_back({"password", "<password>", "\tuser's password"}); -params.push_back({"cash", "<cash>", "\t\tuser's cash"}); -params.push_back({"credit", "<amount>", "\tuser's credit"}); -params.push_back({"credit-expire", "<date>", "\tcredit expiration"}); -params.push_back({"free", "<free mb>", "\tprepaid traffic"}); -params.push_back({"disabled", "<flag>", "\tdisable user (y|n)"}); -params.push_back({"passive", "<flag>", "\tmake user passive (y|n)"}); -params.push_back({"disable-detail-stat", "<flag>", "disable detail stat (y|n)"}); -params.push_back({"always-online", "<flag>", "\tmake user always online (y|n)"}); -params.push_back({"ips", "<ips>", "\t\tcoma-separated list of ips"}); -params.push_back({"tariff", "<tariff name>", "\tcurrent tariff"}); -params.push_back({"next-tariff", "<tariff name>", "tariff starting from the next month"}); -params.push_back({"group", "<group>", "\t\tuser's group"}); -params.push_back({"note", "<note>", "\t\tuser's note"}); -params.push_back({"email", "<email>", "\t\tuser's email"}); -params.push_back({"name", "<real name>", "\tuser's real name"}); -params.push_back({"address", "<address>", "\tuser's postal address"}); -params.push_back({"phone", "<phone>", "\t\tuser's phone number"}); -params.push_back({"session-traffic", "<up/dn, ...>", "coma-separated session upload and download"}); -params.push_back({"month-traffic", "<up/dn, ...>", "coma-separated month upload and download"}); -params.push_back({"user-data", "<value, ...>", "coma-separated user data values"}); +params.push_back(SGCONF::API_ACTION::PARAM("password", "<password>", "\tuser's password")); +params.push_back(SGCONF::API_ACTION::PARAM("cash", "<cash>", "\t\tuser's cash")); +params.push_back(SGCONF::API_ACTION::PARAM("credit", "<amount>", "\tuser's credit")); +params.push_back(SGCONF::API_ACTION::PARAM("credit-expire", "<date>", "\tcredit expiration")); +params.push_back(SGCONF::API_ACTION::PARAM("free", "<free mb>", "\tprepaid traffic")); +params.push_back(SGCONF::API_ACTION::PARAM("disabled", "<flag>", "\tdisable user (y|n)")); +params.push_back(SGCONF::API_ACTION::PARAM("passive", "<flag>", "\tmake user passive (y|n)")); +params.push_back(SGCONF::API_ACTION::PARAM("disable-detail-stat", "<flag>", "disable detail stat (y|n)")); +params.push_back(SGCONF::API_ACTION::PARAM("always-online", "<flag>", "\tmake user always online (y|n)")); +params.push_back(SGCONF::API_ACTION::PARAM("ips", "<ips>", "\t\tcoma-separated list of ips")); +params.push_back(SGCONF::API_ACTION::PARAM("tariff", "<tariff name>", "\tcurrent tariff")); +params.push_back(SGCONF::API_ACTION::PARAM("next-tariff", "<tariff name>", "tariff starting from the next month")); +params.push_back(SGCONF::API_ACTION::PARAM("group", "<group>", "\t\tuser's group")); +params.push_back(SGCONF::API_ACTION::PARAM("note", "<note>", "\t\tuser's note")); +params.push_back(SGCONF::API_ACTION::PARAM("email", "<email>", "\t\tuser's email")); +params.push_back(SGCONF::API_ACTION::PARAM("name", "<real name>", "\tuser's real name")); +params.push_back(SGCONF::API_ACTION::PARAM("address", "<address>", "\tuser's postal address")); +params.push_back(SGCONF::API_ACTION::PARAM("phone", "<phone>", "\t\tuser's phone number")); +params.push_back(SGCONF::API_ACTION::PARAM("session-traffic", "<up/dn, ...>", "coma-separated session upload and download")); +params.push_back(SGCONF::API_ACTION::PARAM("month-traffic", "<up/dn, ...>", "coma-separated month upload and download")); +params.push_back(SGCONF::API_ACTION::PARAM("user-data", "<value, ...>", "coma-separated user data values")); return params; } std::vector<SGCONF::API_ACTION::PARAM> GetCheckParams() { std::vector<SGCONF::API_ACTION::PARAM> params; -params.push_back({"password", "<password>", "\tuser's password"}); +params.push_back(SGCONF::API_ACTION::PARAM("password", "<password>", "\tuser's password")); return params; } std::vector<SGCONF::API_ACTION::PARAM> GetMessageParams() { std::vector<SGCONF::API_ACTION::PARAM> params; -params.push_back({"logins", "<login, ...>", "\tlist of logins to send a message"}); -params.push_back({"text", "<text>", "\t\tmessage text"}); +params.push_back(SGCONF::API_ACTION::PARAM("logins", "<login, ...>", "\tlist of logins to send a message")); +params.push_back(SGCONF::API_ACTION::PARAM("text", "<text>", "\t\tmessage text")); return params; } diff --git a/projects/sgconf/utils.h b/projects/sgconf/utils.h new file mode 100644 index 00000000..2e16b625 --- /dev/null +++ b/projects/sgconf/utils.h @@ -0,0 +1,48 @@ +#ifndef __STG_SGCONF_UTILS_H__ +#define __STG_SGCONF_UTILS_H__ + +#include "stg/common.h" +#include "stg/resetable.h" + +#include <string> +#include <map> + +namespace SGCONF +{ + +template <typename T> +inline +void MaybeSet(const std::map<std::string, std::string> & options, const std::string & name, RESETABLE<T> & res) +{ +std::map<std::string, std::string>::const_iterator it(options.find(name)); +if (it == options.end()) + return; +T value; +if (str2x(it->second, value) < 0) + return; +res = value; +} + +template <typename T, typename F> +inline +void MaybeSet(const std::map<std::string, std::string> & options, const std::string & name, RESETABLE<T> & res, F conv) +{ +std::map<std::string, std::string>::const_iterator it(options.find(name)); +if (it == options.end()) + return; +conv(it->second, res); +} + +template <> +inline +void MaybeSet<std::string>(const std::map<std::string, std::string> & options, const std::string & name, RESETABLE<std::string> & res) +{ +std::map<std::string, std::string>::const_iterator it(options.find(name)); +if (it == options.end()) + return; +res = it->second; +} + +} // namespace SGCONF + +#endif