Note that I haven't tested this
Code: Select all
local account = {
store = {},
counter = 0
}
--
-- Generates a random string of length 32, you can ignore this function
--
function account.genSalt()
local Chars = {}
for Loop = 0, 255 do
Chars[Loop+1] = string.char(Loop)
end
local String = table.concat(Chars)
local Built = {['.'] = Chars}
local AddLookup = function(CharSet)
local Substitute = string.gsub(String, '[^'..CharSet..']', '')
local Lookup = {}
for Loop = 1, string.len(Substitute) do
Lookup[Loop] = string.sub(Substitute, Loop, Loop)
end
Built[CharSet] = Lookup
return Lookup
end
local function srandom(Length, CharSet)
-- Length (number)
-- CharSet (string, optional); e.g. %l%d for lower case letters and digits
local CharSet = CharSet or '.'
if CharSet == '' then
return ''
else
local Result = {}
local Lookup = Built[CharSet] or AddLookup(CharSet)
local Range = table.getn(Lookup)
for Loop = 1,Length do
Result[Loop] = Lookup[math.random(1, Range)]
end
return table.concat(Result)
end
end
return srandom(32, "%l%d")
end
--
-- Creates a new account
--
function account.new(pass)
account.counter = account.counter + 1
local salt = account.genSalt()
account.store[account.counter] = {
hash = minetest.get_password_hash(salt, pass),
salt = salt
}
account.save()
return account.counter
end
--
-- Checks that the given password is the right one
--
function account.checkPassword(id, given)
local stored = account.store[id]
local tocheck = minetest.get_password_hash(stored.salt, given)
return tocheck == stored.hash
end
--
-- Allows changing of password given old password
--
function account.changePassword(id, old, new)
local stored = account.store[id]
local tocheck = minetest.get_password_hash(stored.salt, old)
if tocheck == stored.hash then
local salt = account.genSalt()
stored.salt = salt
stored.hash = minetest.get_password_hash(salt, new)
account.save()
end
end
function account.init()
local file = io.open(minetest.get_worldpath() .. "/password_chest_passwords.txt", "r")
if file then
local from_file = minetest.deserialize(file:read("*all"))
file:close()
if type(from_file) == "table" then
account.store = from_file.store
account.counter = from_file.counter
end
end
end
function account.save()
local file = io.open(minetest.get_worldpath().."/password_chest_passwords.txt", "w")
if file then
file:write(minetest.serialize({
store = account.store,
counter = account.counter
}))
file:close()
end
end
account.init()
When a user sets their password on a new chest
Code: Select all
local entered_password = fields["password"]
local entered_password_verify = fields["password_ver"]
if entered_password == entered_password_verify then
local id = account.newAccount(entered_password)
meta:set_int("acc_id", id)
else
-- mismatching password and verify password
end
When you need to log a user in
Code: Select all
local id = meta:get_int("acc_id")
local entered_password = fields["password_old"]
if account.checkPassword(id, entered_password) then
-- password matches!
else
-- password doesn't match!
end
To change their password
Code: Select all
local id = meta:get_int("acc_id")
local pass_old = fields["password_old"]
local pass_new = fields["password_new"]
local pass_new_ver = fields["password_new_ver"]
if pass_new == pass_new_ver then
if account.changePassword(id, pass_old, pass_new) then
-- success
else
-- wrong old pass
end
else
-- mismatching password and verify password
end