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