fix(profile): no Add GitHub where people sign in with a password
Someone identified was offered Add GitHub wherever GitHub signed people in, and on an instance offering passwords the browser round trip ended in "Couldn't sign in with GitHub.", as the instance adds GitHub to nobody there (ADR 0017, D2; the end-to-end test of 21 Oct). The profile now shows the GitHub row there only to whom it signs in already, and an anonymous person's Sign in with GitHub, which still reaches the account someone has, says why it didn't: a GitHub account nobody has, with the password beneath in its place, or one that signs in with its password now. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
19aabb0266
commit
f3b263a4fb
2 changed files with 123 additions and 8 deletions
|
|
@ -207,8 +207,9 @@ bool _identifiedIn(SessionState state) => switch (state) {
|
|||
};
|
||||
|
||||
/// How an identified person signs in: GitHub, with a way to add it where
|
||||
/// the instance offers it, and an email address, with the password and
|
||||
/// authenticators beneath.
|
||||
/// the instance adds it (not where people sign in with a password, ADR
|
||||
/// 0017, D2: there only one who has it sees it), and an email address,
|
||||
/// with the password and authenticators beneath.
|
||||
class const _SignInWays() extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
@ -217,7 +218,9 @@ class const _SignInWays() extends StatelessWidget {
|
|||
final ways = context.watch<SignInWaysCubit>().state;
|
||||
final gitHub = context.watch<GitHubSignInBloc>().state;
|
||||
final offersGitHub = switch (gitHub) {
|
||||
GitHubSignInStateChecking() || GitHubSignInStateUnavailable() => false,
|
||||
GitHubSignInStateChecking() ||
|
||||
GitHubSignInStateUnavailable() ||
|
||||
GitHubSignInStateReady(linking: false) => false,
|
||||
_ => true,
|
||||
};
|
||||
final busy = gitHub is GitHubSignInStateBusy;
|
||||
|
|
@ -256,8 +259,16 @@ class const _SignInWays() extends StatelessWidget {
|
|||
const _GitHubWaiting(),
|
||||
if (gitHub is GitHubSignInStateTaken)
|
||||
Text(l10n.profileGitHubTaken, style: note),
|
||||
if (gitHub case GitHubSignInStateReady(failed: true))
|
||||
Text(l10n.profileSignInFailed, style: note),
|
||||
if (gitHub case GitHubSignInStateReady(failed: true, :final problem))
|
||||
Text(
|
||||
gitHubProblemText(
|
||||
HalkyonAppLocalizations.of(context),
|
||||
problem,
|
||||
anonymous: false,
|
||||
) ??
|
||||
l10n.profileSignInFailed,
|
||||
style: note,
|
||||
),
|
||||
if (ways.ways.email)
|
||||
way(
|
||||
l10n.profileWayEmail,
|
||||
|
|
@ -273,7 +284,9 @@ class const _SignInWays() extends StatelessWidget {
|
|||
}
|
||||
|
||||
/// The way to keep an anonymous account: signing in with GitHub, where the
|
||||
/// instance offers it.
|
||||
/// instance offers it. Where people sign in with a password it reaches only
|
||||
/// a GitHub account someone has (ADR 0017), and the password beneath keeps
|
||||
/// the account instead.
|
||||
class const _GitHubSignIn() extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) =>
|
||||
|
|
@ -282,10 +295,11 @@ class const _GitHubSignIn() extends StatelessWidget {
|
|||
GitHubSignInStateChecking() ||
|
||||
GitHubSignInStateUnavailable() ||
|
||||
GitHubSignInStateLinked() => const SizedBox.shrink(),
|
||||
GitHubSignInStateReady(:final failed) => _button(
|
||||
GitHubSignInStateReady(:final failed, :final problem) => _button(
|
||||
context,
|
||||
enabled: true,
|
||||
failed: failed,
|
||||
problem: problem,
|
||||
),
|
||||
// Only for someone identified, who sees their ways in instead.
|
||||
GitHubSignInStateTaken() => _button(context, enabled: true),
|
||||
|
|
@ -302,6 +316,7 @@ class const _GitHubSignIn() extends StatelessWidget {
|
|||
BuildContext context, {
|
||||
required bool enabled,
|
||||
bool failed = false,
|
||||
GitHubSignInProblem? problem,
|
||||
}) {
|
||||
final l10n = AppLocalizations.of(context);
|
||||
return Padding(
|
||||
|
|
@ -320,7 +335,14 @@ class const _GitHubSignIn() extends StatelessWidget {
|
|||
),
|
||||
if (failed) ...[
|
||||
const SizedBox(height: 8),
|
||||
Text(l10n.profileSignInFailed),
|
||||
Text(
|
||||
gitHubProblemText(
|
||||
HalkyonAppLocalizations.of(context),
|
||||
problem,
|
||||
anonymous: true,
|
||||
) ??
|
||||
l10n.profileSignInFailed,
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -206,4 +206,97 @@ void main() {
|
|||
expect(find.text('Switch to your GitHub account?'), findsNothing);
|
||||
expect(find.byType(HomeScreen), findsOneWidget);
|
||||
});
|
||||
|
||||
group('where people sign in with a password (ADR 0017)', () {
|
||||
setUp(() => auth.linksGitHub = false);
|
||||
|
||||
testWidgets('anonymous people may still sign in with the GitHub account '
|
||||
'they have; one nobody has is said so, with the password in its '
|
||||
'place', (tester) async {
|
||||
await openProfile(tester);
|
||||
expect(find.text('Sign in with GitHub'), findsOneWidget);
|
||||
|
||||
auth.gitHubError = const GitHubSignInFailed(
|
||||
GitHubSignInProblem.deprecated,
|
||||
);
|
||||
await tester.tap(find.text('Sign in with GitHub'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(
|
||||
find.text(
|
||||
'No account here signs in with this GitHub account yet. To keep '
|
||||
'your progress, set up a password instead.',
|
||||
),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(find.text("Couldn't sign in with GitHub."), findsNothing);
|
||||
expect(
|
||||
find.text('Progress is saved on this device. Sign in to keep it.'),
|
||||
findsOneWidget,
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('a GitHub account that signs in with its password now is '
|
||||
'said so', (tester) async {
|
||||
auth
|
||||
..gitHubLinkOutcome = GitHubLinkOutcome.takenByAnotherPerson
|
||||
..gitHubSwitchError = const GitHubSignInFailed(
|
||||
GitHubSignInProblem.usePassword,
|
||||
);
|
||||
await openProfile(tester);
|
||||
|
||||
await tester.tap(find.text('Sign in with GitHub'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(
|
||||
find.text(
|
||||
'This account signs in with its email address and password now, '
|
||||
'not with GitHub.',
|
||||
),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(auth.gitHubSwitches, 0);
|
||||
});
|
||||
});
|
||||
|
||||
group('someone identified', () {
|
||||
setUp(() {
|
||||
auth = FakeAuthGateway(
|
||||
status: const SignedIn(authUserId: 'ada', isIdentified: true),
|
||||
);
|
||||
auth.addressOwners['ada@example.org'] = 'ada';
|
||||
});
|
||||
|
||||
testWidgets('is offered to add GitHub where the instance adds it', (
|
||||
tester,
|
||||
) async {
|
||||
await openProfile(tester);
|
||||
|
||||
expect(find.text('Add GitHub'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('is offered no GitHub to add where people sign in with a '
|
||||
'password (ADR 0017): the instance would refuse it', (tester) async {
|
||||
auth.linksGitHub = false;
|
||||
|
||||
await openProfile(tester);
|
||||
|
||||
expect(find.text('Add GitHub'), findsNothing);
|
||||
expect(find.text('GitHub'), findsNothing);
|
||||
expect(find.text('Email address'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('who has GitHub there sees it signs them in, with nothing to '
|
||||
'add', (tester) async {
|
||||
auth
|
||||
..linksGitHub = false
|
||||
..gitHubPeople.add('ada');
|
||||
|
||||
await openProfile(tester);
|
||||
|
||||
expect(find.text('GitHub'), findsOneWidget);
|
||||
expect(find.text('Signs you in'), findsWidgets);
|
||||
expect(find.text('Add GitHub'), findsNothing);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue