]> git.lizzy.rs Git - minetest.git/blob - builtin/auth.lua
Split builtin.lua to multiple files
[minetest.git] / builtin / auth.lua
1 -- Minetest: builtin/auth.lua
2
3 --
4 -- Authentication handler
5 --
6
7 function minetest.string_to_privs(str, delim)
8         assert(type(str) == "string")
9         delim = delim or ','
10         privs = {}
11         for _, priv in pairs(string.split(str, delim)) do
12                 privs[priv:trim()] = true
13         end
14         return privs
15 end
16
17 function minetest.privs_to_string(privs, delim)
18         assert(type(privs) == "table")
19         delim = delim or ','
20         list = {}
21         for priv, bool in pairs(privs) do
22                 if bool then
23                         table.insert(list, priv)
24                 end
25         end
26         return table.concat(list, delim)
27 end
28
29 assert(minetest.string_to_privs("a,b").b == true)
30 assert(minetest.privs_to_string({a=true,b=true}) == "a,b")
31
32 minetest.auth_file_path = minetest.get_worldpath().."/auth.txt"
33 minetest.auth_table = {}
34
35 local function read_auth_file()
36         local newtable = {}
37         local file, errmsg = io.open(minetest.auth_file_path, 'rb')
38         if not file then
39                 minetest.log("info", minetest.auth_file_path.." could not be opened for reading ("..errmsg.."); assuming new world")
40                 return
41         end
42         for line in file:lines() do
43                 if line ~= "" then
44                         local name, password, privilegestring = string.match(line, "([^:]*):([^:]*):([^:]*)")
45                         if not name or not password or not privilegestring then
46                                 error("Invalid line in auth.txt: "..dump(line))
47                         end
48                         local privileges = minetest.string_to_privs(privilegestring)
49                         newtable[name] = {password=password, privileges=privileges}
50                 end
51         end
52         io.close(file)
53         minetest.auth_table = newtable
54         minetest.notify_authentication_modified()
55 end
56
57 local function save_auth_file()
58         local newtable = {}
59         -- Check table for validness before attempting to save
60         for name, stuff in pairs(minetest.auth_table) do
61                 assert(type(name) == "string")
62                 assert(name ~= "")
63                 assert(type(stuff) == "table")
64                 assert(type(stuff.password) == "string")
65                 assert(type(stuff.privileges) == "table")
66         end
67         local file, errmsg = io.open(minetest.auth_file_path, 'w+b')
68         if not file then
69                 error(minetest.auth_file_path.." could not be opened for writing: "..errmsg)
70         end
71         for name, stuff in pairs(minetest.auth_table) do
72                 local privstring = minetest.privs_to_string(stuff.privileges)
73                 file:write(name..":"..stuff.password..":"..privstring..'\n')
74         end
75         io.close(file)
76 end
77
78 read_auth_file()
79
80 minetest.builtin_auth_handler = {
81         get_auth = function(name)
82                 assert(type(name) == "string")
83                 -- Figure out what password to use for a new player (singleplayer
84                 -- always has an empty password, otherwise use default, which is
85                 -- usually empty too)
86                 local new_password_hash = ""
87                 if not minetest.is_singleplayer() then
88                         new_password_hash = minetest.get_password_hash(name, minetest.setting_get("default_password"))
89                 end
90                 -- Add player to authentication table if not there already
91                 if not minetest.auth_table[name] then
92                         minetest.builtin_auth_handler.create_auth(name, minetest.get_password_hash(name, minetest.setting_get("default_password")))
93                 end
94                 -- Figure out what privileges the player should have.
95                 -- Take a copy of the privilege table
96                 local privileges = {}
97                 for priv, _ in pairs(minetest.auth_table[name].privileges) do
98                         privileges[priv] = true
99                 end
100                 -- If singleplayer, give all privileges except those marked as give_to_singleplayer = false
101                 if minetest.is_singleplayer() then
102                         for priv, def in pairs(minetest.registered_privileges) do
103                                 if def.give_to_singleplayer then
104                                         privileges[priv] = true
105                                 end
106                         end
107                 -- For the admin, give everything
108                 elseif name == minetest.setting_get("name") then
109                         for priv, def in pairs(minetest.registered_privileges) do
110                                 privileges[priv] = true
111                         end
112                 end
113                 -- All done
114                 return {
115                         password = minetest.auth_table[name].password,
116                         privileges = privileges,
117                 }
118         end,
119         create_auth = function(name, password)
120                 assert(type(name) == "string")
121                 assert(type(password) == "string")
122                 minetest.log('info', "Built-in authentication handler adding player '"..name.."'")
123                 minetest.auth_table[name] = {
124                         password = password,
125                         privileges = minetest.string_to_privs(minetest.setting_get("default_privs")),
126                 }
127                 save_auth_file()
128         end,
129         set_password = function(name, password)
130                 assert(type(name) == "string")
131                 assert(type(password) == "string")
132                 if not minetest.auth_table[name] then
133                         minetest.builtin_auth_handler.create_auth(name, password)
134                 else
135                         minetest.log('info', "Built-in authentication handler setting password of player '"..name.."'")
136                         minetest.auth_table[name].password = password
137                         save_auth_file()
138                 end
139                 return true
140         end,
141         set_privileges = function(name, privileges)
142                 assert(type(name) == "string")
143                 assert(type(privileges) == "table")
144                 if not minetest.auth_table[name] then
145                         minetest.builtin_auth_handler.create_auth(name, minetest.get_password_hash(name, minetest.setting_get("default_password")))
146                 end
147                 minetest.auth_table[name].privileges = privileges
148                 minetest.notify_authentication_modified(name)
149                 save_auth_file()
150         end,
151         reload = function()
152                 read_auth_file()
153                 return true
154         end,
155 }
156
157 function minetest.register_authentication_handler(handler)
158         if minetest.registered_auth_handler then
159                 error("Add-on authentication handler already registered by "..minetest.registered_auth_handler_modname)
160         end
161         minetest.registered_auth_handler = handler
162         minetest.registered_auth_handler_modname = minetest.get_current_modname()
163 end
164
165 function minetest.get_auth_handler()
166         if minetest.registered_auth_handler then
167                 return minetest.registered_auth_handler
168         end
169         return minetest.builtin_auth_handler
170 end
171
172 function minetest.set_player_password(name, password)
173         if minetest.get_auth_handler().set_password then
174                 minetest.get_auth_handler().set_password(name, password)
175         end
176 end
177
178 function minetest.set_player_privs(name, privs)
179         if minetest.get_auth_handler().set_privileges then
180                 minetest.get_auth_handler().set_privileges(name, privs)
181         end
182 end
183
184 function minetest.auth_reload()
185         if minetest.get_auth_handler().reload then
186                 return minetest.get_auth_handler().reload()
187         end
188         return false
189 end
190
191