Ruby | Trying to check password by comparing to a file - ruby

I have some troubles with my code using Ruby. its just for a terminal program, so no website or anything.
In my code I Will have the user create a login. Then I will have the user to login, but I cant seem to figure out how to check if password or username is correct.
The program should compare whatever the user types in as a username/password with the file (userdatabase) - I think i got that right.
Now I am trying to stop the user if the input is not found in the user database, using a while loop, but i cant seem to make that work.
Code:
puts "What will be your user name?"
username = gets.chomp
puts "What will be your password?"
password = gets.chomp
puts "Please repeat your password."
passwordsafe = gets.chomp
f = File.new("student.txt", "w+")
f.puts username + ";" + password + ";" + passwordsafe
f.close
puts "well done, you have created a new user."
lines = IO.readlines("student.txt")
lines.each{|line| print(line)}
puts "now you need to login."
puts "What is your username?"
username = gets.chomp
File.open("student.txt") do |f|
f.any? do |line|
while line.include?(username)
end
end
elsif puts "Sorry your username was incorrect"
end
#lines = IO.readlines("student.txt")
#lines.each{|line| (line)}
puts "what is your password?"
password = gets.chomp

The while is unnecessary.
The username check currently like this:
File.open("student.txt") do |f|
f.any? do |line|
while line.include?(username)
end
end
Could be like this:
File.open("student.txt").each_line.any? do |line|
line.include?(username)
end
Or collapsed to a single line like this:
File.open("student.txt").each_line.any?{ |l| l.include?(username) }
Check the docs on the any? method to make sure you understand what it's expecting: http://ruby-doc.org/core-2.4.2/Enumerable.html#method-i-any-3F
As for the rest of the syntax errors, I'll leave those up to you ;)

Related

How do I add login functionality (username/password) to my app with CSV

Ruby newbie here. Basically I've got several users in a CSV file (headers below):
first_name,age,location,gender,phone_number,email,username,password
I want user's to login with their username which will check the CSV file for the corresponding username, and when it finds the username it will ask the user for the password, if the passwords match then it will run the 'user_mainmenu' variable which then takes the user to the User Main Menu.
def user_login
print "Enter username: "
username_access = $stdin.gets.chomp
CSV.foreach('users.csv', headers: true) do |row|
if row["#username"] == username_access then
#user = User.new(row.to_hash)
break
end
end
print "Enter password: "
password_access = $stdin.gets.chomp
CSV.foreach('users.csv', headers: true) do |row|
if row["#password"] == password_access then
user_mainmenu
break
end
end
end
I'm pretty sure I'm not using the right code, I'm just using Ruby (not allowed to use Rails as its in a course and we are learning that later).
I can't find any answers anywhere as most involve Rails.
Apologies if there isn't enough info or if I'm not being clear enough, first time posting on here.
You don’t need to read a CSV file twice. Using CSV#open and CSV::Table#new, one might get the data in handy format into memory:
def user_login
# load CSV
csv = CSV::Table.new(CSV.open('users.csv', headers: true))
print "Enter username: "
username_access = $stdin.gets.chomp
# detect row with this username
row = csv.detect { |e| e["username"] == username_access }
# immediately throw if no such user
raise "No such user" unless row
print "Enter password: "
password_access = $stdin.gets.chomp
raise "Wrong password" unless row["password"] == password_access
# everything is fine, logged in, return user
User.new(row.to_hash)
end
Had a mentor help me:
def user_login
login_start
verified(gets.chomp)
end
def verified(input)
user_row = authentication(input)
if user_row
puts 'Please enter your password:'
print "> "
password = gets.chomp
if user_row['password'] == password
user_mainmenu
else
puts "Incorrect password."
sleep 1
user_login
end
else
failed
end
end
def authentication(username)
CSV.open('users.csv', headers: true).find { |row| row['username'] == username }
end
def failed
puts "Username not recognised. Please try again."
sleep(1)
user_login
end
def login_start
puts "Enter username:"
print "> "
end

Deleting a row from a CSV file with Ruby

I've seen similar answers to this question but I think I need something more specific to my code. Basically I've called the row from the CSV file but now I need to delete the called row. Sounds simple as I write this yet here I am asking you all for help. I know there is a lot of code here but I figured the more there is the more easier you will be able to understand the context. Apologies if there is too much noise in the code.
def delete_user_menu
puts "============================================"
delete_users_active_list
puts " "
puts "Please type in the name of the user you wish to eradicate: "
print "> "
eradicate(gets.chomp)
end
def eradicate(delete_input)
delete_row = delete_authentication(delete_input)
if delete_row
puts "Are you sure you want to delete #{delete_input} from the database?"
puts "[y]es or [n]o"
print "> "
delete_answer = gets.chomp
if delete_answer == "y"
delete_user
after_deletion_menu
elsif delete_answer == "n"
puts "Close call! Taking you back to main menu."
sleep 2
admin_main_menu
else
puts "Input not recognised. Please try again."
eradicate(delete_input)
end
else
puts "User not recognized. Please try again."
sleep 1
delete_user_menu
end
end
def delete_user
# this is where the delete user function needs to go
after_deletion_menu
end
def after_deletion_menu
puts " "
puts "User deleted! What would you like to do now?"
puts "1. Delete another user"
puts "2. Back to main menu"
print "> "
after_deletion_choice = gets.chomp
if after_deletion_choice == "1"
delete_user_menu
elsif after_deletion_choice == "2"
admin_main_menu
else
puts "Input not recognized. Please try again."
after_deletion_menu
end
end
def delete_users_active_list
CSV.foreach("./users.csv", headers: true) do |row|
username = row['username']
puts "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
puts "Username: #{username}"
end
end
def delete_authentication(username)
CSV.open('users.csv', headers: true).find { |row| row['username'] == username }
end
I've had a look at this question How to remove a row from a CSV with Ruby
but I don't fully understand the answers, hence why I'm here. Any help is much appreciated.
I looked at the link. First, they are reading the entire csv file into table:
table = CSV.table(#csvfile)
then deleting the row from table:
table.delete_if do |row|
row[:foo] == 'true'
end
Finally, they are completely replacing the original file with the new table minus the row:
File.open(#csvfile, 'w') do |f|
f.write(table.to_csv)
end
This is generally how you have to do this kind of operation when you are dealing with a file. It's not like a database.
EDIT - in your case:
delete_user(delete_input)
...
def delete_user(user)
...
table.delete_if { |row| row[:username] == user }
...

How do I get the program to check if the key is "equal" to the value?

I was trying to write a simple username/password prompt. I'm still a beginner with Ruby.
combo = Hash.new
combo["placidlake234"] = "tastychicken"
combo["xxxdarkmasterxxx"] = "pieisgood"
combo["dvpshared"] = "ilikepie"
puts "Enter your username."
username = gets.chomp
def user_check
if username = ["placidlake234"||"xxxdarkmasterxxx"||"dvpshared"]
puts "What is your password?"
password = gets.chomp
pass_check
else
puts "Your username is incorrect."
end
end
def pass_check
if password => username
puts "You have signed into #{username}'s account."
end
end
user_check()
When I try running it, I get a strange error right before username in => username.
There are few things which should be corrected:
I have commented out below
combo = Hash.new
combo["placidlake234"] = "tastychicken"
combo["xxxdarkmasterxxx"] = "pieisgood"
combo["dvpshared"] = "ilikepie"
puts "Enter your username."
username = gets.chomp
def user_check(username, combo)
#HERE combo.keys gives keys.
if combo.keys.include? username
puts "What is your password?"
password = gets.chomp
if pass_check(username, password, combo)
puts "You have signed into #{username}'s account."
else
puts "Wrong password, sorrie"
end
else
puts "Your username is incorrect."
end
end
def pass_check(username, password, combo)
#Here, access by combo[username]
return true if password == combo[username]
false
end
#HERE, pass the arguments, so that it is available in function scope
user_check(username, combo)

How would I access a key from a hash that is within an array that is within a text file in ruby?

I'm trying to create an if/else statement that compares a user's input against all the name keys within a hash that's stored with a text file. How would I write this?
user_accts is the array.
Update of full if/else statement:
elsif choice == "2"
puts "====== NEW CUSTOMER ======"
puts "Choose a username:"
prompt; login_name = gets.chomp
#file.open("cust_accts.txt", "r")
#if #user_accts.map { |acct| acct["name"]}.include?(login_name)
if #user_accts.any? {|acct| acct["name"] == login_name }
puts "Sorry, that username has already been taken"
elsif
puts "Choose a password:"
prompt; login_password = gets.chomp
user_accts << create_account(login_name, login_password)
File.open("cust_accts.txt", "a") { |file| file.puts(user_accts)}
end
original if/else statement:
if login_name == #??? #user_accts.has_key?(login_name) ???
puts "Sorry, that username has already been taken"
elsif
puts "Choose a password:"
prompt; login_password = gets.chomp
user_accts << create_account(login_name, login_password)
File.open("cust_accts.txt", "a") { |file| file.puts(user_accts)}
end
This is exactly what is inputted to the cust_accts.txt file using this command:
user_accts << create_account(login_name, login_password)
File.open("cust_accts.txt", "a") { |file| file.puts(user_accts)}
cust_accts.txt
{"name"=>"Tom", "password"=>"popcorn", "balance"=>0}
{"name"=>"Avril", "password"=>"chain", "balance"=>0}
It's not quite clear what your starting point is.
Assuming you have parsed your text file into #user_accts, so you have:
#user_accts = [{"name"=>"Tom", "password"=>"popcorn", "balance"=>0},
{"name"=>"Avril", "password"=>"chain", "balance"=>0}]
Then you would want to do:
if #user_accts.map {|acct| acct["name"]}.include?(login_name)
puts "Sorry, that username has already been taken"
else
# ...
end
#user_accts = [{"name"=>"Tom", "password"=>"popcorn", "balance"=>0},
{"name"=>"Avril", "password"=>"chain", "balance"=>0}]
if #user_accts.any? {|acct| acct["name"] == "Tom" }
puts "Sorry, that username has already been taken"
else
# ...
end
#=> Sorry, that username has already been taken
It seems like your problem is "How do I store objects in ruby for use at a later date?". If you want to use a text file you need to put it into a format that can be parsed back into a ruby object like JSON or XML. I would recommend using a database though. A database like SQLite is very light weight and easy to learn. An advantage to using a DB is that when you use a DB you can set an option to have your results returned as a hash.
I had a similar problem, eventually decided that a DB was the way to go.

How can I store user defined data in a hash

Help, I am a noob, just need some advice on this bit of code. I have got most of my program working this part has me stuped i want to get a name and password. Then make the name the key and the password the value. Now it must be user defined.. Then I must be able to pull that hash info again. I thought that return would work... here is my code
def login_prompt
vault = {}
puts "WELCOME! please enter an existing username: "
username = gets.chomp
checkname = Noxread.new
comparename = checkname.read_file
comparename.keys.include?("#{username}")
if comparename == true
puts "please enter your password: "
password = gets.chomp
vault[username]= password
else puts "username already exists!! would you like to retry? (y/n)"
case answer
when /^y/
login_prompt
when /^n/
exit
end
end
end
so that should gather the info. and this is my code to merge that and an hash that i pulled from a file. in a NoxRead class
require_relative 'read'
require 'csv'
class Noxwrite
attr_accessor :name :password
def initialize
#name = name
#password = password
end
def upsum
x = Noxread.new
y = x.read_file
z = login_prompt
y.merge(z) {|name, password| name + ',' + password}
return y
end
def write_file
ehash = upsum
CSV.open("data.csv", "wb") do |csv|
csv << ehash
end
end
end
What is the problem with this code. Seems fine, apart from the fact that passwords should not be read like this in open text.
When you write something like
user_hash = login_prompt
user_hash will have the hash as desired
{"username"=>"password"}

Resources