Skip to content

Commit 2db8c82

Browse files
authored
Account anonymization POST handler (internetarchive#11053)
* Add handler for account anonymization requests * Enable testing account anonymization Adds handling for a `test` query parameter. if `test` is "true", the account anonymization will not occur. * Update handler for authorization headers
1 parent 2de9e7d commit 2db8c82

File tree

1 file changed

+57
-0
lines changed

1 file changed

+57
-0
lines changed

openlibrary/plugins/upstream/account.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1170,6 +1170,63 @@ def GET(self):
11701170
# return render.notfound(path, create=False)
11711171

11721172

1173+
class account_anonymization_json(delegate.page):
1174+
path = "/account/anonymize"
1175+
encoding = "json"
1176+
1177+
def POST(self):
1178+
i = web.input(test='false')
1179+
test = i.test == "true"
1180+
1181+
# Validate request origin
1182+
if not self._validate_headers():
1183+
raise web.HTTPError("403 Forbidden", {"Content-Type": "application/json"})
1184+
1185+
# Get S3 keys from request header
1186+
try:
1187+
s3_access, s3_secret = self._parse_auth_header()
1188+
except ValueError:
1189+
raise web.HTTPError("400 Bad Request", {"Content-Type": "application/json"})
1190+
1191+
# Fetch and anonymize account
1192+
xauthn_response = InternetArchiveAccount.s3auth(s3_access, s3_secret)
1193+
if 'error' in xauthn_response:
1194+
raise web.HTTPError("404 Not Found", {"Content-Type": "application/json"})
1195+
1196+
ol_account = OpenLibraryAccount.get(link=xauthn_response.get('itemname', ''))
1197+
if not ol_account:
1198+
raise web.HTTPError("404 Not Found", {"Content-Type": "application/json"})
1199+
1200+
try:
1201+
result = ol_account.anonymize(test=test)
1202+
except Exception:
1203+
raise web.HTTPError(
1204+
"500 Internal Server Error", {"Content-Type": "application/json"}
1205+
)
1206+
1207+
raise web.HTTPError(
1208+
"200 OK", {"Content-Type": "application/json"}, data=json.dumps(result)
1209+
)
1210+
1211+
def _validate_headers(self):
1212+
origin = web.ctx.env.get('HTTP_ORIGIN') or web.ctx.env.get('HTTP_REFERER')
1213+
if not origin:
1214+
return False
1215+
1216+
parsed_origin = urlparse(origin)
1217+
host = parsed_origin.hostname
1218+
return host == "archive.org" or host.endswith(".archive.org")
1219+
1220+
def _parse_auth_header(self):
1221+
header_value = web.ctx.env.get("HTTP_AUTHORIZATION", "")
1222+
try:
1223+
_, keys = header_value.split('LOW ', 1)
1224+
s3_access, s3_secret = keys.split(':', 1)
1225+
return s3_access.strip(), s3_secret.strip()
1226+
except ValueError:
1227+
raise ValueError("Malformed Authorization Header")
1228+
1229+
11731230
def as_admin(f):
11741231
"""Infobase allows some requests only from admin user. This decorator logs in as admin, executes the function and clears the admin credentials."""
11751232

0 commit comments

Comments
 (0)