From d0f740dfeece1435ad5b5fddb21d787c1e507e95 Mon Sep 17 00:00:00 2001 From: Carlos Herrero Date: Tue, 26 Jul 2022 19:11:16 +0200 Subject: [PATCH] Adds anonymous users (#863) * Adds anonymous users * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * removes unused import * Removes random colors Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Zachary Sailer --- jupyter_server/auth/identity.py | 30 +++++++++-- jupyter_server/auth/utils.py | 93 +++++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+), 4 deletions(-) diff --git a/jupyter_server/auth/identity.py b/jupyter_server/auth/identity.py index 2431eaf0d8..133c3706fc 100644 --- a/jupyter_server/auth/identity.py +++ b/jupyter_server/auth/identity.py @@ -9,6 +9,7 @@ import binascii import datetime +import json import os import re import sys @@ -24,6 +25,7 @@ from jupyter_server.transutils import _i18n from .security import passwd_check, set_password +from .utils import get_anonymous_username # circular imports for type checking if TYPE_CHECKING: @@ -290,11 +292,28 @@ def user_to_cookie(self, user: User) -> str: Default is just the user's username. """ # default: username is enough - return user.username + cookie = json.dumps( + { + "username": user.username, + "name": user.name, + "display_name": user.display_name, + "initials": user.initials, + "color": user.color, + } + ) + return cookie def user_from_cookie(self, cookie_value: str) -> User | None: """Inverse of user_to_cookie""" - return User(username=cookie_value) + user = json.loads(cookie_value) + return User( + user["username"], + user["name"], + user["display_name"], + user["initials"], + None, + user["color"], + ) def get_cookie_name(self, handler: JupyterHandler) -> str: """Return the login cookie name @@ -396,7 +415,6 @@ def get_token(self, handler: JupyterHandler) -> str | None: - in URL parameters: ?token= - in header: Authorization: token """ - user_token = handler.get_argument("token", "") if not user_token: # get it from Authorization header @@ -447,8 +465,12 @@ def generate_anonymous_user(self, handler: JupyterHandler) -> User: but does not identify a user. """ user_id = uuid.uuid4().hex + moon = get_anonymous_username() + name = display_name = f"Anonymous {moon}" + initials = f"A{moon[0]}" + color = None handler.log.info(f"Generating new user for token-authenticated request: {user_id}") - return User(user_id) + return User(user_id, name, display_name, initials, None, color) def should_check_origin(self, handler: JupyterHandler) -> bool: """Should the Handler check for CORS origin validation? diff --git a/jupyter_server/auth/utils.py b/jupyter_server/auth/utils.py index d89127ac88..b0f790be1f 100644 --- a/jupyter_server/auth/utils.py +++ b/jupyter_server/auth/utils.py @@ -3,6 +3,7 @@ # Copyright (c) Jupyter Development Team. # Distributed under the terms of the Modified BSD License. import importlib +import random import re import warnings @@ -74,3 +75,95 @@ def match_url_to_resource(url, regex_mapping=None): pattern = re.compile(regex) if pattern.fullmatch(url): return auth_resource + + +# From https://en.wikipedia.org/wiki/Moons_of_Jupiter +moons_of_jupyter = [ + "Metis", + "Adrastea", + "Amalthea", + "Thebe", + "Io", + "Europa", + "Ganymede", + "Callisto", + "Themisto", + "Leda", + "Ersa", + "Pandia", + "Himalia", + "Lysithea", + "Elara", + "Dia", + "Carpo", + "Valetudo", + "Euporie", + "Eupheme", + # 'S/2003 J 18', + # 'S/2010 J 2', + "Helike", + # 'S/2003 J 16', + # 'S/2003 J 2', + "Euanthe", + # 'S/2017 J 7', + "Hermippe", + "Praxidike", + "Thyone", + "Thelxinoe", + # 'S/2017 J 3', + "Ananke", + "Mneme", + # 'S/2016 J 1', + "Orthosie", + "Harpalyke", + "Iocaste", + # 'S/2017 J 9', + # 'S/2003 J 12', + # 'S/2003 J 4', + "Erinome", + "Aitne", + "Herse", + "Taygete", + # 'S/2017 J 2', + # 'S/2017 J 6', + "Eukelade", + "Carme", + # 'S/2003 J 19', + "Isonoe", + # 'S/2003 J 10', + "Autonoe", + "Philophrosyne", + "Cyllene", + "Pasithee", + # 'S/2010 J 1', + "Pasiphae", + "Sponde", + # 'S/2017 J 8', + "Eurydome", + # 'S/2017 J 5', + "Kalyke", + "Hegemone", + "Kale", + "Kallichore", + # 'S/2011 J 1', + # 'S/2017 J 1', + "Chaldene", + "Arche", + "Eirene", + "Kore", + # 'S/2011 J 2', + # 'S/2003 J 9', + "Megaclite", + "Aoede", + # 'S/2003 J 23', + "Callirrhoe", + "Sinope", +] + + +def get_anonymous_username() -> str: + """ + Get a random user-name based on the moons of Jupyter. + This function returns names like "Anonymous Io" or "Anonymous Metis". + """ + return moons_of_jupyter[random.randint(0, len(moons_of_jupyter) - 1)]