|
16 | 16 | Session, |
17 | 17 | SessionManager, |
18 | 18 | ) |
| 19 | +from marimo._server.tokens import AuthToken, SkewProtectionToken |
19 | 20 | from marimo._types.ids import SessionId |
20 | 21 |
|
21 | 22 | if TYPE_CHECKING: |
@@ -254,3 +255,140 @@ async def test_create_session_with_script_config_overrides( |
254 | 255 | ) |
255 | 256 |
|
256 | 257 | session.close() |
| 258 | + |
| 259 | + |
| 260 | +def test_session_manager_auth_token_edit_mode_with_provided_token(): |
| 261 | + """Test that provided auth token is used in EDIT mode""" |
| 262 | + provided_token = AuthToken("custom-edit-token") |
| 263 | + session_manager = SessionManager( |
| 264 | + file_router=AppFileRouter.new_file(), |
| 265 | + mode=SessionMode.EDIT, |
| 266 | + development_mode=False, |
| 267 | + quiet=False, |
| 268 | + include_code=True, |
| 269 | + lsp_server=MagicMock(spec=LspServer), |
| 270 | + config_manager=get_default_config_manager(current_path=None), |
| 271 | + cli_args={}, |
| 272 | + argv=None, |
| 273 | + auth_token=provided_token, |
| 274 | + redirect_console_to_browser=False, |
| 275 | + ttl_seconds=None, |
| 276 | + ) |
| 277 | + |
| 278 | + assert session_manager.auth_token is provided_token |
| 279 | + assert str(session_manager.auth_token) == "custom-edit-token" |
| 280 | + assert session_manager.skew_protection_token is not None |
| 281 | + |
| 282 | + |
| 283 | +def test_session_manager_auth_token_edit_mode_without_provided_token(): |
| 284 | + """Test that random auth token is generated in EDIT mode when none provided""" |
| 285 | + session_manager = SessionManager( |
| 286 | + file_router=AppFileRouter.new_file(), |
| 287 | + mode=SessionMode.EDIT, |
| 288 | + development_mode=False, |
| 289 | + quiet=False, |
| 290 | + include_code=True, |
| 291 | + lsp_server=MagicMock(spec=LspServer), |
| 292 | + config_manager=get_default_config_manager(current_path=None), |
| 293 | + cli_args={}, |
| 294 | + argv=None, |
| 295 | + auth_token=None, |
| 296 | + redirect_console_to_browser=False, |
| 297 | + ttl_seconds=None, |
| 298 | + ) |
| 299 | + |
| 300 | + # Should generate a random token (we can't predict the value, but it should exist) |
| 301 | + assert session_manager.auth_token is not None |
| 302 | + assert str(session_manager.auth_token) != "" |
| 303 | + # Verify it's a random token by checking length (AuthToken.random() uses token_urlsafe(16)) |
| 304 | + assert len(str(session_manager.auth_token)) > 10 |
| 305 | + assert session_manager.skew_protection_token is not None |
| 306 | + |
| 307 | + |
| 308 | +def test_session_manager_auth_token_run_mode_with_provided_token(): |
| 309 | + """Test that provided auth token is used in RUN mode""" |
| 310 | + provided_token = AuthToken("custom-run-token") |
| 311 | + session_manager = SessionManager( |
| 312 | + file_router=AppFileRouter.new_file(), |
| 313 | + mode=SessionMode.RUN, |
| 314 | + development_mode=False, |
| 315 | + quiet=False, |
| 316 | + include_code=True, |
| 317 | + lsp_server=MagicMock(spec=LspServer), |
| 318 | + config_manager=get_default_config_manager(current_path=None), |
| 319 | + cli_args={}, |
| 320 | + argv=None, |
| 321 | + auth_token=provided_token, |
| 322 | + redirect_console_to_browser=False, |
| 323 | + ttl_seconds=None, |
| 324 | + ) |
| 325 | + |
| 326 | + assert session_manager.auth_token is provided_token |
| 327 | + assert str(session_manager.auth_token) == "custom-run-token" |
| 328 | + assert str(session_manager.skew_protection_token) == str( |
| 329 | + SkewProtectionToken.from_code("") |
| 330 | + ) |
| 331 | + |
| 332 | + |
| 333 | +def test_session_manager_auth_token_run_mode_without_provided_token( |
| 334 | + tmp_path: Path, |
| 335 | +): |
| 336 | + """Test that code-based auth token is generated in RUN mode when none provided""" |
| 337 | + # Create a simple marimo file |
| 338 | + notebook_content = dedent( |
| 339 | + """\ |
| 340 | + import marimo |
| 341 | +
|
| 342 | + app = marimo.App() |
| 343 | +
|
| 344 | + @app.cell |
| 345 | + def test_cell(): |
| 346 | + "hello" |
| 347 | + return |
| 348 | + """ |
| 349 | + ) |
| 350 | + |
| 351 | + file_path = tmp_path / "test_notebook.py" |
| 352 | + file_path.write_text(notebook_content) |
| 353 | + |
| 354 | + session_manager = SessionManager( |
| 355 | + file_router=AppFileRouter.infer(str(file_path)), |
| 356 | + mode=SessionMode.RUN, |
| 357 | + development_mode=False, |
| 358 | + quiet=False, |
| 359 | + include_code=True, |
| 360 | + lsp_server=MagicMock(spec=LspServer), |
| 361 | + config_manager=get_default_config_manager(current_path=None), |
| 362 | + cli_args={}, |
| 363 | + argv=None, |
| 364 | + auth_token=None, |
| 365 | + redirect_console_to_browser=False, |
| 366 | + ttl_seconds=None, |
| 367 | + ) |
| 368 | + |
| 369 | + # Should generate a deterministic token based on code |
| 370 | + assert session_manager.auth_token is not None |
| 371 | + assert str(session_manager.auth_token) != "" |
| 372 | + assert str(session_manager.skew_protection_token) != "" |
| 373 | + |
| 374 | + # Create another session manager with the same code - should have same token |
| 375 | + session_manager2 = SessionManager( |
| 376 | + file_router=AppFileRouter.infer(str(file_path)), |
| 377 | + mode=SessionMode.RUN, |
| 378 | + development_mode=False, |
| 379 | + quiet=False, |
| 380 | + include_code=True, |
| 381 | + lsp_server=MagicMock(spec=LspServer), |
| 382 | + config_manager=get_default_config_manager(current_path=None), |
| 383 | + cli_args={}, |
| 384 | + argv=None, |
| 385 | + auth_token=None, |
| 386 | + redirect_console_to_browser=False, |
| 387 | + ttl_seconds=None, |
| 388 | + ) |
| 389 | + |
| 390 | + # Should have the same deterministic token |
| 391 | + assert str(session_manager.auth_token) == str(session_manager2.auth_token) |
| 392 | + assert str(session_manager.skew_protection_token) == str( |
| 393 | + session_manager2.skew_protection_token |
| 394 | + ) |
0 commit comments