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
|
/// Intitule discret au-dessus d'une valeur. Meme forme pour toutes les
|
||||||
/// lignes, y compris celle du TOTP.
|
/// 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;
|
out AValue: TLabel): TLayout;
|
||||||
var
|
var
|
||||||
LCap: TLabel;
|
LCap: TLabel;
|
||||||
begin
|
begin
|
||||||
Result := TLayout.Create(nil); // detruite a la main, voir ClearDetailRows
|
Result := TLayout.Create(nil); // detruite a la main, voir ClearDetailRows
|
||||||
Result.Parent := AParent;
|
Result.Parent := AParent;
|
||||||
|
Result.Index := AOrder;
|
||||||
Result.Align := TAlignLayout.Top;
|
Result.Align := TAlignLayout.Top;
|
||||||
Result.Height := 62;
|
Result.Height := 62;
|
||||||
Result.Margins.Rect := RectF(12, 10, 12, 0);
|
Result.Margins.Rect := RectF(12, 10, 12, 0);
|
||||||
@@ -546,7 +554,7 @@ end;
|
|||||||
procedure TForm8.ShowDetail(AVaultIndex: Integer);
|
procedure TForm8.ShowDetail(AVaultIndex: Integer);
|
||||||
var
|
var
|
||||||
LMeta, LPwdCaption: string;
|
LMeta, LPwdCaption: string;
|
||||||
I: Integer;
|
I, LOrder: Integer;
|
||||||
LRow: TLayout;
|
LRow: TLayout;
|
||||||
LValue: TLabel;
|
LValue: TLabel;
|
||||||
|
|
||||||
@@ -602,11 +610,13 @@ begin
|
|||||||
SetLength(FRowShown, Length(FRows));
|
SetLength(FRowShown, Length(FRows));
|
||||||
SetLength(FRowCtls, Length(FRows));
|
SetLength(FRowCtls, Length(FRows));
|
||||||
|
|
||||||
// Le TOTP EN PREMIER, donc en tete d'ecran : c'est ce qu'on vient chercher
|
// Le TOTP en tete d'ecran : c'est ce qu'on vient chercher sur un telephone.
|
||||||
// sur un telephone. Seule ligne vivante, rafraichie chaque seconde.
|
// Seule ligne vivante, rafraichie chaque seconde.
|
||||||
|
LOrder := 0;
|
||||||
if FCurrent.Totp <> '' then
|
if FCurrent.Totp <> '' then
|
||||||
begin
|
begin
|
||||||
LRow := MakeRow(FDetBody, 'Code 2FA', FTotpValue);
|
LRow := MakeRow(FDetBody, 'Code 2FA', LOrder, FTotpValue);
|
||||||
|
Inc(LOrder);
|
||||||
SetLength(FRowCtls, Length(FRowCtls) + 1);
|
SetLength(FRowCtls, Length(FRowCtls) + 1);
|
||||||
FRowCtls[High(FRowCtls)] := LRow;
|
FRowCtls[High(FRowCtls)] := LRow;
|
||||||
FTotpValue.TextSettings.Font.Size := 26;
|
FTotpValue.TextSettings.Font.Size := 26;
|
||||||
@@ -615,13 +625,10 @@ begin
|
|||||||
FTotpTimer.Enabled := True;
|
FTotpTimer.Enabled := True;
|
||||||
end;
|
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
|
for I := 0 to High(FRows) do
|
||||||
begin
|
begin
|
||||||
LRow := MakeRow(FDetBody, FRows[I].Caption, LValue);
|
LRow := MakeRow(FDetBody, FRows[I].Caption, LOrder, LValue);
|
||||||
|
Inc(LOrder);
|
||||||
FRowCtls[I] := LRow;
|
FRowCtls[I] := LRow;
|
||||||
FRowValues[I] := LValue;
|
FRowValues[I] := LValue;
|
||||||
FRowShown[I] := False;
|
FRowShown[I] := False;
|
||||||
@@ -851,6 +858,29 @@ begin
|
|||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
FLog.Lines.Clear;
|
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);
|
FetchAndDecrypt(LUrl, LTok, LPwd);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user