diff --git a/muxplex/cli.py b/muxplex/cli.py index 1134b09..38c7a1a 100644 --- a/muxplex/cli.py +++ b/muxplex/cli.py @@ -9,11 +9,18 @@ from pathlib import Path _system_service_path = Path("/etc/systemd/system/muxplex.service") -def serve(host: str = "0.0.0.0", port: int = 8088) -> None: +def serve( + host: str = "127.0.0.1", + port: int = 8088, + auth: str = "pam", + session_ttl: int = 604800, +) -> None: """Start the muxplex server.""" import uvicorn # noqa: PLC0415 os.environ.setdefault("MUXPLEX_PORT", str(port)) + os.environ.setdefault("MUXPLEX_AUTH", auth) + os.environ.setdefault("MUXPLEX_SESSION_TTL", str(session_ttl)) from muxplex.main import app # noqa: PLC0415 @@ -69,9 +76,22 @@ def main() -> None: description="muxplex — web-based tmux session dashboard", ) parser.add_argument( - "--host", default="0.0.0.0", help="Bind host (default: 0.0.0.0)" + "--host", default="127.0.0.1", help="Bind host (default: 127.0.0.1)" ) parser.add_argument("--port", type=int, default=8088, help="Port (default: 8088)") + parser.add_argument( + "--auth", + choices=["pam", "password"], + default="pam", + help="Authentication method: pam or password (default: pam)", + ) + parser.add_argument( + "--session-ttl", + type=int, + default=604800, + dest="session_ttl", + help="Session TTL in seconds (default: 604800 = 7 days; 0 = browser session)", + ) sub = parser.add_subparsers(dest="command") sub.add_parser("serve", help="Start the server (default)") @@ -86,4 +106,6 @@ def main() -> None: if args.command == "install-service": install_service(system=args.system) else: - serve(host=args.host, port=args.port) + serve( + host=args.host, port=args.port, auth=args.auth, session_ttl=args.session_ttl + ) diff --git a/muxplex/tests/test_cli.py b/muxplex/tests/test_cli.py index 18a0667..33877d7 100644 --- a/muxplex/tests/test_cli.py +++ b/muxplex/tests/test_cli.py @@ -10,13 +10,15 @@ def test_cli_module_importable(): def test_main_calls_serve_by_default(): - """Calling main() with no args must invoke serve().""" + """Calling main() with no args must invoke serve() with new defaults.""" from muxplex.cli import main with patch("muxplex.cli.serve") as mock_serve: with patch("sys.argv", ["muxplex"]): main() - mock_serve.assert_called_once_with(host="0.0.0.0", port=8088) + mock_serve.assert_called_once_with( + host="127.0.0.1", port=8088, auth="pam", session_ttl=604800 + ) def test_main_passes_custom_host_and_port(): @@ -24,9 +26,46 @@ def test_main_passes_custom_host_and_port(): from muxplex.cli import main with patch("muxplex.cli.serve") as mock_serve: - with patch("sys.argv", ["muxplex", "--host", "127.0.0.1", "--port", "9000"]): + with patch("sys.argv", ["muxplex", "--host", "192.168.1.1", "--port", "9000"]): main() - mock_serve.assert_called_once_with(host="127.0.0.1", port=9000) + mock_serve.assert_called_once_with( + host="192.168.1.1", port=9000, auth="pam", session_ttl=604800 + ) + + +def test_main_default_host_is_localhost(): + """Default --host must be 127.0.0.1 (not 0.0.0.0).""" + from muxplex.cli import main + + with patch("muxplex.cli.serve") as mock_serve: + with patch("sys.argv", ["muxplex"]): + main() + _, kwargs = mock_serve.call_args + assert kwargs["host"] == "127.0.0.1" + + +def test_main_passes_auth_flag(): + """main() with --auth password must forward auth='password' to serve().""" + from muxplex.cli import main + + with patch("muxplex.cli.serve") as mock_serve: + with patch("sys.argv", ["muxplex", "--auth", "password"]): + main() + mock_serve.assert_called_once_with( + host="127.0.0.1", port=8088, auth="password", session_ttl=604800 + ) + + +def test_main_passes_session_ttl_flag(): + """main() with --session-ttl 3600 must forward session_ttl=3600 to serve().""" + from muxplex.cli import main + + with patch("muxplex.cli.serve") as mock_serve: + with patch("sys.argv", ["muxplex", "--session-ttl", "3600"]): + main() + mock_serve.assert_called_once_with( + host="127.0.0.1", port=8088, auth="pam", session_ttl=3600 + ) def test_main_install_service_subcommand():