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