From: Elena Mamontova Date: Tue, 25 Oct 2016 15:34:40 +0000 (+0300) Subject: Merge remote-tracking branch 'other/ticket37' into ticket X-Git-Url: https://git.stg.codes/stg.git/commitdiff_plain/1487578f4887f49661320e24e311074a9af36f80?hp=d1ddf1df6b8987cc1be7dc96608e22998c3e9cb6 Merge remote-tracking branch 'other/ticket37' into ticket --- diff --git a/include/stg/tariff.h b/include/stg/tariff.h index 879c4ecc..2fd797fd 100644 --- a/include/stg/tariff.h +++ b/include/stg/tariff.h @@ -59,6 +59,7 @@ public: virtual double GetFree() const = 0; virtual PERIOD GetPeriod() const = 0; virtual CHANGE_POLICY GetChangePolicy() const = 0; + virtual time_t GetChangePolicyTimeout() const = 0; virtual const std::string & GetName() const = 0; virtual void SetName(const std::string & name) = 0; @@ -67,6 +68,7 @@ public: virtual int64_t GetTraffByType(uint64_t up, uint64_t down) const = 0; virtual int GetThreshold(int dir) const = 0; virtual const TARIFF_DATA & GetTariffData() const = 0; + virtual std::string TariffChangeIsAllowed(const TARIFF & to) const = 0; }; inline diff --git a/include/stg/tariff_conf.h b/include/stg/tariff_conf.h index d8684bd9..79ade2eb 100644 --- a/include/stg/tariff_conf.h +++ b/include/stg/tariff_conf.h @@ -149,6 +149,7 @@ struct TARIFF_CONF std::string name; TARIFF::PERIOD period; TARIFF::CHANGE_POLICY changePolicy; + time_t changePolicyTimeout; TARIFF_CONF() : fee(0), @@ -157,7 +158,8 @@ struct TARIFF_CONF passiveCost(0), name(), period(TARIFF::MONTH), - changePolicy(TARIFF::ALLOW) + changePolicy(TARIFF::ALLOW), + changePolicyTimeout(0) {} TARIFF_CONF(const std::string & n) @@ -167,7 +169,8 @@ struct TARIFF_CONF passiveCost(0), name(n), period(TARIFF::MONTH), - changePolicy(TARIFF::ALLOW) + changePolicy(TARIFF::ALLOW), + changePolicyTimeout(0) {} }; //----------------------------------------------------------------------------- @@ -180,7 +183,8 @@ struct TARIFF_CONF_RES passiveCost(), name(), period(), - changePolicy() + changePolicy(), + changePolicyTimeout() {} TARIFF_CONF_RES & operator=(const TARIFF_CONF & tc) @@ -192,6 +196,7 @@ struct TARIFF_CONF_RES name = tc.name; period = tc.period; changePolicy = tc.changePolicy; + changePolicyTimeout = tc.changePolicyTimeout; return *this; } @@ -205,6 +210,7 @@ struct TARIFF_CONF_RES traffType.maybeSet(tc.traffType); period.maybeSet(tc.period); changePolicy.maybeSet(tc.changePolicy); + changePolicyTimeout.maybeSet(tc.changePolicyTimeout); return tc; } @@ -215,6 +221,7 @@ struct TARIFF_CONF_RES RESETABLE name; RESETABLE period; RESETABLE changePolicy; + RESETABLE changePolicyTimeout; }; //----------------------------------------------------------------------------- struct TARIFF_DATA @@ -255,6 +262,14 @@ struct TARIFF_DATA_RES dirPrice(DIR_NUM) {} + TARIFF_DATA_RES & operator=(const TARIFF_DATA & td) + { + tariffConf = td.tariffConf; + for (size_t i = 0; i < DIR_NUM; ++i) + dirPrice[i] = td.dirPrice[i]; + return *this; + } + TARIFF_DATA GetData() const { TARIFF_DATA td; diff --git a/projects/stargazer/inst/var/02-alter-03.postgresql.sql b/projects/stargazer/inst/var/02-alter-03.postgresql.sql index a686aa68..e8b248bf 100644 --- a/projects/stargazer/inst/var/02-alter-03.postgresql.sql +++ b/projects/stargazer/inst/var/02-alter-03.postgresql.sql @@ -7,6 +7,9 @@ CREATE DOMAIN DM_TARIFF_CHANGE_POLICY AS TEXT NOT NULL CONSTRAINT valid_value CHECK (VALUE IN ('allow', 'to_cheap', 'to_expensive', 'deny')); ALTER TABLE tb_tariffs ADD change_policy DM_TARIFF_CHANGE_POLICY DEFAULT 'allow'; +ALTER TABLE tb_tariffs ADD change_policy_timeout TIMESTAMP NOT NULL DEFAULT '1970-01-01 00:00:00'; +ALTER TABLE tb_tariffs ALTER COLUMN change_policy DROP DEFAULT; +ALTER TABLE tb_tariffs ALTER COLUMN change_policy_timeout DROP DEFAULT; UPDATE tb_info SET version = 8; diff --git a/projects/stargazer/inst/var/02-alter-03.sql b/projects/stargazer/inst/var/02-alter-03.sql index a0199173..d2745203 100644 --- a/projects/stargazer/inst/var/02-alter-03.sql +++ b/projects/stargazer/inst/var/02-alter-03.sql @@ -6,5 +6,11 @@ CREATE DOMAIN DM_TARIFF_CHANGE_POLICY AS VARCHAR(32) NOT NULL CHECK (VALUE IN ('allow', 'to_cheap', 'to_expensive', 'deny')); ALTER TABLE tb_tariffs ADD change_policy DM_TARIFF_CHANGE_POLICY DEFAULT 'allow'; +ALTER TABLE tb_tariffs ADD change_policy_timeout DM_MOMENT DEFAULT '1970-01-01 00:00:00'; + +UPDATE tb_tariffs SET change_policy = 'allow', change_policy_timeout = '1970-01-01 00:00:00'; + +ALTER TABLE tb_tariffs ALTER COLUMN change_policy DROP DEFAULT; +ALTER TABLE tb_tariffs ALTER COLUMN change_policy_timeout DROP DEFAULT; UPDATE tb_info SET version = 2; diff --git a/projects/stargazer/plugins/configuration/rpcconfig/tariff_helper.cpp b/projects/stargazer/plugins/configuration/rpcconfig/tariff_helper.cpp index c96b7d31..7c023e25 100644 --- a/projects/stargazer/plugins/configuration/rpcconfig/tariff_helper.cpp +++ b/projects/stargazer/plugins/configuration/rpcconfig/tariff_helper.cpp @@ -1,6 +1,7 @@ #include // xmlrpc-c devs have missed something :) #include "tariff_helper.h" +#include "stg/common.h" void TARIFF_HELPER::GetTariffInfo(xmlrpc_c::value * info) const { @@ -14,6 +15,7 @@ structVal["passivecost"] = xmlrpc_c::value_double(data.tariffConf.passiveCost); structVal["traffType"] = xmlrpc_c::value_int(data.tariffConf.traffType); structVal["period"] = xmlrpc_c::value_string(TARIFF::PeriodToString(data.tariffConf.period)); structVal["changePolicy"] = xmlrpc_c::value_string(TARIFF::ChangePolicyToString(data.tariffConf.changePolicy)); +structVal["changePolicyTimeout"] = xmlrpc_c::value_string(formatTime(data.tariffConf.changePolicyTimeout)); std::vector prices(DIR_NUM); @@ -77,6 +79,11 @@ if ((it = structVal.find("changePolicy")) != structVal.end()) data.tariffConf.changePolicy = TARIFF::StringToChangePolicy(xmlrpc_c::value_string(it->second)); } +if ((it = structVal.find("changePolicyTimeout")) != structVal.end()) + { + data.tariffConf.changePolicyTimeout = readTime(xmlrpc_c::value_string(it->second)); + } + if ((it = structVal.find("dirprices")) != structVal.end()) { std::vector prices( diff --git a/projects/stargazer/plugins/configuration/rpcconfig/user_helper.cpp b/projects/stargazer/plugins/configuration/rpcconfig/user_helper.cpp index 89c41587..0e7ac9d6 100644 --- a/projects/stargazer/plugins/configuration/rpcconfig/user_helper.cpp +++ b/projects/stargazer/plugins/configuration/rpcconfig/user_helper.cpp @@ -433,13 +433,27 @@ if ((it = structVal.find("tariff")) != structVal.end()) tariff = tariff.substr(0, pos); } - if (tariffs->FindByName(tariff)) - if (ptr->GetProperty().tariffName.Get() != tariff) - if (!ptr->GetProperty().tariffName.Set(tariff, - admin, - login, - &store)) - return true; + const TARIFF * newTariff = tariffs->FindByName(tariff); + if (newTariff) + { + const TARIFF * currentTariff = ptr->GetTariff(); + std::string message = currentTariff->TariffChangeIsAllowed(*newTariff); + if (message.empty()) + { + if (ptr->GetProperty().tariffName.Get() != tariff) + { + if (!ptr->GetProperty().tariffName.Set(tariff, + admin, + login, + &store)) + return true; + } + } + else + { + GetStgLogger()("Tariff change is prohibited for user %s. %s", ptr->GetLogin().c_str(), message.c_str()); + } + } if (nextTariff != "" && tariffs->FindByName(nextTariff)) diff --git a/projects/stargazer/plugins/configuration/rpcconfig/users_methods.cpp b/projects/stargazer/plugins/configuration/rpcconfig/users_methods.cpp index 5adbf441..5a738d16 100644 --- a/projects/stargazer/plugins/configuration/rpcconfig/users_methods.cpp +++ b/projects/stargazer/plugins/configuration/rpcconfig/users_methods.cpp @@ -381,16 +381,29 @@ if (tariffs->FindByName(tariff)) } else { - if (u->GetProperty().tariffName.Set(tariff, + const TARIFF * newTariff = tariffs->FindByName(tariff); + if (newTariff) + { + const TARIFF * currentTariff = u->GetTariff(); + std::string message = currentTariff->TariffChangeIsAllowed(*newTariff); + if (message.empty()) + { + if (u->GetProperty().tariffName.Set(tariff, admin, login, store, comment)) - { - u->ResetNextTariff(); - u->WriteConf(); - *retvalPtr = xmlrpc_c::value_boolean(true); - return; + { + u->ResetNextTariff(); + u->WriteConf(); + *retvalPtr = xmlrpc_c::value_boolean(true); + return; + } + } + else + { + GetStgLogger()("Tariff change is prohibited for user %s. %s", u->GetLogin().c_str(), message.c_str()); + } } } } diff --git a/projects/stargazer/plugins/configuration/sgconfig/parser_tariffs.cpp b/projects/stargazer/plugins/configuration/sgconfig/parser_tariffs.cpp index b33b1305..9c752674 100644 --- a/projects/stargazer/plugins/configuration/sgconfig/parser_tariffs.cpp +++ b/projects/stargazer/plugins/configuration/sgconfig/parser_tariffs.cpp @@ -115,6 +115,7 @@ void GET_TARIFFS::CreateAnswer() "tariffConf.traffType) + "\"/>" + "tariffConf.period) + "\"/>" + "tariffConf.changePolicy) + "\"/>" + + "tariffConf.changePolicyTimeout) + "\"/>" + ""; } @@ -171,7 +172,11 @@ int CHG_TARIFF::Start(void *, const char * el, const char ** attr) { if (strcasecmp(el, m_tag.c_str()) == 0) { - td.tariffConf.name = attr[1]; + const TARIFF * tariff = m_tariffs.FindByName(attr[1]); + if (tariff != NULL) + td = tariff->GetTariffData(); + else + return -1; return 0; } } @@ -295,6 +300,14 @@ int CHG_TARIFF::Start(void *, const char * el, const char ** attr) td.tariffConf.changePolicy = TARIFF::StringToChangePolicy(attr[1]); return 0; } + + if (strcasecmp(el, "ChangePolicyTimeout") == 0) + { + int64_t policyTime = 0; + if (str2x(attr[1], policyTime) == 0) + td.tariffConf.changePolicyTimeout = (time_t)policyTime; + return 0; + } } return -1; } diff --git a/projects/stargazer/plugins/configuration/sgconfig/parser_users.cpp b/projects/stargazer/plugins/configuration/sgconfig/parser_users.cpp index 2e9d7087..8f15c491 100644 --- a/projects/stargazer/plugins/configuration/sgconfig/parser_users.cpp +++ b/projects/stargazer/plugins/configuration/sgconfig/parser_users.cpp @@ -594,11 +594,21 @@ int CHG_USER::ApplyChanges() if (!m_ucr.tariffName.empty()) { - if (m_tariffs.FindByName(m_ucr.tariffName.const_data())) + const TARIFF * newTariff = m_tariffs.FindByName(m_ucr.tariffName.const_data()); + if (newTariff) { - if (!u->GetProperty().tariffName.Set(m_ucr.tariffName.const_data(), &m_currAdmin, m_login, &m_store)) - return -1; - u->ResetNextTariff(); + const TARIFF * tariff = u->GetTariff(); + std::string message = tariff->TariffChangeIsAllowed(*newTariff); + if (message.empty()) + { + if (!u->GetProperty().tariffName.Set(m_ucr.tariffName.const_data(), &m_currAdmin, m_login, &m_store)) + return -1; + u->ResetNextTariff(); + } + else + { + GetStgLogger()("Tariff change is prohibited for user %s. %s", u->GetLogin().c_str(), message.c_str()); + } } else { diff --git a/projects/stargazer/plugins/store/files/file_store.cpp b/projects/stargazer/plugins/store/files/file_store.cpp index d4b29ad9..f63d9686 100644 --- a/projects/stargazer/plugins/store/files/file_store.cpp +++ b/projects/stargazer/plugins/store/files/file_store.cpp @@ -1523,6 +1523,14 @@ if (conf.ReadString("ChangePolicy", &str, "allow") < 0) td->tariffConf.changePolicy = TARIFF::ALLOW; else td->tariffConf.changePolicy = TARIFF::StringToChangePolicy(str); + +if (conf.ReadTime("ChangePolicyTimeout", &td->tariffConf.changePolicyTimeout, 0) < 0) + { + STG_LOCKER lock(&mutex); + errorStr = "Cannot read tariff " + tariffName + ". Parameter ChangePolicyTimeout"; + printfd(__FILE__, "FILES_STORE::RestoreTariff - changepolicytimeout read failed for tariff '%s'\n", tariffName.c_str()); + return -1; + } return 0; } //----------------------------------------------------------------------------- @@ -1585,6 +1593,7 @@ std::string fileName = storeSettings.GetTariffsDir() + "/" + tariffName + ".tf"; cf.WriteString("TraffType", TARIFF::TraffTypeToString(td.tariffConf.traffType)); cf.WriteString("Period", TARIFF::PeriodToString(td.tariffConf.period)); cf.WriteString("ChangePolicy", TARIFF::ChangePolicyToString(td.tariffConf.changePolicy)); + cf.WriteTime("ChangePolicyTimeout", td.tariffConf.changePolicyTimeout); } return 0; diff --git a/projects/stargazer/plugins/store/firebird/firebird_store_tariffs.cpp b/projects/stargazer/plugins/store/firebird/firebird_store_tariffs.cpp index cdee5398..6f8177ca 100644 --- a/projects/stargazer/plugins/store/firebird/firebird_store_tariffs.cpp +++ b/projects/stargazer/plugins/store/firebird/firebird_store_tariffs.cpp @@ -150,54 +150,44 @@ try int32_t id; st->Get(1, id); st->Close(); - if (schemaVersion == 1) + + std::string query = "update tb_tariffs set \ + fee = ?, \ + free = ?, \ + passive_cost = ?, \ + traff_type = ?"; + + if (schemaVersion > 0) + query += ", period = ?"; + if (schemaVersion > 1) + query += ", change_policy = ?, \ + change_policy_timeout = ?"; + + query += " where pk_tariff = ?"; + + unsigned num = 5; + st->Prepare(query); + st->Set(1, td.tariffConf.fee); + st->Set(2, td.tariffConf.free); + st->Set(3, td.tariffConf.passiveCost); + st->Set(4, td.tariffConf.traffType); + + if (schemaVersion > 0) { - st->Prepare("update tb_tariffs set \ - fee = ?, \ - free = ?, \ - passive_cost = ?, \ - traff_type = ?, \ - period = ? \ - where pk_tariff = ?"); - st->Set(1, td.tariffConf.fee); - st->Set(2, td.tariffConf.free); - st->Set(3, td.tariffConf.passiveCost); - st->Set(4, td.tariffConf.traffType); st->Set(5, TARIFF::PeriodToString(td.tariffConf.period)); - st->Set(6, id); + ++num; } - else if (schemaVersion > 1) - { - st->Prepare("update tb_tariffs set \ - fee = ?, \ - free = ?, \ - passive_cost = ?, \ - traff_type = ?, \ - period = ?, \ - change_policy = ? \ - where pk_tariff = ?"); - st->Set(1, td.tariffConf.fee); - st->Set(2, td.tariffConf.free); - st->Set(3, td.tariffConf.passiveCost); - st->Set(4, td.tariffConf.traffType); - st->Set(5, TARIFF::PeriodToString(td.tariffConf.period)); - st->Set(6, TARIFF::ChangePolicyToString(td.tariffConf.changePolicy)); - st->Set(7, id); - } - else + + if (schemaVersion > 1) { - st->Prepare("update tb_tariffs set \ - fee = ?, \ - free = ?, \ - passive_cost = ?, \ - traff_type = ? \ - where pk_tariff = ?"); - st->Set(1, td.tariffConf.fee); - st->Set(2, td.tariffConf.free); - st->Set(3, td.tariffConf.passiveCost); - st->Set(4, td.tariffConf.traffType); - st->Set(5, id); + st->Set(6, TARIFF::ChangePolicyToString(td.tariffConf.changePolicy)); + IBPP::Timestamp policyTimeout; + time_t2ts(td.tariffConf.changePolicyTimeout, &policyTimeout); + st->Set(7, policyTimeout); + num += 2; } + + st->Set(num, id); st->Execute(); st->Close(); @@ -304,7 +294,10 @@ try if (schemaVersion > 0) td->tariffConf.period = TARIFF::StringToPeriod(Get(st, 7)); if (schemaVersion > 1) + { td->tariffConf.changePolicy = TARIFF::StringToChangePolicy(Get(st, 8)); + td->tariffConf.changePolicyTimeout = ts2time_t(Get(st, 9)); + } st->Close(); st->Prepare("select * from tb_tariffs_params where fk_tariff = ?"); st->Set(1, id); diff --git a/projects/stargazer/plugins/store/mysql/mysql_store.cpp b/projects/stargazer/plugins/store/mysql/mysql_store.cpp index f3539dd6..198b5f3b 100644 --- a/projects/stargazer/plugins/store/mysql/mysql_store.cpp +++ b/projects/stargazer/plugins/store/mysql/mysql_store.cpp @@ -7,6 +7,7 @@ #include #include +#include "stg/common.h" #include "stg/user_ips.h" #include "stg/user_conf.h" #include "stg/user_stat.h" @@ -369,7 +370,8 @@ if(!IsTablePresent("tariffs",sock)) res += "PassiveCost DOUBLE DEFAULT 0.0, Fee DOUBLE DEFAULT 0.0," "Free DOUBLE DEFAULT 0.0, TraffType VARCHAR(10) DEFAULT ''," "period VARCHAR(32) NOT NULL DEFAULT 'month'," - "change_policy VARCHAR(32) NOT NULL DEFAULT 'allow')"; + "change_policy VARCHAR(32) NOT NULL DEFAULT 'allow'," + "change_policy_timeout TIMESTAMP NOT NULL DEFAULT 0)"; if(MysqlQuery(res.c_str(),sock)) { @@ -424,7 +426,7 @@ if(!IsTablePresent("tariffs",sock)) res += "PassiveCost=0.0, Fee=10.0, Free=0,"\ "SinglePrice0=1, SinglePrice1=1,PriceDayA1=0.75,PriceDayB1=0.75,"\ "PriceNightA0=1.0,PriceNightB0=1.0,TraffType='up+down',period='month',"\ - "change_policy='allow'"; + "change_policy='allow', change_policy_timeout=0"; if(MysqlQuery(res.c_str(),sock)) { @@ -604,7 +606,8 @@ if (schemaVersion < 1) if (schemaVersion < 2) { - if (MysqlQuery("ALTER TABLE tariffs ADD change_policy VARCHAR(32) NOT NULL DEFAULT 'allow'", sock)) + if (MysqlQuery("ALTER TABLE tariffs ADD change_policy VARCHAR(32) NOT NULL DEFAULT 'allow'", sock) || + MysqlQuery("ALTER TABLE tariffs ADD change_policy_timeout TIMESTAMP NOT NULL DEFAULT 0", sock)) { errorStr = "Couldn't update tariffs table to version 2. With error:\n"; errorStr += mysql_error(sock); @@ -1662,7 +1665,7 @@ else } if (schemaVersion > 1) -{ + { str = row[6+8*DIR_NUM]; param = "ChangePolicy"; @@ -1675,10 +1678,24 @@ if (schemaVersion > 1) } td->tariffConf.changePolicy = TARIFF::StringToChangePolicy(str); + + str = row[7+8*DIR_NUM]; + param = "ChangePolicyTimeout"; + + if (str.length() == 0) + { + mysql_free_result(res); + errorStr = "Cannot read tariff " + tariffName + ". Parameter " + param; + mysql_close(sock); + return -1; + } + + td->tariffConf.changePolicyTimeout = readTime(str); } else { td->tariffConf.changePolicy = TARIFF::ALLOW; + td->tariffConf.changePolicyTimeout = 0; } mysql_free_result(res); @@ -1749,7 +1766,8 @@ if (schemaVersion > 0) res += ", Period='" + TARIFF::PeriodToString(td.tariffConf.period) + "'"; if (schemaVersion > 1) - res += ", change_policy='" + TARIFF::ChangePolicyToString(td.tariffConf.changePolicy) + "'"; + res += ", change_policy='" + TARIFF::ChangePolicyToString(td.tariffConf.changePolicy) + "'"\ + ", change_policy_timeout='" + formatTime(td.tariffConf.changePolicy) + "'"; strprintf(¶m, " WHERE name='%s' LIMIT 1", tariffName.c_str()); res += param; diff --git a/projects/stargazer/plugins/store/postgresql/postgresql_store.h b/projects/stargazer/plugins/store/postgresql/postgresql_store.h index 72a2c22c..6bcb3cd0 100644 --- a/projects/stargazer/plugins/store/postgresql/postgresql_store.h +++ b/projects/stargazer/plugins/store/postgresql/postgresql_store.h @@ -128,9 +128,6 @@ private: int EscapeString(std::string & value) const; - std::string Int2TS(time_t value) const; - time_t TS2Int(const std::string & value) const; - int SaveStat(const USER_STAT & stat, const std::string & login, int year = 0, int month = 0) const; int SaveUserServices(uint32_t uid, const std::vector & services) const; diff --git a/projects/stargazer/plugins/store/postgresql/postgresql_store_messages.cpp b/projects/stargazer/plugins/store/postgresql/postgresql_store_messages.cpp index 27401e26..42a19073 100644 --- a/projects/stargazer/plugins/store/postgresql/postgresql_store_messages.cpp +++ b/projects/stargazer/plugins/store/postgresql/postgresql_store_messages.cpp @@ -33,6 +33,7 @@ #include +#include "stg/common.h" #include "postgresql_store.h" #include "stg/locker.h" #include "stg/message.h" @@ -89,8 +90,8 @@ query << "SELECT sp_add_message(" << "'" << elogin << "', " << "CAST(1 AS SMALLINT), " // Here need to be a version, but, it's uninitiated actually << "CAST(" << msg->header.type << " AS SMALLINT), " - << "CAST('" << Int2TS(msg->header.lastSendTime) << "' AS TIMESTAMP), " - << "CAST('" << Int2TS(msg->header.creationTime) << "' AS TIMESTAMP), " + << "CAST('" << formatTime(msg->header.lastSendTime) << "' AS TIMESTAMP), " + << "CAST('" << formatTime(msg->header.creationTime) << "' AS TIMESTAMP), " << msg->header.showTime << ", " << "CAST(" << msg->header.repeat << " AS SMALLINT), " << msg->header.repeatPeriod << ", " @@ -192,8 +193,8 @@ query << "UPDATE tb_messages SET " << "fk_user = (SELECT pk_user FROM tb_users WHERE name = '" << elogin << "'), " << "ver = " << msg.header.ver << ", " << "msg_type = " << msg.header.type << ", " - << "last_send_time = CAST('" << Int2TS(msg.header.lastSendTime) << "' AS TIMESTAMP), " - << "creation_time = CAST('" << Int2TS(msg.header.creationTime) << "' AS TIMESTAMP), " + << "last_send_time = CAST('" << formatTime(msg.header.lastSendTime) << "' AS TIMESTAMP), " + << "creation_time = CAST('" << formatTime(msg.header.creationTime) << "' AS TIMESTAMP), " << "show_time = " << msg.header.showTime << ", " << "repeat = " << msg.header.repeat << ", " << "repeat_period = " << msg.header.repeatPeriod << ", " @@ -287,8 +288,8 @@ if (tuples != 1) str2x(PQgetvalue(result, 0, 0), msg->header.ver); str2x(PQgetvalue(result, 0, 1), msg->header.type); -msg->header.lastSendTime = static_cast(TS2Int(PQgetvalue(result, 0, 2))); -msg->header.creationTime = static_cast(TS2Int(PQgetvalue(result, 0, 3))); +msg->header.lastSendTime = static_cast(readTime(PQgetvalue(result, 0, 2))); +msg->header.creationTime = static_cast(readTime(PQgetvalue(result, 0, 3))); str2x(PQgetvalue(result, 0, 4), msg->header.showTime); str2x(PQgetvalue(result, 0, 5), msg->header.repeat); str2x(PQgetvalue(result, 0, 6), msg->header.repeatPeriod); @@ -424,8 +425,8 @@ for (int i = 0; i < tuples; ++i) tuple << PQgetvalue(result, i, 0) << " "; tuple << PQgetvalue(result, i, 1) << " "; tuple << PQgetvalue(result, i, 2) << " "; - header.lastSendTime = static_cast(TS2Int(PQgetvalue(result, i, 3))); - header.creationTime = static_cast(TS2Int(PQgetvalue(result, i, 4))); + header.lastSendTime = static_cast(readTime(PQgetvalue(result, i, 3))); + header.creationTime = static_cast(readTime(PQgetvalue(result, i, 4))); tuple << PQgetvalue(result, i, 5) << " "; tuple << PQgetvalue(result, i, 6) << " "; tuple << PQgetvalue(result, i, 7) << " "; diff --git a/projects/stargazer/plugins/store/postgresql/postgresql_store_tariffs.cpp b/projects/stargazer/plugins/store/postgresql/postgresql_store_tariffs.cpp index c509c39c..fd0b38bc 100644 --- a/projects/stargazer/plugins/store/postgresql/postgresql_store_tariffs.cpp +++ b/projects/stargazer/plugins/store/postgresql/postgresql_store_tariffs.cpp @@ -33,6 +33,7 @@ #include +#include "stg/common.h" #include "postgresql_store.h" #include "stg/locker.h" @@ -318,7 +319,8 @@ int32_t id; query << ", period = '" << TARIFF::PeriodToString(td.tariffConf.period) << "'"; if (version > 7) - query << ", change_policy = '" << TARIFF::ChangePolicyToString(td.tariffConf.changePolicy) << "'"; + query << ", change_policy = '" << TARIFF::ChangePolicyToString(td.tariffConf.changePolicy) << "', \ + change_policy_timeout = CAST('" << formatTime(td.tariffConf.changePolicyTimeout) << "' AS TIMESTAMP)"; query << " WHERE pk_tariff = " << id; @@ -459,7 +461,8 @@ if (version > 6) query << ", period"; if (version > 7) - query << ", change_policy"; + query << ", change_policy \ + , change_policy_timeout"; query << " FROM tb_tariffs WHERE name = '" << ename << "'"; @@ -512,7 +515,10 @@ if (version > 6) td->tariffConf.period = TARIFF::StringToPeriod(PQgetvalue(result, 0, 5)); if (version > 7) + { td->tariffConf.changePolicy = TARIFF::StringToChangePolicy(PQgetvalue(result, 0, 6)); + td->tariffConf.changePolicyTimeout = readTime(PQgetvalue(result, 0, 7)); + } PQclear(result); diff --git a/projects/stargazer/plugins/store/postgresql/postgresql_store_users.cpp b/projects/stargazer/plugins/store/postgresql/postgresql_store_users.cpp index db2717ac..1ab5d0e8 100644 --- a/projects/stargazer/plugins/store/postgresql/postgresql_store_users.cpp +++ b/projects/stargazer/plugins/store/postgresql/postgresql_store_users.cpp @@ -33,6 +33,7 @@ #include +#include "stg/common.h" #include "stg/const.h" #include "stg/locker.h" #include "../../../stg_timer.h" @@ -270,9 +271,9 @@ std::ostringstream query; query << "UPDATE tb_users SET " "cash = " << stat.cash << ", " "free_mb = " << stat.freeMb << ", " - "last_activity_time = CAST('" << Int2TS(stat.lastActivityTime) << "' AS TIMESTAMP), " + "last_activity_time = CAST('" << formatTime(stat.lastActivityTime) << "' AS TIMESTAMP), " "last_cash_add = " << stat.lastCashAdd << ", " - "last_cash_add_time = CAST('" << Int2TS(stat.lastCashAddTime) << "' AS TIMESTAMP), " + "last_cash_add_time = CAST('" << formatTime(stat.lastCashAddTime) << "' AS TIMESTAMP), " "passive_time = " << stat.passiveTime << " " "WHERE name = '" << elogin << "'"; @@ -527,7 +528,7 @@ query << "UPDATE tb_users SET " "address = '" << eaddress << "', " "always_online = " << (conf.alwaysOnline ? "'t'" : "'f'") << ", " "credit = " << conf.credit << ", " - "credit_expire = CAST('" << Int2TS(conf.creditExpire) << "' AS TIMESTAMP), " + "credit_expire = CAST('" << formatTime(conf.creditExpire) << "' AS TIMESTAMP), " "disabled = " << (conf.disabled ? "'t'" : "'f'") << ", " "disabled_detail_stat = " << (conf.disabledDetailStat ? "'t'" : "'f'") << ", " "email = '" << eemail << "', " @@ -681,9 +682,9 @@ if (tuples != 1) std::stringstream tuple; tuple << PQgetvalue(result, 0, 0) << " "; tuple << PQgetvalue(result, 0, 1) << " "; - stat->lastActivityTime = TS2Int(PQgetvalue(result, 0, 2)); + stat->lastActivityTime = readTime(PQgetvalue(result, 0, 2)); tuple << PQgetvalue(result, 0, 3) << " "; - stat->lastCashAddTime = TS2Int(PQgetvalue(result, 0, 4)); + stat->lastCashAddTime = readTime(PQgetvalue(result, 0, 4)); tuple << PQgetvalue(result, 0, 5) << " "; PQclear(result); @@ -699,7 +700,7 @@ if (tuples != 1) query << "SELECT dir_num, upload, download " "FROM tb_stats_traffic " "WHERE fk_user IN (SELECT pk_user FROM tb_users WHERE name = '" << elogin << "') AND " - "DATE_TRUNC('month', stats_date) = DATE_TRUNC('month', CAST('" << Int2TS(stgTime) << "' AS TIMESTAMP))"; + "DATE_TRUNC('month', stats_date) = DATE_TRUNC('month', CAST('" << formatTime(stgTime) << "' AS TIMESTAMP))"; result = PQexec(connection, query.str().c_str()); } @@ -832,7 +833,7 @@ uint32_t uid; conf->address = PQgetvalue(result, 0, 1); // address conf->alwaysOnline = !strncmp(PQgetvalue(result, 0, 2), "t", 1); tuple << PQgetvalue(result, 0, 3) << " "; // credit - conf->creditExpire = TS2Int(PQgetvalue(result, 0, 4)); // creditExpire + conf->creditExpire = readTime(PQgetvalue(result, 0, 4)); // creditExpire conf->disabled = !strncmp(PQgetvalue(result, 0, 5), "t", 1); conf->disabledDetailStat = !strncmp(PQgetvalue(result, 0, 6), "t", 1); conf->email = PQgetvalue(result, 0, 7); // email @@ -1078,7 +1079,7 @@ query << "SELECT sp_add_param_log_entry(" "'" << eadminLogin << "', CAST('" << inet_ntostring(admIP) << "/32' AS INET), " "'" << eparam << "', " - "CAST('" << Int2TS(stgTime) << "' AS TIMESTAMP), " + "CAST('" << formatTime(stgTime) << "' AS TIMESTAMP), " "'" << eold << "', " "'" << enew << "', " "'" << emessage << "')"; @@ -1149,7 +1150,7 @@ if (version < 6) { query << "SELECT sp_add_session_log_entry(" "'" << elogin << "', " - "CAST('" << Int2TS(stgTime) << "' AS TIMESTAMP), " + "CAST('" << formatTime(stgTime) << "' AS TIMESTAMP), " "'c', CAST('" << inet_ntostring(ip) << "/32' AS INET), 0)"; } @@ -1157,7 +1158,7 @@ else { query << "SELECT sp_add_session_log_entry(" "'" << elogin << "', " - "CAST('" << Int2TS(stgTime) << "' AS TIMESTAMP), " + "CAST('" << formatTime(stgTime) << "' AS TIMESTAMP), " "'c', CAST('" << inet_ntostring(ip) << "/32' AS INET), 0, 0, '')"; } @@ -1249,7 +1250,7 @@ if (EscapeString(ereason)) // Old database version - no freeMb logging support query << "SELECT sp_add_session_log_entry(" "'" << elogin << "', " - "CAST('" << Int2TS(stgTime) << "' AS TIMESTAMP), " + "CAST('" << formatTime(stgTime) << "' AS TIMESTAMP), " "'d', CAST('0.0.0.0/0' AS INET), " << cash << ")"; } @@ -1257,7 +1258,7 @@ if (EscapeString(ereason)) { query << "SELECT sp_add_session_log_entry(" "'" << elogin << "', " - "CAST('" << Int2TS(stgTime) << "' AS TIMESTAMP), " + "CAST('" << formatTime(stgTime) << "' AS TIMESTAMP), " "'d', CAST('0.0.0.0/0' AS INET), " << cash << ", " << freeMb << ", '" << ereason << "')"; } @@ -1397,8 +1398,8 @@ for (it = statTree.begin(); it != statTree.end(); ++it) "(till_time, from_time, fk_user, " "dir_num, ip, download, upload, cost) " "VALUES (" - "CAST('" << Int2TS(currTime) << "' AS TIMESTAMP), " - "CAST('" << Int2TS(lastStat) << "' AS TIMESTAMP), " + "CAST('" << formatTime(currTime) << "' AS TIMESTAMP), " + "CAST('" << formatTime(lastStat) << "' AS TIMESTAMP), " "(SELECT pk_user FROM tb_users WHERE name = '" << elogin << "'), " << it->first.dir << ", " << "CAST('" << inet_ntostring(it->first.ip) << "' AS INET), " diff --git a/projects/stargazer/plugins/store/postgresql/postgresql_store_utils.cpp b/projects/stargazer/plugins/store/postgresql/postgresql_store_utils.cpp index ef705053..9a5101e1 100644 --- a/projects/stargazer/plugins/store/postgresql/postgresql_store_utils.cpp +++ b/projects/stargazer/plugins/store/postgresql/postgresql_store_utils.cpp @@ -113,35 +113,6 @@ delete[] buf; return 0; } -std::string POSTGRESQL_STORE::Int2TS(time_t ts) const -{ -struct tm brokenTime; - -brokenTime.tm_wday = 0; -brokenTime.tm_yday = 0; -brokenTime.tm_isdst = 0; - -gmtime_r(&ts, &brokenTime); - -char buf[32]; -strftime(buf, 32, "%Y-%m-%d %H:%M:%S", &brokenTime); - -return buf; -} - -time_t POSTGRESQL_STORE::TS2Int(const std::string & ts) const -{ -struct tm brokenTime; - -brokenTime.tm_wday = 0; -brokenTime.tm_yday = 0; -brokenTime.tm_isdst = 0; - -stg_strptime(ts.c_str(), "%Y-%m-%d %H:%M:%S", &brokenTime); - -return stg_timegm(&brokenTime); -} - void POSTGRESQL_STORE::MakeDate(std::string & date, int year, int month) const { struct tm brokenTime; diff --git a/projects/stargazer/tariff_impl.cpp b/projects/stargazer/tariff_impl.cpp index c6785cea..a3084fbc 100644 --- a/projects/stargazer/tariff_impl.cpp +++ b/projects/stargazer/tariff_impl.cpp @@ -145,3 +145,24 @@ else return tariffData.dirPrice[dir].priceDayA; } //----------------------------------------------------------------------------- +std::string TARIFF_IMPL::TariffChangeIsAllowed(const TARIFF & to) const +{ +switch (GetChangePolicy()) + { + case TARIFF::ALLOW: + return ""; + case TARIFF::TO_CHEAP: + if (to.GetFee() < GetFee()) + return ""; + else + return "New tariff '" + to.GetName() + "' is more expensive than current tariff '" + GetName() + "'. The policy is '" + TARIFF::ChangePolicyToString(GetChangePolicy()) + "'."; + case TARIFF::TO_EXPENSIVE: + if (to.GetFee() >= GetFee()) + return ""; + else + return "New tariff '" + to.GetName() + "' is more cheap than current tariff '" + GetName() + "'. The policy is '" + TARIFF::ChangePolicyToString(GetChangePolicy()) + "'."; + case TARIFF::DENY: + return "Current tariff '" + GetName() + "', new tariff '" + to.GetName() + "'. The policy is '" + TARIFF::ChangePolicyToString(GetChangePolicy()) + "'."; + } +} +//----------------------------------------------------------------------------- diff --git a/projects/stargazer/tariff_impl.h b/projects/stargazer/tariff_impl.h index 324be186..4948b3f8 100644 --- a/projects/stargazer/tariff_impl.h +++ b/projects/stargazer/tariff_impl.h @@ -73,6 +73,7 @@ public: double GetFree() const { return tariffData.tariffConf.free; } PERIOD GetPeriod() const { return tariffData.tariffConf.period; } CHANGE_POLICY GetChangePolicy() const { return tariffData.tariffConf.changePolicy; } + time_t GetChangePolicyTimeout() const { return tariffData.tariffConf.changePolicyTimeout; } void Print() const; @@ -88,6 +89,7 @@ public: TARIFF_IMPL & operator=(const TARIFF_IMPL & t); bool operator==(const TARIFF_IMPL & rhs) const { return GetName() == rhs.GetName(); } bool operator!=(const TARIFF_IMPL & rhs) const { return GetName() != rhs.GetName(); } + std::string TariffChangeIsAllowed(const TARIFF & to) const; private: TARIFF_DATA tariffData; diff --git a/projects/stargazer/user_impl.cpp b/projects/stargazer/user_impl.cpp index c160db75..f3410368 100644 --- a/projects/stargazer/user_impl.cpp +++ b/projects/stargazer/user_impl.cpp @@ -1178,10 +1178,24 @@ if (nextTariff.ConstData() != "") { const TARIFF * nt = tariffs->FindByName(nextTariff); if (nt == NULL) + { WriteServLog("Cannot change tariff for user %s. Tariff %s not exist.", login.c_str(), property.tariffName.Get().c_str()); + } else - property.tariffName.Set(nextTariff, sysAdmin, login, store); + { + std::string message = tariff->TariffChangeIsAllowed(*nt); + if (message.empty()) + { + property.tariffName.Set(nextTariff, sysAdmin, login, store); + } + else + { + WriteServLog("Tariff change is prohibited for user %s. %s", + login.c_str(), + message.c_str()); + } + } ResetNextTariff(); WriteConf(); } diff --git a/stglibs/common.lib/common.cpp b/stglibs/common.lib/common.cpp index 76a1b421..a4722a00 100644 --- a/stglibs/common.lib/common.cpp +++ b/stglibs/common.lib/common.cpp @@ -749,6 +749,38 @@ void SwapBytes(int64_t & value) value = temp; } //--------------------------------------------------------------------------- +std::string formatTime(time_t ts) +{ +char buf[32]; +struct tm brokenTime; + +brokenTime.tm_wday = 0; +brokenTime.tm_yday = 0; +brokenTime.tm_isdst = 0; + +gmtime_r(&ts, &brokenTime); + +strftime(buf, 32, "%Y-%m-%d %H:%M:%S", &brokenTime); + +return buf; +} +//--------------------------------------------------------------------------- +time_t readTime(const std::string & ts) +{ +if (ts == "0000-00-00 00:00:00") + return 0; + +struct tm brokenTime; + +brokenTime.tm_wday = 0; +brokenTime.tm_yday = 0; +brokenTime.tm_isdst = 0; + +stg_strptime(ts.c_str(), "%Y-%m-%d %H:%M:%S", &brokenTime); + +return stg_timegm(&brokenTime); +} +//--------------------------------------------------------------------------- int str2x(const std::string & str, int32_t & x) { x = static_cast(strtol(str.c_str(), NULL, 10)); diff --git a/stglibs/common.lib/include/stg/common.h b/stglibs/common.lib/include/stg/common.h index 623d82d0..6201233d 100644 --- a/stglibs/common.lib/include/stg/common.h +++ b/stglibs/common.lib/include/stg/common.h @@ -159,6 +159,8 @@ bool WriteAll(int sd, const void * source, size_t size); std::string ToPrintable(const std::string & src); +std::string formatTime(time_t value); +time_t readTime(const std::string & value); //----------------------------------------------------------------------------- int str2x(const std::string & str, int32_t & x); int str2x(const std::string & str, uint32_t & x); diff --git a/stglibs/conffiles.lib/conffiles.cpp b/stglibs/conffiles.lib/conffiles.cpp index ed2e4447..a9c3e555 100644 --- a/stglibs/conffiles.lib/conffiles.cpp +++ b/stglibs/conffiles.lib/conffiles.cpp @@ -35,6 +35,7 @@ #include // E* #include +#include #include #include @@ -345,6 +346,14 @@ param_val[param] = buf; changed = true; } //--------------------------------------------------------------------------- +void CONFIGFILE::WriteTime(const std::string & param, time_t val) +{ +std::stringstream ss; +ss<::const_iterator it(param_val.find(param)); diff --git a/stglibs/conffiles.lib/include/stg/conffiles.h b/stglibs/conffiles.lib/include/stg/conffiles.h index 48e07b62..49bb6ff3 100644 --- a/stglibs/conffiles.lib/include/stg/conffiles.h +++ b/stglibs/conffiles.lib/include/stg/conffiles.h @@ -67,6 +67,7 @@ public: void WriteString(const std::string & param, const std::string& val); void WriteInt(const std::string & param, int64_t val); void WriteDouble(const std::string & param, double val); + void WriteTime(const std::string & param, time_t val); int Error() const; int Flush() const; diff --git a/tests/test_tariff.cpp b/tests/test_tariff.cpp index 7252a237..188aee8a 100644 --- a/tests/test_tariff.cpp +++ b/tests/test_tariff.cpp @@ -343,5 +343,113 @@ namespace tut ensure_equals("1101 == 0", tariff.GetPriceWithTraffType(0, 6 * 1024 * 1024, 0, 1286461245), 0); // Near 17:30, 6 > 4 DA (ignore night) ensure_equals("1110 == 0", tariff.GetPriceWithTraffType(0, 0 * 1024 * 1024, 0, 1286479245), 0); // Near 22:30, 0 < 4 DA (ignore night) ensure_equals("1111 == 0", tariff.GetPriceWithTraffType(0, 6 * 1024 * 1024, 0, 1286479245), 0); // Near 22:30, 6 > 4 DA (ignore night) + } + + template<> + template<> + void testobject::test<7>() + { + set_test_name("Check changePolicy - ALLOW"); + + TARIFF_DATA td("test"); + td.tariffConf.changePolicy = TARIFF::ALLOW; + td.tariffConf.fee = 100; + TARIFF_IMPL tariff(td); + + td.tariffConf.fee = 50; + TARIFF_IMPL cheaper(td); + + ensure_equals("Allow cheaper", tariff.TariffChangeIsAllowed(cheaper).empty(), true); + + td.tariffConf.fee = 100; + TARIFF_IMPL equal(td); + + ensure_equals("Allow equal", tariff.TariffChangeIsAllowed(equal).empty(), true); + + td.tariffConf.fee = 150; + TARIFF_IMPL expensive(td); + + ensure_equals("Allow expensive", tariff.TariffChangeIsAllowed(expensive).empty(), true); + } + + template<> + template<> + void testobject::test<8>() + { + set_test_name("Check changePolicy - TO_CHEAP"); + + TARIFF_DATA td("test"); + td.tariffConf.changePolicy = TARIFF::TO_CHEAP; + td.tariffConf.fee = 100; + TARIFF_IMPL tariff(td); + + td.tariffConf.fee = 50; + TARIFF_IMPL cheaper(td); + + ensure_equals("Allow cheaper", tariff.TariffChangeIsAllowed(cheaper).empty(), true); + + td.tariffConf.fee = 100; + TARIFF_IMPL equal(td); + + ensure_equals("Prohibit equal", tariff.TariffChangeIsAllowed(equal).empty(), false); + + td.tariffConf.fee = 150; + TARIFF_IMPL expensive(td); + + ensure_equals("Prohibit expensive", tariff.TariffChangeIsAllowed(expensive).empty(), false); + } + + template<> + template<> + void testobject::test<9>() + { + set_test_name("Check changePolicy - TO_EXPENSIVE"); + + TARIFF_DATA td("test"); + td.tariffConf.changePolicy = TARIFF::TO_EXPENSIVE; + td.tariffConf.fee = 100; + TARIFF_IMPL tariff(td); + + td.tariffConf.fee = 50; + TARIFF_IMPL cheaper(td); + + ensure_equals("Prohibit cheaper", tariff.TariffChangeIsAllowed(cheaper).empty(), false); + + td.tariffConf.fee = 100; + TARIFF_IMPL equal(td); + + ensure_equals("Allow equal", tariff.TariffChangeIsAllowed(equal).empty(), true); + + td.tariffConf.fee = 150; + TARIFF_IMPL expensive(td); + + ensure_equals("Allow expensive", tariff.TariffChangeIsAllowed(expensive).empty(), true); + } + + template<> + template<> + void testobject::test<10>() + { + set_test_name("Check changePolicy - DENY"); + + TARIFF_DATA td("test"); + td.tariffConf.changePolicy = TARIFF::DENY; + td.tariffConf.fee = 100; + TARIFF_IMPL tariff(td); + + td.tariffConf.fee = 50; + TARIFF_IMPL cheaper(td); + + ensure_equals("Prohibit cheaper", tariff.TariffChangeIsAllowed(cheaper).empty(), false); + + td.tariffConf.fee = 100; + TARIFF_IMPL equal(td); + + ensure_equals("Prohibit equal", tariff.TariffChangeIsAllowed(equal).empty(), false); + + td.tariffConf.fee = 150; + TARIFF_IMPL expensive(td); + + ensure_equals("Prohibit expensive", tariff.TariffChangeIsAllowed(expensive).empty(), false); } }