diff --git a/doc/tokens.md b/doc/tokens.md index 01e35f7..d827f2e 100644 --- a/doc/tokens.md +++ b/doc/tokens.md @@ -96,7 +96,13 @@ Uzyj, gdy token jest w git remote i chcesz go zapisac w store: ``` Ta komenda kopiuje sekret, usera, endpoint, org i repo z URL-a remota do -`tokens.json`. Nie pyta API o uprawnienia. +`tokens.json`. Nie pyta API o uprawnienia, wiec zawsze zeruje metadane API: +`valid` ustawia na `?`, maski `scope`, `org_perm` i `repo_perm` ustawia na `?`, +a `expires_at` usuwa. Realne uprawnienia wpisuje dopiero: + +```bash +./rvctl tokens update r1 +``` ### Store -> Remote @@ -336,6 +342,10 @@ Pola pobierane z API przez `tokens update r1`: - `org_perm` - mapa praw uzytkownika w organizacji - `repo_perm` - mapa praw uzytkownika w repo +`tokens sync remote r1` nadpisuje pola z git remota i oznacza te metadane jako +nieznane. To celowe: po zmianie sekretu, usera albo repo stare metadane API nie +sa juz wiarygodne. + Minimalny przyklad: ```json diff --git a/rvctl.py b/rvctl.py index 3b361db..c27123f 100644 --- a/rvctl.py +++ b/rvctl.py @@ -789,6 +789,30 @@ def apply_authz_to_token(token_record: dict, authz: dict) -> bool: return changed +def unknown_permission_map(fields: list[tuple[str, str]]) -> dict[str, str]: + return {short_name: "?" for short_name, _ in fields} + + +def reset_token_api_metadata(token_record: dict) -> bool: + changed = False + if token_record.get("valid") != "?": + token_record["valid"] = "?" + changed = True + if token_record.pop("expires_at", None) is not None: + changed = True + + for field_name, fields in [ + ("scope", SCOPE_FIELDS), + ("org_perm", ORG_PERMISSION_FIELDS), + ("repo_perm", REPO_PERMISSION_FIELDS), + ]: + unknown_record = unknown_permission_map(fields) + if token_record.get(field_name) != unknown_record: + token_record[field_name] = unknown_record + changed = True + return changed + + def register_token( token_data: dict, server_info: dict, @@ -796,6 +820,7 @@ def register_token( user_name: str, token_value: str, hydrate: bool = True, + reset_api_metadata: bool = False, ) -> str: endpoint = server_info["endpoint"] token_record = find_token_record(token_data, endpoint, remote_name) @@ -827,6 +852,10 @@ def register_token( token_record[target_name] = source_value result = "updated" + if reset_api_metadata: + if reset_token_api_metadata(token_record) and result == "existing": + result = "updated" + if hydrate: authz = load_gitea_authz( endpoint, @@ -1027,7 +1056,15 @@ def sync_token_from_remote(config: WorkspaceConfig, repo_path: Path, remote_name result = "dry-run" if not dry_run: token_data = load_token_store(config) - result = register_token(token_data, server_info, remote_name, user_name, token_value, hydrate=False) + result = register_token( + token_data, + server_info, + remote_name, + user_name, + token_value, + hydrate=False, + reset_api_metadata=True, + ) write_token_store(config, token_data) return {