Add ObjectRef:punch and ObjectRef:right_click to Lua API
[oweals/minetest.git] / src / auth.cpp
1 /*
2 Minetest-c55
3 Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "auth.h"
21 #include <fstream>
22 #include <jmutexautolock.h>
23 //#include "main.h" // for g_settings
24 #include <sstream>
25 #include "strfnd.h"
26 #include "debug.h"
27
28 std::set<std::string> privsToSet(u64 privs)
29 {
30         std::set<std::string> s;
31         if(privs & PRIV_BUILD)
32                 s.insert("build");
33         if(privs & PRIV_TELEPORT)
34                 s.insert("teleport");
35         if(privs & PRIV_SETTIME)
36                 s.insert("settime");
37         if(privs & PRIV_PRIVS)
38                 s.insert("privs");
39         if(privs & PRIV_SHOUT)
40                 s.insert("shout");
41         if(privs & PRIV_BAN)
42                 s.insert("ban");
43         if(privs & PRIV_GIVE)
44                 s.insert("give");
45         return s;
46 }
47
48 // Convert a privileges value into a human-readable string,
49 // with each component separated by a comma.
50 std::string privsToString(u64 privs)
51 {
52         std::ostringstream os(std::ios_base::binary);
53         if(privs & PRIV_BUILD)
54                 os<<"build,";
55         if(privs & PRIV_TELEPORT)
56                 os<<"teleport,";
57         if(privs & PRIV_SETTIME)
58                 os<<"settime,";
59         if(privs & PRIV_PRIVS)
60                 os<<"privs,";
61         if(privs & PRIV_SHOUT)
62                 os<<"shout,";
63         if(privs & PRIV_BAN)
64                 os<<"ban,";
65         if(privs & PRIV_GIVE)
66                 os<<"give,";
67         if(os.tellp())
68         {
69                 // Drop the trailing comma. (Why on earth can't
70                 // you truncate a C++ stream anyway???)
71                 std::string tmp = os.str();
72                 return tmp.substr(0, tmp.length() -1);
73         }
74         return os.str();
75 }
76
77 // Converts a comma-seperated list of privilege values into a
78 // privileges value. The reverse of privsToString(). Returns
79 // PRIV_INVALID if there is anything wrong with the input.
80 u64 stringToPrivs(std::string str)
81 {
82         u64 privs=0;
83         Strfnd f(str);
84         while(f.atend() == false)
85         {
86                 std::string s = trim(f.next(","));
87                 if(s == "build")
88                         privs |= PRIV_BUILD;
89                 else if(s == "teleport")
90                         privs |= PRIV_TELEPORT;
91                 else if(s == "settime")
92                         privs |= PRIV_SETTIME;
93                 else if(s == "privs")
94                         privs |= PRIV_PRIVS;
95                 else if(s == "shout")
96                         privs |= PRIV_SHOUT;
97                 else if(s == "ban")
98                         privs |= PRIV_BAN;
99                 else if(s == "give")
100                         privs |= PRIV_GIVE;
101                 else
102                         return PRIV_INVALID;
103         }
104         return privs;
105 }
106
107 AuthManager::AuthManager(const std::string &authfilepath):
108                 m_authfilepath(authfilepath),
109                 m_modified(false)
110 {
111         m_mutex.Init();
112         
113         try{
114                 load();
115         }
116         catch(SerializationError &e)
117         {
118                 dstream<<"WARNING: AuthManager: creating "
119                                 <<m_authfilepath<<std::endl;
120         }
121 }
122
123 AuthManager::~AuthManager()
124 {
125         save();
126 }
127
128 void AuthManager::load()
129 {
130         JMutexAutoLock lock(m_mutex);
131         
132         dstream<<"AuthManager: loading from "<<m_authfilepath<<std::endl;
133         std::ifstream is(m_authfilepath.c_str(), std::ios::binary);
134         if(is.good() == false)
135         {
136                 dstream<<"AuthManager: failed loading from "<<m_authfilepath<<std::endl;
137                 throw SerializationError("AuthManager::load(): Couldn't open file");
138         }
139
140         for(;;)
141         {
142                 if(is.eof() || is.good() == false)
143                         break;
144
145                 // Read a line
146                 std::string line;
147                 std::getline(is, line, '\n');
148
149                 std::istringstream iss(line);
150                 
151                 // Read name
152                 std::string name;
153                 std::getline(iss, name, ':');
154
155                 // Read password
156                 std::string pwd;
157                 std::getline(iss, pwd, ':');
158
159                 // Read privileges
160                 std::string stringprivs;
161                 std::getline(iss, stringprivs, ':');
162                 u64 privs = stringToPrivs(stringprivs);
163                 
164                 // Store it
165                 AuthData ad;
166                 ad.pwd = pwd;
167                 ad.privs = privs;
168                 m_authdata[name] = ad;
169         }
170
171         m_modified = false;
172 }
173
174 void AuthManager::save()
175 {
176         JMutexAutoLock lock(m_mutex);
177         
178         dstream<<"AuthManager: saving to "<<m_authfilepath<<std::endl;
179         std::ofstream os(m_authfilepath.c_str(), std::ios::binary);
180         if(os.good() == false)
181         {
182                 dstream<<"AuthManager: failed saving to "<<m_authfilepath<<std::endl;
183                 throw SerializationError("AuthManager::save(): Couldn't open file");
184         }
185         
186         for(core::map<std::string, AuthData>::Iterator
187                         i = m_authdata.getIterator();
188                         i.atEnd()==false; i++)
189         {
190                 std::string name = i.getNode()->getKey();
191                 if(name == "")
192                         continue;
193                 AuthData ad = i.getNode()->getValue();
194                 os<<name<<":"<<ad.pwd<<":"<<privsToString(ad.privs)<<"\n";
195         }
196
197         m_modified = false;
198 }
199
200 bool AuthManager::exists(const std::string &username)
201 {
202         JMutexAutoLock lock(m_mutex);
203         
204         core::map<std::string, AuthData>::Node *n;
205         n = m_authdata.find(username);
206         if(n == NULL)
207                 return false;
208         return true;
209 }
210
211 void AuthManager::set(const std::string &username, AuthData ad)
212 {
213         JMutexAutoLock lock(m_mutex);
214         
215         m_authdata[username] = ad;
216
217         m_modified = true;
218 }
219
220 void AuthManager::add(const std::string &username)
221 {
222         JMutexAutoLock lock(m_mutex);
223         
224         m_authdata[username] = AuthData();
225
226         m_modified = true;
227 }
228
229 std::string AuthManager::getPassword(const std::string &username)
230 {
231         JMutexAutoLock lock(m_mutex);
232         
233         core::map<std::string, AuthData>::Node *n;
234         n = m_authdata.find(username);
235         if(n == NULL)
236                 throw AuthNotFoundException("");
237         
238         return n->getValue().pwd;
239 }
240
241 void AuthManager::setPassword(const std::string &username,
242                 const std::string &password)
243 {
244         JMutexAutoLock lock(m_mutex);
245         
246         core::map<std::string, AuthData>::Node *n;
247         n = m_authdata.find(username);
248         if(n == NULL)
249                 throw AuthNotFoundException("");
250         
251         AuthData ad = n->getValue();
252         ad.pwd = password;
253         n->setValue(ad);
254
255         m_modified = true;
256 }
257
258 u64 AuthManager::getPrivs(const std::string &username)
259 {
260         JMutexAutoLock lock(m_mutex);
261         
262         core::map<std::string, AuthData>::Node *n;
263         n = m_authdata.find(username);
264         if(n == NULL)
265                 throw AuthNotFoundException("");
266         
267         return n->getValue().privs;
268 }
269
270 void AuthManager::setPrivs(const std::string &username, u64 privs)
271 {
272         JMutexAutoLock lock(m_mutex);
273         
274         core::map<std::string, AuthData>::Node *n;
275         n = m_authdata.find(username);
276         if(n == NULL)
277                 throw AuthNotFoundException("");
278         
279         AuthData ad = n->getValue();
280         ad.privs = privs;
281         n->setValue(ad);
282
283         m_modified = true;
284 }
285
286 bool AuthManager::isModified()
287 {
288         JMutexAutoLock lock(m_mutex);
289         return m_modified;
290 }
291
292