Strip remote credentials without deleting remotes

This commit is contained in:
mpabi
2026-04-27 19:59:45 +02:00
parent e60b7c9148
commit ffd12c9905
4 changed files with 31 additions and 18 deletions
+2 -2
View File
@@ -180,8 +180,8 @@ uprawnien; bez zgodnego wpisu maja wartosc `?????????`, `?????` albo `????`.
Zapis z remote do `tokens.json` robi `tokens sync remote r1`. Zapis z remote do `tokens.json` robi `tokens sync remote r1`.
Odczyt `valid` i uprawnien z API robi `tokens update r1`. Odczyt `valid` i uprawnien z API robi `tokens update r1`.
Zapis z `tokens.json` do remota robi `tokens sync store r1`. Zapis z `tokens.json` do remota robi `tokens sync store r1`.
Usuniecie wpisu robi `tokens remove store r1`, a usuniecie git remota Usuniecie wpisu robi `tokens remove store r1`, a usuniecie poswiadczen z URL-a
`tokens remove remote r1`. git remota robi `tokens remove remote r1`.
Kolumna `valid` oznacza, czy token zostal zaakceptowany przez API teraz. Kolumna `valid` oznacza, czy token zostal zaakceptowany przez API teraz.
Jesli przy tokenie w `tokens.json` zapiszesz `expires_at`, `valid` moze pokazac Jesli przy tokenie w `tokens.json` zapiszesz `expires_at`, `valid` moze pokazac
date wygasniecia; bez daty poprawny token pokazuje `forever`. date wygasniecia; bez daty poprawny token pokazuje `forever`.
+5 -3
View File
@@ -437,15 +437,17 @@ Przyklad:
## `tokens remove store|remote|both REMOTE_ID` ## `tokens remove store|remote|both REMOTE_ID`
Usuwa rekord z `tokens.json`, git remote albo oba miejsca. Usuwa rekord z `tokens.json`, poswiadczenia z URL-a git remota albo oba
miejsca. `tokens remove remote` zostawia sam git remote, ale zapisuje jego URL
bez `LOGIN:TOKEN@`.
Domyslnym repo dla `remote` i `both` jest repo, w ktorym lezy `rvctl`. Inne Domyslnym repo dla `remote` i `both` jest repo, w ktorym lezy `rvctl`. Inne
repo mozna wskazac przez `--repo PATH`. repo mozna wskazac przez `--repo PATH`.
Przelaczniki: Przelaczniki:
- `--repo PATH` - `--repo PATH`
Repo, z ktorego ma byc usuniety git remote. Domyslnie repo zawierajace Repo, w ktorym ma byc wyczyszczony URL git remota. Domyslnie repo
`rvctl`. zawierajace `rvctl`.
- `--server ENDPOINT` - `--server ENDPOINT`
Endpoint serwera, jesli `tokens.json` ma kilka rekordow o tym samym `id`. Endpoint serwera, jesli `tokens.json` ma kilka rekordow o tym samym `id`.
- `--dry-run` - `--dry-run`
+3 -1
View File
@@ -29,7 +29,9 @@ Kierunek jest jawny:
- `tokens sync remote r1` czyta git remote `r1` i zapisuje rekord do `tokens.json` - `tokens sync remote r1` czyta git remote `r1` i zapisuje rekord do `tokens.json`
- `tokens sync store r1` czyta `tokens.json` i zapisuje auth do git remote `r1` - `tokens sync store r1` czyta `tokens.json` i zapisuje auth do git remote `r1`
- `tokens update r1` nie synchronizuje sekretu, tylko pobiera metadane z API - `tokens update r1` nie synchronizuje sekretu, tylko pobiera metadane z API
- `tokens remove ... r1` usuwa rekord ze store, git remote albo oba miejsca - `tokens remove store r1` usuwa rekord z `tokens.json`
- `tokens remove remote r1` usuwa poswiadczenia z URL-a git remota, ale zostawia remote
- `tokens remove both r1` usuwa rekord ze store i poswiadczenia z URL-a git remota
## Format `tokens.json` ## Format `tokens.json`
+21 -12
View File
@@ -1511,10 +1511,10 @@ def list_remote_rows(repo_servers: dict[str, dict], server_filter: str | None =
"user": str(row.get("user", "")), "user": str(row.get("user", "")),
"remote": str(row.get("remote", "")), "remote": str(row.get("remote", "")),
"token": short_secret(token_value) if token_value else "", "token": short_secret(token_value) if token_value else "",
"valid": "", "valid": "?",
"scope_mask": "", "scope_mask": "?????????",
"org_mask": "", "org_mask": "?????",
"repo_mask": "", "repo_mask": "????",
} }
) )
return rows return rows
@@ -2008,7 +2008,7 @@ def remove_token_from_store(
} }
def remove_git_remote(repo_path: Path, remote_id: str, dry_run: bool = False) -> dict[str, str]: def remove_git_remote_credentials(repo_path: Path, remote_id: str, dry_run: bool = False) -> dict[str, str]:
repo_root = git_repo_root(repo_path) repo_root = git_repo_root(repo_path)
if repo_root is None: if repo_root is None:
raise SystemExit(f"Missing git repo at path: {repo_path}") raise SystemExit(f"Missing git repo at path: {repo_path}")
@@ -2021,17 +2021,26 @@ def remove_git_remote(repo_path: Path, remote_id: str, dry_run: bool = False) ->
"removed": "0", "removed": "0",
"status": "missing", "status": "missing",
} }
sanitized_url, had_credentials = sanitize_remote_url(remote_url)
if not had_credentials:
return {
"repo_root": str(repo_root),
"remote": remote_id,
"url": sanitized_url,
"removed": "0",
"status": "no_credentials",
}
if not dry_run: if not dry_run:
subprocess.run( subprocess.run(
["git", "-C", str(repo_root), "remote", "remove", remote_id], ["git", "-C", str(repo_root), "remote", "set-url", remote_id, sanitized_url],
check=True, check=True,
) )
return { return {
"repo_root": str(repo_root), "repo_root": str(repo_root),
"remote": remote_id, "remote": remote_id,
"url": safe_remote_url_label(remote_url), "url": sanitized_url,
"removed": "1", "removed": "1",
"status": "dry-run" if dry_run else "removed", "status": "dry-run" if dry_run else "removed",
} }
@@ -2044,7 +2053,7 @@ def run_tokens_remove(config: WorkspaceConfig, args: argparse.Namespace) -> None
return return
if args.target == "remote": if args.target == "remote":
result = remove_git_remote(resolve_launcher_repo_argument(args.repo), args.remote_id, args.dry_run) result = remove_git_remote_credentials(resolve_launcher_repo_argument(args.repo), args.remote_id, args.dry_run)
print_token_action_result(result) print_token_action_result(result)
return return
@@ -2052,7 +2061,7 @@ def run_tokens_remove(config: WorkspaceConfig, args: argparse.Namespace) -> None
repo_path = resolve_launcher_repo_argument(args.repo) repo_path = resolve_launcher_repo_argument(args.repo)
if not args.dry_run: if not args.dry_run:
remove_token_from_store(config, args.remote_id, args.server, dry_run=True) remove_token_from_store(config, args.remote_id, args.server, dry_run=True)
remote_result = remove_git_remote(repo_path, args.remote_id, args.dry_run) remote_result = remove_git_remote_credentials(repo_path, args.remote_id, args.dry_run)
print_token_action_result(remote_result) print_token_action_result(remote_result)
print() print()
store_result = remove_token_from_store(config, args.remote_id, args.server, args.dry_run) store_result = remove_token_from_store(config, args.remote_id, args.server, args.dry_run)
@@ -2520,7 +2529,7 @@ def print_tokens_overview() -> None:
["stats", "[--repo PATH]", "repo + tokens.json", "compare remote URLs with local token store"], ["stats", "[--repo PATH]", "repo + tokens.json", "compare remote URLs with local token store"],
["sync remote", "REMOTE_ID [--repo PATH]", "repo -> tokens.json", "copy one remote URL into the store"], ["sync remote", "REMOTE_ID [--repo PATH]", "repo -> tokens.json", "copy one remote URL into the store"],
["sync store", "REMOTE_ID [--repo PATH]", "tokens.json -> repo", "write one store record into a remote URL"], ["sync store", "REMOTE_ID [--repo PATH]", "tokens.json -> repo", "write one store record into a remote URL"],
["remove", "store|remote|both REMOTE_ID", "selected", "remove token store record or Git remote"], ["remove", "store|remote|both REMOTE_ID", "selected", "remove store record or remote credentials"],
["write", "--remote R [--replace]", "tokens.json -> repo", "write selected token into a remote URL"], ["write", "--remote R [--replace]", "tokens.json -> repo", "write selected token into a remote URL"],
["update", "REMOTE_ID", "API -> tokens.json", "refresh valid/scope/org/repo metadata"], ["update", "REMOTE_ID", "API -> tokens.json", "refresh valid/scope/org/repo metadata"],
], ],
@@ -2537,7 +2546,7 @@ def print_tokens_overview() -> None:
["refresh r1 metadata", "./rvctl tokens update r1"], ["refresh r1 metadata", "./rvctl tokens update r1"],
["write store r1 to remote", "./rvctl tokens sync store r1 --repo PATH"], ["write store r1 to remote", "./rvctl tokens sync store r1 --repo PATH"],
["remove r1 from store", "./rvctl tokens remove store r1"], ["remove r1 from store", "./rvctl tokens remove store r1"],
["remove Git remote r1", "./rvctl tokens remove remote r1"], ["remove auth from r1", "./rvctl tokens remove remote r1"],
["scan selected card", "./rvctl tokens scan --repo ~/dev/workspace/rv/series/inf/03"], ["scan selected card", "./rvctl tokens scan --repo ~/dev/workspace/rv/series/inf/03"],
["compare state", "./rvctl tokens stats --repo ~/dev/workspace/rv/series/inf/03"], ["compare state", "./rvctl tokens stats --repo ~/dev/workspace/rv/series/inf/03"],
["write auth to r1", "./rvctl tokens write --repo PATH --remote r1 --server URL"], ["write auth to r1", "./rvctl tokens write --repo PATH --remote r1 --server URL"],
@@ -2698,7 +2707,7 @@ def build_parser() -> argparse.ArgumentParser:
tokens_remove_parser = tokens_subparsers.add_parser( tokens_remove_parser = tokens_subparsers.add_parser(
"remove", "remove",
help="Remove a token store record, a Git remote, or both.", help="Remove a token store record, Git remote credentials, or both.",
) )
tokens_remove_parser.add_argument("target", choices=["store", "remote", "both"], help="Where to remove REMOTE_ID from.") tokens_remove_parser.add_argument("target", choices=["store", "remote", "both"], help="Where to remove REMOTE_ID from.")
tokens_remove_parser.add_argument("remote_id", help="Remote id, for example 'r1' or 'r1a'.") tokens_remove_parser.add_argument("remote_id", help="Remote id, for example 'r1' or 'r1a'.")