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