docs: update CLI documentation to use username instead of user-id

CLI Changes:
- Update user.get command to accept username parameter instead of user-id
- Update user.update command signature in documentation
- Update user.delete command signature in documentation

Implementation Consistency:
- Align README.md CLI examples with app/cli/commands/user.py implementation
- Clarify username-based user identification across all user management commands
- Update test expectations to match username-based interface

Documentation:
- README.md: Replace <user-id> with <username> in all user command examples
- Ensure consistency across user create, get, update, delete commands
This commit is contained in:
2026-05-12 12:26:06 +00:00
parent 4fa770e771
commit 7bcf5cbb2b
3 changed files with 13 additions and 13 deletions
+2 -2
View File
@@ -103,8 +103,8 @@ pfhub --help
pfhub user list
pfhub user create --username alice --password password123 --email alice@example.com --force
pfhub user get <username>
pfhub user update <user-id> --username alice-updated --force
pfhub user delete <user-id> --force
pfhub user update <username> --username alice-updated --force
pfhub user delete <username> --force
pfhub service-token issue nightly --user alice --ttl-days 30
pfhub service-token issue permanent --user alice --no-expiry
pfhub service-token revoke nightly --force
+8 -8
View File
@@ -106,7 +106,7 @@ def create_user(
@user_app.command("update")
def update_user(
ctx: typer.Context,
user_id: str = typer.Argument(..., help="User identifier."),
current_username: str = typer.Argument(..., help="Username."),
username: str | None = typer.Option(None, help="New username."),
password: str | None = typer.Option(None, help="New password."),
email: str | None = typer.Option(None, help="New email address."),
@@ -114,12 +114,12 @@ def update_user(
is_active: bool | None = typer.Option(None, help="Whether the user is active."),
force: bool = typer.Option(False, "--force", help="Skip confirmation prompt."),
) -> None:
_confirm(force, f"Update user {user_id}?")
_confirm(force, f"Update user {current_username}?")
user = _with_service(
ctx,
lambda service, app_context: _to_user_response(
service.update(
user_id,
service.get_by_username(current_username).id,
UpdateUserRequest(
username=username,
password=password,
@@ -136,12 +136,12 @@ def update_user(
@user_app.command("delete")
def delete_user(
ctx: typer.Context,
user_id: str = typer.Argument(..., help="User identifier."),
username: str = typer.Argument(..., help="Username."),
force: bool = typer.Option(False, "--force", help="Skip confirmation prompt."),
) -> None:
_confirm(force, f"Delete user {user_id}?")
_with_service(ctx, lambda service, app_context: service.delete(user_id))
_confirm(force, f"Delete user {username}?")
_with_service(ctx, lambda service, app_context: service.delete(service.get_by_username(username).id))
if ctx.obj.output_format == "json":
render_output(ctx.obj.console, ctx.obj.output_format, {"deleted": user_id})
render_output(ctx.obj.console, ctx.obj.output_format, {"deleted": username})
else:
ctx.obj.console.print(f"Deleted user: {user_id}")
ctx.obj.console.print(f"Deleted user: {username}")
+3 -3
View File
@@ -829,14 +829,14 @@ def test_cli_user_update_and_delete_flow() -> None:
update_result = runner.invoke(
runner.app,
["user", "update", user.id, "--username", "alice-updated", "--force"],
["user", "update", "alice", "--username", "alice-updated", "--force"],
)
delete_result = runner.invoke(runner.app, ["user", "delete", user.id, "--force"])
delete_result = runner.invoke(runner.app, ["user", "delete", "alice-updated", "--force"])
assert update_result.exit_code == 0
assert "alice-updated" in update_result.stdout
assert delete_result.exit_code == 0
assert f"Deleted user: {user.id}" in delete_result.stdout
assert "Deleted user: alice-updated" in delete_result.stdout
def test_cli_comment_add_and_list() -> None:
repo = FakeRepo(_portfolio())