Force absent users to do the access captcha again

Before this, if a request was not coming from an existing user (no token
in the request or no user with the given token), then and only then
would we send the access captcha.  This meant that if a user left a chat
message and became absent, they wouldn't be prompted to do the access
captcha again until their message was eventuallly rotated.  (While
messages exist we don't delete the users who posted them.)

This commit makes it so if user['verified'] is None, the user is kicked
and prompted with the access captcha.  This is automatically done for
absent users by a background task.
このコミットが含まれているのは:
n9k 2022-07-20 07:39:33 +00:00
コミット b1f5bbdecd
3個のファイルの変更34行の追加22行の削除

ファイルの表示

@ -137,6 +137,7 @@ def with_user_from(context, fallback_to_token=False, ignore_allowedness=False):
user['headers'] = tuple(context.headers) user['headers'] = tuple(context.headers)
if not ignore_allowedness: if not ignore_allowedness:
assert_allowedness(timestamp, user) assert_allowedness(timestamp, user)
if user is not None and user['verified'] is not None:
response = await f(timestamp, user, *args, **kwargs) response = await f(timestamp, user, *args, **kwargs)
elif fallback_to_token: elif fallback_to_token:
#assert not broadcaster #assert not broadcaster

ファイルの表示

@ -64,9 +64,13 @@ async def t_sunset_users(timestamp, iteration):
if iteration == 0: if iteration == 0:
return return
# Deverify absent users # De-access absent users
for user in get_absent_users(timestamp): absent_users = tuple(get_absent_users(timestamp))
user['verified'] = False for user in absent_users:
user['verified'] = None
# Absent users should have no connected websockets,
# so in normal operation this should always be a no-op
broadcast(users=absent_users, payload={'type': 'kick'})
# Remove as many absent users as possible # Remove as many absent users as possible

ファイルの表示

@ -54,7 +54,11 @@ async def websocket_outbound(queue, user):
await websocket.close(1001) await websocket.close(1001)
break break
else: else:
await websocket.send_json(payload) if user['verified'] is None:
await websocket.send_json({'type': 'kick'})
await websocket.close(1001)
else:
await websocket.send_json(payload)
async def websocket_inbound(queue, user): async def websocket_inbound(queue, user):
while True: while True:
@ -73,25 +77,28 @@ async def websocket_inbound(queue, user):
except AllowednessException: except AllowednessException:
payload = {'type': 'kick'} payload = {'type': 'kick'}
else: else:
try: if user['verified'] is None:
receipt_type, parsed = parse_websocket_data(receipt) payload = {'type': 'kick'}
except Malformed as e:
error , *_ = e.args
payload = {
'type': 'error',
'because': error,
}
else: else:
match receipt_type: try:
case WS.MESSAGE: receipt_type, parsed = parse_websocket_data(receipt)
handle = handle_inbound_message except Malformed as e:
case WS.APPEARANCE: error , *_ = e.args
handle = handle_inbound_appearance payload = {
case WS.CAPTCHA: 'type': 'error',
handle = handle_inbound_captcha 'because': error,
case WS.PONG: }
handle = handle_inbound_pong else:
payload = handle(timestamp, queue, user, *parsed) match receipt_type:
case WS.MESSAGE:
handle = handle_inbound_message
case WS.APPEARANCE:
handle = handle_inbound_appearance
case WS.CAPTCHA:
handle = handle_inbound_captcha
case WS.PONG:
handle = handle_inbound_pong
payload = handle(timestamp, queue, user, *parsed)
# Write to websocket # Write to websocket
if payload is not None: if payload is not None: