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