Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local protocol = "sync_protocol"
- local clientPath = "/disk/users/"
- local MAX_ATTEMPTS = 3 -- Maximum number of incorrect password attempts allowed
- local LOCKOUT_TIME = 30 -- Lockout time in seconds after reaching maximum attempts
- local USERS_FOLDER = "/disk/users/"
- local ERROR_FOLDER = "/disk/error/"
- local BSOD_PROGRAM = "BSOD.lua"
- local CURRENT_USER_FILE = ".currentusr"
- local SHOW_ALL_USERS_FILE = "/disk/config/security/login/ShowAllUsers.cfg"
- -- Utility function to draw a centered popup window with a text-based border
- local function drawPopupWindow(headerText, contentLines, windowWidth, windowHeight)
- term.clear()
- local w, h = term.getSize()
- -- Determine dimensions of the popup
- local maxLength = #headerText
- for _, line in ipairs(contentLines) do
- maxLength = math.max(maxLength, #line)
- end
- windowWidth = windowWidth or (maxLength + 4)
- windowHeight = windowHeight or (#contentLines + 4)
- local xStart = math.floor(w / 2 - windowWidth / 2)
- local yStart = math.floor(h / 2 - windowHeight / 2)
- -- Draw border with animation
- term.setCursorPos(xStart, yStart)
- term.write("+" .. string.rep("-", windowWidth - 2) .. "+")
- for i = 1, windowHeight - 2 do
- term.setCursorPos(xStart, yStart + i)
- term.write("|" .. string.rep(" ", windowWidth - 2) .. "|")
- os.sleep(0.05)
- end
- term.setCursorPos(xStart, yStart + windowHeight - 1)
- term.write("+" .. string.rep("-", windowWidth - 2) .. "+")
- -- Draw header
- term.setCursorPos(xStart + 2, yStart + 1)
- term.write(headerText)
- -- Draw content
- for i, line in ipairs(contentLines) do
- term.setCursorPos(xStart + 2, yStart + 1 + i + 1)
- term.write(line)
- os.sleep(0.05)
- end
- end
- -- Function to list all users
- local function listUsers()
- local users = fs.list(USERS_FOLDER)
- local usernames = {}
- for _, user in ipairs(users) do
- local userDir = fs.combine(USERS_FOLDER, user)
- if fs.isDir(userDir) then
- table.insert(usernames, user)
- end
- end
- return usernames
- end
- -- Function to handle user selection from the list
- local function drawUsersScreen(usernames, selectedIndex)
- local contentLines = {}
- for i, username in ipairs(usernames) do
- if i == selectedIndex then
- table.insert(contentLines, "> " .. username)
- else
- table.insert(contentLines, " " .. username)
- end
- end
- drawPopupWindow("Select your user account:", contentLines, 30, #contentLines + 4)
- end
- -- Function to select a user from the list interactively
- local function selectUserFromList()
- local usernames = listUsers()
- local selectedIndex = 1
- while true do
- drawUsersScreen(usernames, selectedIndex)
- local event, key = os.pullEvent("key")
- if key == keys.up then
- selectedIndex = math.max(1, selectedIndex - 1)
- elseif key == keys.down then
- selectedIndex = math.min(#usernames, selectedIndex + 1)
- elseif key == keys.enter then
- return usernames[selectedIndex]
- end
- end
- end
- -- Function to get user credentials
- local function getUserCredentials(username)
- local passwordFile = fs.combine(USERS_FOLDER .. username, "password.txt")
- if fs.exists(passwordFile) then
- local file = fs.open(passwordFile, "r")
- local storedPassword = file.readLine()
- file.close()
- return storedPassword
- else
- return nil
- end
- end
- -- Function to save the current user
- local function saveCurrentUser(username)
- if fs.exists(CURRENT_USER_FILE) then
- fs.delete(CURRENT_USER_FILE)
- end
- local file = fs.open(CURRENT_USER_FILE, "w")
- file.write(username)
- file.close()
- end
- -- Function to lock out user
- local function lockoutUser(username)
- local disabledFile = fs.combine(USERS_FOLDER .. username, "disabled.txt")
- local file = fs.open(disabledFile, "w")
- file.close()
- end
- -- Function to check if user is disabled
- local function checkDisabled(username)
- local disabledFile = fs.combine(USERS_FOLDER .. username, "disabled.txt")
- return fs.exists(disabledFile)
- end
- -- Function to check credentials for user login
- local function checkCredentials(username)
- if checkDisabled(username) then
- drawPopupWindow("Doggy OS Account Lockout Service", {"This user account has been disabled."})
- os.sleep(2)
- return false
- end
- local storedPassword = getUserCredentials(username)
- if not storedPassword then
- drawPopupWindow("Doggy OS Login Failure", {"User account doesn't exist or is corrupted."})
- os.sleep(3)
- return false
- end
- local attempts = 0
- repeat
- drawPopupWindow("Login to Doggy OS", {"Username: " .. username, "Attempts left: " .. (MAX_ATTEMPTS - attempts), "", "Enter password:"})
- term.setCursorPos(1, select(2, term.getSize()))
- term.write(":")
- local enteredPassword = read("*")
- attempts = attempts + 1
- if enteredPassword == storedPassword then
- saveCurrentUser(username)
- return true
- else
- drawPopupWindow("Access Denied", {"Incorrect Password"})
- os.sleep(2)
- end
- until attempts >= MAX_ATTEMPTS
- lockoutUser(username)
- drawPopupWindow("Doggy OS Account Lockout Service", {"Too many incorrect attempts."})
- os.sleep(2)
- return false
- end
- -- Synchronization related code
- local function getFileHash(filePath)
- if not fs.exists(filePath) then return nil end
- local f = fs.open(filePath, "r")
- local content = f.readAll()
- f.close()
- return textutils.serialize(content)
- end
- local function getFileList(path)
- local files = {}
- local function scan(dir)
- for _, file in pairs(fs.list(dir)) do
- local fullPath = dir .. file
- if fs.isDir(fullPath) then
- scan(fullPath .. "/")
- else
- files[fullPath:sub(#clientPath + 1)] = getFileHash(fullPath)
- end
- end
- end
- scan(path)
- return files
- end
- local function syncFiles(username)
- local userPath = clientPath .. username .. "/"
- -- Ensure the username directory exists
- if not fs.exists(userPath) or not fs.isDir(userPath) then
- print("Error: User directory '" .. username .. "' not found.")
- return
- end
- -- Open the modem
- rednet.open(peripheral.getName(peripheral.find("modem") or error("No modem found")))
- -- Get server ID from the .domaincontrollerID file
- local function getServerID()
- local filePath = ".domaincontrollerID"
- if not fs.exists(filePath) then
- print("Error: .domaincontrollerID file not found.")
- return nil
- end
- -- Read the server ID from the file
- local file = fs.open(filePath, "r")
- local serverID = tonumber(file.readAll())
- file.close()
- -- If the server ID is valid, return it
- if serverID then
- return serverID
- else
- print("Error: Invalid server ID in .domaincontrollerID.")
- return nil
- end
- end
- local serverID = getServerID()
- if not serverID then return end
- -- Perform sync
- print("Syncing user: " .. username .. " with server " .. serverID)
- -- Send file list to server
- rednet.send(serverID, { action = "sync_request", user = username, files = getFileList(userPath) }, protocol)
- local id, response = rednet.receive(protocol, 5)
- if id == serverID and response.action == "sync_response" then
- -- Download files to client
- for file, content in pairs(response.files_to_client or {}) do
- local filePath = userPath .. file
- local f = fs.open(filePath, "w")
- f.write(content)
- f.close()
- print("Downloaded:", file)
- end
- -- Upload files from client
- rednet.send(serverID, { action = "sync_upload", user = username, files_to_server = getFileList(userPath) }, protocol)
- else
- print("No response from server.")
- end
- print("Sync complete.")
- end
- -- Main function for login and sync
- local function main()
- term.setTextColor(colors.white)
- term.setBackgroundColor(colors.black)
- term.clear()
- local username
- if fs.exists(SHOW_ALL_USERS_FILE) then
- username = selectUserFromList()
- else
- drawPopupWindow("Protected by Doggy OS Security", {"Enter username:"})
- username = read()
- end
- -- Attempt login
- if not checkCredentials(username) then
- return
- end
- -- Sync user data after login
- syncFiles(username)
- shell.run("/disk/os/gui")
- end
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement