AGPL-3.0-only, a source link in the app, and everything on dev since #5 #6

Merged
bvandeusen merged 214 commits from dev into main 2026-10-21 21:40:00 -04:00
Showing only changes of commit 31d8b1e65b - Show all commits
+9 -18
View File
@@ -659,21 +659,9 @@ async def revoke_own_device():
# using" is meaningless rather than merely unauthorized. The web app
# revokes by id.
return json_error("no device token was presented", 400)
async with session_scope() as db:
row = await db.scalar(
select(DeviceToken).where(
DeviceToken.token_hash == hash_token(token),
# Owner-scoped like every other device route. The hash already pins
# a single row; the guarantee shouldn't rest on one column.
DeviceToken.user_id == g.user_id,
)
)
if row is None:
return not_found()
await db.delete(row)
await db.commit()
await audit.record(audit.DEVICE_UNLINKED, user_id=g.user_id, email=await _email_of(db), detail=row.name)
return jsonify({"ok": True})
# Owner-scoped like every other device route. The hash already pins a single
# row; the guarantee shouldn't rest on one column.
return await _unlink_device(DeviceToken.token_hash == hash_token(token))
@bp.delete("/devices/<device_id>")
@@ -682,10 +670,13 @@ async def revoke_device(device_id: str):
did = parse_uuid(device_id)
if did is None:
return not_found()
return await _unlink_device(DeviceToken.id == did)
async def _unlink_device(which):
"""Delete the caller's device token matching `which`, and say so in the audit log."""
async with session_scope() as db:
row = await db.scalar(
select(DeviceToken).where(DeviceToken.id == did, DeviceToken.user_id == g.user_id)
)
row = await db.scalar(select(DeviceToken).where(which, DeviceToken.user_id == g.user_id))
if row is None:
return not_found()
await db.delete(row)