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