]> git.stg.codes - stg.git/blob - include/stg/user_property.h
7d68e73410fc502ecf5ef8831dd4d7c090b474ba
[stg.git] / include / stg / user_property.h
1 /*
2 $Revision: 1.44 $
3 $Date: 2010/09/13 05:54:43 $
4 $Author: faust $
5 */
6
7 #ifndef USER_PROPERTY_H
8 #define USER_PROPERTY_H
9
10 #include <unistd.h> // access
11
12 #include <ctime>
13 #include <string>
14 #include <set>
15 #include <map>
16 #include <sstream>
17 #include <iostream>
18
19 #include "stg/logger.h"
20 #include "stg/locker.h"
21 #include "stg/scriptexecuter.h"
22
23 #include "store.h"
24 #include "admin.h"
25 #include "notifer.h"
26 #include "noncopyable.h"
27
28 extern volatile time_t stgTime;
29 //-----------------------------------------------------------------------------
30 class USER_PROPERTY_BASE {
31 public:
32     virtual std::string ToString() const = 0;
33 };
34 //-----------------------------------------------------------------------------
35 template<typename varT>
36 class USER_PROPERTY : public USER_PROPERTY_BASE {
37 public:
38     USER_PROPERTY(varT & val);
39     virtual ~USER_PROPERTY();
40
41     void Set(const varT & rvalue);
42
43     USER_PROPERTY<varT> & operator= (const varT & rvalue);
44
45     const varT * operator&() const throw() { return &value; }
46     const varT & ConstData() const throw() { return value; }
47
48     operator const varT&() const throw() { return value; }
49
50     void    AddBeforeNotifier(PROPERTY_NOTIFIER_BASE<varT> * n);
51     void    DelBeforeNotifier(const PROPERTY_NOTIFIER_BASE<varT> * n);
52
53     void    AddAfterNotifier(PROPERTY_NOTIFIER_BASE<varT> * n);
54     void    DelAfterNotifier(const PROPERTY_NOTIFIER_BASE<varT> * n);
55
56     time_t  ModificationTime() const throw() { return modificationTime; }
57     void    ModifyTime() throw();
58
59     std::string ToString() const;
60 private:
61     varT & value;
62     time_t modificationTime;
63     std::set<PROPERTY_NOTIFIER_BASE<varT> *> beforeNotifiers;
64     std::set<PROPERTY_NOTIFIER_BASE<varT> *> afterNotifiers;
65     pthread_mutex_t mutex;
66 };
67 //-----------------------------------------------------------------------------
68 template<typename varT>
69 class USER_PROPERTY_LOGGED: public USER_PROPERTY<varT> {
70 public:
71     USER_PROPERTY_LOGGED(varT & val,
72                          const std::string & n,
73                          bool isPassword,
74                          bool isStat,
75                          STG_LOGGER & logger,
76                          const std::string & sd,
77                          std::map<std::string, USER_PROPERTY_BASE*> & properties);
78     virtual ~USER_PROPERTY_LOGGED() {}
79
80     USER_PROPERTY_LOGGED<varT> * GetPointer() throw() { return this; }
81     const varT & Get() const { return USER_PROPERTY<varT>::ConstData(); }
82     const std::string & GetName() const { return name; }
83     bool Set(const varT & val,
84              const ADMIN * admin,
85              const std::string & login,
86              const STORE * store,
87              const std::string & msg = "");
88 private:
89     void WriteAccessDenied(const std::string & login,
90                            const ADMIN * admin,
91                            const std::string & parameter);
92
93     void WriteSuccessChange(const std::string & login,
94                             const ADMIN * admin,
95                             const std::string & parameter,
96                             const std::string & oldValue,
97                             const std::string & newValue,
98                             const std::string & msg,
99                             const STORE * store);
100
101     void OnChange(const std::string & login,
102                   const std::string & paramName,
103                   const std::string & oldValue,
104                   const std::string & newValue,
105                   const ADMIN  * admin);
106
107     STG_LOGGER &      stgLogger;
108     bool              isPassword;
109     bool              isStat;
110     std::string       name;
111     const std::string scriptsDir;
112 };
113 //-----------------------------------------------------------------------------
114 class USER_PROPERTIES : private NONCOPYABLE {
115 /*
116  В этом месте важен порядок следования приватной и открытой частей.
117  Это связано с тем, что часть которая находится в публичной секции
118  по сути является завуалированной ссылкой на закрытую часть. Т.о. нам нужно
119  чтобы конструкторы из закрытой части вызвались раньше открытой. Поэтомому в
120  начале идет закрытая секция
121  * */
122
123 private:
124     USER_STAT stat;
125     USER_CONF conf;
126
127     std::map<std::string, USER_PROPERTY_BASE *> properties;
128 public:
129     USER_PROPERTIES(const std::string & sd);
130
131     USER_STAT & Stat() { return stat; }
132     USER_CONF & Conf() { return conf; }
133     const USER_STAT & GetStat() const { return stat; }
134     const USER_CONF & GetConf() const { return conf; }
135     void SetStat(const USER_STAT & s) { stat = s; }
136     void SetConf(const USER_CONF & c) { conf = c; }
137
138     void SetProperties(const USER_PROPERTIES & p) { stat = p.stat; conf = p.conf; }
139
140     std::string GetPropertyValue(const std::string & name) const;
141     bool                  Exists(const std::string & name) const;
142
143     USER_PROPERTY_LOGGED<double>            cash;
144     USER_PROPERTY_LOGGED<DIR_TRAFF>         up;
145     USER_PROPERTY_LOGGED<DIR_TRAFF>         down;
146     USER_PROPERTY_LOGGED<double>            lastCashAdd;
147     USER_PROPERTY_LOGGED<time_t>            passiveTime;
148     USER_PROPERTY_LOGGED<time_t>            lastCashAddTime;
149     USER_PROPERTY_LOGGED<double>            freeMb;
150     USER_PROPERTY_LOGGED<time_t>            lastActivityTime;
151
152     USER_PROPERTY_LOGGED<std::string>       password;
153     USER_PROPERTY_LOGGED<int>               passive;
154     USER_PROPERTY_LOGGED<int>               disabled;
155     USER_PROPERTY_LOGGED<int>               disabledDetailStat;
156     USER_PROPERTY_LOGGED<int>               alwaysOnline;
157     USER_PROPERTY_LOGGED<std::string>       tariffName;
158     USER_PROPERTY_LOGGED<std::string>       nextTariff;
159     USER_PROPERTY_LOGGED<std::string>       address;
160     USER_PROPERTY_LOGGED<std::string>       note;
161     USER_PROPERTY_LOGGED<std::string>       group;
162     USER_PROPERTY_LOGGED<std::string>       email;
163     USER_PROPERTY_LOGGED<std::string>       phone;
164     USER_PROPERTY_LOGGED<std::string>       realName;
165     USER_PROPERTY_LOGGED<double>            credit;
166     USER_PROPERTY_LOGGED<time_t>            creditExpire;
167     USER_PROPERTY_LOGGED<USER_IPS>          ips;
168     USER_PROPERTY_LOGGED<std::string>       userdata0;
169     USER_PROPERTY_LOGGED<std::string>       userdata1;
170     USER_PROPERTY_LOGGED<std::string>       userdata2;
171     USER_PROPERTY_LOGGED<std::string>       userdata3;
172     USER_PROPERTY_LOGGED<std::string>       userdata4;
173     USER_PROPERTY_LOGGED<std::string>       userdata5;
174     USER_PROPERTY_LOGGED<std::string>       userdata6;
175     USER_PROPERTY_LOGGED<std::string>       userdata7;
176     USER_PROPERTY_LOGGED<std::string>       userdata8;
177     USER_PROPERTY_LOGGED<std::string>       userdata9;
178 };
179 //=============================================================================
180
181 //-----------------------------------------------------------------------------
182 //-----------------------------------------------------------------------------
183 //-----------------------------------------------------------------------------
184 template <typename varT>
185 inline
186 USER_PROPERTY<varT>::USER_PROPERTY(varT & val)
187     : value(val),
188       modificationTime(stgTime),
189       beforeNotifiers(),
190       afterNotifiers(),
191       mutex()
192 {
193 pthread_mutex_init(&mutex, NULL);
194 }
195 //-----------------------------------------------------------------------------
196 template <typename varT>
197 inline
198 USER_PROPERTY<varT>::~USER_PROPERTY()
199 {
200 pthread_mutex_destroy(&mutex);
201 }
202 //-----------------------------------------------------------------------------
203 template <typename varT>
204 inline
205 void USER_PROPERTY<varT>::ModifyTime() throw()
206 {
207 modificationTime = stgTime;
208 }
209 //-----------------------------------------------------------------------------
210 template <typename varT>
211 inline
212 void USER_PROPERTY<varT>::Set(const varT & rvalue)
213 {
214 STG_LOCKER locker(&mutex, __FILE__, __LINE__);
215
216 typename std::set<PROPERTY_NOTIFIER_BASE<varT> *>::iterator ni;
217
218 varT oldVal = value;
219
220 ni = beforeNotifiers.begin();
221 while (ni != beforeNotifiers.end())
222     (*ni++)->Notify(oldVal, rvalue);
223
224 value = rvalue;
225 modificationTime = stgTime;
226
227 ni = afterNotifiers.begin();
228 while (ni != afterNotifiers.end())
229     (*ni++)->Notify(oldVal, rvalue);
230 }
231 //-----------------------------------------------------------------------------
232 template <typename varT>
233 inline
234 USER_PROPERTY<varT> & USER_PROPERTY<varT>::operator= (const varT & newValue)
235 {
236 Set(newValue);
237 return *this;
238 }
239 //-----------------------------------------------------------------------------
240 template <typename varT>
241 inline
242 void USER_PROPERTY<varT>::AddBeforeNotifier(PROPERTY_NOTIFIER_BASE<varT> * n)
243 {
244 STG_LOCKER locker(&mutex, __FILE__, __LINE__);
245 beforeNotifiers.insert(n);
246 }
247 //-----------------------------------------------------------------------------
248 template <typename varT>
249 inline
250 void USER_PROPERTY<varT>::DelBeforeNotifier(const PROPERTY_NOTIFIER_BASE<varT> * n)
251 {
252 STG_LOCKER locker(&mutex, __FILE__, __LINE__);
253 beforeNotifiers.erase(const_cast<PROPERTY_NOTIFIER_BASE<varT> *>(n));
254 }
255 //-----------------------------------------------------------------------------
256 template <typename varT>
257 inline
258 void USER_PROPERTY<varT>::AddAfterNotifier(PROPERTY_NOTIFIER_BASE<varT> * n)
259 {
260 STG_LOCKER locker(&mutex, __FILE__, __LINE__);
261 afterNotifiers.insert(n);
262 }
263 //-----------------------------------------------------------------------------
264 template <typename varT>
265 inline
266 void USER_PROPERTY<varT>::DelAfterNotifier(const PROPERTY_NOTIFIER_BASE<varT> * n)
267 {
268 STG_LOCKER locker(&mutex, __FILE__, __LINE__);
269 afterNotifiers.erase(const_cast<PROPERTY_NOTIFIER_BASE<varT> *>(n));
270 }
271 //-----------------------------------------------------------------------------
272 //-----------------------------------------------------------------------------
273 //-----------------------------------------------------------------------------
274 template <typename varT>
275 inline
276 USER_PROPERTY_LOGGED<varT>::USER_PROPERTY_LOGGED(varT & val,
277                                                  const std::string & n,
278                                                  bool isPass,
279                                                  bool isSt,
280                                                  STG_LOGGER & logger,
281                                                  const std::string & sd,
282                                                  std::map<std::string, USER_PROPERTY_BASE*> & properties)
283
284     : USER_PROPERTY<varT>(val),
285       stgLogger(logger),
286       isPassword(isPass),
287       isStat(isSt),
288       name(n),
289       scriptsDir(sd)
290 {
291 properties.insert(std::make_pair(name, this));
292 }
293 //-------------------------------------------------------------------------
294 template <typename varT>
295 bool USER_PROPERTY_LOGGED<varT>::Set(const varT & val,
296                                      const ADMIN * admin,
297                                      const std::string & login,
298                                      const STORE * store,
299                                      const std::string & msg)
300 {
301 const PRIV * priv = admin->GetPriv();
302
303 if ((priv->userConf && !isStat) ||
304     (priv->userStat && isStat) ||
305     (priv->userPasswd && isPassword) ||
306     (priv->userCash && name == "cash"))
307     {
308     std::stringstream oldVal;
309     std::stringstream newVal;
310
311     oldVal.flags(oldVal.flags() | std::ios::fixed);
312     newVal.flags(newVal.flags() | std::ios::fixed);
313
314     oldVal << USER_PROPERTY<varT>::ConstData();
315     newVal << val;
316
317     OnChange(login, name, oldVal.str(), newVal.str(), admin);
318
319     if (isPassword)
320         {
321         WriteSuccessChange(login, admin, name, "******", "******", msg, store);
322         }
323     else
324         {
325         WriteSuccessChange(login, admin, name, oldVal.str(), newVal.str(), msg, store);
326         }
327     USER_PROPERTY<varT>::Set(val);
328     return true;
329     }
330 else
331     {
332     WriteAccessDenied(login, admin, name);
333     return false;
334     }
335 return true;
336 }
337 //-------------------------------------------------------------------------
338 template <typename varT>
339 inline
340 void USER_PROPERTY_LOGGED<varT>::WriteAccessDenied(const std::string & login,
341                                                    const ADMIN * admin,
342                                                    const std::string & parameter)
343 {
344 stgLogger("%s Change user \'%s.\' Parameter \'%s\'. Access denied.",
345           admin->GetLogStr().c_str(), login.c_str(), parameter.c_str());
346 }
347 //-------------------------------------------------------------------------
348 template <typename varT>
349 inline
350 void USER_PROPERTY_LOGGED<varT>::WriteSuccessChange(const std::string & login,
351                                                     const ADMIN * admin,
352                                                     const std::string & parameter,
353                                                     const std::string & oldValue,
354                                                     const std::string & newValue,
355                                                     const std::string & msg,
356                                                     const STORE * store)
357 {
358 stgLogger("%s User \'%s\': \'%s\' parameter changed from \'%s\' to \'%s\'. %s",
359           admin->GetLogStr().c_str(),
360           login.c_str(),
361           parameter.c_str(),
362           oldValue.c_str(),
363           newValue.c_str(),
364           msg.c_str());
365
366 store->WriteUserChgLog(login, admin->GetLogin(), admin->GetIP(), parameter, oldValue, newValue, msg);
367 }
368 //-------------------------------------------------------------------------
369 template <typename varT>
370 void USER_PROPERTY_LOGGED<varT>::OnChange(const std::string & login,
371                                           const std::string & paramName,
372                                           const std::string & oldValue,
373                                           const std::string & newValue,
374                                           const ADMIN * admin)
375 {
376 std::string filePath = scriptsDir + "/OnChange";
377
378 if (access(filePath.c_str(), X_OK) == 0)
379     {
380     std::string execString("\"" + filePath + "\" \"" + login + "\" \"" + paramName + "\" \"" + oldValue + "\" \"" + newValue + "\" \"" + admin->GetLogin() + "\" \"" + admin->GetIPStr() + "\"");
381     ScriptExec(execString.c_str());
382     }
383 else
384     {
385     stgLogger("Script OnChange cannot be executed. File %s not found.", filePath.c_str());
386     }
387 }
388 //-------------------------------------------------------------------------
389 //-------------------------------------------------------------------------
390 //-------------------------------------------------------------------------
391 inline
392 std::string USER_PROPERTIES::GetPropertyValue(const std::string & name) const
393 {
394 std::map<std::string, USER_PROPERTY_BASE*>::const_iterator it = properties.find(name);
395 if (it == properties.end())
396     return "";
397 return it->second->ToString();
398 }
399 //-----------------------------------------------------------------------------
400 inline
401 bool USER_PROPERTIES::Exists(const std::string & name) const
402 {
403 if (properties.find(name)!=properties.end()) return true;
404 return false;
405 }
406 //-------------------------------------------------------------------------
407 //-------------------------------------------------------------------------
408 //-------------------------------------------------------------------------
409 template<typename varT>
410 inline
411 std::ostream & operator<< (std::ostream & stream, const USER_PROPERTY<varT> & value)
412 {
413 return stream << value.ConstData();
414 }
415 //-----------------------------------------------------------------------------
416 template<typename varT>
417 inline
418 std::string USER_PROPERTY<varT>::ToString() const
419 {
420 std::ostringstream stream;
421 stream << value;
422 return stream.str();
423 }
424 #endif // USER_PROPERTY_H