]> git.stg.codes - stg.git/blob - projects/stargazer/plugins/configuration/rpcconfig/user_helper.cpp
Verbose test reports on failures.
[stg.git] / projects / stargazer / plugins / configuration / rpcconfig / user_helper.cpp
1 #include "user_helper.h"
2
3 #include "stg/tariffs.h"
4 #include "stg/tariff.h"
5 #include "stg/admin.h"
6 #include "stg/store.h"
7 #include "stg/users.h"
8 #include "stg/user.h"
9 #include "stg/user_ips.h"
10 #include "stg/user_property.h"
11 #include "stg/common.h"
12 #include "stg/const.h"
13
14 #include <cmath>
15
16 //------------------------------------------------------------------------------
17
18 void USER_HELPER::GetUserInfo(xmlrpc_c::value * info,
19                               bool hidePassword)
20 {
21 std::map<std::string, xmlrpc_c::value> structVal;
22
23 structVal["result"] = xmlrpc_c::value_boolean(true);
24 structVal["login"] = xmlrpc_c::value_string(ptr->GetLogin());
25
26 if (!hidePassword)
27     {
28     structVal["password"] = xmlrpc_c::value_string(ptr->GetProperties().password.Get());
29     }
30 else
31     {
32     structVal["password"] = xmlrpc_c::value_string("++++++++");
33     }
34
35 structVal["cash"] = xmlrpc_c::value_double(ptr->GetProperties().cash.Get());
36 structVal["freemb"] = xmlrpc_c::value_double(ptr->GetProperties().freeMb.Get());
37 structVal["credit"] = xmlrpc_c::value_double(ptr->GetProperties().credit.Get());
38
39 if (ptr->GetProperties().nextTariff.Get() != "")
40     {
41     structVal["tariff"] = xmlrpc_c::value_string(
42             ptr->GetProperties().tariffName.Get() +
43             "/" +
44             ptr->GetProperties().nextTariff.Get()
45             );
46     }
47 else
48     {
49     structVal["tariff"] = xmlrpc_c::value_string(ptr->GetProperties().tariffName.Get());
50     }
51
52 structVal["note"] = xmlrpc_c::value_string(IconvString(ptr->GetProperties().note, "KOI8-RU", "UTF-8"));
53
54 structVal["phone"] = xmlrpc_c::value_string(IconvString(ptr->GetProperties().phone, "KOI8-RU", "UTF-8"));
55
56 structVal["address"] = xmlrpc_c::value_string(IconvString(ptr->GetProperties().address, "KOI8-RU", "UTF-8"));
57
58 structVal["email"] = xmlrpc_c::value_string(IconvString(ptr->GetProperties().email, "KOI8-RU", "UTF-8"));
59
60 std::vector<xmlrpc_c::value> userdata;
61
62 userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperties().userdata0.Get(), "KOI8-RU", "UTF-8")));
63 userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperties().userdata1.Get(), "KOI8-RU", "UTF-8")));
64 userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperties().userdata2.Get(), "KOI8-RU", "UTF-8")));
65 userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperties().userdata3.Get(), "KOI8-RU", "UTF-8")));
66 userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperties().userdata4.Get(), "KOI8-RU", "UTF-8")));
67 userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperties().userdata5.Get(), "KOI8-RU", "UTF-8")));
68 userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperties().userdata6.Get(), "KOI8-RU", "UTF-8")));
69 userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperties().userdata7.Get(), "KOI8-RU", "UTF-8")));
70 userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperties().userdata8.Get(), "KOI8-RU", "UTF-8")));
71 userdata.push_back(xmlrpc_c::value_string(IconvString(ptr->GetProperties().userdata9.Get(), "KOI8-RU", "UTF-8")));
72
73 structVal["userdata"] = xmlrpc_c::value_array(userdata);
74
75 structVal["name"] = xmlrpc_c::value_string(IconvString(ptr->GetProperties().realName, "KOI8-RU", "UTF-8"));
76
77 structVal["group"] = xmlrpc_c::value_string(IconvString(ptr->GetProperties().group, "KOI8-RU", "UTF-8"));
78
79 structVal["status"] = xmlrpc_c::value_boolean(ptr->GetConnected());
80 structVal["aonline"] = xmlrpc_c::value_boolean(ptr->GetProperties().alwaysOnline.Get());
81 structVal["currip"] = xmlrpc_c::value_string(inet_ntostring(ptr->GetCurrIP()));
82 structVal["pingtime"] = xmlrpc_c::value_int(static_cast<int>(ptr->GetPingTime()));
83 structVal["ips"] = xmlrpc_c::value_string(ptr->GetProperties().ips.Get().toString());
84
85 std::map<std::string, xmlrpc_c::value> traffInfo;
86 std::vector<xmlrpc_c::value> mu(DIR_NUM);
87 std::vector<xmlrpc_c::value> md(DIR_NUM);
88 std::vector<xmlrpc_c::value> su(DIR_NUM);
89 std::vector<xmlrpc_c::value> sd(DIR_NUM);
90
91 auto upload = ptr->GetProperties().up.Get();
92 auto download = ptr->GetProperties().down.Get();
93 auto supload = ptr->GetSessionUpload();
94 auto sdownload = ptr->GetSessionDownload();
95
96 for (int j = 0; j < DIR_NUM; j++)
97     {
98     mu[j] = xmlrpc_c::value_string(std::to_string(upload[j]));
99     md[j] = xmlrpc_c::value_string(std::to_string(download[j]));
100     su[j] = xmlrpc_c::value_string(std::to_string(supload[j]));
101     sd[j] = xmlrpc_c::value_string(std::to_string(sdownload[j]));
102     }
103
104 traffInfo["mu"] = xmlrpc_c::value_array(mu);
105 traffInfo["md"] = xmlrpc_c::value_array(md);
106 traffInfo["su"] = xmlrpc_c::value_array(su);
107 traffInfo["sd"] = xmlrpc_c::value_array(sd);
108
109 structVal["traff"] = xmlrpc_c::value_struct(traffInfo);
110
111 structVal["down"] = xmlrpc_c::value_boolean(ptr->GetProperties().disabled.Get());
112 structVal["disableddetailstat"] = xmlrpc_c::value_boolean(ptr->GetProperties().disabledDetailStat.Get());
113 structVal["passive"] = xmlrpc_c::value_boolean(ptr->GetProperties().passive.Get());
114 structVal["lastcash"] = xmlrpc_c::value_double(ptr->GetProperties().lastCashAdd.Get());
115 structVal["lasttimecash"] = xmlrpc_c::value_int(static_cast<int>(ptr->GetProperties().lastCashAddTime.Get()));
116 structVal["lastactivitytime"] = xmlrpc_c::value_int(static_cast<int>(ptr->GetProperties().lastActivityTime.Get()));
117 structVal["creditexpire"] = xmlrpc_c::value_int(static_cast<int>(ptr->GetProperties().creditExpire.Get()));
118
119 *info = xmlrpc_c::value_struct(structVal);
120 }
121
122 //------------------------------------------------------------------------------
123
124 bool USER_HELPER::SetUserInfo(const xmlrpc_c::value & info,
125                               const STG::Admin& admin,
126                               const std::string & login,
127                               const STG::Store & store,
128                               STG::Tariffs * tariffs)
129 {
130 std::map<std::string, xmlrpc_c::value> structVal(
131     static_cast<std::map<std::string, xmlrpc_c::value> >(xmlrpc_c::value_struct(info))
132     );
133
134 std::map<std::string, xmlrpc_c::value>::iterator it;
135
136 bool check = false;
137 bool alwaysOnline = ptr->GetProperties().alwaysOnline;
138 if ((it = structVal.find("aonline")) != structVal.end())
139     {
140     check = true;
141     alwaysOnline = xmlrpc_c::value_boolean(it->second);
142     }
143 bool onlyOneIP = ptr->GetProperties().ips.ConstData().onlyOneIP();
144 if ((it = structVal.find("ips")) != structVal.end())
145     {
146     check = true;
147     onlyOneIP = STG::UserIPs::parse(xmlrpc_c::value_string(it->second)).onlyOneIP();
148     }
149
150 if (check && alwaysOnline && !onlyOneIP)
151     {
152     printfd(__FILE__, "Requested change leads to a forbidden state: AlwaysOnline with multiple IP's\n");
153     return true;
154     }
155
156 if ((it = structVal.find("ips")) != structVal.end())
157     {
158     auto ips = STG::UserIPs::parse(xmlrpc_c::value_string(it->second));
159
160     for (size_t i = 0; i < ips.count(); ++i)
161         {
162         using ConstUserPtr = const STG::User*;
163         ConstUserPtr user;
164         uint32_t ip = ips[i].ip;
165         if (users.IsIPInUse(ip, login, &user))
166             {
167             printfd(__FILE__, "Trying to assign an IP %s to '%s' that is already in use by '%s'\n", inet_ntostring(ip).c_str(), login.c_str(), user->GetLogin().c_str());
168             return true;
169             }
170         }
171
172     if (!ptr->GetProperties().ips.Set(ips, admin, login, store))
173         return true;
174     }
175
176 if ((it = structVal.find("aonline")) != structVal.end())
177     {
178     bool value(xmlrpc_c::value_boolean(it->second));
179     if (ptr->GetProperties().alwaysOnline.Get() != value)
180         if (!ptr->GetProperties().alwaysOnline.Set(value, admin, login, store))
181             return true;
182     }
183
184 if ((it = structVal.find("password")) != structVal.end())
185     {
186     std::string value(xmlrpc_c::value_string(it->second));
187     if (ptr->GetProperties().password.Get() != value)
188         if (!ptr->GetProperties().password.Set(value, admin, login, store))
189             return true;
190     }
191
192 if ((it = structVal.find("address")) != structVal.end())
193     {
194     std::string value(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-RU"));
195     if (ptr->GetProperties().address.Get() != value)
196         if (!ptr->GetProperties().address.Set(value, admin, login, store))
197             return true;
198     }
199
200 if ((it = structVal.find("phone")) != structVal.end())
201     {
202     std::string value(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-RU"));
203     if (ptr->GetProperties().phone.Get() != value)
204         if (!ptr->GetProperties().phone.Set(value, admin, login, store))
205             return true;
206     }
207
208 if ((it = structVal.find("email")) != structVal.end())
209     {
210     std::string value(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-RU"));
211     if (ptr->GetProperties().email.Get() != value)
212         if (!ptr->GetProperties().email.Set(value, admin, login, store))
213             return true;
214     }
215
216 if ((it = structVal.find("cash")) != structVal.end())
217     {
218     double value(xmlrpc_c::value_double(it->second));
219     if (std::fabs(ptr->GetProperties().cash.Get() - value) > 1.0e-3)
220         if (!ptr->GetProperties().cash.Set(value, admin, login, store))
221             return true;
222     }
223
224 if ((it = structVal.find("creditexpire")) != structVal.end())
225     {
226     time_t value(xmlrpc_c::value_int(it->second));
227     if (ptr->GetProperties().creditExpire.Get() != value)
228         if (!ptr->GetProperties().creditExpire.Set(value, admin, login, store))
229             return true;
230     }
231
232 if ((it = structVal.find("credit")) != structVal.end())
233     {
234     double value(xmlrpc_c::value_double(it->second));
235     if (std::fabs(ptr->GetProperties().credit.Get() - value) > 1.0e-3)
236         if (!ptr->GetProperties().credit.Set(value, admin, login, store))
237             return true;
238     }
239
240 if ((it = structVal.find("freemb")) != structVal.end())
241     {
242     double value(xmlrpc_c::value_double(it->second));
243     if (std::fabs(ptr->GetProperties().freeMb.Get() - value) > 1.0e-3)
244         if (!ptr->GetProperties().freeMb.Set(value, admin, login, store))
245             return true;
246     }
247
248 if ((it = structVal.find("down")) != structVal.end())
249     {
250     bool value(xmlrpc_c::value_boolean(it->second));
251     if (ptr->GetProperties().disabled.Get() != value)
252         if (!ptr->GetProperties().disabled.Set(value, admin, login, store))
253             return true;
254     }
255
256 if ((it = structVal.find("passive")) != structVal.end())
257     {
258     bool value(xmlrpc_c::value_boolean(it->second));
259     if (ptr->GetProperties().passive.Get() != value)
260         if (!ptr->GetProperties().passive.Set(value, admin, login, store))
261             return true;
262     }
263
264 if ((it = structVal.find("disableddetailstat")) != structVal.end())
265     {
266     bool value(xmlrpc_c::value_boolean(it->second));
267     if (ptr->GetProperties().disabledDetailStat.Get() != value)
268         if (!ptr->GetProperties().disabledDetailStat.Set(value, admin, login, store))
269             return true;
270     }
271
272 if ((it = structVal.find("name")) != structVal.end())
273     {
274     std::string value(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-RU"));
275     if (ptr->GetProperties().realName.Get() != value)
276         if (!ptr->GetProperties().realName.Set(value, admin, login, store))
277             return true;
278     }
279
280 if ((it = structVal.find("group")) != structVal.end())
281     {
282     std::string value(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-RU"));
283     if (ptr->GetProperties().group.Get() != value)
284         if (!ptr->GetProperties().group.Set(value, admin, login, store))
285             return true;
286     }
287
288 if ((it = structVal.find("note")) != structVal.end())
289     {
290     std::string value(IconvString(xmlrpc_c::value_string(it->second), "UTF-8", "KOI8-RU"));
291     if (ptr->GetProperties().note.Get() != value)
292         if (!ptr->GetProperties().note.Set(value, admin, login, store))
293             return true;
294     }
295
296 if ((it = structVal.find("userdata")) != structVal.end())
297     {
298     std::vector<STG::UserPropertyLogged<std::string> *> userdata;
299     userdata.push_back(ptr->GetProperties().userdata0.GetPointer());
300     userdata.push_back(ptr->GetProperties().userdata1.GetPointer());
301     userdata.push_back(ptr->GetProperties().userdata2.GetPointer());
302     userdata.push_back(ptr->GetProperties().userdata3.GetPointer());
303     userdata.push_back(ptr->GetProperties().userdata4.GetPointer());
304     userdata.push_back(ptr->GetProperties().userdata5.GetPointer());
305     userdata.push_back(ptr->GetProperties().userdata6.GetPointer());
306     userdata.push_back(ptr->GetProperties().userdata7.GetPointer());
307     userdata.push_back(ptr->GetProperties().userdata8.GetPointer());
308     userdata.push_back(ptr->GetProperties().userdata9.GetPointer());
309
310     std::vector<xmlrpc_c::value> udata(
311         xmlrpc_c::value_array(it->second).vectorValueValue()
312         );
313
314     for (unsigned i = 0; i < userdata.size(); ++i)
315         {
316         std::string value(IconvString(xmlrpc_c::value_string(udata[i]), "UTF-8", "KOI8-RU"));
317         if (userdata[i]->Get() != value)
318             if (!userdata[i]->Set(value, admin, login, store))
319                 return true;
320         }
321     }
322
323 if ((it = structVal.find("traff")) != structVal.end())
324     {
325     std::map<std::string, xmlrpc_c::value> traff(
326         static_cast<std::map<std::string, xmlrpc_c::value> >(xmlrpc_c::value_struct(it->second))
327         );
328
329     auto dtData = ptr->GetProperties().up.Get();
330     if ((it = traff.find("mu")) != traff.end())
331         {
332         std::vector<xmlrpc_c::value> data(xmlrpc_c::value_array(it->second).vectorValueValue());
333
334         for (int i = 0; i < std::min(DIR_NUM, static_cast<int>(data.size())); ++i)
335             {
336             int64_t value;
337             if (str2x(xmlrpc_c::value_string(data[i]), value))
338                 printfd(__FILE__, "USER_HELPER::SetUserInfo(): 'Invalid month upload value'\n");
339             else
340                 dtData[i] = value;
341             }
342         if (!ptr->GetProperties().up.Set(dtData, admin, login, store))
343             return true;
344         }
345     dtData = ptr->GetProperties().down.Get();
346     if ((it = traff.find("md")) != traff.end())
347         {
348         std::vector<xmlrpc_c::value> data(xmlrpc_c::value_array(it->second).vectorValueValue());
349
350         for (int i = 0; i < std::min(DIR_NUM, static_cast<int>(data.size())); ++i)
351             {
352             int64_t value;
353             if (str2x(xmlrpc_c::value_string(data[i]), value))
354                 printfd(__FILE__, "USER_HELPER::SetUserInfo(): 'Invalid month download value'\n");
355             else
356                 dtData[i] = value;
357             }
358         if (!ptr->GetProperties().down.Set(dtData, admin, login, store))
359             return true;
360         }
361     }
362
363 if ((it = structVal.find("tariff")) != structVal.end())
364     {
365     std::string tariff(xmlrpc_c::value_string(it->second));
366     size_t pos = tariff.find('/');
367     std::string nextTariff;
368     if (pos != std::string::npos)
369         {
370         nextTariff = tariff.substr(pos + 1);
371         tariff = tariff.substr(0, pos);
372         }
373
374     const auto newTariff = tariffs->FindByName(tariff);
375     if (newTariff)
376         {
377         const auto currentTariff = ptr->GetTariff();
378         std::string message = currentTariff->TariffChangeIsAllowed(*newTariff, time(NULL));
379         if (message.empty())
380             {
381             if (ptr->GetProperties().tariffName.Get() != tariff)
382                 {
383                 if (!ptr->GetProperties().tariffName.Set(tariff, admin, login, store))
384                     return true;
385                 }
386             }
387         else
388             {
389                 STG::PluginLogger::get("conf_rpc")("Tariff change is prohibited for user %s. %s", ptr->GetLogin().c_str(), message.c_str());
390             }
391         }
392
393     if (nextTariff != "" &&
394         tariffs->FindByName(nextTariff))
395         if (ptr->GetProperties().nextTariff.Get() != nextTariff)
396             if (!ptr->GetProperties().nextTariff.Set(tariff, admin, login, store))
397                 return true;
398     }
399
400 return false;
401 }