/* $Revision: 1.44 $ $Date: 2010/09/13 05:54:43 $ $Author: faust $ */ #ifndef USER_PROPERTY_H #define USER_PROPERTY_H #include <unistd.h> // access #include <ctime> #include <string> #include <set> #include <map> #include <sstream> #include <iostream> #include "stg/logger.h" #include "stg/locker.h" #include "stg/scriptexecuter.h" #include "stg/common.h" #include "store.h" #include "admin.h" #include "notifer.h" #include "noncopyable.h" extern volatile time_t stgTime; //----------------------------------------------------------------------------- class USER_PROPERTY_BASE { public: virtual std::string ToString() const = 0; }; //----------------------------------------------------------------------------- typedef std::map<std::string, USER_PROPERTY_BASE *> REGISTRY; //----------------------------------------------------------------------------- template<typename varT> class USER_PROPERTY : public USER_PROPERTY_BASE { public: USER_PROPERTY(varT & val); virtual ~USER_PROPERTY(); void Set(const varT & rvalue); USER_PROPERTY<varT> & operator= (const varT & rvalue); const varT * operator&() const throw() { return &value; } const varT & ConstData() const throw() { return value; } operator const varT&() const throw() { return value; } void AddBeforeNotifier(PROPERTY_NOTIFIER_BASE<varT> * n); void DelBeforeNotifier(const PROPERTY_NOTIFIER_BASE<varT> * n); void AddAfterNotifier(PROPERTY_NOTIFIER_BASE<varT> * n); void DelAfterNotifier(const PROPERTY_NOTIFIER_BASE<varT> * n); time_t ModificationTime() const throw() { return modificationTime; } void ModifyTime() throw(); std::string ToString() const; private: varT & value; time_t modificationTime; std::set<PROPERTY_NOTIFIER_BASE<varT> *> beforeNotifiers; std::set<PROPERTY_NOTIFIER_BASE<varT> *> afterNotifiers; pthread_mutex_t mutex; }; //----------------------------------------------------------------------------- template<typename varT> class USER_PROPERTY_LOGGED: public USER_PROPERTY<varT> { public: USER_PROPERTY_LOGGED(varT & val, const std::string & n, bool isPassword, bool isStat, STG_LOGGER & logger, const std::string & sd, REGISTRY & properties); virtual ~USER_PROPERTY_LOGGED() {} USER_PROPERTY_LOGGED<varT> * GetPointer() throw() { return this; } const varT & Get() const { return USER_PROPERTY<varT>::ConstData(); } const std::string & GetName() const { return name; } bool Set(const varT & val, const ADMIN * admin, const std::string & login, const STORE * store, const std::string & msg = ""); private: void WriteAccessDenied(const std::string & login, const ADMIN * admin, const std::string & parameter); void WriteSuccessChange(const std::string & login, const ADMIN * admin, const std::string & parameter, const std::string & oldValue, const std::string & newValue, const std::string & msg, const STORE * store); void OnChange(const std::string & login, const std::string & paramName, const std::string & oldValue, const std::string & newValue, const ADMIN * admin); STG_LOGGER & stgLogger; bool isPassword; bool isStat; std::string name; const std::string scriptsDir; }; //----------------------------------------------------------------------------- class USER_PROPERTIES : private NONCOPYABLE { /* Ð’ Ñтом меÑте важен порÑдок ÑÐ»ÐµÐ´Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ñ€Ð¸Ð²Ð°Ñ‚Ð½Ð¾Ð¹ и открытой чаÑтей. Ðто ÑвÑзано Ñ Ñ‚ÐµÐ¼, что чаÑÑ‚ÑŒ ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð½Ð°Ñ…Ð¾Ð´Ð¸Ñ‚ÑÑ Ð² публичной Ñекции по Ñути ÑвлÑетÑÑ Ð·Ð°Ð²ÑƒÐ°Ð»Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð½Ð¾Ð¹ ÑÑылкой на закрытую чаÑÑ‚ÑŒ. Т.о. нам нужно чтобы конÑтрукторы из закрытой чаÑти вызвалиÑÑŒ раньше открытой. ПоÑтомому в начале идет Ð·Ð°ÐºÑ€Ñ‹Ñ‚Ð°Ñ ÑÐµÐºÑ†Ð¸Ñ * */ private: USER_STAT stat; USER_CONF conf; REGISTRY properties; public: USER_PROPERTIES(const std::string & sd); USER_STAT & Stat() { return stat; } USER_CONF & Conf() { return conf; } 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; } std::string GetPropertyValue(const std::string & name) const; bool Exists(const std::string & name) const; USER_PROPERTY_LOGGED<double> cash; USER_PROPERTY_LOGGED<DIR_TRAFF> up; USER_PROPERTY_LOGGED<DIR_TRAFF> down; USER_PROPERTY_LOGGED<double> lastCashAdd; USER_PROPERTY_LOGGED<time_t> passiveTime; USER_PROPERTY_LOGGED<time_t> lastCashAddTime; USER_PROPERTY_LOGGED<double> freeMb; USER_PROPERTY_LOGGED<time_t> lastActivityTime; USER_PROPERTY_LOGGED<std::string> password; USER_PROPERTY_LOGGED<int> passive; USER_PROPERTY_LOGGED<int> disabled; USER_PROPERTY_LOGGED<int> disabledDetailStat; USER_PROPERTY_LOGGED<int> alwaysOnline; USER_PROPERTY_LOGGED<std::string> tariffName; USER_PROPERTY_LOGGED<std::string> nextTariff; USER_PROPERTY_LOGGED<std::string> address; USER_PROPERTY_LOGGED<std::string> note; USER_PROPERTY_LOGGED<std::string> group; USER_PROPERTY_LOGGED<std::string> email; USER_PROPERTY_LOGGED<std::string> phone; USER_PROPERTY_LOGGED<std::string> realName; USER_PROPERTY_LOGGED<double> credit; USER_PROPERTY_LOGGED<time_t> creditExpire; USER_PROPERTY_LOGGED<USER_IPS> ips; USER_PROPERTY_LOGGED<std::string> userdata0; USER_PROPERTY_LOGGED<std::string> userdata1; USER_PROPERTY_LOGGED<std::string> userdata2; USER_PROPERTY_LOGGED<std::string> userdata3; USER_PROPERTY_LOGGED<std::string> userdata4; USER_PROPERTY_LOGGED<std::string> userdata5; USER_PROPERTY_LOGGED<std::string> userdata6; USER_PROPERTY_LOGGED<std::string> userdata7; USER_PROPERTY_LOGGED<std::string> userdata8; USER_PROPERTY_LOGGED<std::string> userdata9; }; //============================================================================= //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- template <typename varT> inline USER_PROPERTY<varT>::USER_PROPERTY(varT & val) : value(val), modificationTime(stgTime), beforeNotifiers(), afterNotifiers(), mutex() { pthread_mutex_init(&mutex, NULL); } //----------------------------------------------------------------------------- template <typename varT> inline USER_PROPERTY<varT>::~USER_PROPERTY() { pthread_mutex_destroy(&mutex); } //----------------------------------------------------------------------------- template <typename varT> inline void USER_PROPERTY<varT>::ModifyTime() throw() { modificationTime = stgTime; } //----------------------------------------------------------------------------- template <typename varT> inline void USER_PROPERTY<varT>::Set(const varT & rvalue) { STG_LOCKER locker(&mutex); typename std::set<PROPERTY_NOTIFIER_BASE<varT> *>::iterator ni; varT oldVal = value; ni = beforeNotifiers.begin(); while (ni != beforeNotifiers.end()) (*ni++)->Notify(oldVal, rvalue); value = rvalue; modificationTime = stgTime; ni = afterNotifiers.begin(); while (ni != afterNotifiers.end()) (*ni++)->Notify(oldVal, rvalue); } //----------------------------------------------------------------------------- template <typename varT> inline USER_PROPERTY<varT> & USER_PROPERTY<varT>::operator= (const varT & newValue) { Set(newValue); return *this; } //----------------------------------------------------------------------------- template <typename varT> inline void USER_PROPERTY<varT>::AddBeforeNotifier(PROPERTY_NOTIFIER_BASE<varT> * n) { STG_LOCKER locker(&mutex); beforeNotifiers.insert(n); } //----------------------------------------------------------------------------- template <typename varT> inline void USER_PROPERTY<varT>::DelBeforeNotifier(const PROPERTY_NOTIFIER_BASE<varT> * n) { STG_LOCKER locker(&mutex); beforeNotifiers.erase(const_cast<PROPERTY_NOTIFIER_BASE<varT> *>(n)); } //----------------------------------------------------------------------------- template <typename varT> inline void USER_PROPERTY<varT>::AddAfterNotifier(PROPERTY_NOTIFIER_BASE<varT> * n) { STG_LOCKER locker(&mutex); afterNotifiers.insert(n); } //----------------------------------------------------------------------------- template <typename varT> inline void USER_PROPERTY<varT>::DelAfterNotifier(const PROPERTY_NOTIFIER_BASE<varT> * n) { STG_LOCKER locker(&mutex); afterNotifiers.erase(const_cast<PROPERTY_NOTIFIER_BASE<varT> *>(n)); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- template <typename varT> inline USER_PROPERTY_LOGGED<varT>::USER_PROPERTY_LOGGED(varT & val, const std::string & n, bool isPass, bool isSt, STG_LOGGER & logger, const std::string & sd, REGISTRY & properties) : USER_PROPERTY<varT>(val), stgLogger(logger), isPassword(isPass), isStat(isSt), name(n), scriptsDir(sd) { properties.insert(std::make_pair(ToLower(name), this)); } //------------------------------------------------------------------------- template <typename varT> bool USER_PROPERTY_LOGGED<varT>::Set(const varT & val, const ADMIN * admin, const std::string & login, const STORE * store, const std::string & msg) { const PRIV * priv = admin->GetPriv(); if ((priv->userConf && !isStat) || (priv->userStat && isStat) || (priv->userPasswd && isPassword) || (priv->userCash && name == "cash")) { std::stringstream oldVal; std::stringstream newVal; oldVal.flags(oldVal.flags() | std::ios::fixed); newVal.flags(newVal.flags() | std::ios::fixed); oldVal << USER_PROPERTY<varT>::ConstData(); 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<varT>::Set(val); return true; } else { WriteAccessDenied(login, admin, name); return false; } return true; } //------------------------------------------------------------------------- template <typename varT> inline void USER_PROPERTY_LOGGED<varT>::WriteAccessDenied(const std::string & login, const ADMIN * admin, const std::string & parameter) { stgLogger("%s Change user \'%s.\' Parameter \'%s\'. Access denied.", admin->GetLogStr().c_str(), login.c_str(), parameter.c_str()); } //------------------------------------------------------------------------- template <typename varT> inline void USER_PROPERTY_LOGGED<varT>::WriteSuccessChange(const std::string & login, const ADMIN * admin, const std::string & parameter, const std::string & oldValue, const std::string & newValue, const std::string & msg, const 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->GetIP(), parameter, oldValue, newValue, msg); } //------------------------------------------------------------------------- template <typename varT> void USER_PROPERTY_LOGGED<varT>::OnChange(const std::string & login, const std::string & paramName, const std::string & oldValue, const std::string & newValue, const ADMIN * admin) { std::string filePath = scriptsDir + "/OnChange"; if (access(filePath.c_str(), X_OK) == 0) { std::string execString("\"" + filePath + "\" \"" + login + "\" \"" + paramName + "\" \"" + oldValue + "\" \"" + newValue + "\" \"" + admin->GetLogin() + "\" \"" + admin->GetIPStr() + "\""); ScriptExec(execString.c_str()); } else { stgLogger("Script OnChange cannot be executed. File %s not found.", filePath.c_str()); } } //------------------------------------------------------------------------- //------------------------------------------------------------------------- //------------------------------------------------------------------------- inline std::string USER_PROPERTIES::GetPropertyValue(const std::string & name) const { REGISTRY::const_iterator it = properties.find(ToLower(name)); if (it == properties.end()) return ""; return it->second->ToString(); } //----------------------------------------------------------------------------- inline bool USER_PROPERTIES::Exists(const std::string & name) const { return properties.find(ToLower(name)) != properties.end(); } //------------------------------------------------------------------------- //------------------------------------------------------------------------- //------------------------------------------------------------------------- template<typename varT> inline std::ostream & operator<< (std::ostream & stream, const USER_PROPERTY<varT> & value) { return stream << value.ConstData(); } //----------------------------------------------------------------------------- template<typename varT> inline std::string USER_PROPERTY<varT>::ToString() const { std::ostringstream stream; stream << value; return stream.str(); } #endif // USER_PROPERTY_H