This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
TechMasterGeneral's profile picture

User permissions

Started by TechMasterGeneral, 14 February 2014 - 08:24 AM
TechMasterGeneral #1
Posted 14 February 2014 - 09:24 AM
So…. I have another question to ask about tables…
I want to make a user permissions system to control adding and deleting users… I have the adding and deleting part down… but i need to know if i can add permissions to the same key/value pair as the username and password or if i have to make another table… I also need help checking the permissions… here is the code i have so far…
Spoiler


--[[ ICBM missile control panel by LuaCrawler
This goes with the door and launch controller for it to work.

for automatic load change the name of the file to startup and remove the extension.

]]

-- Variables
local delay = 5
local modem = peripheral.wrap("top")
local passwd = "passwd"
local server = 10
local rChan = tonumber(os.getComputerID())
local users = {
	["Admin"] = "password",
}
local userPerm = {
	["Admin"] = "admin"
}

local logo = {
}

local function changePass()




-- Startup Function
local function startup()
	term.clear()
	term.setCursorPos(1,1)
	term.setCursorPos(18,8)
	term.setTextColor(colors.lime)
	print("MissileCraft 1.04")
	term.setCursorPos(18,9)
	print("'Speedy Skeleton'")
	sleep(5)
	term.clear()
	term.setCursorPos(1,1)
	term.setTextColor(colors.white)
	modem.open(tonumber(os.getComputerID()))

end
-- Actual program run
startup()
while true do
	term.clear()
	term.setCursorPos(1, 1)
	textutils.slowPrint("Enter username:", 10)
	local cmd = read()
-- Now check store password as variable
	term.clear()
	term.setCursorPos(1, 1)
	textutils.slowPrint("Enter your password", 10)
	local passwd = read()
	for k,v in pairs(users) do
		if cmd == k and passwd == v then
			term.clear()
			term.setCursorPos(1,1)
			term.setTextColor(colors.red)
			print("ICBM launch system V. 1.0")
			term.setTextColor(colors.white)
			print("What would you like to do?")
			write("> ")
			local cmd2 = read()

			if cmd2 == "exit" then
				return
			elseif cmd2 == "launch missile" or cmd2 == "Launch Missile" then
				os.loadAPI("/LoadBar")
				local bar = LoadBar.init(LoadBar.STANDARD, logo, 10, 30, 14, colors.red, nil, nil, nil )
				local function doStuff()
					bar:setMessage( "Loading..." )
					for i = 0, 9 do
						sleep(0.5)
						bar:triggerUpdate("Initializing component("..(bar:getCurrentProgress()+1).."/10)")
					end
					bar:triggerUpdate("Done!")
				end
				local function doBar()
					bar:run( true )
				end
				parallel.waitForAll( doBar, doStuff )
				term.clear()
				term.setBackgroundColor(colors.gray)
				term.setCursorPos(1, 1)
				for i = 1, 19 do
					print("													  ")
				end
				term.setTextColor(colors.yellow)
				term.setCursorPos(1, 1)
				textutils.slowPrint("Remote missile launch system")
				textutils.slowPrint("Usage: launch <label>", 15)
				term.setTextColor(colors.white)
				lSilo = read()
				if lSilo == "exit" or lSilo == "quit" then
					break
				else
					modem.transmit(server, rChan, lSilo)
				end
			else
				if cmd2 == "open" or cmd2 == "open door" then
					term.setTextColor(colors.green)
					print("Door opened")
					modem.transmit(3,1, cmd2)
					term.setTextColor(colors.white)
				elseif cmd2 == "close" or cmd2 == "close door" then
					modem.transmit(3,1, cmd2)
					term.setTextColor(colors.green)
					print("Door closed")
					term.setTextColor(colors.white)
				end
			end

			function save(table)
				local file = fs.open("users.txt", "w")
				file.write(textutils.serialize(users))
				file.close()
			end

			if cmd2 == "add user" then
				print("Enter your username for verification.")
				uName = read()
				for k,v in pairs(userPerm) do
					if k == uName and v == "admin" or v == "moderator" then
						print( "Enter your password "..k )
						pass = read()
						if uName == k and pass == v then
							term.setTextColor(colors.gray)
							textutils.slowPrint("Enter the username: ")
							usr = read()
							textutils.slowPrint("Enter the password: ")
							pass = read()
							users[usr] = pass
							save(users)
							print("What permissions should the user have:")
							textutils.slowPrint("admin, moderator, or user")
							perm = read()
							userPerm[usr] = perm
							term.setTextColor(colors.white)
							print("User created!")

						elseif k == not uName and v == not pass then
							print("You don't have enough permissions!")
						end
					end
				end
			elseif cmd2 == "remove user" then
				print("Enter username for verification")
				uName2 = read()
				for k,v in pairs(userPerm) do
					if k == uName2 and v == "admin" or v == "moderator" then
						print("Enter your password "..k )
						pass2 = read()
						if uName2 == k and pass2 == v then
							textutils.slowPrint("Enter the username you want to delete: ")
							delUsr = read()
							users[delUsr] = nil
							save(users)
							userPerm[delUsr] = nil
							print("User Removed!")
						end
					end
				end
			else
				if cmd2 == "list users" then
					for k,v in pairs(users) do
						print(k.. " : " ..v)
					end
				end
			end		
			if cmd == not k and pass == not v or cmd == k and pass == not v then
				term.setTextColor(colors.red)
				print("Incorrect password! Logging failed attempt!")
				file = fs.open("/etc/log.txt", "w")
				rFile = fs.open("/etc/log.txt", "a")
				fExist = fs.exists("/etc/log.txt")
				if fExist == false then
					file:write("Failed login attempt on "..os.time())
				elseif fExist == true then
					rFile:write("Failed login attempt on "..os.time())
				end
			end
		end
	end

	os.startTimer(delay)
	while true do
		local evt, p1, p2, p3, p4, p5 = os.pullEvent()
		if evt == "timer" then
			break
		elseif evt == "modem_message" then
			print("Message from:"..p2)
			print(p4)
		end
	end
end

You can comment on certain lines with this website:
http://chopapp.com/#hzbgpo28


Nevermind… doesn't work for some reason
Edited on 14 February 2014 - 08:27 AM
Bomb Bloke #2
Posted 14 February 2014 - 11:28 AM
Say you take these tables:

local users = {
        ["Admin"] = "password",
        ["JoeUser"] = "anotherPassword"
}
local userPerm = {
        ["Admin"] = "admin",
        ["JoeUser"] = "user"
}

… and redefine them like this:

local users = {
        ["Admin"] = {["password"] = "password", ["permissions"] = "admin"},
        ["JoeUser"] = {["password"] = "anotherPassword", ["permissions"] = "user"}
}

Every index in the "users" table now points to another table.

This allows you to eg get the password for "Admin" by checking the value of:

users["Admin"].password

So say you had a username stored in the variable "curUser", and you wanted to know if that user existed, you'd just do:

if users[curUser] then
        -- User exists.
else
        -- User does not exist.
end

And if you wanted to compare their permissions, you'd do something like:

if users[curUser].permissions == "admin" then ...

Edit: Note that you can't index into a table that doesn't exist. If a username isn't in your users table, then attempting to check their eg password will cause your script to error out. Check that the user's in the table first, then check what their password/permissions/whatever are.
Edited on 14 February 2014 - 10:31 AM
TechMasterGeneral #3
Posted 14 February 2014 - 06:21 PM
Say you take these tables:

local users = {
		["Admin"] = "password",
		["JoeUser"] = "anotherPassword"
}
local userPerm = {
		["Admin"] = "admin",
		["JoeUser"] = "user"
}

… and redefine them like this:

local users = {
		["Admin"] = {["password"] = "password", ["permissions"] = "admin"},
		["JoeUser"] = {["password"] = "anotherPassword", ["permissions"] = "user"}
}

Every index in the "users" table now points to another table.

This allows you to eg get the password for "Admin" by checking the value of:

users["Admin"].password

So say you had a username stored in the variable "curUser", and you wanted to know if that user existed, you'd just do:

if users[curUser] then
		-- User exists.
else
		-- User does not exist.
end

And if you wanted to compare their permissions, you'd do something like:

if users[curUser].permissions == "admin" then ...

Edit: Note that you can't index into a table that doesn't exist. If a username isn't in your users table, then attempting to check their eg password will cause your script to error out. Check that the user's in the table first, then check what their password/permissions/whatever are.

So then i wouldn't need the

for k,v in pairs(users) do
i would just do

if users[curUser] then
--Run code here
?
Bomb Bloke #4
Posted 14 February 2014 - 06:44 PM
Exactly.
TechMasterGeneral #5
Posted 14 February 2014 - 08:20 PM
So then to add a user with their permissions to the table i would need to do:

users[usr] = pass, perm
?
TechMasterGeneral #6
Posted 14 February 2014 - 08:38 PM
What would be the best way to keep from starting a loop all over again… cus i want if a user gets a password wrong i don't want it to log out… also… would it be better if i made all the sections of if code to be functions… i'm thinking it may be better to if this param is true then do this function… if not then do this function..
Bomb Bloke #7
Posted 15 February 2014 - 01:28 AM
So then to add a user with their permissions to the table i would need to do:
users[usr] = pass, perm
?
No, that's not right - the idea is that you store a table against users[user], so you end up with a collection of tables in a table. In your code block there you've just put a list of variables in it (only the first of which would actually be captured).

You could do it like this:

users[usr] = {["password"] = pass, ["permissions"] = perm}

Or like this:

users[usr] = {}
users[usr].password = pass
users[usr].permissions = perm

Or a variety of other ways, which boil down to rephrasings of the same thing - "put a table in this table, fill it with these values".

What would be the best way to keep from starting a loop all over again… cus i want if a user gets a password wrong i don't want it to log out…
Don't quite getcha here. If a user fails to log in, then surely they'd expect to be logged out? What are you intending to happen instead?

also… would it be better if i made all the sections of if code to be functions… i'm thinking it may be better to if this param is true then do this function… if not then do this function..
Go with whatever you find easier to read and maintain.

Personally I dislike using functions unless doing so will actually decrease the length of my script - for example, if I want to run the same code twice under different circumstances, it'll generally get dumped into a function. A classic example would be if you want to write text in a special way (eg centered) on a regular basis.

On some occasions, functions can be handy for escaping loops - say you're nested three levels deep, and you suddenly wish to break out of them all. It can be done, but it's not as simple as inserting three break statements (and ComputerCraft's Lua lacks a "goto")! But if those loops are isolated away inside a function, then you need only return from that in order to escape them all.
TechMasterGeneral #8
Posted 15 February 2014 - 09:47 AM
So then to add a user with their permissions to the table i would need to do:
users[usr] = pass, perm
?
No, that's not right - the idea is that you store a table against users[user], so you end up with a collection of tables in a table. In your code block there you've just put a list of variables in it (only the first of which would actually be captured).

You could do it like this:

users[usr] = {["password"] = pass, ["permissions"] = perm}

Or like this:

users[usr] = {}
users[usr].password = pass
users[usr].permissions = perm

Or a variety of other ways, which boil down to rephrasings of the same thing - "put a table in this table, fill it with these values".

What would be the best way to keep from starting a loop all over again… cus i want if a user gets a password wrong i don't want it to log out…
Don't quite getcha here. If a user fails to log in, then surely they'd expect to be logged out? What are you intending to happen instead?

also… would it be better if i made all the sections of if code to be functions… i'm thinking it may be better to if this param is true then do this function… if not then do this function..
Go with whatever you find easier to read and maintain.

Personally I dislike using functions unless doing so will actually decrease the length of my script - for example, if I want to run the same code twice under different circumstances, it'll generally get dumped into a function. A classic example would be if you want to write text in a special way (eg centered) on a regular basis.

On some occasions, functions can be handy for escaping loops - say you're nested three levels deep, and you suddenly wish to break out of them all. It can be done, but it's not as simple as inserting three break statements (and ComputerCraft's Lua lacks a "goto")! But if those loops are isolated away inside a function, then you need only return from that in order to escape them all.
Kk… I see..
I wanted it so that say… when asked for the username Admin accidentally puts in admin… i don't want it to go and logout i just want it to go back to the beginning and ask for the username again…
I just wasn't sure about making all that stuff functions… i though it may be more efficient… but i think i'll leave it until i get the code stable then reconsider
Bomb Bloke #9
Posted 15 February 2014 - 07:44 PM
Ah, I see - the script asks for a username more then once, and you're not talking about the first instance.

The answer is more "while"/"repeat" loops, which are generally the way to go whenever you want something looped until a given condition is met.

Here's an example of a quick login process which will repeat its requests for a valid username/password combo until it gets one:

local users = {
                ["Admin"] = {["password"] = "password", ["permissions"] = "admin"},
                ["Mod"] = {["password"] = "anotherPassword", ["permissions"] = "moderator"},
                ["JoeUser"] = {["password"] = "yetAnotherPassword", ["permissions"] = "user"}
}

local curUser,curPass

while (not users[curUser]) or users[curUser].password ~= curPass do
	print("Enter username:")
	curUser = read()

	print("Enter password:")
	curPass = read()

	if (not users[curUser]) or users[curUser].password ~= curPass then
		print("Error: Invalid username/password combination. Please try again.")
		print("")
	end
end

-- User has logged in, carry on down here...

You could add in extra conditions or loops to make it specifically wait for users with certain permission levels, eg:

local users = {
                ["Admin"] = {["password"] = "password", ["permissions"] = "admin"},
                ["Mod"] = {["password"] = "anotherPassword", ["permissions"] = "moderator"},
                ["JoeUser"] = {["password"] = "yetAnotherPassword", ["permissions"] = "user"}
}

local curUser,curPass

while (not users[curUser]) or users[curUser].password ~= curPass or users[curUser].permissions ~= "admin" do
	print("Enter username:")
	curUser = read()

	print("Enter password:")
	curPass = read()

	if (not users[curUser]) or users[curUser].password ~= curPass then
		print("Error: Invalid username/password combination. Please try again.")
		print()
	elseif users[curUser].permissions ~= "admin" then
		print("Login valid, but lacks sufficient privileges. Please try another account.")
		print()
	end
end

-- User has logged in, carry on down here...