1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
import base64
import json
import os
from cryptography.fernet import Fernet
from pathlib import Path
from django.conf import settings
from django.contrib.auth.models import User
from django.db import models
from troggle.core.models.troggle import DataIssue
"""This imports the registered troggle users, who are nearly-all, but not quite, Persons.
exceptions are "expo" and "expoadmin" which are created by the databaseReset.py import program.
This can import unencrypted email addresses but never exports them.
Passwords are only ever stored as hashes using the standard Django functions.
"""
todo = """
- Make all this work with New people who have never been on expo before
"""
USERS_FILE = "users.json"
ENCRYPTED_DIR = "encrypted"
def register_user(u, email, password=None, pwhash=None):
try:
if existing_user := User.objects.filter(username=u): # WALRUS
print(f" - deleting existing user '{existing_user[0]}' before importing")
existing_user[0].delete()
user = User.objects.create_user(u, email)
if pwhash:
user.password = pwhash
elif password:
user.set_password(password) # function creates hash and stores hash
print(f" # hashing provided clear-text password {password} to make pwhash for user {u}")
else:
user.set_password('secret') # function creates hash and stores hash
print(f" # hashing 'secret' password to make pwhash for user {u}")
user.is_staff = False
user.is_superuser = False
user.save()
print(f" - receated and reset user '{user}'")
except Exception as e:
print(f"Exception <{e}>\n{len(User.objects.all())} users now in db:\n{User.objects.all()}")
raise
return user
def get_encryptor():
key = settings.LONGTERM_SECRET_KEY # Django generated
k = base64.urlsafe_b64encode(key.encode("utf8")[:32]) # make Fernet compatible
f = Fernet(k)
return f
def load_users():
"""These are the previously registered users of the troggle system.
"""
PARSER_USERS = "_users"
DataIssue.objects.filter(parser=PARSER_USERS).delete()
f = get_encryptor()
jsonfile = settings.EXPOWEB / ENCRYPTED_DIR / USERS_FILE
jsonurl = "/" + str(Path(ENCRYPTED_DIR) / USERS_FILE)
if not (jsonfile.is_file()):
message = f" ! Users json file does not exist: '{jsonfile}'"
DataIssue.objects.create(parser=PARSER_USERS, message=message)
print(message)
return None
with open(jsonfile, 'r', encoding='utf-8') as json_f:
message = ""
try:
registered_users_dict = json.load(json_f)
except FileNotFoundError:
message = f"File {jsonfile} not found!"
except json.JSONDecodeError:
message = f"Invalid JSON format! - JSONDecodeError for {jsonfile}"
except Exception as e:
message = f"! Troggle USERs. Failed to load {jsonfile} JSON file. Exception <{e}>"
if message:
print(message)
DataIssue.objects.update_or_create(parser=PARSER_USERS, message=message, url=jsonurl)
return None
users_list = registered_users_dict["registered_users"]
print(f" - {len(users_list)} users read from JSON")
for userdata in users_list:
if not userdata["username"]:
message = f"! user: BAD username for {userdata} in {jsonfile}"
print(message)
DataIssue.objects.update_or_create(parser=PARSER_USERS, message=message, url=jsonurl)
continue
else:
if userdata["username"] in [ "expo", "expoadmin" ]:
continue
if "encrypted" not in userdata:
userdata["encrypted"] = True
try:
u = userdata["username"]
email = userdata["email"]
if userdata["encrypted"]:
email = f.decrypt(email).decode()
print(f" - user: '{u} <{email}>' ")
except Exception as e:
print(f"Exception <{e}>\n")
formatted_json = json.dumps(userdata, indent=4)
print(formatted_json)
raise
return None
if "pwhash" in userdata:
pwhash = userdata["pwhash"]
new_user = register_user(u, email, pwhash=pwhash)
else:
new_user = register_user(u, email)
# save_users() no need on initial parsing
|