diff --git a/android-client/PMA.SyncClient.pas b/android-client/PMA.SyncClient.pas index dd75d1d..d529491 100644 --- a/android-client/PMA.SyncClient.pas +++ b/android-client/PMA.SyncClient.pas @@ -73,6 +73,12 @@ type /// n'y ressemble pas est de toute facon inutilisable. function IsGitea: Boolean; + /// POURQUOI UN 404 OU UN 401, en clair pour l'utilisateur. Gitea repond 404 + /// aussi bien pour un fichier absent que pour un depot ou un proprietaire + /// inexistant : deux requetes de plus tranchent - le depot, puis + /// l'utilisateur. Vide si rien de plus precis n'a pu etre etabli. + function Diagnose(AHttpCode: Integer): string; + /// Publie un conteneur. ASha est celui du fichier qu'on a lu : Gitea s'en /// sert pour refuser (409) une ecriture si quelqu'un d'autre a publie /// entre-temps. Vide = creation d'un fichier qui n'existait pas. @@ -99,6 +105,55 @@ begin Result := FBaseUrl.ToLower.Contains('/api/v1/repos/'); end; +function TSyncClient.Diagnose(AHttpCode: Integer): string; +var + LHttp: THTTPClient; + LApi, LOwner, LRepo: string; + LParts: TArray; + LP: Integer; + + function CodeOf(const AUrl: string): Integer; + begin + try + Result := LHttp.Get(AUrl).StatusCode; + except + Result := 0; + end; + end; + +begin + Result := ''; + if AHttpCode = 401 then + Exit('Token refused - expired, revoked or mistyped'); + if (AHttpCode <> 404) or not IsGitea then Exit; + // https://hote/api/v1/repos/OWNER/REPO/contents/FICHIER + LP := Pos('/api/v1/repos/', LowerCase(FBaseUrl)); + LApi := Copy(FBaseUrl, 1, LP + Length('/api/v1/') - 1); + LParts := Copy(FBaseUrl, LP + Length('/api/v1/repos/'), MaxInt).Split(['/']); + if Length(LParts) < 2 then Exit; + LOwner := LParts[0]; + LRepo := LParts[1]; + LHttp := THTTPClient.Create; + try + LHttp.ConnectionTimeout := FTimeoutMs; + LHttp.ResponseTimeout := FTimeoutMs; + LHttp.HandleRedirects := False; + LHttp.CustomHeaders['Authorization'] := 'token ' + FToken; + case CodeOf(LApi + 'repos/' + LOwner + '/' + LRepo) of + 200: Result := 'No vault in this repository yet - sync from the PC first'; + 401: Result := 'Token refused - expired, revoked or mistyped'; + 404: + if CodeOf(LApi + 'users/' + LOwner) = 404 then + Result := 'User "' + LOwner + '" does not exist' + else + Result := 'Repository "' + LOwner + '/' + LRepo + + '" not found, or this token cannot see it'; + end; + finally + LHttp.Free; + end; +end; + /// Le sha du fichier ecrit, tire de la reponse au PUT : Gitea rend /// { "content": { "sha": ... }, "commit": { ... } }. Vide si la forme change - /// l'appelant relira, ce qui coute un appel mais ne perd rien. diff --git a/android-client/web/app.html b/android-client/web/app.html index 5d83aa7..da8dfed 100644 --- a/android-client/web/app.html +++ b/android-client/web/app.html @@ -276,7 +276,7 @@ /* UN REFUS N'EST PAS UN ETAT. "Master password: 8 characters at least" se lisait du meme gris que "Vault on this device" - on ne voyait pas que l'application venait de refuser quelque chose. */ - .status.err { color: #ff9d9d; } + .status.err, .note.err { color: #ff9d9d; } .stack { display: flex; flex-direction: column; gap: 8px; } /* L'espace de 8 px vit A L'INTERIEUR de chaque pile. Deux piles voisines se touchaient donc, et "Create vault" collait a "Download vault" alors que @@ -568,6 +568,7 @@

Repository

+