feat(android): a local account, so the app serves without a repository
Until now the phone could only read a vault that came from elsewhere: without a URL, a token and a sync password it showed nothing. It now signs in like the desktop does - username and master password - and can create its own vault, with no network at all. The local container carries exactly what the repository would carry: same format, same encryption under the password. Two reasons, not one. It is the desktop's model, where the master password protects the vault at rest rather than the hardware alone; and the format staying the repository's means sync keeps working with nothing to convert. No Keystore on that file - it is already encrypted under the password, and binding it to the device would make it unrecoverable after a reinstall. vault.bin keeps that role: it is the fast-open cache, and only it needs sealing. The password opens the container - the decryption itself is the check, no secret is ever compared - and the username, read from inside once open, says whose vault it is. The home screen now knows which of three situations it is in: nothing here yet, a container without a cache, or a cache ready to open. Verified on the device: with the cache set aside, the screen offers username, master password and Create vault, alongside the download path. Creating an account could not be exercised to the end - the device locked its screen mid-run - and the vault that was set aside is back in place, same size, still sealed under its code.
This commit is contained in:
@@ -35,6 +35,11 @@ type
|
||||
/// ecrire quand meme la ferait reapparaitre.
|
||||
function PatchEntryField(const APlainJson, AUuid, AField, AValue: string): string;
|
||||
|
||||
/// Un instantane vide, au nom de ce compte. Sert a l'inscription depuis le
|
||||
/// telephone : meme forme que ce qu'ecrit le poste, pour qu'un coffre ne
|
||||
/// naisse pas dans un dialecte a part.
|
||||
function NewEmptySnapshot(const AUsername: string): string;
|
||||
|
||||
/// Horodatage UTC au format que tout le reste emploie (toISOString cote JS).
|
||||
/// MELANGER heure locale et UTC a deja decale l'arbitrage de la fusion une
|
||||
/// fois : il n'y a qu'une source d'heure ici, et elle est en UTC.
|
||||
@@ -48,6 +53,28 @@ begin
|
||||
TTimeZone.Local.ToUniversalTime(Now));
|
||||
end;
|
||||
|
||||
function NewEmptySnapshot(const AUsername: string): string;
|
||||
var
|
||||
LRoot: TJSONObject;
|
||||
begin
|
||||
LRoot := TJSONObject.Create;
|
||||
try
|
||||
// Les memes cles que buildSyncSnapshot, tableaux vides compris : un lecteur
|
||||
// qui trouve la cle absente et un lecteur qui la trouve vide ne se
|
||||
// comportent pas forcement pareil, et ce coffre sera lu par le poste.
|
||||
LRoot.AddPair('version', TJSONNumber.Create(1));
|
||||
LRoot.AddPair('snapshot_at', NowUtcIso);
|
||||
LRoot.AddPair('username', AUsername);
|
||||
LRoot.AddPair('folders', TJSONArray.Create);
|
||||
LRoot.AddPair('avatar_b64', '');
|
||||
LRoot.AddPair('entries', TJSONArray.Create);
|
||||
LRoot.AddPair('tombstones', TJSONArray.Create);
|
||||
Result := LRoot.ToJSON;
|
||||
finally
|
||||
LRoot.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
function PatchEntryField(const APlainJson, AUuid, AField, AValue: string): string;
|
||||
var
|
||||
LRoot, LEntry: TJSONObject;
|
||||
|
||||
Reference in New Issue
Block a user