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