/* $Revision: 1.44 $ $Date: 2010/09/13 05:54:43 $ $Author: faust $ */ #ifndef USER_PROPERTY_H #define USER_PROPERTY_H #include #include #include #include #include #include #include "base_store.h" #include "stg_logger.h" #include "admin.h" #include "settings.h" #include "notifer.h" #include "stg_logger.h" #include "stg_locker.h" #include "script_executer.h" using namespace std; extern const volatile time_t stgTime; //----------------------------------------------------------------------------- template class USER_PROPERTY { public: USER_PROPERTY(varT& val); USER_PROPERTY& operator= (const varT&); USER_PROPERTY& operator-= (const varT&); virtual ~USER_PROPERTY(); const varT * operator&() const throw(); const varT& ConstData() const throw(); operator const varT&() const throw() { return value; } //bool IsEmpty() const throw(); void AddBeforeNotifier(PROPERTY_NOTIFIER_BASE * n); void DelBeforeNotifier(PROPERTY_NOTIFIER_BASE * n); void AddAfterNotifier(PROPERTY_NOTIFIER_BASE * n); void DelAfterNotifier(PROPERTY_NOTIFIER_BASE * n); time_t ModificationTime() const throw(); void ModifyTime() throw(); protected: varT & value; time_t modificationTime; //typedef set *>::iterator notifier_iter_t; mutable set *> beforeNotifiers; mutable set *> afterNotifiers; mutable pthread_mutex_t mutex; }; //----------------------------------------------------------------------------- template class USER_PROPERTY_LOGGED: public USER_PROPERTY { public: USER_PROPERTY_LOGGED(varT& val, const string n, bool isPassword, bool isStat, STG_LOGGER & logger, const SETTINGS * s); virtual ~USER_PROPERTY_LOGGED(); //operator const varT&() const throw();; USER_PROPERTY_LOGGED * GetPointer() throw(); const varT & Get() const; const string & GetName() const; bool Set(const varT & val, const ADMIN & admin, const string & login, const BASE_STORE * store, const string & msg = ""); protected: void WriteAccessDenied(const string & login, const ADMIN & admin, const string & parameter); void WriteSuccessChange(const string & login, const ADMIN & admin, const string & parameter, const string & oldValue, const string & newValue, const string & msg, const BASE_STORE * store); void OnChange(const string & login, const string & paramName, const string & oldValue, const string & newValue, const ADMIN & admin); string name; // parameter name. needed for logging bool isPassword; // is parameter password. when true, it will be logged as ******* bool isStat; // is parameter a stat data or conf data? mutable pthread_mutex_t mutex; STG_LOGGER & stgLogger; // server's logger const SETTINGS * settings; }; //----------------------------------------------------------------------------- class USER_PROPERTIES { friend class USER; /* В этом месте важен порядок следования приватной и открытой частей. Это связано с тем, что часть которая находится в публичной секции по сути является завуалированной ссылкой на закрытую часть. Т.о. нам нужно чтобы конструкторы из закрытой части вызвались раньше открытой. Поэтомому в начале идет закрытая секция * */ private: USER_STAT stat; USER_CONF conf; public: USER_PROPERTIES(const SETTINGS * settings); const USER_STAT & GetStat() const { return stat; } const USER_CONF & GetConf() const { return conf; } void SetStat(const USER_STAT & s) { stat = s; } void SetConf(const USER_CONF & c) { conf = c; } void SetProperties(const USER_PROPERTIES & p) { stat = p.stat; conf = p.conf; } USER_PROPERTY_LOGGED cash; USER_PROPERTY_LOGGED up; USER_PROPERTY_LOGGED down; USER_PROPERTY_LOGGED lastCashAdd; USER_PROPERTY_LOGGED passiveTime; USER_PROPERTY_LOGGED lastCashAddTime; USER_PROPERTY_LOGGED freeMb; USER_PROPERTY_LOGGED lastActivityTime; USER_PROPERTY_LOGGED password; USER_PROPERTY_LOGGED passive; USER_PROPERTY_LOGGED disabled; USER_PROPERTY_LOGGED disabledDetailStat; USER_PROPERTY_LOGGED alwaysOnline; USER_PROPERTY_LOGGED tariffName; USER_PROPERTY_LOGGED nextTariff; USER_PROPERTY_LOGGED address; USER_PROPERTY_LOGGED note; USER_PROPERTY_LOGGED group; USER_PROPERTY_LOGGED email; USER_PROPERTY_LOGGED phone; USER_PROPERTY_LOGGED realName; USER_PROPERTY_LOGGED credit; USER_PROPERTY_LOGGED creditExpire; USER_PROPERTY_LOGGED ips; USER_PROPERTY_LOGGED userdata0; USER_PROPERTY_LOGGED userdata1; USER_PROPERTY_LOGGED userdata2; USER_PROPERTY_LOGGED userdata3; USER_PROPERTY_LOGGED userdata4; USER_PROPERTY_LOGGED userdata5; USER_PROPERTY_LOGGED userdata6; USER_PROPERTY_LOGGED userdata7; USER_PROPERTY_LOGGED userdata8; USER_PROPERTY_LOGGED userdata9; }; //============================================================================= //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- template USER_PROPERTY::USER_PROPERTY(varT& val) : value(val) { pthread_mutex_init(&mutex, NULL); modificationTime = stgTime; } //----------------------------------------------------------------------------- template USER_PROPERTY::~USER_PROPERTY() { } //----------------------------------------------------------------------------- template void USER_PROPERTY::ModifyTime() throw() { modificationTime = stgTime; } //----------------------------------------------------------------------------- template USER_PROPERTY& USER_PROPERTY::operator= (const varT& newValue) { STG_LOCKER locker(&mutex, __FILE__, __LINE__); /* TODO if (value == newValue) return *this;*/ typename set *>::iterator ni; varT oldVal = value; ni = beforeNotifiers.begin(); while (ni != beforeNotifiers.end()) (*ni++)->Notify(oldVal, newValue); value = newValue; modificationTime = stgTime; ni = afterNotifiers.begin(); while (ni != afterNotifiers.end()) (*ni++)->Notify(oldVal, newValue); return *this; } //----------------------------------------------------------------------------- template USER_PROPERTY& USER_PROPERTY::operator-= (const varT& delta) { STG_LOCKER locker(&mutex, __FILE__, __LINE__); typename set *>::iterator ni; varT oldVal = value; ni = beforeNotifiers.begin(); while (ni != beforeNotifiers.end()) (*ni++)->Notify(oldVal, oldVal - delta); value -= delta; modificationTime = stgTime; ni = afterNotifiers.begin(); while (ni != afterNotifiers.end()) (*ni++)->Notify(oldVal, value); return *this; } //----------------------------------------------------------------------------- template const varT * USER_PROPERTY::operator&() const throw() { STG_LOCKER locker(&mutex, __FILE__, __LINE__); return &value; } //----------------------------------------------------------------------------- template const varT& USER_PROPERTY::ConstData() const throw() { STG_LOCKER locker(&mutex, __FILE__, __LINE__); return value; } //----------------------------------------------------------------------------- /*template bool USER_PROPERTY::IsEmpty() const throw() { STG_LOCKER locker(&mutex, __FILE__, __LINE__); return !is_set; }*/ //----------------------------------------------------------------------------- template void USER_PROPERTY::AddBeforeNotifier(PROPERTY_NOTIFIER_BASE * n) { STG_LOCKER locker(&mutex, __FILE__, __LINE__); beforeNotifiers.insert(n); } //----------------------------------------------------------------------------- template void USER_PROPERTY::DelBeforeNotifier(PROPERTY_NOTIFIER_BASE * n) { STG_LOCKER locker(&mutex, __FILE__, __LINE__); beforeNotifiers.erase(n); } //----------------------------------------------------------------------------- template void USER_PROPERTY::AddAfterNotifier(PROPERTY_NOTIFIER_BASE * n) { STG_LOCKER locker(&mutex, __FILE__, __LINE__); afterNotifiers.insert(n); } //----------------------------------------------------------------------------- template void USER_PROPERTY::DelAfterNotifier(PROPERTY_NOTIFIER_BASE * n) { STG_LOCKER locker(&mutex, __FILE__, __LINE__); afterNotifiers.erase(n); } //----------------------------------------------------------------------------- template time_t USER_PROPERTY::ModificationTime() const throw() { STG_LOCKER locker(&mutex, __FILE__, __LINE__); return modificationTime; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- template USER_PROPERTY_LOGGED::USER_PROPERTY_LOGGED( varT& val, string n, bool isPass, bool isSt, STG_LOGGER & logger, const SETTINGS * s) :USER_PROPERTY(val), stgLogger(logger) { pthread_mutex_init(&mutex, NULL); STG_LOCKER locker(&mutex, __FILE__, __LINE__); USER_PROPERTY::value = val; isPassword = isPass; isStat = isSt; name = n; settings = s; } //----------------------------------------------------------------------------- template USER_PROPERTY_LOGGED::~USER_PROPERTY_LOGGED() { STG_LOCKER locker(&mutex, __FILE__, __LINE__); } //----------------------------------------------------------------------------- template USER_PROPERTY_LOGGED * USER_PROPERTY_LOGGED::GetPointer() throw() { STG_LOCKER locker(&mutex, __FILE__, __LINE__); return this; } //----------------------------------------------------------------------------- template const varT & USER_PROPERTY_LOGGED::Get() const { STG_LOCKER locker(&mutex, __FILE__, __LINE__); return USER_PROPERTY::value; }; //------------------------------------------------------------------------- template const string & USER_PROPERTY_LOGGED::GetName() const { STG_LOCKER locker(&mutex, __FILE__, __LINE__); return name; }; //------------------------------------------------------------------------- template bool USER_PROPERTY_LOGGED::Set(const varT & val, const ADMIN & admin, const string & login, const BASE_STORE * store, const string & msg) { STG_LOCKER locker(&mutex, __FILE__, __LINE__); //cout << "USER_PROPERTY_LOGGED " << val << endl; //value = val; //modificationTime = stgTime; const PRIV * priv = admin.GetPriv(); string adm_login = admin.GetLogin(); string adm_ip = admin.GetAdminIPStr(); if ((priv->userConf && !isStat) || (priv->userStat && isStat) || (priv->userPasswd && isPassword) || (priv->userCash && name == "cash")) { stringstream oldVal; stringstream newVal; oldVal.flags(oldVal.flags() | ios::fixed); newVal.flags(newVal.flags() | ios::fixed); oldVal << USER_PROPERTY::value; newVal << val; OnChange(login, name, oldVal.str(), newVal.str(), admin); if (isPassword) { WriteSuccessChange(login, admin, name, "******", "******", msg, store); } else { WriteSuccessChange(login, admin, name, oldVal.str(), newVal.str(), msg, store); } USER_PROPERTY::operator =(val); return true; } else { WriteAccessDenied(login, admin, name); return false; } return true; } //------------------------------------------------------------------------- template void USER_PROPERTY_LOGGED::WriteAccessDenied(const string & login, const ADMIN & admin, const string & parameter) { stgLogger("%s Change user \'%s.\' Parameter \'%s\'. Access denied.", admin.GetLogStr().c_str(), login.c_str(), parameter.c_str()); } //------------------------------------------------------------------------- template void USER_PROPERTY_LOGGED::WriteSuccessChange(const string & login, const ADMIN & admin, const string & parameter, const string & oldValue, const string & newValue, const string & msg, const BASE_STORE * store) { stgLogger("%s User \'%s\': \'%s\' parameter changed from \'%s\' to \'%s\'. %s", admin.GetLogStr().c_str(), login.c_str(), parameter.c_str(), oldValue.c_str(), newValue.c_str(), msg.c_str()); store->WriteUserChgLog(login, admin.GetLogin(), admin.GetAdminIP(), parameter, oldValue, newValue, msg); } //------------------------------------------------------------------------- template void USER_PROPERTY_LOGGED::OnChange(const string & login, const string & paramName, const string & oldValue, const string & newValue, const ADMIN & admin) { string str1; str1 = settings->GetConfDir() + "/OnChange"; if (access(str1.c_str(), X_OK) == 0) { string str2("\"" + str1 + "\" \"" + login + "\" \"" + paramName + "\" \"" + oldValue + "\" \"" + newValue + "\" \"" + admin.GetLogin() + "\" \"" + admin.GetAdminIPStr() + "\""); ScriptExec(str2); } else { stgLogger("Script OnChange cannot be executed. File %s not found.", str1.c_str()); } } //------------------------------------------------------------------------- //------------------------------------------------------------------------- //------------------------------------------------------------------------- template stringstream & operator<< (stringstream & s, const USER_PROPERTY & v) { s << v.ConstData(); return s; } //----------------------------------------------------------------------------- template ostream & operator<< (ostream & o, const USER_PROPERTY & v) { return o << v.ConstData(); } //----------------------------------------------------------------------------- #endif // USER_PROPERTY_H