From 23568049da9a848e980ac0dc70474a6d0e110850 Mon Sep 17 00:00:00 2001 From: r-zakarya <82443831+r-zakarya@users.noreply.github.com> Date: Sun, 6 Sep 2026 19:18:39 +0100 Subject: [PATCH] feat(android): saisir le secret 2FA des la creation d'une entree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le formulaire New entry n'avait pas le champ et AddEntry ecrivait totp_secret = '' en dur : il fallait enregistrer l'entree puis la rouvrir pour poser un second facteur, alors que l'editeur portait deja le champ. Meme intitule que l'editeur ("2FA secret"), masque pour une note comme site et identifiant, et achemine par &o= — t, s, u, p, k, d etaient pris. Co-Authored-By: Claude Opus 5 --- android-client/PMA.VaultPatch.pas | 6 +++--- android-client/web/app.html | 7 +++++++ mainApk.pas | 10 ++++++---- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/android-client/PMA.VaultPatch.pas b/android-client/PMA.VaultPatch.pas index 22f6c03..f7396ea 100644 --- a/android-client/PMA.VaultPatch.pas +++ b/android-client/PMA.VaultPatch.pas @@ -49,7 +49,7 @@ function NewEmptySnapshot(const AUsername: string): string; /// /// Un uuid neuf, et lui seul : pas de tombstone, on ne supprime pas encore. function AddEntry(const APlainJson, ATitle, ASite, AUsername, APassword, - AKind, AFolder: string): string; + AKind, AFolder, ATotp: string): string; /// Retire une entree de l'instantane et laisse une PIERRE TOMBALE a sa place. /// @@ -532,7 +532,7 @@ begin end; function AddEntry(const APlainJson, ATitle, ASite, AUsername, APassword, - AKind, AFolder: string): string; + AKind, AFolder, ATotp: string): string; var LRoot, LEntry: TJSONObject; LEntries: TJSONArray; @@ -560,7 +560,7 @@ begin else LEntry.AddPair('folder', 'All'); EnsureFolder(LRoot, AFolder); LEntry.AddPair('tags', TJSONArray.Create); - LEntry.AddPair('totp_secret', ''); + LEntry.AddPair('totp_secret', ATotp); LEntry.AddPair('kind', AKind); LEntry.AddPair('template', ''); LEntry.AddPair('custom_fields', TJSONArray.Create); diff --git a/android-client/web/app.html b/android-client/web/app.html index f34bd41..37d864b 100644 --- a/android-client/web/app.html +++ b/android-client/web/app.html @@ -1359,6 +1359,11 @@ function openNewEntry() { // qu'aucune confirmation ne rattrape et qu'on ne peut relire nulle part. + '
Password
' + '
' + newBodyControl('login') + '
' + // LE SECRET, pas le code. Il manquait ici alors que l'editeur le portait + // deja : on pouvait poser un second facteur sur une entree existante, pas + // sur une entree qu'on venait de creer - il fallait enregistrer puis + // rouvrir. Meme intitule que l'editeur pour qu'on reconnaisse le champ. + + newField('nTotp', '2FA secret', 'nTotpRow') + '
' // flex:1 et non .wide : .wide ne regle que le rembourrage, et la largeur // pleine vient d'etre etire dans son conteneur. @@ -1388,6 +1393,7 @@ document.getElementById('fields').addEventListener('click', function (ev) { // demander de remplir ce que rien n'affichera. document.getElementById('nSiteRow').hidden = (kind === 'note'); document.getElementById('nUserRow').hidden = (kind === 'note'); + document.getElementById('nTotpRow').hidden = (kind === 'note'); // Le corps d'une note EST son mot de passe cote stockage : meme champ, // autre intitule, et rien a masquer - mais plusieurs lignes. @@ -1418,6 +1424,7 @@ document.getElementById('fields').addEventListener('click', function (ev) { + '&s=' + encodeURIComponent(v('nSite')) + '&u=' + encodeURIComponent(v('nUser')) + '&p=' + encodeURIComponent(document.getElementById('nPwd').value) + + '&o=' + encodeURIComponent(v('nTotp')) + '&k=' + newKind); }); document.getElementById('new').addEventListener('click', openNewEntry); diff --git a/mainApk.pas b/mainApk.pas index a76ba54..3a2b117 100644 --- a/mainApk.pas +++ b/mainApk.pas @@ -306,7 +306,7 @@ type /// Ajoute une entree au coffre. Le mot de passe voyage par le pont, /// comme 'setfield' - meme regle, meme journalisation muette. procedure CreateEntry(const ATitle, ASite, AUser, APwd, AKind, - AFolder: string); + AFolder, ATotp: string); function UuidsFromIndexes(const AList: string): TArray; /// Supprime des entrees, pierres tombales comprises. Sans retour. /// Liste vide = l'entree ouverte. @@ -1572,7 +1572,7 @@ begin end; procedure TForm8.CreateEntry(const ATitle, ASite, AUser, APwd, AKind, - AFolder: string); + AFolder, ATotp: string); begin // Une entree sans rien pour la reconnaitre serait une ligne muette dans la // liste, et rien ne permettrait de la retrouver pour la corriger. @@ -1584,7 +1584,8 @@ begin CommitChange('Added: ' + ATitle, 'new entry from phone', '', function (APlain: string): string begin - Result := AddEntry(APlain, ATitle, ASite, AUser, APwd, AKind, AFolder); + Result := AddEntry(APlain, ATitle, ASite, AUser, APwd, AKind, AFolder, + ATotp); end); end; @@ -1750,7 +1751,8 @@ begin TNetEncoding.URL.Decode(Param('u')), TNetEncoding.URL.Decode(Param('p')), TNetEncoding.URL.Decode(Param('k')), - TNetEncoding.URL.Decode(Param('d'))) + TNetEncoding.URL.Decode(Param('d')), + TNetEncoding.URL.Decode(Param('o'))) else if LAction = 'history' then ShowPasswordHistory