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.
There doesn't seem to be a way to catch a 403 Forbidden error opening a
websocket with JavaScript, so this commit changes the behaviour to this:
open the websocket normally, send one "kick" message, close the
websocket.
This should eliminate the possibilty of the websocket-closing background
task closing a newly opened websocket that hasn't yet ponged our ping
(if we have even sent a ping yet).
As opposed to just the broadcaster token. This makes the broadcaster
username/password login mandatory, which previously was only mandatory
in the `auth_required` wrapper, but not elsewhere (so for example
leaving comments as the broadcaster was possible with the token only). A
less safe alternative to this would be to compare tokens in `check_auth`
once the Authorization header didn't match.
Also implements stack/queue behaviour where if the eyes limit would be
exceeded, either the new eyes cause the oldest eyes to be deleted OR
the new eyes aren't created at all. The default is the first option.
This commit adds the concept of eyes. One "eyes" is one instance of a
response to GET /stream.mp4. Currently the number of eyes clients can
have is unbounded, but this is a DoS vector.
Client and server both close the connection if they don't hear from the
other party after a timeout period. This is a failsafe and should
improve reliability.
Might not be necessary, but if it is then it prevents a sitation where a
websocket is still open but we've forgotten about it, so we will never
broadcast any new messages to it and the client will be practically frozen in
time until they disconnect and open a new websocket.
Also update the user's last_seen when the websocket is closed. This prevents a
user with js enabled who's actually idle being considered absent and being
rotated when their websocket accidentally closes for a few seconds.
The nojs button appears when the stream is online and the user is not watching.
The js button appears when the stream is online and the media element either
(1) is not using the network or (2) fires an error event.