Skip to content

Commit d0f740d

Browse files
hbcarlospre-commit-ci[bot]Zsailer
authored andcommitted
Adds anonymous users (jupyter-server#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 <[email protected]>
1 parent 63446c5 commit d0f740d

File tree

2 files changed

+119
-4
lines changed

2 files changed

+119
-4
lines changed

jupyter_server/auth/identity.py

+26-4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import binascii
1111
import datetime
12+
import json
1213
import os
1314
import re
1415
import sys
@@ -24,6 +25,7 @@
2425
from jupyter_server.transutils import _i18n
2526

2627
from .security import passwd_check, set_password
28+
from .utils import get_anonymous_username
2729

2830
# circular imports for type checking
2931
if TYPE_CHECKING:
@@ -290,11 +292,28 @@ def user_to_cookie(self, user: User) -> str:
290292
Default is just the user's username.
291293
"""
292294
# default: username is enough
293-
return user.username
295+
cookie = json.dumps(
296+
{
297+
"username": user.username,
298+
"name": user.name,
299+
"display_name": user.display_name,
300+
"initials": user.initials,
301+
"color": user.color,
302+
}
303+
)
304+
return cookie
294305

295306
def user_from_cookie(self, cookie_value: str) -> User | None:
296307
"""Inverse of user_to_cookie"""
297-
return User(username=cookie_value)
308+
user = json.loads(cookie_value)
309+
return User(
310+
user["username"],
311+
user["name"],
312+
user["display_name"],
313+
user["initials"],
314+
None,
315+
user["color"],
316+
)
298317

299318
def get_cookie_name(self, handler: JupyterHandler) -> str:
300319
"""Return the login cookie name
@@ -396,7 +415,6 @@ def get_token(self, handler: JupyterHandler) -> str | None:
396415
- in URL parameters: ?token=<token>
397416
- in header: Authorization: token <token>
398417
"""
399-
400418
user_token = handler.get_argument("token", "")
401419
if not user_token:
402420
# get it from Authorization header
@@ -447,8 +465,12 @@ def generate_anonymous_user(self, handler: JupyterHandler) -> User:
447465
but does not identify a user.
448466
"""
449467
user_id = uuid.uuid4().hex
468+
moon = get_anonymous_username()
469+
name = display_name = f"Anonymous {moon}"
470+
initials = f"A{moon[0]}"
471+
color = None
450472
handler.log.info(f"Generating new user for token-authenticated request: {user_id}")
451-
return User(user_id)
473+
return User(user_id, name, display_name, initials, None, color)
452474

453475
def should_check_origin(self, handler: JupyterHandler) -> bool:
454476
"""Should the Handler check for CORS origin validation?

jupyter_server/auth/utils.py

+93
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# Copyright (c) Jupyter Development Team.
44
# Distributed under the terms of the Modified BSD License.
55
import importlib
6+
import random
67
import re
78
import warnings
89

@@ -74,3 +75,95 @@ def match_url_to_resource(url, regex_mapping=None):
7475
pattern = re.compile(regex)
7576
if pattern.fullmatch(url):
7677
return auth_resource
78+
79+
80+
# From https://en.wikipedia.org/wiki/Moons_of_Jupiter
81+
moons_of_jupyter = [
82+
"Metis",
83+
"Adrastea",
84+
"Amalthea",
85+
"Thebe",
86+
"Io",
87+
"Europa",
88+
"Ganymede",
89+
"Callisto",
90+
"Themisto",
91+
"Leda",
92+
"Ersa",
93+
"Pandia",
94+
"Himalia",
95+
"Lysithea",
96+
"Elara",
97+
"Dia",
98+
"Carpo",
99+
"Valetudo",
100+
"Euporie",
101+
"Eupheme",
102+
# 'S/2003 J 18',
103+
# 'S/2010 J 2',
104+
"Helike",
105+
# 'S/2003 J 16',
106+
# 'S/2003 J 2',
107+
"Euanthe",
108+
# 'S/2017 J 7',
109+
"Hermippe",
110+
"Praxidike",
111+
"Thyone",
112+
"Thelxinoe",
113+
# 'S/2017 J 3',
114+
"Ananke",
115+
"Mneme",
116+
# 'S/2016 J 1',
117+
"Orthosie",
118+
"Harpalyke",
119+
"Iocaste",
120+
# 'S/2017 J 9',
121+
# 'S/2003 J 12',
122+
# 'S/2003 J 4',
123+
"Erinome",
124+
"Aitne",
125+
"Herse",
126+
"Taygete",
127+
# 'S/2017 J 2',
128+
# 'S/2017 J 6',
129+
"Eukelade",
130+
"Carme",
131+
# 'S/2003 J 19',
132+
"Isonoe",
133+
# 'S/2003 J 10',
134+
"Autonoe",
135+
"Philophrosyne",
136+
"Cyllene",
137+
"Pasithee",
138+
# 'S/2010 J 1',
139+
"Pasiphae",
140+
"Sponde",
141+
# 'S/2017 J 8',
142+
"Eurydome",
143+
# 'S/2017 J 5',
144+
"Kalyke",
145+
"Hegemone",
146+
"Kale",
147+
"Kallichore",
148+
# 'S/2011 J 1',
149+
# 'S/2017 J 1',
150+
"Chaldene",
151+
"Arche",
152+
"Eirene",
153+
"Kore",
154+
# 'S/2011 J 2',
155+
# 'S/2003 J 9',
156+
"Megaclite",
157+
"Aoede",
158+
# 'S/2003 J 23',
159+
"Callirrhoe",
160+
"Sinope",
161+
]
162+
163+
164+
def get_anonymous_username() -> str:
165+
"""
166+
Get a random user-name based on the moons of Jupyter.
167+
This function returns names like "Anonymous Io" or "Anonymous Metis".
168+
"""
169+
return moons_of_jupyter[random.randint(0, len(moons_of_jupyter) - 1)]

0 commit comments

Comments
 (0)