From 1202e4ad539c5f085b78fee67ab6371dc4f62633 Mon Sep 17 00:00:00 2001 From: Kherel Date: Wed, 18 Aug 2021 11:36:40 +0200 Subject: [PATCH] change password generator --- lib/logic/api_maps/hetzner.dart | 14 +- .../cubit/forms/user/user_form_cubit.dart | 6 +- lib/logic/cubit/users/users_cubit.dart | 18 -- lib/logic/models/jobs/job.dart | 4 +- lib/logic/models/user.dart | 6 +- lib/utils/password_generator.dart | 229 ++++++++---------- lib/utils/password_generator2.dart | 14 -- pubspec.lock | 90 +++---- pubspec.yaml | 10 +- test/widget_test.dart | 134 ++++++++-- 10 files changed, 273 insertions(+), 252 deletions(-) delete mode 100644 lib/utils/password_generator2.dart diff --git a/lib/logic/api_maps/hetzner.dart b/lib/logic/api_maps/hetzner.dart index 037db18cf3..0c29a04006 100644 --- a/lib/logic/api_maps/hetzner.dart +++ b/lib/logic/api_maps/hetzner.dart @@ -7,7 +7,7 @@ import 'package:selfprivacy/logic/api_maps/api_map.dart'; import 'package:selfprivacy/logic/models/hetzner_server_info.dart'; import 'package:selfprivacy/logic/models/server_details.dart'; import 'package:selfprivacy/logic/models/user.dart'; -import 'package:selfprivacy/utils/password_generator2.dart'; +import 'package:selfprivacy/utils/password_generator.dart'; class HetznerApi extends ApiMap { bool hasLoger; @@ -73,30 +73,26 @@ class HetznerApi extends ApiMap { required User rootUser, required String domainName, }) async { - var dbPassword = getRandomString(40); - const chars = - 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890'; - - var dbStorageName = getRandomString(6, chars); var client = await getClient(); Response dbCreateResponse = await client.post( '/volumes', data: { "size": 10, - "name": dbStorageName, + "name": StringGenerators.dbStorageName(), "labels": {"labelkey": "value"}, "location": "fsn1", "automount": false, "format": "ext4" }, ); + + var dbPassword = StringGenerators.dbPassword(); var dbId = dbCreateResponse.data['volume']['id']; var data = jsonDecode( - '''{"name":"$domainName","server_type":"cx11","start_after_create":false,"image":"ubuntu-20.04", "volumes":[$dbId], "networks":[], "user_data":"#cloud-config\\nruncmd:\\n- curl https://git.selfprivacy.org/ilchub/selfprivacy-nixos-infect/raw/branch/master/nixos-infect | PROVIDER=hetzner NIX_CHANNEL=nixos-21.05 DOMAIN=$domainName LUSER=${rootUser.login} PASSWORD=${rootUser.password} HASHED_PASSWORD=${rootUser.hashPassword.hash} SALT=${rootUser.hashPassword.salt} CF_TOKEN=$cloudFlareKey DB_PASSWORD=$dbPassword bash 2>&1 | tee /tmp/infect.log","labels":{},"automount":true, "location": "fsn1"}''' - ); + '''{"name":"$domainName","server_type":"cx11","start_after_create":false,"image":"ubuntu-20.04", "volumes":[$dbId], "networks":[], "user_data":"#cloud-config\\nruncmd:\\n- curl https://git.selfprivacy.org/ilchub/selfprivacy-nixos-infect/raw/branch/master/nixos-infect | PROVIDER=hetzner NIX_CHANNEL=nixos-21.05 DOMAIN=$domainName LUSER=${rootUser.login} PASSWORD=${rootUser.password} HASHED_PASSWORD=${rootUser.hashPassword.hash} SALT=${rootUser.hashPassword.salt} CF_TOKEN=$cloudFlareKey DB_PASSWORD=$dbPassword bash 2>&1 | tee /tmp/infect.log","labels":{},"automount":true, "location": "fsn1"}'''); Response serverCreateResponse = await client.post( '/servers', diff --git a/lib/logic/cubit/forms/user/user_form_cubit.dart b/lib/logic/cubit/forms/user/user_form_cubit.dart index a30b90f820..5501b38b29 100644 --- a/lib/logic/cubit/forms/user/user_form_cubit.dart +++ b/lib/logic/cubit/forms/user/user_form_cubit.dart @@ -4,8 +4,8 @@ import 'package:cubit_form/cubit_form.dart'; import 'package:selfprivacy/logic/cubit/jobs/jobs_cubit.dart'; import 'package:selfprivacy/logic/models/jobs/job.dart'; import 'package:selfprivacy/logic/models/user.dart'; -import 'package:selfprivacy/utils/password_generator.dart'; import 'package:easy_localization/easy_localization.dart'; +import 'package:selfprivacy/utils/password_generator.dart'; class UserFormCubit extends FormCubit { UserFormCubit({ @@ -32,7 +32,7 @@ class UserFormCubit extends FormCubit { ); password = FieldCubit( - initalValue: isEdit ? user!.password : genPass(), + initalValue: isEdit ? user!.password : StringGenerators.userPassword(), validations: [ RequiredStringValidation('validations.required'.tr()), ValidationModel((s) => passwordRegExp.hasMatch(s), @@ -56,7 +56,7 @@ class UserFormCubit extends FormCubit { late FieldCubit password; void genNewPassword() { - password.externalSetValue(genPass()); + password.externalSetValue(StringGenerators.userPassword()); } final JobsCubit jobsCubit; diff --git a/lib/logic/cubit/users/users_cubit.dart b/lib/logic/cubit/users/users_cubit.dart index ecc0c89767..5d634dc462 100644 --- a/lib/logic/cubit/users/users_cubit.dart +++ b/lib/logic/cubit/users/users_cubit.dart @@ -34,21 +34,3 @@ class UsersCubit extends Cubit { emit(UsersState(users)); } } - -// final initMockUsers = [ -// User(login: 'Heartbreaking.Goose', password: genPass()), -// User(login: 'Alma.lawson', password: genPass()), -// User(login: 'Bee.gees', password: genPass()), -// User(login: 'Bim.jennings', password: genPass()), -// User(login: 'Debra.holt', password: genPass()), -// User(login: 'Georgia.young', password: genPass()), -// User(login: 'Kenzi.lawson', password: genPass()), -// User(login: 'Le.jennings', password: genPass()), -// User(login: 'Kirill.Zh', password: genPass()), -// User(login: 'Tina.Bolton', password: genPass()), -// User(login: 'Rebekah.Lynn', password: genPass()), -// User(login: 'Aleena.Armstrong', password: genPass()), -// User(login: 'Rosemary.Williams', password: genPass()), -// User(login: 'Sullivan.Nixon', password: genPass()), -// User(login: 'Aleena.Armstrong', password: genPass()), -// ]; diff --git a/lib/logic/models/jobs/job.dart b/lib/logic/models/jobs/job.dart index 3d6bc386d5..2fcc8e8763 100644 --- a/lib/logic/models/jobs/job.dart +++ b/lib/logic/models/jobs/job.dart @@ -1,6 +1,6 @@ import 'package:equatable/equatable.dart'; import 'package:flutter/material.dart'; -import 'package:selfprivacy/utils/password_generator2.dart'; +import 'package:selfprivacy/utils/password_generator.dart'; import '../user.dart'; @@ -9,7 +9,7 @@ class Job extends Equatable { Job({ String? id, required this.title, - }) : id = id ?? getRandomString(5); + }) : id = id ?? StringGenerators.simpleId(); final String title; final String id; diff --git a/lib/logic/models/user.dart b/lib/logic/models/user.dart index c50d13fe00..0d1c48b3a7 100644 --- a/lib/logic/models/user.dart +++ b/lib/logic/models/user.dart @@ -4,6 +4,7 @@ import 'package:crypt/crypt.dart'; import 'package:equatable/equatable.dart'; import 'package:selfprivacy/utils/color_utils.dart'; import 'package:hive/hive.dart'; +import 'package:selfprivacy/utils/password_generator.dart'; part 'user.g.dart'; @@ -25,7 +26,10 @@ class User extends Equatable { Color get color => stringToColor(login); - Crypt get hashPassword => Crypt.sha512(password); + Crypt get hashPassword => Crypt.sha512( + password, + salt: StringGenerators.passwordSalt(), + ); String toString() { return login; diff --git a/lib/utils/password_generator.dart b/lib/utils/password_generator.dart index a0ce627381..f7bdd2d656 100644 --- a/lib/utils/password_generator.dart +++ b/lib/utils/password_generator.dart @@ -1,138 +1,99 @@ import 'dart:math'; -var generator = PasswordGenerator(); +Random _rnd = Random(); -String genPass() { - generator.generate(8); - return generator.getGeneratedValue(); -} - -///Generates a password. -/// -///The password [_generatedValue] is of a specified length, including letters [_letterGen] of mixed cases, -///numbers [_numGen], and symbols[_symGen] depending on user choice. -class PasswordGenerator { - late bool _letterGen; - late bool _numGen; - late bool _symGen; - late String _generatedValue; - - ///Constructor. - /// - ///[_letterGen] is true to make password generation possible from the opening of the application, and - ///[_generatedValue] is intialized to the value below so the text containing it can be first generated - ///upon users request - PasswordGenerator() { - _letterGen = true; - _numGen = true; - _symGen = false; - _generatedValue = "Press Generate"; - } - - ///Call to generate a value, of [n] length - void generate(int n) { - //Discards the old value - _generatedValue = ""; - - ///Cannot generate a value without any character types selected - if (!_letterGen && !_numGen && !_symGen) { - _generatedValue = "No character type selected"; - return; - } - - ///'Randomly' selectes caracter type to generate and append [toAppend] to [_generatedValue] - // ignore: unnecessary_statements - for (n; n > 0; n--) { - String? toAppend; - var random = new Random(); - - ///loops until a valid character is generated, meaning the user has to check the character value - ///to be generated. 'Randomly' picks a character type. - while (toAppend == null) { - int selector = random.nextInt(3); - - if (selector == 0) { - toAppend = _generateLetter(); - } else if (selector == 1) { - toAppend = _generateNumber(); - } else { - toAppend = _generateSymbol(); - } - } - - _generatedValue += toAppend; - toAppend = null; - } - } - - ///Generates a letter when called. - String _generateLetter() { - if (!_letterGen) return ''; - - ///Finds the integer value for the range between a-z and A-Z, with [base] UTF-16 value for lowercase letters and - ///[baseUpper] UTF-16 value for uppercase letters - int base = "a".codeUnitAt(0); - int baseUpper = "A".codeUnitAt(0); - int maxRand = ("z".codeUnitAt(0) - base) + 1; - Random random = new Random(); - - ///Randomly selects between upper and lower case generation, randomly generates value from [maxRand], then adding base, - ///which creates a UTF-16 encoded character to be converted into a string of one character between a-z/A-Z. - ///This string is then returned. - if (random.nextInt(2) == 0) { - return String.fromCharCodes([random.nextInt(maxRand) + base]); - } else { - return String.fromCharCodes([random.nextInt(maxRand) + baseUpper]); - } - } - - ///Generates a number when called - String? _generateNumber() { - if (!_numGen) return null; - - ///Finds the integer value for the range between 0-9 - int base = "0".codeUnitAt(0); - int maxRand = ("9".codeUnitAt(0) - base) + 1; - Random random = new Random(); - - ///Randomly generates value from [maxRand], then adding base, which creates a UTF-16 encoded character to be converted into a - ///string of one character between 0-9. This string is then returned. - return String.fromCharCodes([random.nextInt(maxRand) + base]); - } - - ///Generates a symbol when called - String? _generateSymbol() { - if (!_symGen) return null; - - ///Finds the integer value for the range between symbols !-. - - ///(note) which includes symbols !"#$%&'()*+,=. - int base = "!".codeUnitAt(0); - int maxRand = (".".codeUnitAt(0) - base) + 1; - Random random = new Random(); - - ///Randomly generates value from [maxRand], then adding base, which creates a UTF-16 encoded character to be - ///converted into a string of one character between !-. . This string is then returned. - return String.fromCharCodes([random.nextInt(maxRand) + base]); - } - - ///Toggles letter generation - void checkLetterGen(bool value) { - _letterGen = value; - } - - ///Toggles number generation - void checkNumGen(bool value) { - _numGen = value; - } - - ///Toggles symbol generation - void checkSymGen(bool value) { - _symGen = value; - } - - ///Returns the generated value to be used by generator app - String getGeneratedValue() { - return _generatedValue; - } +typedef StringGeneratorFunction = String Function(); + +class StringGenerators { + static const letters = 'abcdefghijklmnopqrstuvwxyz'; + static const numbers = '1234567890'; + static const symbols = '_'; + + static String getRandomString( + int length, { + hasLowercaseLetters = false, + hasUppercaseLetters = false, + hasNumbers = false, + hasSymbols = false, + isStrict = false, + }) { + var chars = ''; + if (hasLowercaseLetters) chars += letters; + if (hasUppercaseLetters) chars += letters.toUpperCase(); + if (hasNumbers) chars += numbers; + if (hasSymbols) chars += symbols; + + assert(chars.isNotEmpty, 'chart empty'); + + if (!isStrict) { + return genString(length, chars); + } + + var res = ''; + var loose = length; + if (hasLowercaseLetters) { + loose -= 1; + res += genString(1, letters); + } + if (hasUppercaseLetters) { + loose -= 1; + res += genString(1, letters.toUpperCase()); + } + if (hasNumbers) { + loose -= 1; + res += genString(1, numbers.toUpperCase()); + } + if (hasSymbols) { + loose -= 1; + res += genString(1, symbols); + } + res += genString(loose, chars); + + var shuffledlist = res.split('')..shuffle(); + return shuffledlist.join(); + } + + static String genString(int length, String chars) { + return String.fromCharCodes( + Iterable.generate( + length, + (_) => chars.codeUnitAt( + _rnd.nextInt(chars.length), + ), + ), + ); + } + + static StringGeneratorFunction userPassword = () => getRandomString( + 8, + hasLowercaseLetters: true, + hasUppercaseLetters: true, + hasNumbers: true, + isStrict: true, + ); + + static StringGeneratorFunction passwordSalt = () => getRandomString( + 8, + hasLowercaseLetters: true, + ); + + static StringGeneratorFunction simpleId = () => getRandomString( + 5, + hasLowercaseLetters: true, + ); + + static StringGeneratorFunction dbPassword = () => getRandomString( + 40, + hasLowercaseLetters: true, + hasUppercaseLetters: true, + hasNumbers: true, + hasSymbols: true, + ); + + static StringGeneratorFunction dbStorageName = () => getRandomString( + 6, + hasLowercaseLetters: true, + hasUppercaseLetters: true, + hasNumbers: true, + ); } diff --git a/lib/utils/password_generator2.dart b/lib/utils/password_generator2.dart deleted file mode 100644 index 36114d5574..0000000000 --- a/lib/utils/password_generator2.dart +++ /dev/null @@ -1,14 +0,0 @@ -import 'dart:math'; - -const _chars = - 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890_'; -Random _rnd = Random(); - -String getRandomString(int length, [chars = _chars]) => String.fromCharCodes( - Iterable.generate( - length, - (_) => chars.codeUnitAt( - _rnd.nextInt(chars.length), - ), - ), - ); diff --git a/pubspec.lock b/pubspec.lock index dca1a9511c..5f0d58098f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -28,7 +28,7 @@ packages: name: args url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.2.0" async: dependency: transitive description: @@ -37,12 +37,12 @@ packages: source: hosted version: "2.6.1" basic_utils: - dependency: "direct dev" + dependency: "direct main" description: name: basic_utils url: "https://pub.dartlang.org" source: hosted - version: "3.1.0" + version: "3.4.0" bloc: dependency: transitive description: @@ -63,7 +63,7 @@ packages: name: build url: "https://pub.dartlang.org" source: hosted - version: "2.0.2" + version: "2.0.3" build_config: dependency: transitive description: @@ -84,7 +84,7 @@ packages: name: build_resolvers url: "https://pub.dartlang.org" source: hosted - version: "2.0.3" + version: "2.0.4" build_runner: dependency: "direct dev" description: @@ -112,7 +112,7 @@ packages: name: built_value url: "https://pub.dartlang.org" source: hosted - version: "8.1.0" + version: "8.1.2" characters: dependency: transitive description: @@ -140,7 +140,7 @@ packages: name: cli_util url: "https://pub.dartlang.org" source: hosted - version: "0.3.0" + version: "0.3.3" clock: dependency: transitive description: @@ -168,7 +168,7 @@ packages: name: convert url: "https://pub.dartlang.org" source: hosted - version: "3.0.0" + version: "3.0.1" coverage: dependency: transitive description: @@ -196,7 +196,7 @@ packages: name: cubit_form url: "https://pub.dartlang.org" source: hosted - version: "1.0.16" + version: "1.0.18" cupertino_icons: dependency: "direct main" description: @@ -210,7 +210,7 @@ packages: name: dart_style url: "https://pub.dartlang.org" source: hosted - version: "2.0.1" + version: "2.0.3" dio: dependency: "direct main" description: @@ -259,7 +259,7 @@ packages: name: extended_masked_text url: "https://pub.dartlang.org" source: hosted - version: "2.2.1" + version: "2.3.0" fake_async: dependency: transitive description: @@ -306,14 +306,14 @@ packages: name: flutter_bloc url: "https://pub.dartlang.org" source: hosted - version: "7.0.1" + version: "7.1.0" flutter_launcher_icons: dependency: "direct dev" description: name: flutter_launcher_icons url: "https://pub.dartlang.org" source: hosted - version: "0.9.0" + version: "0.9.1" flutter_localizations: dependency: transitive description: flutter @@ -325,14 +325,14 @@ packages: name: flutter_markdown url: "https://pub.dartlang.org" source: hosted - version: "0.6.2" + version: "0.6.4" flutter_secure_storage: dependency: "direct main" description: name: flutter_secure_storage url: "https://pub.dartlang.org" source: hosted - version: "4.2.0" + version: "4.2.1" flutter_test: dependency: "direct dev" description: flutter @@ -426,7 +426,7 @@ packages: name: io url: "https://pub.dartlang.org" source: hosted - version: "1.0.0" + version: "1.0.3" ionicons: dependency: "direct main" description: @@ -454,7 +454,7 @@ packages: name: json_serializable url: "https://pub.dartlang.org" source: hosted - version: "4.1.3" + version: "4.1.4" logging: dependency: transitive description: @@ -552,14 +552,14 @@ packages: name: path_provider_linux url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.2" path_provider_macos: dependency: transitive description: name: path_provider_macos url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.2" path_provider_platform_interface: dependency: transitive description: @@ -573,7 +573,7 @@ packages: name: path_provider_windows url: "https://pub.dartlang.org" source: hosted - version: "2.0.1" + version: "2.0.3" pedantic: dependency: transitive description: @@ -601,14 +601,14 @@ packages: name: plugin_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.1" pointycastle: dependency: transitive description: name: pointycastle url: "https://pub.dartlang.org" source: hosted - version: "3.1.2" + version: "3.3.0" pool: dependency: transitive description: @@ -629,7 +629,7 @@ packages: name: process url: "https://pub.dartlang.org" source: hosted - version: "4.2.1" + version: "4.2.3" provider: dependency: "direct main" description: @@ -706,14 +706,14 @@ packages: name: shared_preferences_linux url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.2" shared_preferences_macos: dependency: transitive description: name: shared_preferences_macos url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.2" shared_preferences_platform_interface: dependency: transitive description: @@ -727,21 +727,21 @@ packages: name: shared_preferences_web url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.1" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.2" shelf: dependency: transitive description: name: shelf url: "https://pub.dartlang.org" source: hosted - version: "1.1.4" + version: "1.2.0" shelf_packages_handler: dependency: transitive description: @@ -755,7 +755,7 @@ packages: name: shelf_static url: "https://pub.dartlang.org" source: hosted - version: "1.0.0" + version: "1.1.0" shelf_web_socket: dependency: transitive description: @@ -774,14 +774,14 @@ packages: name: source_gen url: "https://pub.dartlang.org" source: hosted - version: "1.0.2" + version: "1.0.3" source_helper: dependency: transitive description: name: source_helper url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.1" source_map_stack_trace: dependency: transitive description: @@ -886,42 +886,42 @@ packages: name: url_launcher url: "https://pub.dartlang.org" source: hosted - version: "6.0.6" + version: "6.0.9" url_launcher_linux: dependency: transitive description: name: url_launcher_linux url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.1" url_launcher_macos: dependency: transitive description: name: url_launcher_macos url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.1" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.0.3" + version: "2.0.4" url_launcher_web: dependency: transitive description: name: url_launcher_web url: "https://pub.dartlang.org" source: hosted - version: "2.0.1" + version: "2.0.2" url_launcher_windows: dependency: transitive description: name: url_launcher_windows url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.1" vector_math: dependency: transitive description: @@ -942,35 +942,35 @@ packages: name: wakelock url: "https://pub.dartlang.org" source: hosted - version: "0.5.2" + version: "0.5.3+3" wakelock_macos: dependency: transitive description: name: wakelock_macos url: "https://pub.dartlang.org" source: hosted - version: "0.1.0+1" + version: "0.1.0+2" wakelock_platform_interface: dependency: transitive description: name: wakelock_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "0.2.1+1" + version: "0.2.1+2" wakelock_web: dependency: transitive description: name: wakelock_web url: "https://pub.dartlang.org" source: hosted - version: "0.2.0+1" + version: "0.2.0+2" wakelock_windows: dependency: transitive description: name: wakelock_windows url: "https://pub.dartlang.org" source: hosted - version: "0.1.0" + version: "0.1.0+1" watcher: dependency: transitive description: @@ -998,7 +998,7 @@ packages: name: win32 url: "https://pub.dartlang.org" source: hosted - version: "2.2.1" + version: "2.2.5" xdg_directories: dependency: transitive description: @@ -1021,5 +1021,5 @@ packages: source: hosted version: "3.1.0" sdks: - dart: ">=2.13.0 <3.0.0" - flutter: ">=2.0.0" + dart: ">=2.13.4 <3.0.0" + flutter: ">=2.2.3" diff --git a/pubspec.yaml b/pubspec.yaml index a9f7d60012..44eadcb7a1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,8 +4,8 @@ publish_to: 'none' version: 0.1.3+5 environment: - sdk: '>=2.12.0 <3.0.0' - flutter: ">=2.0.0" + sdk: '>=2.13.4 <3.0.0' + flutter: ">=2.2.3" dependencies: flutter: @@ -16,9 +16,9 @@ dependencies: dio: ^4.0.0-beta7 easy_localization: ^3.0.0 either_option: ^2.0.1-dev.1 - equatable: ^2.0.0 + equatable: ^2.0.3 fl_chart: ^0.35.0 - flutter_bloc: ^7.0.0 + flutter_bloc: ^7.1.0 flutter_markdown: ^0.6.0 flutter_secure_storage: ^4.1.0 get_it: ^6.0.0 @@ -35,11 +35,11 @@ dependencies: unicons: ^1.0.2 url_launcher: ^6.0.2 wakelock: ^0.5.0+2 + basic_utils: ^3.4.0 dev_dependencies: flutter_test: sdk: flutter - basic_utils: ^3.0.0-nullsafety.1 build_runner: ^1.11.5 flutter_launcher_icons: ^0.9.0 hive_generator: ^1.0.0 diff --git a/test/widget_test.dart b/test/widget_test.dart index 6eed7a461b..aaa334192c 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -1,30 +1,122 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility that Flutter provides. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - -import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:selfprivacy/main.dart'; +import 'package:selfprivacy/utils/password_generator.dart'; void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(MyApp()); + group('StringGenerators', () { + group('Basic', () { + test('assert chart empty', () { + expect(() { + StringGenerators.getRandomString(8); + }, throwsAssertionError); + }); - // Verify that our counter starts at 0. - expect(find.text('0'), findsOneWidget); - expect(find.text('1'), findsNothing); + test('only lowercase string', () { + var length = 8; + var generatedString = + StringGenerators.getRandomString(length, hasLowercaseLetters: true); - // Tap the '+' icon and trigger a frame. - await tester.tap(find.byIcon(Icons.add)); - await tester.pump(); + expect(generatedString, isNot(matches(regExpNewLines))); + expect(generatedString, isNot(matches(regExpWhiteSpaces))); + expect(generatedString, isNot(matches(regExpNumbers))); + expect(generatedString, isNot(matches(regExpUppercaseLetters))); + expect(generatedString, isNot(matches(regExpSymbols))); + expect(generatedString.length, equals(length)); + expect(generatedString, matches(regExpLowercaseLetters)); + }); - // Verify that our counter has incremented. - expect(find.text('0'), findsNothing); - expect(find.text('1'), findsOneWidget); + test('only uppercase string', () { + var length = 8; + var generatedString = StringGenerators.getRandomString(length, + hasLowercaseLetters: false, hasUppercaseLetters: true); + + expect(generatedString, isNot(matches(regExpNewLines))); + expect(generatedString, isNot(matches(regExpWhiteSpaces))); + expect(generatedString, isNot(matches(regExpNumbers))); + expect(generatedString, isNot(matches(regExpLowercaseLetters))); + expect(generatedString, isNot(matches(regExpSymbols))); + expect(generatedString.length, equals(length)); + expect(generatedString, matches(regExpUppercaseLetters)); + }); + + test('only numbers string', () { + var length = 8; + var generatedString = StringGenerators.getRandomString(length, + hasLowercaseLetters: false, + hasUppercaseLetters: false, + hasNumbers: true); + + expect(generatedString, isNot(matches(regExpNewLines))); + expect(generatedString, isNot(matches(regExpWhiteSpaces))); + expect(generatedString, isNot(matches(regExpUppercaseLetters))); + expect(generatedString, isNot(matches(regExpLowercaseLetters))); + expect(generatedString, isNot(matches(regExpSymbols))); + expect(generatedString.length, equals(length)); + expect(generatedString, matches(regExpNumbers)); + }); + + test('only symbols string', () { + var length = 8; + var generatedString = StringGenerators.getRandomString( + length, + hasLowercaseLetters: false, + hasUppercaseLetters: false, + hasNumbers: false, + hasSymbols: true, + ); + + expect(generatedString, isNot(matches(regExpNewLines))); + expect(generatedString, isNot(matches(regExpWhiteSpaces))); + expect(generatedString, isNot(matches(regExpUppercaseLetters))); + expect(generatedString, isNot(matches(regExpLowercaseLetters))); + expect(generatedString, isNot(matches(regExpNumbers))); + expect(generatedString.length, equals(length)); + expect(generatedString, matches(regExpSymbols)); + }); + }); + + group('Strict mode', () { + test('All', () { + var length = 5; + var generatedString = StringGenerators.getRandomString(length, + hasLowercaseLetters: true, + hasUppercaseLetters: true, + hasNumbers: true, + hasSymbols: true, + isStrict: true); + + expect(generatedString, isNot(matches(regExpNewLines))); + expect(generatedString, isNot(matches(regExpWhiteSpaces))); + expect(generatedString, matches(regExpLowercaseLetters)); + expect(generatedString, matches(regExpUppercaseLetters)); + expect(generatedString, matches(regExpNumbers)); + expect(generatedString, matches(regExpSymbols)); + expect(generatedString.length, equals(length)); + }); + test('Lowercase letters and numbers', () { + var length = 3; + var generatedString = StringGenerators.getRandomString(length, + hasLowercaseLetters: true, + hasUppercaseLetters: false, + hasNumbers: true, + hasSymbols: false, + isStrict: true); + + expect(generatedString, isNot(matches(regExpNewLines))); + expect(generatedString, isNot(matches(regExpWhiteSpaces))); + expect(generatedString, isNot(matches(regExpUppercaseLetters))); + expect(generatedString, isNot(matches(regExpSymbols))); + expect(generatedString, matches(regExpLowercaseLetters)); + expect(generatedString, matches(regExpNumbers)); + expect(generatedString.length, equals(length)); + }); + }); }); } + +var regExpNewLines = RegExp(r"[\n\r]+"); +var regExpWhiteSpaces = RegExp(r"[\s]+"); +var regExpUppercaseLetters = RegExp(r"[A-Z]"); +var regExpLowercaseLetters = RegExp(r"[a-z]"); +var regExpNumbers = RegExp(r"[0-9]"); +var regExpSymbols = RegExp(r'(?:_|[^\w\s])+');