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