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