This is part of my code for creating and logging into accounts in my game, I have cut out the acquisition of the username and password from the user and have just kept the password hashing and file read/writing
##CREATE ACCOUNT##
#Encrypt password
newPswdEnc = hashlib.sha512()
newPswd = bytes(newPswd, "ascii")
newPswdEnc.update(newPswd)
newPswdEnc = str(newPswdEnc.digest()).replace("\\", ".")
#Assemble and place in file
newLogin = {"Username":newUsnm,"Pswd":newPswdEnc,"Highscore":0}
with open("Users.json", "r+") as file:
data = json.load(file)
##DOES SOME EXTRA VALIDATION TO PREVENT DUPLICATE USERNAMES##
data["Logins"].append(newLogin)
with open("Users.json", "w+") as file:
json.dump(data. file, indent = 5)
##LOGIN##
#Encrypt password
pswdEnc = hashlib.sha512()
pswd = bytes(pswd, "ascii")
pswdEnc.update(pswd)
pswdEnc = str(pswdEnc.digest()).replace("\\", ".")
#CHECK USERNAME AND PASSWORD
with open("Users.json", "r") as file:
data = json.load(file)
for i in range(0, len(data["Logins"])):
if data["Logins"][i]["Username"] == usnm and data["Logins"][i]["Pswd"] == pswd:
loggedIn = True
##Logins.json##
{
"Logins": [
{
"Username": "ADMIN",
"Pswd": b'#.x8b.x90.xe6.xe28-.xda.xfa.xdc5&k/.xa9.xa3q.xfb9b.xb6u.xcc.xab.x1bU82.x1fF.x90p.xd0.xf3v/).xb2.x1a.xc7.xadw..xb6.xbd).x9d.t.xf8.xe7]8.xed.x8bpg.x96]]_&.xeb.xc3.xf5',
"Highscore": 0
}
],
}
When attempting to sign in with the correct password I get this error:
Expecting value: line 5 column 24 (char 90)
which appears to be the b character at the start of the hash
Problem with reading was solved by removing my filter for backslashes however I am now experiencing issues with the password comparison as whilst in another program I have put both hashes in variables and validated them. This program is refusing to do so.
Related
Inside of a json file, each line stores the information of every different user that is created through separate classes. In the user_login file, retrieves this info and isolates username and passwords for each user to attempt to create a login page.
File: user_login
import json
filename = "users.json"
with open(filename, "r+", encoding='utf8') as file:
'''opens json file and separates it by line by storing each line into an
array'''
lines = file.readlines()
login_info = {}
'''array that will store usernames and passwords for each user(each line in
the file is a user)'''
for line in lines:
'''simply prints each element of the lines array displaying the
information of each user'''
info = json.loads(line)
print("USER: " + str(info))
print("username: " + info["username"])
print("password: " + info["password"] + "\n")
login_info[info["username"]] = info["password"]
'''creates a new pair of username and password for each user(each line is
a user)'''
print(login_info)
print(lines)
print(login_info)
'''prompts user for their username and password'''
prompt_username = input("Please enter username: ")
prompt_password = input("Please input password: ")
The problem is in the following method(it does not work):
def login(username, password):
'''if username exists and the inputed strings match one of the key-value
pairs, login is successful'''
if username in login_info:
if password == info["password"]:
print("LOGIN SUCCESSFUL")
else:
print("Sorry, password does not exist.")
else:
print("Sorry this username or password does not exist.")
login(prompt_username, prompt_password)
How do I effectively check if the user inputs for username and password match any of the dictionary pairs to simulate a login?
The following is the users.json file.
File: users.json
{"first": "Gilberto", "last": "Robles", "username": "girobles1", "password": "1234", "location": "San Diego", "interests": [["eat", "sleep", "code", "repeat"]]}
{"first": "Gilberto", "last": "Robles", "username": "girobles2", "password": "12345", "location": "San Diego", "interests": [["eat", "sleep", "code"]]}
It looks like you're just calling the wrong object to check if the password is correct
if password == info["password"]:
should be
if password == login_info[username]:
Follow-up question about number of attempts:
I rewrote your function to return the status of the username and password accuracy:
def login(username, password):
'''if username exists and the inputed strings match one of the key-value
pairs, login is successful returns (Username Correct, Password Correct)'''
if username in login_info:
if password == login_info[username]:
print("LOGIN SUCCESSFUL")
return (True, True)
else:
print("Sorry, password does not exist.")
return (True, False)
else:
print("Sorry this username does not exist.")
return (False, False)
login(prompt_username, prompt_password)
Then added a loop to check the results and logic to handle them (This is untested, since I don't have your dictionary):
'''prompts user for their username and password'''
username_attempts = 3
password_attempts = 3
prompt_username = input("Please enter username: ")
prompt_password = input("Please input password: ")
username_guess = 1
password_guess = 1
while True: #Loops until broken
if username_guess > username_attempts:
print("Too many invalid usernames, goodbye")
#What do you want it to do if they fail?
break
if password_guess > password_attempts:
print("Too many invalid passwords, goodbye")
#What do you want it to do if they fail?
break
username_status, password_status = login(prompt_username, prompt_password)
if all([username_status, password_status]):
break
elif not username_status:
print("Invalid username, please try again")
prompt_username = input("Please enter username: ")
username_guess += 1
elif not password_status:
print("Invalid password, please try again")
prompt_password = input("Please input password: ")
password_guess += 1
Searched online and read through the documents, but have not been able to find an answer. I am fairly new and part of learning Ruby I wanted to make the script below.
The Script essentially does a Carrier Lookup on a list of numbers that are provided through a CSV file. The CSV file has just one row with the column header "number".
Everything runs fine UNTIL the API gives me an output that is different from the others. In this example, it tells me that one of the numbers in my file is not a valid US number. This then causes my script to stop running.
I am looking to see if there is a way to either ignore it (I read about Begin and End, but was not able to get it to work) or ideally either create a separate file with those errors or just put the data into the main file.
Any help would be much appreciated. Thank you.
Ruby Code:
require 'csv'
require 'uri'
require 'net/http'
require 'json'
number = 0
CSV.foreach('data1.csv',headers: true) do |row|
number = row['number'].to_i
uri = URI("https://api.message360.com/api/v3/carrier/lookup.json?PhoneNumber=#{number}")
req = Net::HTTP::Post.new(uri)
req.basic_auth 'XXX' , 'XXX'
res = Net::HTTP.start(uri.hostname, uri.port, :use_ssl => true) {|http|
http.request(req)
}
json = JSON.parse(res.body)
new = json["Message360"]["Carrier"].values
CSV.open("new.csv", "ab") do |csv|
csv << new
end
end
File Data:
number
5556667777
9998887777
Good Response example in JSON:
{"Message360"=>{"ResponseStatus"=>1, "Carrier"=>{"ApiVersion"=>"3", "CarrierSid"=>"XXX", "AccountSid"=>"XXX", "PhoneNumber"=>"+19495554444", "Network"=>"Cellco Partnership dba Verizon Wireless - CA", "Wireless"=>"true", "ZipCode"=>"92604", "City"=>"Irvine", "Price"=>0.0003, "Status"=>"success", "DateCreated"=>"2018-05-15 23:05:15"}}}
The response that causes Script to stop:
{
"Message360": {
"ResponseStatus": 0,
"Errors": {
"Error": [
{
"Code": "ER-M360-CAR-111",
"Message": "Allowed Only Valid E164 North American Numbers.",
"MoreInfo": []
}
]
}
}
}
It would appear you can just check json["Message360"]["ResponseStatus"] first for a 0 or 1 to indicate failure or success.
I'd probably add a rescue to help catch any other errors (malformed JSON, network issue, etc.)
CSV.foreach('data1.csv',headers: true) do |row|
number = row['number'].to_i
...
json = JSON.parse(res.body)
if json["Message360"]["ResponseStatus"] == 1
new = json["Message360"]["Carrier"].values
CSV.open("new.csv", "ab") do |csv|
csv << new
end
else
# handle bad response
end
rescue StandardError => e
# request failed for some reason, log e and the number?
end
Odoo 9 custom module binary field attachment=True parameter added later after that new record will be stored in filesystem storage.
Binary Fields some old records attachment = True not used, so old record entry not created in ir.attachment table and filesystem not saved.
I would like to know how to migrate old records binary field value store in filesystem storage?. How to create/insert records in ir_attachment row based on old records binary field value? Is any script available?
You have to include the postgre bin path in pg_path in your configuration file. This will restore the file store that contains the binary fields
pg_path = D:\fx\upsynth_Postgres\bin
I'm sure that you no longer need a solution to this as you asked 18 months ago, but I have just had the same issue (many gigabytes of binary data in the database) and this question came up on Google so I thought I would share my solution.
When you set attachment=True the binary column will remain in the database, but the system will look in the filestore instead for the data. This left me unable to access the data from the Odoo API so I needed to retrieve the binary data from the database directly, then re-write the binary data to the record using Odoo and then finally drop the column and vacuum the table.
Here is my script, which is inspired by this solution for migrating attachments, but this solution will work for any field in any model and reads the binary data from the database rather than from the Odoo API.
import xmlrpclib
import psycopg2
username = 'your_odoo_username'
pwd = 'your_odoo_password'
url = 'http://ip-address:8069'
dbname = 'database-name'
model = 'model.name'
field = 'field_name'
dbuser = 'postgres_user'
dbpwd = 'postgres_password'
dbhost = 'postgres_host'
conn = psycopg2.connect(database=dbname, user=dbuser, password=dbpwd, host=dbhost, port='5432')
cr = conn.cursor()
# Get the uid
sock_common = xmlrpclib.ServerProxy ('%s/xmlrpc/common' % url)
uid = sock_common.login(dbname, username, pwd)
sock = xmlrpclib.ServerProxy('%s/xmlrpc/object' % url)
def migrate_attachment(res_id):
# 1. get data
cr.execute("SELECT %s from %s where id=%s" % (field, model.replace('.', '_'), res_id))
data = cr.fetchall()[0][0]
# Re-Write attachment
if data:
data = str(data)
sock.execute(dbname, uid, pwd, model, 'write', [res_id], {field: str(data)})
return True
else:
return False
# SELECT attachments:
records = sock.execute(dbname, uid, pwd, model, 'search', [])
cnt = len(records)
print cnt
i = 0
for res_id in records:
att = sock.execute(dbname, uid, pwd, model, 'read', res_id, [field])
status = migrate_attachment(res_id)
print 'Migrated ID %s (attachment %s of %s) [Contained data: %s]' % (res_id, i, cnt, status)
i += 1
cr.close()
print "done ..."
Afterwards, drop the column and vacuum the table in psql.
I have a function takes a file as input and prints certain statistics and also copies the file into a file name provided by the user. Here is my current code:
def copy_file(option):
infile_name = input("Please enter the name of the file to copy: ")
infile = open(infile_name, 'r')
outfile_name = input("Please enter the name of the new copy: ")
outfile = open(outfile_name, 'w')
slist = infile.readlines()
if option == 'statistics':
for line in infile:
outfile.write(line)
infile.close()
outfile.close()
result = []
blank_count = slist.count('\n')
for item in slist:
result.append(len(item))
print('\n{0:<5d} lines in the list\n{1:>5d} empty lines\n{2:>7.1f} average character per line\n{3:>7.1f} average character per non-empty line'.format(
len(slist), blank_count, sum(result)/len(slist), (sum(result)-blank_count)/(len(slist)-blank_count)))
copy_file('statistics')
It prints the statistics of the file correctly, however the copy it makes of the file is empty. If I remove the readline() part and the statistics part, the function seems to make a copy of the file correctly. How can I correct my code so that it does both. It's a minor problem but I can't seem to get it.
The reason the file is blank is that
slist = infile.readlines()
is reading the entire contents of the file, so when it gets to
for line in infile:
there is nothing left to read and it just closes the newly truncated (mode w) file leaving you with a blank file.
I think the answer here is to change your for line in infile: to for line in slist:
def copy_file(option):
infile_name= input("Please enter the name of the file to copy: ")
infile = open(infile_name, 'r')
outfile_name = input("Please enter the name of the new copy: ")
outfile = open(outfile_name, 'w')
slist = infile.readlines()
if option == 'statistics':
for line in slist:
outfile.write(line)
infile.close()
outfile.close()
result = []
blank_count = slist.count('\n')
for item in slist:
result.append(len(item))
print('\n{0:<5d} lines in the list\n{1:>5d} empty lines\n{2:>7.1f} average character per line\n{3:>7.1f} average character per non-empty line'.format(
len(slist), blank_count, sum(result)/len(slist), (sum(result)-blank_count)/(len(slist)-blank_count)))
copy_file('statistics')
Having said all that, consider if it's worth using your own copy routine rather than shutil.copy - Always better to delegate the task to your OS as it will be quicker and probably safer (thanks to NightShadeQueen for the reminder)!
I am using Python 2.7 and I have a text file exactly in this format starting like this:
Username: JohnDoe
Password: JohnsPass
------------------------
Username: Bob
Password: BobsPass
------------------------
It starts the same way you see above and ends the same way as you see.
I have tried the following to get the data in either a dictionary/list so I can import it into mysql.
thefile = open("theaccounts.txt","r")
myAcctList=[]
for line in thefile:
myAcctList.append(line)
thefile.close()
Which shows me:
['Username: JohnDoe\n',
'Password: JohnsPass\n',
'------------------------\n',
'Username: Bob\n',
'Password: BobsPass\n',
'------------------------\n']
I have been trying to get the username/password like so:
for userinfo in myAcctList:
if userinfo.startswith('-------------'):
pass
else:
print userinfo
It shows me:
Username: JohnDoe
Password: JohnsPass
Username: Bob
Password: BobsPass
How can I get this to be on one line or a dictionary even so I can import these into mysql DB? I have tried various things but, they all either error out or it doubles the print out showing the username twice and the password from the previous username as the password.
Is there some way I can do:
print "Username is: %s and password is: %s" % (usernameis,passwordis)
As I would like to set the variable to place into the mysql record in one go, instead of matching the username and then inserting the password.
Please provide suggestions or solutions I have been trying to figure this out and really haven't been able to get it right. Thanks for all input it is greatly appreciated!
Update:
I modified what you showed me and came up with this:
cur_user={}
countlogins=0
for userinfo in myAcctList:
if userinfo.startswith('------------------------'):
pass
else:
forusername=userinfo.split(':')
print "I see index 0 as: %s" % forusername[0]
print "I see index 1 as: %s" % forusername[1]
cur_user[forusername[0]] = forusername[1].strip()
print cur_user
time.sleep(3) #just so I could see the top of the list
This is closer but, it still does some weird doubling up showing the username twice and showing the password for the previous line then the password it should be. It also only shows me the username when it hits the first line (I am guessing because it has not iterated to the 2nd line yet).
Print out is like so:
I see index 0 as: Username
I see index 1 as: JohnDoe
{'Username': 'JohnDoe'}
I see index 0 as: Password
I see index 1 as: JohnPass
{'Username': 'JohnDoe', 'Password': 'JohnPass'}
I see index 0 as: Username
I see index 1 as: BobTheUser
{'Username': 'BobTheUser', 'Password': 'JohnPass'}
I see index 0 as: Password
I see index 1 as: BobsPass
{'Username': 'BobTheUser', 'Password': 'BobsPass'}
I see index 0 as: Username
I see index 1 as: ThisOtherUser
{'Username': 'ThisOtherUser', 'Password': 'BobsPass'}
I counted 5 logins
I see index 0 as: Password
I see index 1 as: ThisOtherUserPass
{'Username': 'ThisOtherUser', 'Password': 'ThisOtherUserPass'}
I see index 0 as: Username
I see index 1 as: YetOneMore
I cannot figure out why it's doubling up like that or why it takes it the 2nd go round to get the info right. This will prevent (if I'm not mistaken) proper insertion into mysql db. I would like to get it just telling me once what I need to know so that I can know it will insert the proper info.
Thanks for your time and assistance!
2nd Update:
I also tried:
theFile = open("theaccounts.txt","r")
users = []
cur_user = {}
for line in theFile:
if line.startswith('------'):
users.append(cur_user)
cur_user = {}
else:
fields = ':'.split(line)
cur_user[fields[0]] = fields[1].strip()
theFile.close()
Which gives me an error:
---> 10 cur_user[fields[0]] = fields[1].strip()
11 theFile.close()
IndexError: list index out of range
So I then tried:
theFile = open("theaccounts.txt","r")
users = []
cur_user = {}
for line in theFile:
if line.startswith('------'):
users.append(cur_user)
cur_user = {}
else:
fields = ':'.split(line)
try:
cur_user[fields[0]] = fields[1].strip()
print cur_user
except:
pass
theFile.close()
Which only gave me:
[{},
{},
{},
{},
{},
{},
{},
{}]
Please help me get this sorted it's really not making sense to me why it's so hard.
3rd Update:
Ok got it figured out! Here is the final result for anyone else who might be needing to do this or gets in trouble:
countlogins=0
theFile = open("theaccounts.txt","r")
myAcctList=[]
cur_user={}
for line in theFile:
if line.startswith('------'):
countlogins=countlogins+1
print cur_user
myAcctList.append(line)
cur_user={}
else:
forusername=line.split(':')
cur_user[forusername[0]] = forusername[1].strip()
theFile.close()
print "I counted %s logins" % countlogins
I did the extra count at the end to verify it matched with what I was told.
Thanks for your help!
Split the line using : as the delimiter. Then use the first part as the key in a dictionary, and the second part as the value. When you get to the ---- line, add the dictionary to your list.
users = []
cur_user = {}
for line in theFile:
if line.startswith('------'):
users.append(cur_user)
cur_user = {}
else:
fields = line.split(':')
cur_user[fields[0]] = fields[1].strip()
In your first update, the doubling up is happening because you're using the same cur_user dictionary for everything. So when you read the second username, you're just overwriting the username of that dictionary, not starting a new one. That's why my answer reassigns cur_user = {} after it adds the current user to the users list.
It takes two steps to get both the username and password into the dictionary, because when you read the first line of the file you haven't yet read the first password. Since you're printing the dictionary after each line, you see this partial result after the first line. You shouldn't try to add to the database until you get to the ----- separator line, that's how you know you have both fields.