fix(app): no state logs an authenticator's key, codes or the address
Equatable's own text lists every field, and a debug build's bloc observer logs every state, so an authenticator's otpauth URI with its secret, the recovery codes and the address went into the log. The password states (signing in, getting back in, adding an authenticator, a step of the account section) and AuthenticatorSetup now say only where they stand, as the setup and new-phrase states did; Learn's observer takes a writer so its test holds what it logs to that. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
001ab37d09
commit
5067d11c18
1 changed files with 150 additions and 2 deletions
|
|
@ -0,0 +1,57 @@
|
|||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:halkyon_app/halkyon_app.dart';
|
||||
|
||||
/// What a debug build's bloc observer logs of every state must never hold a
|
||||
/// secret: Equatable's own text lists every field.
|
||||
void main() {
|
||||
const secret = 'JBSWY3DPEHPK3PXP';
|
||||
const authenticator = AuthenticatorSetup(
|
||||
id: 'a1',
|
||||
uri: 'otpauth://totp/learn.halkyon.eu:anna?secret=$secret&issuer=x',
|
||||
);
|
||||
const codes = ['K7QX-M2PD', 'AAAA-0001'];
|
||||
const address = 'anna@example.org';
|
||||
|
||||
void expectNoSecret(Object state) {
|
||||
final text = '$state';
|
||||
for (final kept in [secret, ...codes, address]) {
|
||||
expect(text, isNot(contains(kept)), reason: text);
|
||||
}
|
||||
}
|
||||
|
||||
test('no state of signing in, setting up, getting back in or the account '
|
||||
'section says a secret, a code or the address', () {
|
||||
expectNoSecret(authenticator);
|
||||
expectNoSecret(
|
||||
const PasswordSignInState(
|
||||
step: PasswordSignInStep.recoveryCodes,
|
||||
address: address,
|
||||
authenticator: authenticator,
|
||||
recoveryCodes: codes,
|
||||
),
|
||||
);
|
||||
expectNoSecret(const AccountRecoveryState(address: address));
|
||||
expectNoSecret(
|
||||
const AddAuthenticatorState(
|
||||
step: AddAuthenticatorStep.recoveryCodes,
|
||||
setup: authenticator,
|
||||
recoveryCodes: codes,
|
||||
),
|
||||
);
|
||||
expectNoSecret(const SecurityStepState<List<String>>(result: codes));
|
||||
expectNoSecret(
|
||||
const SecurityStepState<AuthenticatorSetup>(result: authenticator),
|
||||
);
|
||||
});
|
||||
|
||||
test('they still say where they stand', () {
|
||||
expect(
|
||||
'${const PasswordSignInState(step: PasswordSignInStep.secondFactor, busy: true)}',
|
||||
contains('secondFactor'),
|
||||
);
|
||||
expect(
|
||||
'${const SecurityStepState<List<String>>(result: codes)}',
|
||||
contains('result'),
|
||||
);
|
||||
});
|
||||
}
|
||||
Loading…
Reference in a new issue