Let's summarize our learning in the chapter using a couple of sample use cases.
Sample use cases
First use case
Consider the first scenario as follows:
A travel agency has three customers. For our use case, the requirement is to suggest a package for a specific city using the predefined preferences for any two customers. As an additional output or suggestion, there needs to be a suggestion on weather status for the next five days. Also, to provide an enhanced end user experience, ask a single question to determine check-in time and type of transport for the journey.
The code is as follows:
...
import getpass
import base64
import requests
from collections import Counter
import re
#ask for username .. will be displayed when typed
uname=input("Enter your username :")
#ask for password ... will not be displayed when typed
#(try in cmd or invoke using python command)
p = getpass.getpass(prompt="Enter your password: ")
#construct credential with *.* as separator between username and password
creds=uname+"*.*"+p
#encrypted creds of the registered customers
#for testing username:password is customer1:password1 , customer2:password2, and so on
#create a dictionary:
customers={
"customer1":b'Y3VzdG9tZXIxKi4qcGFzc3dvcmQx',
"customer2":b'Y3VzdG9tZXIyKi4qcGFzc3dvcmQy',
"customer3":b'Y3VzdG9tZXIzKi4qcGFzc3dvcmQz'
}
###Decrypt a given set of credentials
def decryptcredential(pwd):
rvalue=base64.b64decode(pwd)
rvalue=rvalue.decode()
return rvalue
###Encrypt a given set of credentials
def encryptcredential(pwd):
rvalue=base64.b64encode(pwd.encode())
return rvalue
#to validate if a customer is legitimate
flag=True
### procedure for validated customer
def validatedcustomer(customer):
print ("Hello "+customer)
inputcity=input("Which city do you want to travel (ex London/Paris/Chicago): ")
inputaddinfo=input("Any specific checkin time [AM/PM] and preferred mode of travel [car/bus]: ")
#### extract the regex values from additional info
regex=re.compile('\d+:\d+\s[AP]M')
time=re.findall(regex,inputaddinfo)
if "car" in inputaddinfo:
transport="car"
else:
if "bus" in inputaddinfo:
transport="bus"
### create sentence based upon the additional info provided
print ("\n\nYou have selected to checkin at "+time[0]+", and your preferred transport will be "+transport+" .")
getcityinfo=validatecity(inputcity)
### this is to sort the dictionary from highest to lowest based upon weather types
sorted_d = [(k, getcityinfo[k]) for k in sorted(getcityinfo, key=getcityinfo.get, reverse=True)]
###iterate through the weathers to construct a sentence
sentence="Weather prediction for next 5 days is (chance of) "
for item in sorted_d:
sentence=sentence+" "+item[0]+": "+str(item[1])+"%,"
print (sentence)
### to validate the average weather for that city for next 5 days
def validatecity(inputcity):
#create empty list
weathers=[]
weatherpercentage={}
#remove any additional spaces accidentally entered
inputcity=inputcity.strip()
urlx="https://samples.openweathermap.org/data/2.5/forecast?q="+inputcity+"&appid=b6907d289e10d714a6e88b30761fae22"
#send the request to URL using GET Method
r = requests.get(url = urlx)
output=r.json()
### this is to parse the type of weather and count them in a list
for item in output['list']:
weathers.append(item['weather'][0]['description'])
countweather=Counter(weathers)
#### this is to find the percentage of each weather type from the given output (36 variations are returned from API)
for item in countweather:
weatherpercentage[item]=int((countweather[item]/36) * 100)
return weatherpercentage
### validate if the username is part of any customers
if (uname in customers):
encryptedcreds=encryptcredential(creds)
getcustomercreds=customers[uname]
### validate if the credentials provided is the same as stored credentials for that customer
if not(str(encryptedcreds.decode()) == str(getcustomercreds.decode())):
flag=False
else:
flag=False
if not(flag):
print ("Unauthorized customer.")
else:
validatedcustomer(uname)
Scenario 1: Incorrect username and password:
C:\gdrive\book2\github\edition2\chapter1>python use_case1.py
Enter your username :abhishek
Enter your password:
Unauthorized customer.
Scenario 2: Correct username but incorrect password:
C:\gdrive\book2\github\edition2\chapter1>python use_case1.py
Enter your username :customer1
Enter your password:
Unauthorized customer.
C:\gdrive\book2\github\edition2\chapter1>
Scenario 3: Correct username and password:
C:\gdrive\book2\github\edition2\chapter1>python use_case1.py
Enter your username :customer1
Enter your password:
Hello customer1
Which city do you want to travel (ex London/Paris/Chicago): paris
Any specific checkin time [AM/PM] and preferred mode of travel [car/bus]: travel checkin at 12:30 PM by bus
You have selected to checkin at 12:30 PM, and your preferred transport will be bus .
Weather prediction for next 5 days is (chance of) clear sky: 61%, light rain: 27%, few clouds: 5%, broken clouds: 2%, moderate rain: 2%,
C:\gdrive\book2\github\edition2\chapter1>
As we can see in the preceding output, the customer selected paris, with a check in time of 12:30 PM and bus as their mode of transport.
Based upon the location selected, the API call was made to the weather site, and a prediction of the weather for the next 5 days was returned in JSON. This has been evaluated in terms of a percentage, and a result value was given, which predicts a 61% chance of clear sky, followed by a 27% chance of light rain.
Let's run this output for another customer:
C:\gdrive\book2\github\edition2\chapter1>python use_case1.py
Enter your username :customer2
Enter your password:
Hello customer2
Which city do you want to travel (ex London/Paris/Chicago): Chicago
Any specific checkin time [AM/PM] and preferred mode of travel [car/bus]: checkin preferred at 10:00 AM and travel by car
You have selected to checkin at 10:00 AM, and your preferred transport will be car .
Weather prediction for next 5 days is (chance of) clear sky: 51%, light rain: 37%, few clouds: 5%, broken clouds: 2%, moderate rain: 2%,
C:\gdrive\book2\github\edition2\chapter1>
In this particular situation, we see that customer2 has a check-in preference of 10:00 AM and prefers to travel by car.
Also, as per their selection of Chicago, the prediction of the weather is clear sky: 51%, light rain: 37%, few clouds: 5%, broken clouds: 2%, moderate rain: 2%.
Second use case
Consider the second scenario as follows:
As an admin, you need to provide a script to users to add/delete themselves based upon authentication status and if authenticated successfully, provide an option to change their passwords:
...
import getpass
import base64
import os.path
###Check with credential storage file exists. If not, then create one, otherwise read data from the current file
storedcreds=[]
if (os.path.isfile("usecase_creds.txt")):
fopen=open("usecase_creds.txt")
storedcreds=fopen.readlines()
else:
fopen=open("usecase_creds.txt","w")
###Decrypt a given set of credentials
def decryptcredential(pwd):
rvalue=base64.b64decode(pwd)
rvalue=rvalue.decode()
return rvalue
###Encrypt a given set of credentials
def encryptcredential(pwd):
rvalue=base64.b64encode(pwd.encode())
return rvalue
#### this is used to deregister a authenticated user
def deregister(getencryptedcreds):
with open("usecase_creds.txt") as f:
newText=f.read().replace(getencryptedcreds+"\n","")
with open("usecase_creds.txt", "w") as f:
f.write(newText)
print ("you are deregistered")
#this is to store the read encrypted creds from file into expanded username and password combo
storedcredsexpanded=[]
for item in storedcreds:
item=item.strip()
#to ensure we do not parse the blank values or blank lines
if (len(item) > 2):
tmpval=decryptcredential(item)
storedcredsexpanded.append(tmpval)
#ask for username .. will be displayed when typed
uname=input("Enter your username :")
#ask for password ... will not be displayed when typed
#(try in cmd or invoke using python command)
p = getpass.getpass(prompt="Enter your password: ")
#construct credential with *.* as separator between username and password
creds=uname+"*.*"+p
#encrypted creds of the registered customers
#for testing username:password is customer1:password1 , customer2:password2, and so on...
getencryptedcreds=encryptcredential(creds)
#validate authentication of user
flag=False
usrauthenticated=False
for item in storedcreds:
if (getencryptedcreds.decode() in item):
flag=True
if (flag):
print ("Authenticated successfully")
usrauthenticated=True
else:
print ("Authentication failed")
#validate if user exists
tmpvalue=decryptcredential(getencryptedcreds)
#split username and password
tmpvalue=tmpvalue.split("*.*")
usrflag=False
###validate if this username exists otherwise give an option for new registration
for item in storedcredsexpanded:
item=item.split("*.*")
if (tmpvalue[0] == item[0]):
print ("User already exists but password incorrect. Please contact Admin for password reset")
usrflag=True
break
#if user does not exist
if (usrflag==False):
readinput=input("User does not exist, Do you want to register yourself (Y/N) ")
readinput=readinput.strip()
readinput=readinput.lower()
if (readinput == "y"):
uname=input("Enter your username :")
p = getpass.getpass(prompt="Enter your password: ")
creds=uname+"*.*"+p
getencryptedcreds=encryptcredential(creds)
## to convert bytes to string
getencryptedcreds=getencryptedcreds.decode()
##open file in append mode
fopen=open("usecase_creds.txt","a")
fopen.write(getencryptedcreds+"\n")
fopen.close()
print ("User added successfully")
if (usrauthenticated):
readinput=input("Do you want to deregister yourself (Y/N) ")
readinput=readinput.strip()
readinput=readinput.lower()
if (readinput == "y"):
deregister(getencryptedcreds.decode())
else:
readinput=input("Do you want to change your password (Y/N) ")
readinput=readinput.strip()
readinput=readinput.lower()
if (readinput == "y"):
p = getpass.getpass(prompt="Enter your password: ")
creds=uname+"*.*"+p
newencryptedcreds=encryptcredential(creds)
newencryptedcreds=newencryptedcreds.decode()
getencryptedcreds=getencryptedcreds.decode()
###updated the credential of the user
with open("usecase_creds.txt") as f:
newText=f.read().replace(getencryptedcreds, newencryptedcreds)
with open("usecase_creds.txt", "w") as f:
f.write(newText)
print ("Your password is updated successfully")
The outputs based upon different scenario are as follows:
Scenario 1: A user who is not registered receives the following output:
C:\gdrive\book2\github\edition2\chapter1>python use_case2.py
Enter your username :newcustomer
Enter your password:
Authentication failed
User does not exist, Do you want to register yourself (Y/N) y
Enter your username :newcustomer
Enter your password:
User added successfully
C:\gdrive\book2\github\edition2\chapter1>
Scenario 2: A user who is registered but forgot their password receives this output:
C:\gdrive\book2\github\edition2\chapter1>python use_case2.py
Enter your username :newcustomer
Enter your password:
Authentication failed
User already exists but password incorrect. Please contact Admin for password reset
C:\gdrive\book2\github\edition2\chapter1>
Scenario 3: A user who is a registered customer, and wants to change their password if authenticated successfully, receives the following output:
C:\gdrive\book2\github\edition2\chapter1>python use_case2.py
Enter your username :customer2
Enter your password:
Authenticated successfully
Do you want to deregister yourself (Y/N) n
Do you want to change your password (Y/N) y
Enter your password:
Your password is updated successfully
Scenario 4: A user who is a registered customer, and want to deregister themselves if authenticated successfully, receives the following output:
C:\gdrive\book2\github\edition2\chapter1>python use_case2.py
Enter your username :newcustomer
Enter your password:
Authenticated successfully
Do you want to deregister yourself (Y/N) y
you are deregistered
C:\gdrive\book2\github\edition2\chapter1>
All of these preceding operations are saved in the background, using the file operations, under the file named usecase_creds.txt:
Additionally, as an example, here is the current output of usecase_creds.txt, which shows that none of the credentials storage in the file occurs in clear-text (or human-readable format):
C:\gdrive\book2\github\edition2\chapter1>more usecase_creds.txt
Y3VzdG9tZXIxKi4qcGFzc3dvcmQx
Y3VzdG9tZXIyKi4qbmV3cGFzc3dvcmQ=
YWJoaXNoZWsqLipoZWxsb3dvcmxk
C:\gdrive\book2\github\edition2\chapter1>