Advertisement
Guest User

server.lua

a guest
Dec 10th, 2018
138
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 9.61 KB | None | 0 0
  1. local channels = {
  2.   atm = 1,
  3.   db = 2,
  4. }
  5.  
  6. os.loadAPI("/common.lua")
  7. os.loadAPI("/sha256.lua")
  8.  
  9. local database = {}
  10. local dbpath = "/bank.db"
  11. local logpath = "/bank.log"
  12. local maintenance_pass = "test"
  13. local modem = peripheral.find("modem")
  14.  
  15. local function loadDB(path)
  16.   local ret = {}
  17.   if fs.exists(path) then
  18.     local f = fs.open(path, "r")
  19.     local c = f.readAll()
  20.     ret = textutils.unserialise(c)
  21.     if not ret then return false end
  22.   end
  23.   return ret
  24. end
  25. local function saveDB(path, db)
  26.   local f = fs.open(path, "w")
  27.   local s = textutils.serialise(db)
  28.   f.write(s)
  29.   f.close()
  30.   return true
  31. end
  32. local function printHeader(str, ny)
  33.   local w, h = term.getSize()
  34.   local x, y = term.getCursorPos()
  35.   term.setCursorPos(math.ceil(w/2) - math.floor(#str/2), ny or 1)
  36.   term.clearLine()
  37.   term.write(str)
  38.   term.setCursorPos(x, y)
  39. end
  40. local logfile = fs.open(logpath, "a")
  41. local function log(top, str, nosave)
  42.   local form = (top and ("["..top.."] ") or "")..(str)
  43.   print(form)
  44.   printHeader("Database running with "..dbpath)
  45.   if not nosave then
  46.     logfile.writeLine(form)
  47.     logfile.flush()
  48.   end
  49. end
  50.  
  51. database = loadDB(dbpath)
  52. saveDB(dbpath, database)
  53.  
  54. modem.open(channels.db)
  55. term.clear()
  56. term.setCursorPos(1,2)
  57. logfile.writeLine()
  58. log("Init", "Database started")
  59.  
  60. while true do
  61.   local event, side, chan, reply, msg = os.pullEvent()
  62.   if event == "modem_message" and chan == channels.db and reply == channels.atm and type(msg) == "table" then
  63.  
  64.     if msg[1] == "auth" then
  65.       local user = msg[2]:lower()
  66.       local userdata = database[user]
  67.       if userdata then
  68.         modem.transmit(reply, channels.db, {true, userdata.salt})
  69.         local resp = common.waitForMsg(reply, 2)
  70.         if resp and resp[1] then
  71.           local ok = resp[2] == userdata.passwd
  72.           modem.transmit(reply, channels.db, {ok, not ok and "Wrong password" or nil})
  73.           log("Auth", (ok and "Valid" or "Invalid").." auth: "..user)
  74.         else log("Auth", user.." timed out")
  75.         end
  76.       else
  77.         log("Auth", "User not found: "..user)
  78.         modem.transmit(reply, channels.db, {false, "User not found"})
  79.       end
  80.  
  81.     elseif msg[1] == "register" then
  82.       local user = msg[2]:lower()
  83.       local ok = true
  84.       if user:find("%s") then ok = false log("Register", "Tried registering with a space: "..user) modem.transmit(reply, channels.db, {false, "Username cannot contain spaces"}) end
  85.       if database[user] then ok = false log("Register", "User already exists: "..user) modem.transmit(reply, channels.db, {false, "User already exists"}) end
  86.       if ok then
  87.         local salt = common.genSalt(16)
  88.         modem.transmit(reply, channels.db, {true, salt})
  89.         local r = common.waitForMsg(reply, 2)
  90.         if r and r[1] and type(r[2]) == "string" and #r[2] == 64 then
  91.           database[user] = {}
  92.           database[user].balance = 0
  93.           database[user].passwd = r[2]
  94.           database[user].salt = salt
  95.           saveDB(dbpath, database)
  96.           log("Register", user.." created")
  97.           modem.transmit(reply, channels.db, {true})
  98.         else
  99.           log("Register", user.." timed out")
  100.         end
  101.       end
  102.  
  103.     elseif msg[1] == "balance" then
  104.       local user = msg[2]:lower()
  105.       local userdata = database[user]
  106.       if msg[3] == userdata.passwd then
  107.         modem.transmit(reply, channels.db, {true, userdata.balance})
  108.         log("Balance", "Sent balance: "..user)
  109.       else
  110.         modem.transmit(reply, channels.db, {false, "Invalid hash"})
  111.         log("Balance", "Invalid hash from: "..user)
  112.       end
  113.  
  114.     elseif msg[1] == "transfer" then
  115.       local user = msg[2]:lower()
  116.       local recip = msg[4]:lower()
  117.       local hash = msg[3]
  118.       local amt = tonumber(msg[5]) or math.huge
  119.       amt = math.abs(amt)
  120.       local userdat = database[user]
  121.       local recipdat = database[recip]
  122.       local ok = true
  123.  
  124.       if not recipdat then ok = false log("Transfer", user.." tried to send to invalid: "..recip) modem.transmit(reply, channels.db, {false, "Recipient doesn't exist"}) end
  125.       if userdat.passwd ~= hash then ok = false log("Transfer", "Invalid hash from: "..user) modem.transmit(reply, channels.db, {false, "Invalid hash"}) end
  126.       if userdat.balance < amt then ok = false log("Transfer", user.." tried to send "..amt.." but has "..userdat.balance.." to "..recip) modem.transmit(reply, channels.db, {false, "Insufficent funds"}) end
  127.       if ok then
  128.         database[user].balance = userdat.balance - amt
  129.         database[recip].balance = recipdat.balance + amt
  130.         saveDB(dbpath, database)
  131.         modem.transmit(reply, channels.db, {true, userdat.balance})
  132.         log("Transfer", user.." transfered "..amt.." to "..recip)
  133.       end
  134.     end
  135.  
  136.   elseif event == "key" and side == keys.enter then
  137.     log("Admin", "Enter password")
  138.     write("> ")
  139.     local pswd = read("*")
  140.     if pswd == maintenance_pass then
  141.       log("Admin", "Entering maintenance mode")
  142.       while true do
  143.         write("> ")
  144.         local cmd = read()
  145.         cmd = common.split(cmd, "%s")
  146.         if cmd[1] == "set" then
  147.           local user = cmd[2]
  148.           local amt = tonumber(cmd[3]) or 0
  149.           if type(user) ~= "string" or type(amt) ~= "number" then
  150.             log("Error", "Usage: set <user> <balance>")
  151.           else
  152.             user = user:lower()
  153.             if database[user] then
  154.               database[user].balance = amt
  155.               saveDB(dbpath, database)
  156.               log("Admin", "Set "..user.." balance to "..amt)
  157.             else
  158.               log("Admin", "Cannot set balance of "..user)
  159.             end
  160.           end
  161.  
  162.         elseif cmd[1] == "add" then
  163.           local user = cmd[2]
  164.           local amt = tonumber(cmd[3]) or 0
  165.           if type(user) ~= "string" or type(amt) ~= "number" then
  166.             log("Error", "Usage: add <user> <amount>")
  167.           else
  168.             user = user:lower()
  169.             if database[user] then
  170.               database[user].balance = database[user].balance + amt
  171.               saveDB(dbpath, database)
  172.               log("Admin", (amt >= 0 and "Added " or "Removed ")..amt.." to "..user.."'s balance")
  173.             else
  174.               log("Admin", "Cannot add to balance of "..user)
  175.             end
  176.           end
  177.  
  178.         elseif cmd[1] == "create" then
  179.           local user = cmd[2]
  180.           if type(user) ~= "string" then
  181.             log("Error", "Usage: create <user>")
  182.           else
  183.             user = user:lower()
  184.             local ok = true
  185.             if user:find("%s") then ok = false log("Admin", "Tried registering with a space: "..user) end
  186.             if database[user] then ok = false log("Admin", "User already exists: "..user) end
  187.             if ok then
  188.               log("Admin", "Enter password: ")
  189.               write("> ")
  190.               local pass = read()
  191.               local salt = common.genSalt(16)
  192.               local hash = sha256.pbkdf2(pass, salt, 64):toHex()
  193.               database[user] = {}
  194.               database[user].balance = 0
  195.               database[user].passwd = hash
  196.               database[user].salt = salt
  197.               saveDB(dbpath, database)
  198.               log("Admin", user.." created")
  199.             end
  200.           end
  201.  
  202.         elseif cmd[1] == "delete" then
  203.           local user = cmd[2]
  204.           if type(user) ~= "string" then
  205.             log("Error", "Usage: delete <user>")
  206.           else
  207.             user = user:lower()
  208.             if database[user] then
  209.               database[user] = nil
  210.               saveDB(dbpath, database)
  211.               log("Admin", user.." deleted from database")
  212.             else
  213.               log("Admin", "Tried to delete invalid user: "..user)
  214.             end
  215.           end
  216.  
  217.         elseif cmd[1] == "recover" then
  218.           local user = cmd[2]
  219.           if type(user) ~= "string" then
  220.             log("Error", "Usage: recover <user>")
  221.           else
  222.             user = user:lower()
  223.             if database[user] then
  224.               log("Admin", "Enter new password: ")
  225.               write("> ")
  226.               local pass = read()
  227.               local salt = common.genSalt(16)
  228.               local hash = sha256.pbkdf2(pass, salt, 64):toHex()
  229.               database[user].passwd = hash
  230.               database[user].salt = salt
  231.               saveDB(dbpath, database)
  232.               log("Admin", user.." password changed")
  233.             else
  234.               log("Admin", user.." does not exists")
  235.             end
  236.           end
  237.  
  238.         elseif cmd[1] == "list" then
  239.           local users = {}
  240.           for user, userdat in pairs(database) do
  241.             log(nil, user..": "..userdat.balance, true)
  242.           end
  243.         elseif cmd[1] == "help" then
  244.           log(nil, "set <user> <balance> \16 Sets a user balance", true)
  245.           log(nil, "add <user> <amount> \16 Add/Remove from user balance", true)
  246.           log(nil, "create <user> \16 Adds account to database", true)
  247.           log(nil, "delete <user> \16 Removes account from database", true)
  248.           log(nil, "recover <user> \16 Changes account's password", true)
  249.           log(nil, "list \16 Lists registered accounts", true)
  250.           log(nil, "quit \16 Quits maintenance mode", true)
  251.           log(nil, "stop \16 Stops the database", true)
  252.  
  253.         elseif cmd[1] == "quit" then break
  254.         elseif cmd[1] == "stop" then return
  255.  
  256.         else log("Command", "Invalid command: "..(cmd[1] or ""), true)
  257.         end
  258.         repeat event, side = os.pullEvent("key") until side == keys.enter
  259.       end
  260.       log("Admin", "Exiting maintenance")
  261.     else
  262.       log("Admin", "Wrong password")
  263.     end
  264.   end
  265. end
  266. log("Admin", "Database shutting down")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement