mirror of
				https://gitlab.com/comunic/comunicmobile
				synced 2025-11-04 12:14:11 +00:00 
			
		
		
		
	Apply password policy on all forms
This commit is contained in:
		@@ -1,5 +1,5 @@
 | 
			
		||||
import 'package:comunic/ui/widgets/dialogs/auto_sized_dialog_content_widget.dart';
 | 
			
		||||
import 'package:comunic/utils/input_utils.dart';
 | 
			
		||||
import 'package:comunic/ui/widgets/new_password_input_widget.dart';
 | 
			
		||||
import 'package:comunic/utils/intl_utils.dart';
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
 | 
			
		||||
@@ -8,27 +8,44 @@ import 'package:flutter/material.dart';
 | 
			
		||||
/// @author Pierre HUBERT
 | 
			
		||||
 | 
			
		||||
/// Ask the user to enter a new password
 | 
			
		||||
Future<String> showInputNewPassword(BuildContext context) async {
 | 
			
		||||
Future<String> showInputNewPassword({
 | 
			
		||||
  @required BuildContext context,
 | 
			
		||||
  @required UserInfoForPassword userInfo,
 | 
			
		||||
}) async {
 | 
			
		||||
  assert(context != null);
 | 
			
		||||
  assert(userInfo != null);
 | 
			
		||||
  return await showDialog(
 | 
			
		||||
      context: context, builder: (c) => _InputNewPasswordDialog());
 | 
			
		||||
      context: context,
 | 
			
		||||
      builder: (c) => _InputNewPasswordDialog(
 | 
			
		||||
            userInfo: userInfo,
 | 
			
		||||
          ));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class _InputNewPasswordDialog extends StatefulWidget {
 | 
			
		||||
  final UserInfoForPassword userInfo;
 | 
			
		||||
 | 
			
		||||
  const _InputNewPasswordDialog({
 | 
			
		||||
    Key key,
 | 
			
		||||
    @required this.userInfo,
 | 
			
		||||
  })  : assert(userInfo != null),
 | 
			
		||||
        super(key: key);
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  __InputNewPasswordDialogState createState() =>
 | 
			
		||||
      __InputNewPasswordDialogState();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class __InputNewPasswordDialogState extends State<_InputNewPasswordDialog> {
 | 
			
		||||
  final _controller1 = TextEditingController();
 | 
			
		||||
  final _controller1 = GlobalKey<NewPasswordInputWidgetState>();
 | 
			
		||||
  final _controller2 = TextEditingController();
 | 
			
		||||
  final _focusScopeNode = FocusScopeNode();
 | 
			
		||||
 | 
			
		||||
  String get _password => _controller1.text;
 | 
			
		||||
  String get _password => _controller1.currentState.value;
 | 
			
		||||
 | 
			
		||||
  bool get _input1Valid => validatePassword(_password);
 | 
			
		||||
  bool get _input1Valid =>
 | 
			
		||||
      _controller1.currentState != null && _controller1.currentState.valid;
 | 
			
		||||
 | 
			
		||||
  bool get _input2Valid => _controller1.text == _controller2.text;
 | 
			
		||||
  bool get _input2Valid => _controller1.currentState.value == _controller2.text;
 | 
			
		||||
 | 
			
		||||
  bool get _isValid => _input1Valid && _input2Valid;
 | 
			
		||||
 | 
			
		||||
@@ -65,12 +82,10 @@ class __InputNewPasswordDialogState extends State<_InputNewPasswordDialog> {
 | 
			
		||||
      child: Column(
 | 
			
		||||
        children: <Widget>[
 | 
			
		||||
          // Input 1
 | 
			
		||||
          _buildPasswordField(
 | 
			
		||||
            controller: _controller1,
 | 
			
		||||
          NewPasswordInputWidget(
 | 
			
		||||
            key: _controller1,
 | 
			
		||||
            user: widget.userInfo,
 | 
			
		||||
            label: tr("Your new password"),
 | 
			
		||||
            errorText: _controller1.text.isNotEmpty && !_input1Valid
 | 
			
		||||
                ? tr("Invalid password!")
 | 
			
		||||
                : null,
 | 
			
		||||
            textInputAction: TextInputAction.next,
 | 
			
		||||
            onSubmitted: () => _focusScopeNode.nextFocus(),
 | 
			
		||||
          ),
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,7 @@ class __InputUserPasswordDialogState
 | 
			
		||||
  String get _currPass => _controller.text;
 | 
			
		||||
 | 
			
		||||
  bool get _canSubmit =>
 | 
			
		||||
      validatePassword(_controller.text) && _status != _Status.CHECKING;
 | 
			
		||||
      legacyValidatePassword(_controller.text) && _status != _Status.CHECKING;
 | 
			
		||||
 | 
			
		||||
  void _setStatus(_Status s) => setState(() => _status = s);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -139,9 +139,11 @@ class __CreateAccountRouteBodyState extends State<_CreateAccountRouteBody> {
 | 
			
		||||
                label: tr("Password"),
 | 
			
		||||
                onEdited: _updateUI,
 | 
			
		||||
                icon: Icon(Icons.lock),
 | 
			
		||||
                email: _emailController.text,
 | 
			
		||||
                firstName: _firstNameController.text,
 | 
			
		||||
                lastName: _lastNameController.text,
 | 
			
		||||
                user: UserInfoForPassword(
 | 
			
		||||
                  firstName: _firstNameController.text,
 | 
			
		||||
                  lastName: _lastNameController.text,
 | 
			
		||||
                  email: _emailController.text,
 | 
			
		||||
                ),
 | 
			
		||||
              ),
 | 
			
		||||
 | 
			
		||||
              // Verify password
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,8 @@
 | 
			
		||||
import 'package:comunic/helpers/account_helper.dart';
 | 
			
		||||
import 'package:comunic/models/res_check_password_reset_token.dart';
 | 
			
		||||
import 'package:comunic/ui/dialogs/input_new_password_dialog.dart';
 | 
			
		||||
import 'package:comunic/ui/widgets/async_screen_widget.dart';
 | 
			
		||||
import 'package:comunic/ui/widgets/new_password_input_widget.dart';
 | 
			
		||||
import 'package:comunic/ui/widgets/safe_state.dart';
 | 
			
		||||
import 'package:comunic/utils/intl_utils.dart';
 | 
			
		||||
import 'package:comunic/utils/ui_utils.dart';
 | 
			
		||||
@@ -47,12 +49,13 @@ class __PasswordResetBodyState extends SafeState<_PasswordResetBody> {
 | 
			
		||||
  final _key = GlobalKey<AsyncScreenWidgetState>();
 | 
			
		||||
 | 
			
		||||
  var _status = _Status.BEFORE_CHANGE;
 | 
			
		||||
  ResCheckPasswordToken _tokenInfo;
 | 
			
		||||
 | 
			
		||||
  void _setStatus(_Status s) => setState(() => _status = s);
 | 
			
		||||
 | 
			
		||||
  Future<void> _validateToken() async {
 | 
			
		||||
    _status = _Status.BEFORE_CHANGE;
 | 
			
		||||
    await AccountHelper.validatePasswordResetToken(widget.token);
 | 
			
		||||
    _tokenInfo = await AccountHelper.validatePasswordResetToken(widget.token);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
@@ -108,7 +111,14 @@ class __PasswordResetBodyState extends SafeState<_PasswordResetBody> {
 | 
			
		||||
  void _changePassword() async {
 | 
			
		||||
    try {
 | 
			
		||||
      // Ask for new password
 | 
			
		||||
      final newPass = await showInputNewPassword(context);
 | 
			
		||||
      final newPass = await showInputNewPassword(
 | 
			
		||||
        context: context,
 | 
			
		||||
        userInfo: UserInfoForPassword(
 | 
			
		||||
          firstName: _tokenInfo.firstName,
 | 
			
		||||
          lastName: _tokenInfo.lastName,
 | 
			
		||||
          email: _tokenInfo.email,
 | 
			
		||||
        ),
 | 
			
		||||
      );
 | 
			
		||||
      if (newPass == null) return;
 | 
			
		||||
      _setStatus(_Status.WHILE_CHANGE);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,13 @@
 | 
			
		||||
import 'package:comunic/helpers/account_helper.dart';
 | 
			
		||||
import 'package:comunic/helpers/settings_helper.dart';
 | 
			
		||||
import 'package:comunic/helpers/users_helper.dart';
 | 
			
		||||
import 'package:comunic/models/security_settings.dart';
 | 
			
		||||
import 'package:comunic/ui/dialogs/input_new_password_dialog.dart';
 | 
			
		||||
import 'package:comunic/ui/dialogs/input_user_password_dialog.dart';
 | 
			
		||||
import 'package:comunic/ui/widgets/dialogs/auto_sized_dialog_content_widget.dart';
 | 
			
		||||
import 'package:comunic/ui/widgets/new_password_input_widget.dart';
 | 
			
		||||
import 'package:comunic/ui/widgets/settings/header_spacer_section.dart';
 | 
			
		||||
import 'package:comunic/utils/account_utils.dart';
 | 
			
		||||
import 'package:comunic/utils/intl_utils.dart';
 | 
			
		||||
import 'package:comunic/utils/ui_utils.dart';
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
@@ -55,11 +58,21 @@ class _AccountSecuritySettingsScreenState
 | 
			
		||||
  /// Change current user password
 | 
			
		||||
  void _changePassword() async {
 | 
			
		||||
    try {
 | 
			
		||||
      final currEmail = await AccountHelper.getCurrentAccountEmailAddress();
 | 
			
		||||
      final currUser = await UsersHelper().getSingleWithThrow(userID());
 | 
			
		||||
 | 
			
		||||
      final currPassword = await showUserPasswordDialog(context);
 | 
			
		||||
 | 
			
		||||
      if (currPassword == null) return;
 | 
			
		||||
 | 
			
		||||
      final newPassword = await showInputNewPassword(context);
 | 
			
		||||
      final newPassword = await showInputNewPassword(
 | 
			
		||||
        context: context,
 | 
			
		||||
        userInfo: UserInfoForPassword(
 | 
			
		||||
          firstName: currUser.firstName,
 | 
			
		||||
          lastName: currUser.lastName,
 | 
			
		||||
          email: currEmail,
 | 
			
		||||
        ),
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      if (newPassword == null) return;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,5 @@
 | 
			
		||||
import 'package:comunic/helpers/server_config_helper.dart';
 | 
			
		||||
import 'package:comunic/models/server_config.dart';
 | 
			
		||||
import 'package:comunic/models/user.dart';
 | 
			
		||||
import 'package:comunic/utils/intl_utils.dart';
 | 
			
		||||
import 'package:comunic/utils/ui_utils.dart';
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
@@ -9,26 +8,38 @@ import 'package:flutter/material.dart';
 | 
			
		||||
///
 | 
			
		||||
/// @author Pierre Hubert
 | 
			
		||||
 | 
			
		||||
class NewPasswordInputWidget extends StatefulWidget {
 | 
			
		||||
  final Widget icon;
 | 
			
		||||
  final VoidCallback onEdited;
 | 
			
		||||
  final String label;
 | 
			
		||||
 | 
			
		||||
  final User user;
 | 
			
		||||
class UserInfoForPassword {
 | 
			
		||||
  final String firstName;
 | 
			
		||||
  final String lastName;
 | 
			
		||||
  final String email;
 | 
			
		||||
 | 
			
		||||
  const UserInfoForPassword({
 | 
			
		||||
    @required this.firstName,
 | 
			
		||||
    @required this.lastName,
 | 
			
		||||
    @required this.email,
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class NewPasswordInputWidget extends StatefulWidget {
 | 
			
		||||
  final Widget icon;
 | 
			
		||||
  final VoidCallback onEdited;
 | 
			
		||||
  final VoidCallback onSubmitted;
 | 
			
		||||
  final TextInputAction textInputAction;
 | 
			
		||||
  final String label;
 | 
			
		||||
 | 
			
		||||
  final UserInfoForPassword user;
 | 
			
		||||
 | 
			
		||||
  const NewPasswordInputWidget({
 | 
			
		||||
    Key key,
 | 
			
		||||
    this.icon,
 | 
			
		||||
    this.onEdited,
 | 
			
		||||
    this.onSubmitted,
 | 
			
		||||
    this.textInputAction,
 | 
			
		||||
    @required this.label,
 | 
			
		||||
    this.user,
 | 
			
		||||
    this.firstName,
 | 
			
		||||
    this.lastName,
 | 
			
		||||
    this.email,
 | 
			
		||||
  }) : super(key: key);
 | 
			
		||||
    @required this.user,
 | 
			
		||||
  })  : assert(label != null),
 | 
			
		||||
        assert(user != null),
 | 
			
		||||
        super(key: key);
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  NewPasswordInputWidgetState createState() => NewPasswordInputWidgetState();
 | 
			
		||||
@@ -73,6 +84,9 @@ class NewPasswordInputWidgetState extends State<NewPasswordInputWidget> {
 | 
			
		||||
        controller: _controller,
 | 
			
		||||
        obscureText: true,
 | 
			
		||||
        onChanged: (s) => _onChanged(),
 | 
			
		||||
        onSubmitted:
 | 
			
		||||
            widget.onSubmitted == null ? null : (s) => widget.onSubmitted(),
 | 
			
		||||
        textInputAction: widget.textInputAction,
 | 
			
		||||
        decoration: InputDecoration(
 | 
			
		||||
          errorText: _errorMessage,
 | 
			
		||||
          errorMaxLines: 3,
 | 
			
		||||
@@ -92,28 +106,21 @@ class NewPasswordInputWidgetState extends State<NewPasswordInputWidget> {
 | 
			
		||||
 | 
			
		||||
    // Mandatory checks
 | 
			
		||||
    if (!_policy.allowMailInPassword &&
 | 
			
		||||
        (widget.email ?? "").isNotEmpty &&
 | 
			
		||||
        (widget.email.toLowerCase().contains(value.toLowerCase()) ||
 | 
			
		||||
            value.toLowerCase().contains(widget.email.toLowerCase()))) {
 | 
			
		||||
      return tr("Your password must not contains part of your email address!");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!_policy.allowMailInPassword &&
 | 
			
		||||
        (widget.email ?? "").isNotEmpty &&
 | 
			
		||||
        (widget.email.toLowerCase().contains(value.toLowerCase()) ||
 | 
			
		||||
            value.toLowerCase().contains(widget.email.toLowerCase()))) {
 | 
			
		||||
        (widget.user.email ?? "").isNotEmpty &&
 | 
			
		||||
        (widget.user.email.toLowerCase().contains(value.toLowerCase()) ||
 | 
			
		||||
            value.toLowerCase().contains(widget.user.email.toLowerCase()))) {
 | 
			
		||||
      return tr("Your password must not contains part of your email address!");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!_policy.allowNameInPassword &&
 | 
			
		||||
        (widget.firstName ?? "").isNotEmpty &&
 | 
			
		||||
        value.toLowerCase().contains(widget.firstName.toLowerCase())) {
 | 
			
		||||
        (widget.user.firstName ?? "").isNotEmpty &&
 | 
			
		||||
        value.toLowerCase().contains(widget.user.firstName.toLowerCase())) {
 | 
			
		||||
      return tr("Your password must not contains your first name!");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!_policy.allowNameInPassword &&
 | 
			
		||||
        (widget.lastName ?? "").isNotEmpty &&
 | 
			
		||||
        value.toLowerCase().contains(widget.lastName.toLowerCase())) {
 | 
			
		||||
        (widget.user.lastName ?? "").isNotEmpty &&
 | 
			
		||||
        value.toLowerCase().contains(widget.user.lastName.toLowerCase())) {
 | 
			
		||||
      return tr("Your password must not contains your last name!");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user