auth.lua 5.8 KB

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