forked from kherel/selfprivacy.org.app
parent
8ea1b28d73
commit
1202e4ad53
@ -1,138 +1,99 @@ |
||||
import 'dart:math'; |
||||
|
||||
var generator = PasswordGenerator(); |
||||
|
||||
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; |
||||
Random _rnd = Random(); |
||||
|
||||
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); |
||||
} |
||||
|
||||
///'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; |
||||
var res = ''; |
||||
var loose = length; |
||||
if (hasLowercaseLetters) { |
||||
loose -= 1; |
||||
res += genString(1, letters); |
||||
} |
||||
} |
||||
|
||||
///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]); |
||||
if (hasUppercaseLetters) { |
||||
loose -= 1; |
||||
res += genString(1, letters.toUpperCase()); |
||||
} |
||||
} |
||||
|
||||
///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; |
||||
} |
||||
if (hasNumbers) { |
||||
loose -= 1; |
||||
res += genString(1, numbers.toUpperCase()); |
||||
} |
||||
if (hasSymbols) { |
||||
loose -= 1; |
||||
res += genString(1, symbols); |
||||
} |
||||
res += genString(loose, chars); |
||||
|
||||
///Toggles number generation |
||||
void checkNumGen(bool value) { |
||||
_numGen = value; |
||||
var shuffledlist = res.split('')..shuffle(); |
||||
return shuffledlist.join(); |
||||
} |
||||
|
||||
///Toggles symbol generation |
||||
void checkSymGen(bool value) { |
||||
_symGen = value; |
||||
static String genString(int length, String chars) { |
||||
return String.fromCharCodes( |
||||
Iterable.generate( |
||||
length, |
||||
(_) => chars.codeUnitAt( |
||||
_rnd.nextInt(chars.length), |
||||
), |
||||
), |
||||
); |
||||
} |
||||
|
||||
///Returns the generated value to be used by generator app |
||||
String getGeneratedValue() { |
||||
return _generatedValue; |
||||
} |
||||
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, |
||||
); |
||||
} |
||||
|
@ -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), |
||||
), |
||||
), |
||||
); |
@ -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])+'); |
||||
|
Loading…
Reference in new issue