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