]> git.stg.codes - stg.git/blob - projects/stargazer/plugins/authorization/ao/ao.cpp
More subscriptions, less notifiers.
[stg.git] / projects / stargazer / plugins / authorization / ao / ao.cpp
1 /*
2  *    This program is free software; you can redistribute it and/or modify
3  *    it under the terms of the GNU General Public License as published by
4  *    the Free Software Foundation; either version 2 of the License, or
5  *    (at your option) any later version.
6  *
7  *    This program is distributed in the hope that it will be useful,
8  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *    GNU General Public License for more details.
11  *
12  *    You should have received a copy of the GNU General Public License
13  *    along with this program; if not, write to the Free Software
14  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15  */
16
17 /*
18  *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
19  */
20
21 #include "ao.h"
22
23 #include "stg/user.h"
24 #include "stg/users.h"
25 #include "stg/user_property.h"
26 #include "stg/common.h"
27
28 #include <algorithm> // for_each
29 #include <functional> // mem_fun_ref
30 #include <csignal>
31 #include <cassert>
32
33 #include <unistd.h>
34
35 extern "C" STG::Plugin* GetPlugin()
36 {
37     static AUTH_AO plugin;
38     return &plugin;
39 }
40 //-----------------------------------------------------------------------------
41 //-----------------------------------------------------------------------------
42 //-----------------------------------------------------------------------------
43 std::string AUTH_AO::GetVersion() const
44 {
45 return "Always Online authorizator v.1.0";
46 }
47 //-----------------------------------------------------------------------------
48 AUTH_AO::AUTH_AO()
49     : users(NULL),
50       isRunning(false),
51       logger(STG::PluginLogger::get("auth_ao"))
52 {
53 }
54 //-----------------------------------------------------------------------------
55 int AUTH_AO::Start()
56 {
57 printfd(__FILE__, "AUTH_AO::Start()\n");
58 GetUsers();
59
60 m_onAddUserConn = users->onAdd([this](auto user){ AddUser(user); });
61 m_onDelUserConn = users->onDel([this](auto user){ DelUser(user); });
62
63 std::for_each(userList.begin(), userList.end(), [this](auto user){ UpdateUserAuthorization(user); });
64
65 isRunning = true;
66
67 return 0;
68 }
69 //-----------------------------------------------------------------------------
70 int AUTH_AO::Stop()
71 {
72 printfd(__FILE__, "AUTH_AO::Stop()\n");
73 if (!isRunning)
74     return 0;
75
76 m_onAddUserConn.disconnect();
77 m_onDelUserConn.disconnect();
78
79 auto it = userList.begin();
80 while (it != userList.end())
81     {
82     if ((*it)->IsAuthorizedBy(this))
83         users->Unauthorize((*it)->GetLogin(), this);
84     UnSetUserNotifiers(*it);
85     ++it;
86     }
87 isRunning = false;
88 return 0;
89 }
90 //-----------------------------------------------------------------------------
91 void AUTH_AO::SetUserNotifiers(UserPtr u)
92 {
93 // ---------- AlwaysOnline -------------------
94 CHG_BEFORE_NOTIFIER<int> BeforeChgAONotifier(*this, u);
95 CHG_AFTER_NOTIFIER<int>  AfterChgAONotifier(*this, u);
96
97 BeforeChgAONotifierList.push_front(BeforeChgAONotifier);
98 AfterChgAONotifierList.push_front(AfterChgAONotifier);
99
100 u->GetProperties().alwaysOnline.AddBeforeNotifier(&BeforeChgAONotifierList.front());
101 u->GetProperties().alwaysOnline.AddAfterNotifier(&AfterChgAONotifierList.front());
102 // ---------- AlwaysOnline end ---------------
103
104 // ---------- IP -------------------
105 CHG_BEFORE_NOTIFIER<STG::UserIPs> BeforeChgIPNotifier(*this, u);
106 CHG_AFTER_NOTIFIER<STG::UserIPs>  AfterChgIPNotifier(*this, u);
107
108 BeforeChgIPNotifierList.push_front(BeforeChgIPNotifier);
109 AfterChgIPNotifierList.push_front(AfterChgIPNotifier);
110
111 u->GetProperties().ips.AddBeforeNotifier(&BeforeChgIPNotifierList.front());
112 u->GetProperties().ips.AddAfterNotifier(&AfterChgIPNotifierList.front());
113 // ---------- IP end ---------------
114 }
115 //-----------------------------------------------------------------------------
116 void AUTH_AO::UnSetUserNotifiers(UserPtr u)
117 {
118 // ---      AlwaysOnline        ---
119 auto aoBIter = find_if(BeforeChgAONotifierList.begin(),
120                        BeforeChgAONotifierList.end(),
121                        [u](auto notifier){ return notifier.GetUser() == u; });
122
123 if (aoBIter != BeforeChgAONotifierList.end())
124     {
125     aoBIter->GetUser()->GetProperties().alwaysOnline.DelBeforeNotifier(&(*aoBIter));
126     BeforeChgAONotifierList.erase(aoBIter);
127     }
128
129 auto aoAIter = find_if(AfterChgAONotifierList.begin(),
130                        AfterChgAONotifierList.end(),
131                        [u](auto notifier){ return notifier.GetUser() == u; });
132
133 if (aoAIter != AfterChgAONotifierList.end())
134     {
135     aoAIter->GetUser()->GetProperties().alwaysOnline.DelAfterNotifier(&(*aoAIter));
136     AfterChgAONotifierList.erase(aoAIter);
137     }
138 // ---      AlwaysOnline end    ---
139
140 // ---          IP              ---
141 auto ipBIter = std::find_if(BeforeChgIPNotifierList.begin(),
142                             BeforeChgIPNotifierList.end(),
143                             [u](auto notifier){ return notifier.GetUser() == u; });
144
145 if (ipBIter != BeforeChgIPNotifierList.end())
146     {
147     ipBIter->GetUser()->GetProperties().ips.DelBeforeNotifier(&(*ipBIter));
148     BeforeChgIPNotifierList.erase(ipBIter);
149     }
150
151 auto ipAIter = find_if(AfterChgIPNotifierList.begin(),
152                        AfterChgIPNotifierList.end(),
153                        [u](auto notifier){ return notifier.GetUser() == u; });
154
155 if (ipAIter != AfterChgIPNotifierList.end())
156     {
157     ipAIter->GetUser()->GetProperties().ips.DelAfterNotifier(&(*ipAIter));
158     AfterChgIPNotifierList.erase(ipAIter);
159     }
160 // ---          IP end          ---
161 }
162 //-----------------------------------------------------------------------------
163 void AUTH_AO::GetUsers()
164 {
165 UserPtr u;
166 int h = users->OpenSearch();
167 assert(h && "USERS::OpenSearch is always correct");
168
169 while (!users->SearchNext(h, &u))
170     {
171     userList.push_back(u);
172     SetUserNotifiers(u);
173     }
174
175 users->CloseSearch(h);
176 }
177 //-----------------------------------------------------------------------------
178 void AUTH_AO::UpdateUserAuthorization(ConstUserPtr u) const
179 {
180 if (u->GetProperties().alwaysOnline)
181     {
182     auto ips = u->GetProperties().ips.get();
183     if (ips.onlyOneIP())
184         {
185         users->Authorize(u->GetLogin(), ips[0].ip, 0xFFffFFff, this);
186         }
187     }
188 }
189 //-----------------------------------------------------------------------------
190 void AUTH_AO::AddUser(UserPtr u)
191 {
192 SetUserNotifiers(u);
193 userList.push_back(u);
194 UpdateUserAuthorization(u);
195 }
196 //-----------------------------------------------------------------------------
197 void AUTH_AO::DelUser(UserPtr u)
198 {
199 if (u->IsAuthorizedBy(this))
200     users->Unauthorize(u->GetLogin(), this);
201 UnSetUserNotifiers(u);
202 userList.erase(std::remove(userList.begin(), userList.end(), u), userList.end());
203 }
204 //-----------------------------------------------------------------------------
205 int AUTH_AO::SendMessage(const STG::Message &, uint32_t) const
206 {
207 errorStr = "Authorization modele \'AlwaysOnline\' does not support sending messages";
208 return -1;
209 }
210 //-----------------------------------------------------------------------------
211 template <typename varParamType>
212 void CHG_BEFORE_NOTIFIER<varParamType>::notify(const varParamType &, const varParamType &)
213 {
214 if (user->IsAuthorizedBy(&auth))
215     auth.users->Unauthorize(user->GetLogin(), &auth);
216 }
217 //-----------------------------------------------------------------------------
218 template <typename varParamType>
219 void CHG_AFTER_NOTIFIER<varParamType>::notify(const varParamType &, const varParamType &)
220 {
221 auth.UpdateUserAuthorization(user);
222 }
223 //-----------------------------------------------------------------------------