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