123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 |
- import 'package:flutter/cupertino.dart';
- import 'package:flutter/material.dart';
- import 'package:flutter/widgets.dart';
- import 'package:photos/core/configuration.dart';
- import 'package:photos/core/event_bus.dart';
- import 'package:photos/events/user_authenticated_event.dart';
- import 'package:photos/user_authenticator.dart';
- class SignInWidget extends StatefulWidget {
- final Function() onReconfigurationRequested;
- const SignInWidget(
- this.onReconfigurationRequested, {
- Key key,
- }) : super(key: key);
- @override
- _SignInWidgetState createState() => _SignInWidgetState();
- }
- enum Mode { sign_up, sign_in, unknown }
- class _SignInWidgetState extends State<SignInWidget> {
- Mode mode = Mode.unknown;
- final _usernameController = TextEditingController();
- final _passwordController = TextEditingController();
- final _repeatPasswordController = TextEditingController();
- @override
- Widget build(BuildContext context) {
- if (mode == Mode.sign_up) {
- return _getSignUpWidget(context);
- } else {
- return _getSignInWidget(context);
- }
- }
- Widget _getSignUpWidget(BuildContext context) {
- return Container(
- child: SingleChildScrollView(
- child: Column(
- children: <Widget>[
- Padding(
- padding: const EdgeInsets.fromLTRB(0, 16, 0, 0),
- child: Text("Create an account to get started"),
- ),
- TextFormField(
- decoration: InputDecoration(
- hintText: 'username',
- contentPadding: EdgeInsets.all(20),
- ),
- controller: _usernameController,
- autofocus: true,
- autocorrect: false,
- ),
- TextFormField(
- decoration: InputDecoration(
- hintText: 'password',
- contentPadding: EdgeInsets.all(20),
- ),
- autocorrect: false,
- obscureText: true,
- controller: _passwordController,
- ),
- TextFormField(
- decoration: InputDecoration(
- hintText: 'repeat password',
- contentPadding: EdgeInsets.all(20),
- ),
- autocorrect: false,
- obscureText: true,
- controller: _repeatPasswordController,
- ),
- CupertinoButton(
- child: Text("Sign Up"),
- onPressed: () async {
- if (_passwordController.text != _repeatPasswordController.text) {
- _showPasswordMismatchDialog();
- } else {
- try {
- final userCreated = await UserAuthenticator.instance.create(
- _usernameController.text, _passwordController.text);
- if (userCreated) {
- Navigator.of(context).pop();
- _showSelectEncryptionLevelDialog();
- } else {
- _showGenericErrorDialog();
- }
- } catch (e) {
- _showGenericErrorDialog(error: e);
- }
- }
- },
- ),
- CupertinoButton(
- child: Text("Have an account?"),
- onPressed: () {
- setState(() {
- mode = Mode.sign_in;
- });
- },
- ),
- ],
- ),
- ));
- }
- Widget _getSignInWidget(BuildContext context) {
- return Container(
- child: SingleChildScrollView(
- child: Column(
- mainAxisAlignment: MainAxisAlignment.center,
- children: <Widget>[
- TextFormField(
- // initialValue: Configuration.instance.getUsername(),
- decoration: InputDecoration(
- hintText: 'username',
- contentPadding: EdgeInsets.all(20),
- ),
- autofocus: true,
- autocorrect: false,
- controller: _usernameController,
- ),
- TextFormField(
- // initialValue: Configuration.instance.getPassword(),
- decoration: InputDecoration(
- hintText: 'password',
- contentPadding: EdgeInsets.all(20),
- ),
- autocorrect: false,
- obscureText: true,
- controller: _passwordController,
- ),
- CupertinoButton(
- child: Text("Sign In"),
- onPressed: () async {
- final loggedIn = await UserAuthenticator.instance
- .login(_usernameController.text, _passwordController.text);
- if (loggedIn) {
- Navigator.of(context).pop();
- if (Configuration.instance.getEncryptedKey() != null) {
- showDialog(
- context: context,
- barrierDismissible: false,
- builder: (BuildContext context) {
- return PassphraseDialog(false);
- },
- );
- }
- } else {
- _showAuthenticationFailedErrorDialog();
- }
- },
- ),
- CupertinoButton(
- child: Text("Don't have an account?"),
- onPressed: () {
- setState(() {
- mode = Mode.sign_up;
- });
- },
- ),
- ],
- ),
- ));
- }
- void _showPasswordMismatchDialog() {
- showDialog<void>(
- context: context,
- barrierDismissible: false, // user must tap button!
- builder: (BuildContext context) {
- return CupertinoAlertDialog(
- title: Text("Passwords don't match"),
- content: Padding(
- padding: const EdgeInsets.fromLTRB(0, 16, 0, 0),
- child: Text("Please make sure that the passwords you enter match."),
- ),
- actions: <Widget>[
- CupertinoDialogAction(
- child: Text('OK'),
- onPressed: () {
- Navigator.of(context).pop();
- },
- ),
- ],
- );
- },
- );
- }
- void _showGenericErrorDialog({Exception error}) {
- showDialog<void>(
- context: context,
- barrierDismissible: false, // user must tap button!
- builder: (BuildContext context) {
- return CupertinoAlertDialog(
- title: Text("Ooops."),
- content: Padding(
- padding: const EdgeInsets.fromLTRB(0, 16, 0, 0),
- child: error == null
- ? Text("Something went wrong.")
- : Text(error.toString()),
- ),
- actions: <Widget>[
- CupertinoDialogAction(
- child: Text('OK'),
- onPressed: () {
- Navigator.of(context).pop();
- },
- ),
- ],
- );
- },
- );
- }
- void _showAuthenticationFailedErrorDialog() {
- showDialog<void>(
- context: context,
- barrierDismissible: false, // user must tap button!
- builder: (BuildContext context) {
- return CupertinoAlertDialog(
- title: Text('Login failed'),
- content: Padding(
- padding: const EdgeInsets.fromLTRB(0, 16, 0, 0),
- child: Text(
- 'Please make sure that the credentials entered are correct.'),
- ),
- actions: <Widget>[
- CupertinoDialogAction(
- child: Text('Reconfigure'),
- onPressed: () {
- Navigator.of(context).pop();
- Configuration.instance.setEndpoint(null);
- widget.onReconfigurationRequested();
- },
- ),
- CupertinoDialogAction(
- child: Text('OK'),
- onPressed: () {
- Navigator.of(context).pop();
- },
- ),
- ],
- );
- },
- );
- }
- void _showSelectEncryptionLevelDialog() {
- showDialog(
- context: context,
- barrierDismissible: false,
- builder: (BuildContext context) {
- return SelectEncryptionLevelWidget();
- },
- );
- }
- }
- class SelectEncryptionLevelWidget extends StatelessWidget {
- const SelectEncryptionLevelWidget({
- Key key,
- }) : super(key: key);
- @override
- Widget build(BuildContext context) {
- return CupertinoAlertDialog(
- title: Text('Choose encryption level'),
- content: Padding(
- padding: const EdgeInsets.fromLTRB(0, 16, 0, 0),
- child: Column(
- children: [
- Text('Would you like to enable end-to-end encryption?'),
- Padding(padding: EdgeInsets.all(8)),
- Text(
- 'This will mean you will not be able to use features like search and sharing.'),
- ],
- ),
- ),
- actions: <Widget>[
- CupertinoDialogAction(
- child: Text('Use E2E encryption'),
- onPressed: () {
- Navigator.of(context).pop();
- Configuration.instance.setOptInForE2E(true);
- showDialog(
- context: context,
- barrierDismissible: false,
- builder: (BuildContext context) {
- return PassphraseDialog(true);
- },
- );
- },
- ),
- CupertinoDialogAction(
- child: Text("Use encryption at rest"),
- onPressed: () {
- Navigator.of(context).pop();
- Configuration.instance.setOptInForE2E(false);
- Bus.instance.fire(UserAuthenticatedEvent());
- },
- ),
- ],
- );
- }
- }
- class PassphraseDialog extends StatefulWidget {
- final bool isFreshRegistration;
- const PassphraseDialog(
- this.isFreshRegistration, {
- Key key,
- }) : super(key: key);
- @override
- _PassphraseDialogState createState() => _PassphraseDialogState();
- }
- class _PassphraseDialogState extends State<PassphraseDialog> {
- String _passphrase = "";
- @override
- Widget build(BuildContext context) {
- return CupertinoAlertDialog(
- title: Text('Enter passphrase'),
- content: Padding(
- padding: const EdgeInsets.fromLTRB(0, 16, 0, 0),
- child: Column(
- children: [
- CupertinoTextField(
- autofocus: true,
- style: Theme.of(context).textTheme.subtitle1,
- keyboardType: TextInputType.visiblePassword,
- onChanged: (value) {
- _passphrase = value;
- },
- ),
- ],
- ),
- ),
- actions: <Widget>[
- CupertinoDialogAction(
- child: Text('Save'),
- onPressed: () async {
- Navigator.of(context).pop();
- if (widget.isFreshRegistration) {
- await Configuration.instance.generateAndSaveKey(_passphrase);
- await UserAuthenticator.instance.setEncryptedKeyOnServer();
- } else {
- await Configuration.instance.decryptEncryptedKey(_passphrase);
- }
- Bus.instance.fire(UserAuthenticatedEvent());
- },
- )
- ],
- );
- }
- }
|