fix(android): sync went through the door it should have knocked on, and rows kept flipping
Synchroniser rebuilt the vault from the server and displayed it without ever asking for the pattern - the same result as Ouvrir le coffre, one button away, with the protection bypassed. It now passes the same gate, conditioned on a protected cache existing on this device, since that is what expresses the user's choice. Row order was not merely inverted, it alternated: right on first open, upside down after a lock. FMX's stacking conventions already differ between TLayout and TVertScrollBox; after rows are destroyed and rebuilt they are not even constant. Each row now states its Index explicitly rather than trusting insertion order. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+40
-10
@@ -395,13 +395,21 @@ end;
|
||||
|
||||
/// Intitule discret au-dessus d'une valeur. Meme forme pour toutes les
|
||||
/// lignes, y compris celle du TOTP.
|
||||
function MakeRow(AParent: TFmxObject; const ACaption: string;
|
||||
/// AOrder fixe la place de la ligne dans la liste d'enfants du parent.
|
||||
///
|
||||
/// SANS LUI L'ORDRE N'EST PAS STABLE : observe sur appareil, le formulaire
|
||||
/// s'affichait dans le bon ordre a la premiere ouverture puis a l'envers apres
|
||||
/// un verrouillage. Les conventions d'empilement de FMX different deja entre
|
||||
/// TLayout et TVertScrollBox ; apres destruction et recreation des lignes,
|
||||
/// elles ne sont meme plus constantes. On ne s'y fie donc pas du tout.
|
||||
function MakeRow(AParent: TFmxObject; const ACaption: string; AOrder: Integer;
|
||||
out AValue: TLabel): TLayout;
|
||||
var
|
||||
LCap: TLabel;
|
||||
begin
|
||||
Result := TLayout.Create(nil); // detruite a la main, voir ClearDetailRows
|
||||
Result.Parent := AParent;
|
||||
Result.Index := AOrder;
|
||||
Result.Align := TAlignLayout.Top;
|
||||
Result.Height := 62;
|
||||
Result.Margins.Rect := RectF(12, 10, 12, 0);
|
||||
@@ -546,7 +554,7 @@ end;
|
||||
procedure TForm8.ShowDetail(AVaultIndex: Integer);
|
||||
var
|
||||
LMeta, LPwdCaption: string;
|
||||
I: Integer;
|
||||
I, LOrder: Integer;
|
||||
LRow: TLayout;
|
||||
LValue: TLabel;
|
||||
|
||||
@@ -602,11 +610,13 @@ begin
|
||||
SetLength(FRowShown, Length(FRows));
|
||||
SetLength(FRowCtls, Length(FRows));
|
||||
|
||||
// Le TOTP EN PREMIER, donc en tete d'ecran : c'est ce qu'on vient chercher
|
||||
// sur un telephone. Seule ligne vivante, rafraichie chaque seconde.
|
||||
// Le TOTP en tete d'ecran : c'est ce qu'on vient chercher sur un telephone.
|
||||
// Seule ligne vivante, rafraichie chaque seconde.
|
||||
LOrder := 0;
|
||||
if FCurrent.Totp <> '' then
|
||||
begin
|
||||
LRow := MakeRow(FDetBody, 'Code 2FA', FTotpValue);
|
||||
LRow := MakeRow(FDetBody, 'Code 2FA', LOrder, FTotpValue);
|
||||
Inc(LOrder);
|
||||
SetLength(FRowCtls, Length(FRowCtls) + 1);
|
||||
FRowCtls[High(FRowCtls)] := LRow;
|
||||
FTotpValue.TextSettings.Font.Size := 26;
|
||||
@@ -615,13 +625,10 @@ begin
|
||||
FTotpTimer.Enabled := True;
|
||||
end;
|
||||
|
||||
// DANS L'ORDRE, ici : au sein d'un TVertScrollBox les enfants alignes en
|
||||
// haut s'empilent dans l'ordre de creation - l'inverse d'un TLayout, ou le
|
||||
// dernier cree se retrouve en tete. Se tromper de convention renvoie le
|
||||
// formulaire a l'envers, sans rien casser d'autre.
|
||||
for I := 0 to High(FRows) do
|
||||
begin
|
||||
LRow := MakeRow(FDetBody, FRows[I].Caption, LValue);
|
||||
LRow := MakeRow(FDetBody, FRows[I].Caption, LOrder, LValue);
|
||||
Inc(LOrder);
|
||||
FRowCtls[I] := LRow;
|
||||
FRowValues[I] := LValue;
|
||||
FRowShown[I] := False;
|
||||
@@ -851,6 +858,29 @@ begin
|
||||
Exit;
|
||||
end;
|
||||
FLog.Lines.Clear;
|
||||
|
||||
// MEME PORTE QUE « Ouvrir le coffre ». Sans cela la protection ne tenait
|
||||
// qu'a un bouton pres : synchroniser reconstruit le coffre depuis le serveur
|
||||
// et l'affiche, ce qui revient exactement au meme resultat sans passer par
|
||||
// l'authentification. La condition est la presence d'un cache protege sur
|
||||
// cet appareil - c'est lui qui exprime le choix de l'utilisateur.
|
||||
if VaultNeedsAuth and (FVault.Count = 0) then
|
||||
begin
|
||||
Status('Authentification...');
|
||||
AuthenticateThen('Acceder au coffre',
|
||||
procedure(AOutcome: TBioOutcome)
|
||||
begin
|
||||
if AOutcome = boOK then
|
||||
FetchAndDecrypt(LUrl, LTok, LPwd)
|
||||
else
|
||||
begin
|
||||
Log('Synchronisation refusee : ' + LastBiometricError);
|
||||
Status('Authentification requise');
|
||||
end;
|
||||
end);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
FetchAndDecrypt(LUrl, LTok, LPwd);
|
||||
end;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user