147 lines
4.6 KiB
Lua
147 lines
4.6 KiB
Lua
local MP = minetest.get_modpath("forgot_password")
|
|
local S = minetest.get_translator("forgot_password")
|
|
local storage = minetest.get_mod_storage()
|
|
local settings = minetest.settings
|
|
|
|
local http = minetest.request_http_api and minetest.request_http_api() or error("Please allow forgot_password to access the Minetest HTTP API!")
|
|
|
|
local url = settings:get("forgot_password.http_url") or error("Please set forgot_password.http_url!")
|
|
local token = settings:get("forgot_password.http_token") or error("Please set forgot_password.http_token!")
|
|
|
|
local confirm = {
|
|
template_path = settings:get("forgot_password.confirm_email_template") or MP .. "/email/confirm.txt",
|
|
template = "", -- Load it later
|
|
subject = settings:get("forgot_password.confirm_email_subject") or "Confirm your Minetest account email address"
|
|
}
|
|
|
|
local passwd = {
|
|
template_path = settings:get("forgot_password.passwd_email_template") or MP .. "/email/passwd.txt",
|
|
template = "", -- Load it later
|
|
subject = settings:get("forgot_password.passwd_email_subject") or "Recover your Minetest account"
|
|
}
|
|
|
|
do -- Load confirm template
|
|
local f = io.open(confirm.template_path)
|
|
if f then
|
|
confirm.template = f:read("*a")
|
|
else
|
|
error("forgot_password.confirm_email_template contains an invalid value.")
|
|
end
|
|
end
|
|
|
|
do -- Load password recover template
|
|
local f = io.open(passwd.template_path)
|
|
if f then
|
|
passwd.template = f:read("*a")
|
|
else
|
|
error("forgot_password.passwd_email_template contains an invalid value.")
|
|
end
|
|
end
|
|
|
|
local charset = {} do -- [0-9a-zA-Z]
|
|
for c = 48, 57 do table.insert(charset, string.char(c)) end
|
|
for c = 65, 90 do table.insert(charset, string.char(c)) end
|
|
for c = 97, 122 do table.insert(charset, string.char(c)) end
|
|
end
|
|
|
|
local function randomString(length)
|
|
if not length then length = 15 end
|
|
if length <= 0 then return '' end
|
|
return randomString(length - 1) .. charset[math.random(1, #charset)]
|
|
end
|
|
|
|
function substparam(str,key,value)
|
|
return string.gsub(str,"{" .. key .. "}",value)
|
|
end
|
|
|
|
function confirm.get_email(name,email,confirm_code)
|
|
local RSTR = confirm.template
|
|
RSTR = substparam(RSTR,"name",name)
|
|
RSTR = substparam(RSTR,"email",email)
|
|
RSTR = substparam(RSTR,"confirm_code",confirm_code)
|
|
return RSTR
|
|
end
|
|
|
|
function passwd.get_email(name,ip,reset_login_name)
|
|
local RSTR = passwd.template
|
|
RSTR = substparam(RSTR,"name",name)
|
|
RSTR = substparam(RSTR,"ip",ip)
|
|
RSTR = substparam(RSTR,"reset_login_name",reset_login_name)
|
|
return RSTR
|
|
end
|
|
|
|
function sendmail(to,subject,body)
|
|
return http.fetch_async({
|
|
url = url,
|
|
method = "POST",
|
|
data = {
|
|
token = token,
|
|
to = to,
|
|
subject = subject,
|
|
body = body,
|
|
},
|
|
user_agent = "Minetest-Forget-Password",
|
|
multipart = true
|
|
})
|
|
end
|
|
|
|
-- Set Email
|
|
minetest.register_chatcommand("set_email",{
|
|
description = S("Set email address for password recovery"),
|
|
param = S("<email address>"),
|
|
func = function(name,param)
|
|
if not param:match("^[%w.]+@%w+%.%w+$") then
|
|
return false, "Invalid email address!"
|
|
end
|
|
local confirm_token = randomString()
|
|
storage:set_string("confirm-" .. name,confirm_token)
|
|
storage:set_string("tmp-email-" .. name,param)
|
|
local body = confirm.get_email(name,param,confirm_token)
|
|
sendmail(param,confirm.subject,body)
|
|
return true, "Confirm email sent."
|
|
end,
|
|
})
|
|
minetest.register_chatcommand("confirm_email",{
|
|
description = S("Confirm email"),
|
|
param = S("<confirm code>"),
|
|
func = function(name,param)
|
|
local confirm_token = storage:get("confirm-" .. name)
|
|
if param == confirm_token then
|
|
local tmp_email = storage:get("tmp-email-" .. name)
|
|
if not tmp_email then
|
|
return false, "Please run /set_email first!"
|
|
end
|
|
storage:set_string("email-" .. name,tmp_email)
|
|
return true, "Email set."
|
|
end
|
|
return false, "Code does not match."
|
|
end,
|
|
})
|
|
|
|
-- Password recover
|
|
minetest.register_on_prejoinplayer(function(name,ip)
|
|
minetest.log("Processing player" .. name)
|
|
local t = {}
|
|
for str in string.gmatch(name, "([^*-]+)") do
|
|
table.insert(t,str)
|
|
end
|
|
if t[2] == "FP" then
|
|
-- Forget password!
|
|
local email = storage:get("email-" .. t[1])
|
|
if email then
|
|
local reset_login_token = randomString()
|
|
storage:set_string("recover-" .. reset_login_token,t[1])
|
|
local reset_login_name = reset_login_token
|
|
local body = passwd.get_email(t[1],ip,reset_login_name)
|
|
sendmail(email,passwd.subject,body)
|
|
end
|
|
return "Password reset email sent."
|
|
end
|
|
local sname = storage:get("recover-" .. name)
|
|
if sname and sname ~= "" then
|
|
storage:set_string("recover-" .. name,"")
|
|
minetest.get_auth_handler().set_password(sname,minetest.get_password_hash(sname, name))
|
|
return "Password of " .. sname .. " set to " .. name .. ". \nPLEASE CHANGE YOUR PASSWORD AFTER LOGIN!"
|
|
end
|
|
end)
|