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