Skip to content

Commit 64cf162

Browse files
author
Mark Charlton
committed
dabbling in more Wk10
1 parent 7d355e8 commit 64cf162

File tree

9 files changed

+353
-1
lines changed

9 files changed

+353
-1
lines changed

Assessment/Wk10/char_classes.json

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"warrior": {
3+
"str": 15,
4+
"int": "-",
5+
"wis": "-",
6+
"dex": 12,
7+
"con": 10
8+
},
9+
"wizard": {
10+
"str": "-",
11+
"int": 15,
12+
"wis": 10,
13+
"dex": 10,
14+
"con": "-"
15+
},
16+
"thief": {
17+
"str": 10,
18+
"int": 9,
19+
"wis": "-",
20+
"dex": 15,
21+
"con": "-"
22+
},
23+
"necromancer": {
24+
"str": 10,
25+
"int": 10,
26+
"wis": 15,
27+
"dex": "-",
28+
"con": "-"
29+
}
30+
}
67.9 KB
Loading

Assessment/Wk10/character_gen_data.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# read data from json file
2+
3+
# imports
4+
import json
5+
6+
7+
# definitions
8+
REDON= "\033[31m" # Red text.
9+
GREENON = "\033[32m" # Green text.
10+
COLOUROFF = "\033[0m" #Reset special formatting (such as colour).
11+
12+
CLEAR = '\x1b[2K'
13+
RESET = '\033[2J'
14+
15+
16+
def show_char_stats():
17+
18+
#print (RESET)
19+
20+
print ( "-" * 80)
21+
print ( f"| {'Class':12}", end="|" )
22+
for key in a_attributes:
23+
print ( f'{a_attributes[key]["Name"]:^12}', end="|" )
24+
print ("")
25+
print ( "-" * 80)
26+
27+
for key in a_characters:
28+
print (a_posit[key], end="")
29+
print ( f' {key:12}', end="|" )
30+
for this_key in a_characters[key]:
31+
print ( f' {a_characters[key][this_key]:>2} ', end="|" )
32+
print ("")
33+
34+
print ( "-" * 80)
35+
36+
a_attributes = {"S": {"Name": "Strength", "Min": 3, "Max": 18, "Initial": 0, "Current": 0},
37+
"I": {"Name": "Intelligence", "Min": 3, "Max": 18, "Initial": 0, "Current": 0},
38+
"W": {"Name": "Wisdom","Min": 3, "Max": 18, "Initial": 0, "Current": 0},
39+
"D": {"Name": "Dexterity","Min": 3, "Max": 18, "Initial": 0, "Current": 0},
40+
"C": {"Name": "Constitution","Min": 3, "Max": 18, "Initial": 0, "Current": 0}}
41+
42+
a_characters = { "Warrior": {"S": 0, "I": 0, "W": 0, "D": 0, "C": 0},
43+
"Wizard": {"S": 0, "I": 0, "W": 0, "D": 0, "C": 0},
44+
"Thief": {"S": 0, "I": 0, "W": 0, "D": 0, "C": 0},
45+
"Necromancer": {"S": 0, "I": 0, "W": 0, "D": 0, "C": 0}}
46+
47+
a_posit = {
48+
"Warrior": "1",
49+
"1": "Warrior",
50+
"Wizard": "2",
51+
"2": "Wizard",
52+
"Thief": "3",
53+
"3": "Thief",
54+
"Necromancer": "4",
55+
"4": "Necromancer"
56+
}
57+
58+
59+
print ("Importing data from JSON")
60+
print ("------------------------")
61+
62+
63+
# Opening JSON file
64+
with open('char_classes.json') as json_file:
65+
d_json_data=json.load(json_file)
66+
#print(d_json_data)
67+
68+
for char in d_json_data:
69+
s_role=char.capitalize()
70+
for k, v in d_json_data[char].items():
71+
s_attr=k[0].upper()
72+
if v == '-':
73+
v = 0
74+
75+
a_characters[s_role][s_attr]=int(v)
76+
77+
print ("Character requirements are:")
78+
show_char_stats()
79+

Assessment/Wk10/security_checker.py

Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
# Security system
2+
3+
# imports
4+
import os
5+
import hashlib
6+
import binascii
7+
import json
8+
import time
9+
import sys
10+
11+
sys.path.append(os.path.abspath('..\\inc\\'))
12+
13+
import screen as s
14+
import helpers as h
15+
16+
# classes
17+
class User:
18+
min_len = 8
19+
allow_spaces = 0
20+
allow_leading_number = 0
21+
locked = 0
22+
lockouts = 0
23+
lockout_release = 0
24+
attempts = 0
25+
attempt_limit = 3
26+
lockout_period = 60
27+
loggedin = 0
28+
29+
def __init__(self, username):
30+
self.username=username
31+
if username in a_users.keys():
32+
self.passwordhash=a_users[username]
33+
else:
34+
self.passwordhash=""
35+
36+
if username in a_lockout.keys():
37+
if time.time() < a_lockout[username]["r"]:
38+
self.locked=1
39+
self.lockout_release = a_lockout[username]["r"]
40+
self.lockouts= a_lockout[username]["a"]
41+
42+
43+
def check_password_complexity(self, password):
44+
valid_pass = 1
45+
s_err=""
46+
try:
47+
if self.min_len > 0:
48+
if len(password) < self.min_len:
49+
s_err += f"* Minimum length {self.min_len}\n"
50+
valid_pass = 0
51+
if self.allow_spaces == 0:
52+
if " " in password:
53+
s_err += f"* No spaces"
54+
valid_pass = 0
55+
if self.allow_leading_number == 0:
56+
if password[0].isdigit():
57+
s_err += f"* Cannot begin with a number"
58+
valid_pass = 0
59+
except:
60+
pass
61+
62+
if valid_pass == 0:
63+
print ("Invalid Password. Please ensure it meets the minimum requirements: ")
64+
print ( s_err )
65+
66+
return valid_pass
67+
68+
def set_password(self, password):
69+
if self.check_password_complexity(password) == 1:
70+
self.passwordhash=self.hash_password(password)
71+
72+
73+
def hash_password(self,password):
74+
salt =hashlib.sha256(os.urandom(60)).hexdigest().encode('ascii')
75+
pwdhash = hashlib.pbkdf2_hmac('sha512', password.encode('utf-8'),
76+
salt, 200000)
77+
pwdhash = binascii.hexlify(pwdhash)
78+
return (salt + pwdhash).decode('ascii')
79+
80+
def verify_password(self,provided_password):
81+
f_return = False
82+
if self.is_locked_out():
83+
t_release = time.strftime("%d/%m/%Y %H:%M:%S", time.gmtime(self.lockout_release))
84+
print ( f"Sorry your account is locked out until {t_release}.\nPlease try again later")
85+
else:
86+
salt = self.passwordhash[:64]
87+
pwdhash = hashlib.pbkdf2_hmac('sha512',
88+
provided_password.encode('utf-8'),
89+
salt.encode('ascii'),
90+
200000)
91+
stored_password = self.passwordhash[64:]
92+
pwdhash = binascii.hexlify(pwdhash).decode('ascii')
93+
f_return = (pwdhash == stored_password)
94+
if f_return==True:
95+
self.loggedin = 1
96+
elif f_return == False:
97+
print ( "Sorry that username / password combination wasn't recognised. \nPlease try again")
98+
self.attempts += 1
99+
if self.attempts >= self.attempt_limit:
100+
# reset attempts
101+
self.attempts = 0
102+
# unlock account
103+
self.locked = 1
104+
# increment the punishment counter
105+
self.lockouts +=1
106+
# set the release time
107+
self.lockout_release = int(time.time()) + (self.lockout_period * self.lockouts)
108+
a_lockout[self.username] = {"r": self.lockout_release, "a": self.lockouts}
109+
110+
return f_return
111+
112+
def is_locked_out(self):
113+
f_locked=0
114+
if self.locked == 1:
115+
t_now = time.time()
116+
t_lockout = self.lockout_release
117+
if t_now < t_lockout:
118+
f_locked = 1
119+
else:
120+
self.locked=0
121+
self.lockout_release=0
122+
return f_locked
123+
124+
125+
def load_file():
126+
global a_users
127+
128+
if os.path.isfile(s_filename):
129+
with open(s_filename) as sec_file:
130+
a_users=json.load(sec_file)
131+
pass
132+
133+
else:
134+
# nothing to do
135+
pass
136+
137+
def write_file():
138+
with open(s_filename, "w") as sec_file:
139+
json.dump(a_users,sec_file)
140+
pass
141+
142+
# definitions
143+
s_filename = "security_checker_users.json"
144+
a_users = {}
145+
a_lockout = {}
146+
147+
# Load the security file first.
148+
load_file()
149+
150+
# debug
151+
#print (a_users)
152+
153+
while True:
154+
print ( "Password Verifier 2000 " )
155+
print ( "-----------------------")
156+
print ( "1. New User" )
157+
print ( "2. Existing User" )
158+
print ( "3. Print Users" )
159+
print ( "0. Exit" )
160+
print ( "-----------------------")
161+
print ( "" )
162+
i_menu = h.get_int("Please enter your selection",1,3)
163+
164+
if i_menu == 0:
165+
break
166+
elif i_menu == 1:
167+
s_usr = input( "Please enter your username [Enter to quit]: ")
168+
if s_usr=="":
169+
break
170+
171+
if s_usr in a_users.keys():
172+
print ( f"{s.REDON}Username {s_usr} is already taken.{s.COLOUROFF}")
173+
time.sleep(1)
174+
break
175+
176+
usr = User(s_usr)
177+
178+
while True:
179+
print ( f"Please enter a password for new user {s_usr}")
180+
s_p_1 = input ( "Please enter the new password: ")
181+
if s_p_1 == "":
182+
break
183+
s_p_2 = input ( "Please re-enter the new password: ")
184+
185+
if s_p_1 == s_p_2:
186+
if usr.check_password_complexity(s_p_1) == 1:
187+
usr.set_password(s_p_1)
188+
a_users[usr.username] = usr.passwordhash
189+
write_file()
190+
print ( f"{s.GREENON}User {usr.username} added successfully.{s.COLOUROFF} ")
191+
time.sleep (1)
192+
break
193+
else:
194+
print (f"{s.REDON}Password complexity rules not met.{s.COLOUROFF}\nPlease try again")
195+
else:
196+
print (f"{s.REDON}Passwords do not match.{s.COLOUROFF}\nPlease try again")
197+
elif i_menu == 2:
198+
199+
s_usr = input( "Please enter your username [Enter to quit]: ")
200+
if s_usr=="":
201+
break
202+
203+
print ( f"Welcome back {s_usr}.")
204+
if s_usr in a_users.keys():
205+
usr = User(s_usr)
206+
207+
if usr.is_locked_out():
208+
t_release = time.strftime("%d/%m/%Y %H:%M:%S", time.gmtime(usr.lockout_release))
209+
print ( f"{s.REDON}Sorry your account is locked out until {t_release}.{s.COLOUROFF}\nPlease try again later")
210+
time.sleep(1)
211+
continue
212+
else:
213+
f_loggedin=0
214+
while usr.locked == 0 and usr.loggedin == 0:
215+
s_pwd_try = input ( f"Please enter password for user {usr.username}: " )
216+
if usr.verify_password(s_pwd_try) == True:
217+
break
218+
219+
if usr.loggedin == 1:
220+
print ( f"{s.GREENON}Welcome to the Password Verifier 2000.{s.COLOUROFF}\n{s.ORANGEON}You successfully entered your username and password!{s.COLOUROFF}" )
221+
else:
222+
print ( f"{s.REDON}{s.REVON}Password attempts limit exceeded.{s.REVOFF}{s.COLOUROFF} \nYour account has been locked for 60 seconds." )
223+
else:
224+
print ( f"{s.REDON}Username not found. Please try again{s.COLOUROFF}" )
225+
226+
elif i_menu == 3:
227+
print ("System Users")
228+
print ("------------")
229+
230+
for this_user in a_users:
231+
usr = User(this_user)
232+
if usr.is_locked_out():
233+
s_colour = s.REDON
234+
else:
235+
s_colour = s.GREENON
236+
237+
print ( f"{s_colour}{usr.username}{s.COLOUROFF}" )
238+
239+
print ("------------")
240+
print ( "" )
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"Dave": "319bc54aaa80ec8196f6b21a8477dee75dbd7858d29020b3c5ebb88201799ddf53ff15de17ad0ccff87705bb8890858a7905d510735c5a3e2b2276628847c4ecba3715dccd25531eae9e5203370dca763586cb4ccc326da4683f5b64453692af"}
Binary file not shown.
76 Bytes
Binary file not shown.

Assessment/inc/helpers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ def get_int(input_prompt, min_val=int(1), max_val=int(100)):
66

77
try:
88
while not ((int_val >= min_val and int_val <= max_val)) :
9-
get_val=input(input_prompt + f" (Min: {str(min_val)} Max: {str(max_val)} Exit: 0)")
9+
get_val=input(input_prompt + f" (Min: {str(min_val)} Max: {str(max_val)} Exit: 0): ")
1010
int_val=int(get_val)
1111

1212
## exit if select 0

Assessment/inc/screen.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,7 @@
1111
BLUEON = "\033[34m" # Blue text.
1212
REDON= "\033[31m" # Red text.
1313
GREENON = "\033[32m" # Green text.
14+
ORANGEON = "\033[38;2;255;165;0m"
15+
YELLOWON = "\033[38;2;255;255;0m"
1416
COLOUROFF = "\033[0m" #Reset special formatting (such as colour).
1517
#print ( UP, end=CLEAR)

0 commit comments

Comments
 (0)