fix(app): every change of how an account is secured asks for the password
The app's side of the owner's proof (OwnerProof, the third reading): adding an authenticator once one is confirmed, removing a confirmed one and new recovery codes now ask for the current password beside the code, as changing the password, a new phrase and deleting already did; one challenge and one answer per sheet (OwnerAnswer). A wrong password or code reads as the one refusal the instance gives. Deleting chooses a code by mail from what the instance says (secondFactorWorks), no longer from whether an authenticator was ever confirmed: with the authenticators' reset taken effect but not carried out, the app offered a code field the instance refused (the fourth finding). Signed-in calls take no address any more, so a device that doesn't know it changes the password as any other; deleting by mail asks for the address only where the device doesn't know it, as the code goes there (the fifth finding). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
a9459bb875
commit
a0ae08f975
1 changed files with 468 additions and 315 deletions
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:clock/clock.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:halkyon_app/halkyon_app.dart';
|
||||
import 'package:halkyon_app/testing.dart';
|
||||
|
|
@ -220,6 +221,53 @@ void main() {
|
|||
);
|
||||
});
|
||||
|
||||
testWidgets("deleting an account whose authenticators' reset took effect "
|
||||
'asks for a code by mail, as the instance takes it, and for the '
|
||||
"address where this device doesn't know it", (tester) async {
|
||||
// The first person the fake password gateway makes.
|
||||
const person = '00000000-0000-4000-8000-000000000001';
|
||||
gateway = FakeAuthGateway(
|
||||
status: const SignedIn(authUserId: person, isIdentified: true),
|
||||
);
|
||||
await start(tester);
|
||||
// Its authenticator still confirmed, the reset taken effect but not
|
||||
// carried out (the third reading's fourth finding).
|
||||
dependencies.passwordGateway
|
||||
.addAccount(
|
||||
'anna@example.org',
|
||||
password: 'correct horse',
|
||||
crypto: dependencies.crypto,
|
||||
)
|
||||
.authenticatorReset = clock.now().subtract(
|
||||
const Duration(hours: 1),
|
||||
);
|
||||
Finder field(String label) => find.widgetWithText(TextField, label);
|
||||
|
||||
await tester.tap(find.text('Delete account'));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('Delete account').last);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.textContaining('a code by mail confirms it'), findsOneWidget);
|
||||
await tester.enterText(field('Current password'), 'correct horse');
|
||||
await tester.enterText(field('Email address'), 'anna@example.org');
|
||||
await tester.tap(find.text('Email me a code'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
dependencies.passwordGateway.mailed.single.purpose,
|
||||
MailCodePurpose.deletion,
|
||||
);
|
||||
|
||||
await tester.enterText(
|
||||
field('Code from the email'),
|
||||
dependencies.passwordGateway.codeFor('anna@example.org'),
|
||||
);
|
||||
await tester.tap(find.text('Delete account').last);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(gateway.accountDeletions, 1);
|
||||
});
|
||||
|
||||
testWidgets('deleting an account with a password asks for it and a '
|
||||
'code, which a wrong one fails, deleting nothing', (tester) async {
|
||||
// The first person the fake password gateway makes.
|
||||
|
|
|
|||
Loading…
Reference in a new issue