Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/authenticator/phone validator #5511

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions devtools_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
description: This file stores settings for Dart & Flutter DevTools.
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
extensions:
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,8 @@ amplifytools.xcconfig
#amplify-do-not-edit-end

amplify_outputs.dart

# amplify
.amplify
amplify_outputs*
amplifyconfiguration*

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

276 changes: 30 additions & 246 deletions packages/authenticator/amplify_authenticator/example/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,271 +1,55 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import 'package:amplify_auth_cognito/amplify_auth_cognito.dart';
import 'package:amplify_authenticator/amplify_authenticator.dart';
import 'package:amplify_authenticator_example/resolvers/localized_button_resolver.dart';
import 'package:amplify_authenticator_example/resolvers/localized_dial_code_resolver.dart';
import 'package:amplify_authenticator_example/resolvers/localized_input_resolver.dart';
import 'package:amplify_authenticator_example/resolvers/localized_title_resolver.dart';
import 'package:amplify_flutter/amplify_flutter.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

import 'amplifyconfiguration.dart';

void main() {
runApp(const MyApp());
}

class MyApp extends StatefulWidget {
const MyApp({super.key});

@override
State<MyApp> createState() => _MyAppState();
}
import 'amplify_outputs.dart';

class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
_configureAmplify();
Future<void> main() async {
try {
WidgetsFlutterBinding.ensureInitialized();
await _configureAmplify();
runApp(const MyApp());
} on AmplifyException catch (e) {
runApp(Text('Error configuring Amplify: ${e.message}'));
}
}

/// When using the Authenticator, configuration of Amplify is still the
/// responsibility of the developer. This allows you the opportunity to
/// customize plugin options and add/remove them as needed.
void _configureAmplify() async {
final authPlugin = AmplifyAuthCognito(
// FIXME: In your app, make sure to remove this line and set up
/// Keychain Sharing in Xcode as described in the docs:
/// https://docs.amplify.aws/lib/project-setup/platform-setup/q/platform/flutter/#enable-keychain
secureStorageFactory: AmplifySecureStorage.factoryFrom(
macOSOptions:
// ignore: invalid_use_of_visible_for_testing_member
MacOSSecureStorageOptions(useDataProtection: false),
),
);
try {
await Amplify.addPlugin(authPlugin);
await Amplify.configure(amplifyconfig);
print('Successfully configured');
} on Exception catch (e) {
print('Error configuring Amplify: $e');
}
}

/// Our custom username validator, which ensures that all usernames contain
/// the word "amplify".
String? _validateUsername(UsernameInput? input) {
final username = input?.username;
if (username == null || username.isEmpty) {
return 'Username cannot be empty';
}

final containsAmplify = username.contains('amplify');
if (!containsAmplify) {
return 'Username needs to include amplify';
}

return null;
Future<void> _configureAmplify() async {
try {
await Amplify.addPlugin(AmplifyAuthCognito());
await Amplify.configure(amplifyConfig);
safePrint('Successfully configured');
} on Exception catch (e) {
safePrint('Error configuring Amplify: $e');
}
}

class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
// First, we set up the custom localizations for Authenticator buttons by
// creating a custom resolver which conforms to the `ButtonResolver` class
// from the Authenticator library.
//
// In addition to ButtonResolver, which handles the labels for buttons,
// there are also resolvers for input fields, screen titles, and
// navigation-related items, all of which can be customized as well. To keep
// this demo simple, we only specify a custom button resolver, which
// automatically configures the default for the others.
const stringResolver = AuthStringResolver(
buttons: LocalizedButtonResolver(),
dialCodes: LocalizedDialResolver(),
titles: LocalizedTitleResolver(),
inputs: LocalizedInputResolver(),
);

// We wrap our MaterialApp in an Authenticator component. This component
// handles all the screens and logic whenever the user is signed out. Once
// the user is signed in, the Authenticator will use your MaterialApp's
// navigator to show the correct screen.
return Authenticator(
stringResolver: stringResolver,
onException: (exception) {
print('[ERROR]: $exception');
},

// Next, we create a custom Sign Up form which uses our custom username
// validator.
//
// Providing a custom SignUpForm allows for simple customizations such as
// adding a sign up attribute or adding a custom validator. More complex
// customizations can be achieved by providing a custom builder method to
// Authenticator.builder()
dialCodeOptions: const DialCodeOptions(defaultDialCode: DialCode.im),
signUpForm: SignUpForm.custom(
fields: [
SignUpFormField.username(
validator: _validateUsername,
),
SignUpFormField.email(required: true),
SignUpFormField.username(),
SignUpFormField.phoneNumber(required: true),
SignUpFormField.password(),
SignUpFormField.passwordConfirmation(),
SignUpFormField.address(),
SignUpFormField.custom(
title: 'Bio',
attributeKey: const CognitoUserAttributeKey.custom('bio'),
),
SignUpFormField.custom(
title: 'Age',
attributeKey: const CognitoUserAttributeKey.custom('age'),
),
],
),

// Your MaterialApp should be the child of the Authenticator.
child: MaterialApp(
title: 'Authenticator Demo',
theme: ThemeData.light(useMaterial3: true),
darkTheme: ThemeData.dark(useMaterial3: true),
themeMode: ThemeMode.system,
debugShowCheckedModeBanner: false,

// These lines enable our custom localizations specified in the lib/l10n
// directory, which will be used later to customize the values displayed
// in the Authenticator component.
localizationsDelegates: const [
AppLocalizations.delegate,
],
supportedLocales: const [
Locale('en'), // English
Locale('es'), // Spanish
],

// The Authenticator component must wrap your Navigator component which
// can be done using the `builder` method.
builder: Authenticator.builder(),

initialRoute: '/routeA',
routes: {
'/routeA': (BuildContext context) => const RouteA(),
'/routeB': (BuildContext context) => const RouteB(),
},
),
);
}

// Some routes in your application may not require authentication.
// To handle this use case, instead of providing Authenticator.builder(),
// simply wrap the routes that require authentication in an
// AuthenticatedView widget.
//
// uncomment the build method below to try this out

// @override
// Widget build(BuildContext context) {
// return Authenticator(
// child: MaterialApp(
// theme: ThemeData.light(),
// darkTheme: ThemeData.dark(),
// themeMode: ThemeMode.system,
// debugShowCheckedModeBanner: false,
// initialRoute: '/routeA',
// routes: {
// '/routeA': (BuildContext context) => const RouteA(),
// '/routeB': (BuildContext context) {
// return const AuthenticatedView(
// child: RouteB(),
// );
// },
// },
// ),
// );
// }

// Providing a `builder` argument to Authenticator.builder allows you to
// build a custom UI for the authenticator composed of a mix of
// prebuilt widgets from the amplify_authenticator package, and widgets
// you build yourself.
//
// See authenticator_with_custom_layout.dart for more info
//
// Uncomment the build method below (and comment out the one above) to
// see a simple example of this

// @override
// Widget build(BuildContext context) {
// return const AuthenticatorWithCustomLayout();
// }

// Below is another example of a custom authenticator, with a custom
// onboarding widget

// @override
// Widget build(BuildContext context) {
// return const AuthenticatorWithOnboarding();
// }

// Below is yet another example of a custom authenticator, with a widget to
// support Cognito's Custom Auth flow
// @override
// Widget build(BuildContext context) {
// return const AuthenticatorWithCustomAuthFlow();
// }
}

/// The screen which is shown once the user is logged in. We can use
/// [SignOutButton] from the Authenticator library anywhere in our app to
/// provide a pre-configured sign out experience. Alternatively, we can call
/// [Amplify.Auth.signOut] which will also notify the Authenticator.
class RouteA extends StatelessWidget {
const RouteA({super.key});

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Route A'),
),
body: Center(
child: Column(
children: [
ElevatedButton(
onPressed: () =>
Navigator.of(context).pushReplacementNamed('/routeB'),
child: const Text('Goto Route B'),
),
const SizedBox(height: 20),
const SignOutButton(),
],
),
),
);
}
}

class RouteB extends StatelessWidget {
const RouteB({super.key});

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Route B'),
),
body: Center(
child: Column(
children: [
ElevatedButton(
onPressed: () =>
Navigator.of(context).pushReplacementNamed('/routeA'),
child: const Text('Goto Route A'),
home: const Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SignOutButton(),
],
),
const SizedBox(height: 20),
const SignOutButton(),
],
),
),
),
);
Expand Down
Loading
Loading