feat(auth): add yt-cli style auth login --base-url #10

Merged
David merged 1 commit from feat/auth-login into main 2026-05-13 21:03:32 +02:00
Owner

Summary

Adds youtrack-cli auth login --base-url <url> matching the yt-cli flow. Trims trailing slashes off the URL, prompts for the API token with no echo (rpassword), verifies it against the server, and only then writes URL + token to ~/.youtrack-cli.yaml (still 0600 via the existing Config::save). Existing config set/view/show left alone for board/sprint defaults; only the "missing config" error hint now points at auth login.

Flow

$ youtrack-cli auth login --base-url https://yourdomain.youtrack.cloud
API token: ************
Authenticated as jdoe (Jane Doe) on https://yourdomain.youtrack.cloud
Saved credentials to /home/you/.youtrack-cli.yaml

On 401 or 403 the message is token rejected by <url> (HTTP 401); not saved and the config file is untouched. On other non-2xx the response body is echoed back. Empty token after trim is rejected before any HTTP call.

What changed

  • src/cli.rs: new Auth { cmd: AuthCommands } variant with Login(AuthLoginArgs { base_url }).
  • src/commands/auth/: new module. login.rs does the prompt + verify (GET /api/users/me?fields=login,fullName) + save; mod.rs dispatches.
  • src/commands/mod.rs: register and dispatch the new module.
  • src/config.rs: error hint when the config file is missing now points at auth login --base-url <url>.
  • Cargo.toml/Cargo.lock: add rpassword = "7". No other deps changed.

Tests

  • verify_token_returns_user_on_200 wiremock-asserts the exact URL/query/header shape and parses the response.
  • verify_token_rejects_401: 401 surfaces "token rejected" and never writes.
  • verify_token_rejects_500: non-401/403 errors include status + body in the message.
  • trim_trailing_slash unit test on the URL normalizer.
  • cargo fmt --check, cargo clippy --all-targets -- -D warnings, cargo test --all-targets all green locally.

Test plan

  • cargo run -- auth login --base-url https://<your-instance> with a real token: confirms the masked-prompt UX and the saved YAML.
  • cargo run -- auth login --base-url https://<your-instance> with a deliberately bad token: confirms the file is not touched (stat -c %Y ~/.youtrack-cli.yaml before and after).
  • cargo run -- config show after a successful login still renders the masked token from the new YAML.

Follow-ups (out of scope)

  • auth logout and auth status if you want the full yt-cli auth surface; this PR only ships login per the brief.
  • Switching config set url/token to a deprecation warning, once auth login is the documented path.
## Summary Adds `youtrack-cli auth login --base-url <url>` matching the yt-cli flow. Trims trailing slashes off the URL, prompts for the API token with no echo (rpassword), verifies it against the server, and only then writes URL + token to `~/.youtrack-cli.yaml` (still 0600 via the existing `Config::save`). Existing `config set/view/show` left alone for board/sprint defaults; only the "missing config" error hint now points at `auth login`. ## Flow ``` $ youtrack-cli auth login --base-url https://yourdomain.youtrack.cloud API token: ************ Authenticated as jdoe (Jane Doe) on https://yourdomain.youtrack.cloud Saved credentials to /home/you/.youtrack-cli.yaml ``` On 401 or 403 the message is `token rejected by <url> (HTTP 401); not saved` and the config file is untouched. On other non-2xx the response body is echoed back. Empty token after trim is rejected before any HTTP call. ## What changed - `src/cli.rs`: new `Auth { cmd: AuthCommands }` variant with `Login(AuthLoginArgs { base_url })`. - `src/commands/auth/`: new module. `login.rs` does the prompt + verify (`GET /api/users/me?fields=login,fullName`) + save; `mod.rs` dispatches. - `src/commands/mod.rs`: register and dispatch the new module. - `src/config.rs`: error hint when the config file is missing now points at `auth login --base-url <url>`. - `Cargo.toml`/`Cargo.lock`: add `rpassword = "7"`. No other deps changed. ## Tests - `verify_token_returns_user_on_200` wiremock-asserts the exact URL/query/header shape and parses the response. - `verify_token_rejects_401`: 401 surfaces "token rejected" and never writes. - `verify_token_rejects_500`: non-401/403 errors include status + body in the message. - `trim_trailing_slash` unit test on the URL normalizer. - `cargo fmt --check`, `cargo clippy --all-targets -- -D warnings`, `cargo test --all-targets` all green locally. ## Test plan - [ ] `cargo run -- auth login --base-url https://<your-instance>` with a real token: confirms the masked-prompt UX and the saved YAML. - [ ] `cargo run -- auth login --base-url https://<your-instance>` with a deliberately bad token: confirms the file is not touched (`stat -c %Y ~/.youtrack-cli.yaml` before and after). - [ ] `cargo run -- config show` after a successful login still renders the masked token from the new YAML. ## Follow-ups (out of scope) - `auth logout` and `auth status` if you want the full yt-cli auth surface; this PR only ships `login` per the brief. - Switching `config set url/token` to a deprecation warning, once `auth login` is the documented path.
feat(auth): add auth login --base-url for credential setup
All checks were successful
Check / fmt + clippy + build + tests (pull_request) Successful in 17s
Create release / Create release from merged PR (pull_request) Has been skipped
2052ef0ba7
New `youtrack-cli auth login --base-url <url>` mirrors the yt-cli flow. It trims trailing slashes off the base URL, hidden-prompts for an API token via rpassword, calls `GET <url>/api/users/me?fields=login,fullName` with `Authorization: Bearer <token>`, and only writes the URL + token to `~/.youtrack-cli.yaml` after the request returns 2xx. On 401/403 the user is told the token was rejected and nothing is saved; on other non-2xx the response body is echoed back for diagnosis. The existing `config set/view/show` group is unchanged so board/sprint defaults still flow through it; only the "missing config" error hint now points at `auth login` instead of `config set`. Tests use wiremock to cover the 200, 401, and 500 paths, plus a unit test for the base URL normalizer.
David merged commit a3e7119a28 into main 2026-05-13 21:03:32 +02:00
David deleted branch feat/auth-login 2026-05-13 21:03:32 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
pandoras-box/youtrack-cli!10
No description provided.