Repository navigation
Expand file tree
/
Copy pathauth.py
More file actions
132 lines (102 loc) · 3.87 KB
/
Copy pathauth.py
File metadata and controls
132 lines (102 loc) · 3.87 KB
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
122
123
124
125
126
127
128
129
130
131
132
import secrets
import threading
import os
import shutil
from logger import print
print("auth module loaded.")
stored = {}
if os.path.exists("authdata"):
if os.path.isfile("authdata"):
print("authentication data: removed (should not be a file)")
os.remove("authdata")
os.makedirs("authdata")
else:
print("authentication data: OK")
else:
print("authentication data: not created")
os.makedirs("authdata")
for file in os.listdir("authdata"):
path = os.path.join("authdata", file)
if os.path.isfile(path):
with open(path, "r", encoding="utf-8") as f:
stored[file] = f.read().strip().splitlines()
class TokenStore:
def __init__(self):
print("Auth module store initialized.")
self._tokens = {}
self._lock = threading.Lock()
for key, value in stored.items():
for token in value:
self._tokens[token] = {"email": key.strip().lower()}
print(f"Re-activated a token for {key.strip().lower()}")
def _save(self, email, token):
path = os.path.join("authdata", email.strip().lower())
with open(path, "a", encoding="utf-8") as f:
f.write(token + "\n")
def issue(self, email):
token = secrets.token_urlsafe(32)
with self._lock:
self._tokens[token] = {
"email": email.strip().lower(),
}
return token
def validate(self, token):
if not token:
print("Cannot validate empty token.")
return None
with self._lock:
record = self._tokens.get(token)
if record is None:
print("Invalid token.")
return None
result = dict(record)
print(f"Validated token for {result['email']}")
return result
def revoke(self, token):
if not token:
print("Cannot revoke empty token.")
return False
with self._lock:
record = self._tokens.pop(token, None)
if record is not None:
path = os.path.join("authdata", record["email"])
if os.path.isfile(path):
with open(path, "r", encoding="utf-8") as f:
tokens = f.read().splitlines()
with open(path, "w", encoding="utf-8") as f:
for saved_token in tokens:
if saved_token != token:
f.write(saved_token + "\n")
print(f"Token revoked: {record is not None}")
return record is not None
def clear(self):
with self._lock:
os.makedirs("authdata", exist_ok=True)
# Group tokens by account.
stored = {}
for token, record in self._tokens.items():
email = record["email"]
stored.setdefault(email, []).append(token)
# Write the current state to disk.
for file in os.listdir("authdata"):
path = os.path.join("authdata", file)
if os.path.isfile(path):
os.remove(path)
print(f"removed outdated status: {path}")
for email, tokens in stored.items():
path = os.path.join("authdata", email)
with open(path, "w", encoding="utf-8") as f:
f.write("\n".join(tokens) + "\n")
print(f"wrote up-to-date status: {path}")
if self._tokens:
cl = 1
print("Clearing tokens...")
else:
cl = 0
print("No tokens to clear")
if cl == 1:
while self._tokens:
token = next(iter(self._tokens))
self._tokens.pop(token)
print(f"Unloaded a token.")
print(f"Cleared tokens")