auth.lua 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. -- Minetest: builtin/auth.lua
  2. --
  3. -- Builtin authentication handler
  4. --
  5. -- Make the auth object private, deny access to mods
  6. local core_auth = core.auth
  7. core.auth = nil
  8. core.builtin_auth_handler = {
  9. get_auth = function(name)
  10. assert(type(name) == "string")
  11. local auth_entry = core_auth.read(name)
  12. -- If no such auth found, return nil
  13. if not auth_entry then
  14. return nil
  15. end
  16. -- Figure out what privileges the player should have.
  17. -- Take a copy of the privilege table
  18. local privileges = {}
  19. for priv, _ in pairs(auth_entry.privileges) do
  20. privileges[priv] = true
  21. end
  22. -- If singleplayer, give all privileges except those marked as give_to_singleplayer = false
  23. if core.is_singleplayer() then
  24. for priv, def in pairs(core.registered_privileges) do
  25. if def.give_to_singleplayer then
  26. privileges[priv] = true
  27. end
  28. end
  29. -- For the admin, give everything
  30. elseif name == core.settings:get("name") then
  31. for priv, def in pairs(core.registered_privileges) do
  32. if def.give_to_admin then
  33. privileges[priv] = true
  34. end
  35. end
  36. end
  37. -- All done
  38. return {
  39. password = auth_entry.password,
  40. privileges = privileges,
  41. last_login = auth_entry.last_login,
  42. }
  43. end,
  44. create_auth = function(name, password)
  45. assert(type(name) == "string")
  46. assert(type(password) == "string")
  47. core.log('info', "Built-in authentication handler adding player '"..name.."'")
  48. return core_auth.create({
  49. name = name,
  50. password = password,
  51. privileges = core.string_to_privs(core.settings:get("default_privs")),
  52. last_login = -1, -- Defer login time calculation until record_login (called by on_joinplayer)
  53. })
  54. end,
  55. delete_auth = function(name)
  56. assert(type(name) == "string")
  57. local auth_entry = core_auth.read(name)
  58. if not auth_entry then
  59. return false
  60. end
  61. core.log('info', "Built-in authentication handler deleting player '"..name.."'")
  62. return core_auth.delete(name)
  63. end,
  64. set_password = function(name, password)
  65. assert(type(name) == "string")
  66. assert(type(password) == "string")
  67. local auth_entry = core_auth.read(name)
  68. if not auth_entry then
  69. core.builtin_auth_handler.create_auth(name, password)
  70. else
  71. core.log('info', "Built-in authentication handler setting password of player '"..name.."'")
  72. auth_entry.password = password
  73. core_auth.save(auth_entry)
  74. end
  75. return true
  76. end,
  77. set_privileges = function(name, privileges)
  78. assert(type(name) == "string")
  79. assert(type(privileges) == "table")
  80. local auth_entry = core_auth.read(name)
  81. if not auth_entry then
  82. auth_entry = core.builtin_auth_handler.create_auth(name,
  83. core.get_password_hash(name,
  84. core.settings:get("default_password")))
  85. end
  86. -- Run grant callbacks
  87. for priv, _ in pairs(privileges) do
  88. if not auth_entry.privileges[priv] then
  89. core.run_priv_callbacks(name, priv, nil, "grant")
  90. end
  91. end
  92. -- Run revoke callbacks
  93. for priv, _ in pairs(auth_entry.privileges) do
  94. if not privileges[priv] then
  95. core.run_priv_callbacks(name, priv, nil, "revoke")
  96. end
  97. end
  98. auth_entry.privileges = privileges
  99. core_auth.save(auth_entry)
  100. core.notify_authentication_modified(name)
  101. end,
  102. reload = function()
  103. core_auth.reload()
  104. return true
  105. end,
  106. record_login = function(name)
  107. assert(type(name) == "string")
  108. local auth_entry = core_auth.read(name)
  109. assert(auth_entry)
  110. auth_entry.last_login = os.time()
  111. core_auth.save(auth_entry)
  112. end,
  113. iterate = function()
  114. local names = {}
  115. local nameslist = core_auth.list_names()
  116. for k,v in pairs(nameslist) do
  117. names[v] = true
  118. end
  119. return pairs(names)
  120. end,
  121. }
  122. core.register_on_prejoinplayer(function(name, ip)
  123. if core.registered_auth_handler ~= nil then
  124. return -- Don't do anything if custom auth handler registered
  125. end
  126. local auth_entry = core_auth.read(name)
  127. if auth_entry ~= nil then
  128. return
  129. end
  130. local name_lower = name:lower()
  131. for k in core.builtin_auth_handler.iterate() do
  132. if k:lower() == name_lower then
  133. return string.format("\nCannot create new player called '%s'. "..
  134. "Another account called '%s' is already registered. "..
  135. "Please check the spelling if it's your account "..
  136. "or use a different nickname.", name, k)
  137. end
  138. end
  139. end)
  140. --
  141. -- Authentication API
  142. --
  143. function core.register_authentication_handler(handler)
  144. if core.registered_auth_handler then
  145. error("Add-on authentication handler already registered by "..core.registered_auth_handler_modname)
  146. end
  147. core.registered_auth_handler = handler
  148. core.registered_auth_handler_modname = core.get_current_modname()
  149. handler.mod_origin = core.registered_auth_handler_modname
  150. end
  151. function core.get_auth_handler()
  152. return core.registered_auth_handler or core.builtin_auth_handler
  153. end
  154. local function auth_pass(name)
  155. return function(...)
  156. local auth_handler = core.get_auth_handler()
  157. if auth_handler[name] then
  158. return auth_handler[name](...)
  159. end
  160. return false
  161. end
  162. end
  163. core.set_player_password = auth_pass("set_password")
  164. core.set_player_privs = auth_pass("set_privileges")
  165. core.remove_player_auth = auth_pass("delete_auth")
  166. core.auth_reload = auth_pass("reload")
  167. local record_login = auth_pass("record_login")
  168. core.register_on_joinplayer(function(player)
  169. record_login(player:get_player_name())
  170. end)