Skip to content

Commit

Permalink
bug fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
frankmer committed Oct 2, 2024
1 parent eb0a21d commit 1d2ab18
Show file tree
Hide file tree
Showing 20 changed files with 177 additions and 95 deletions.
4 changes: 2 additions & 2 deletions integration_test/two_step_rollout_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ Future<void> _addTwoStepHotpTokenTest(WidgetTester tester) async {
const qrCode =
'otpauth://hotp/OATH0001DBD0?secret=AALIBQJMOGEE7SAVEZ5D3K2ADO7MVFQD&counter=1&digits=6&issuer=privacyIDEA&2step_salt=8&2step_output=20&2step_difficulty=10000';
final notifier = globalRef!.read(tokenProvider.notifier);
await scanQrCode([notifier], qrCode);
await scanQrCode(resultHandlerList: [notifier], qrCode: qrCode);
Logger.info('Finding phone part dialog');
await pumpUntilFindNWidgets(tester, find.text(AppLocalizationsEn().phonePart), 1, const Duration(seconds: 20));
expect(find.text(AppLocalizationsEn().phonePart), findsOneWidget);
Expand All @@ -95,7 +95,7 @@ Future<void> _addTwoStepTotpTokenTest(WidgetTester tester) async {
const qrCode =
'otpauth://totp/TOTP00009D5F?secret=NZ4OPONKAAGDFN2QHV26ZWYVTLFER4C6&period=30&digits=6&issuer=privacyIDEA&2step_salt=8&2step_output=20&2step_difficulty=10000';
final notifier = globalRef!.read(tokenProvider.notifier);
await scanQrCode([notifier], qrCode);
await scanQrCode(resultHandlerList: [notifier], qrCode: qrCode);
Logger.info('Finding phone part dialog');
await pumpUntilFindNWidgets(tester, find.text(AppLocalizationsEn().phonePart), 1, const Duration(seconds: 20));
expect(find.text(AppLocalizationsEn().phonePart), findsOneWidget);
Expand Down
2 changes: 1 addition & 1 deletion integration_test/views_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ Future<void> _settingsViewTest(WidgetTester tester) async {
const qrCode =
'otpauth://pipush/label?url=http%3A%2F%2Fwww.example.com&ttl=10&issuer=issuer&enrollment_container=enrollmentCredentials&v=1&serial=serial&serial=serial&sslverify=0';
final notifier = globalRef!.read(tokenProvider.notifier);
await scanQrCode([notifier], qrCode);
await scanQrCode(resultHandlerList: [notifier], qrCode: qrCode);

await pumpUntilFindNWidgets(tester, find.text(AppLocalizationsEn().pushToken), 1, const Duration(minutes: 5));
expect(find.text(AppLocalizationsEn().pushToken), findsOneWidget);
Expand Down
9 changes: 9 additions & 0 deletions lib/l10n/app_cs.arb
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,14 @@
"@isPiTokenQuestion": {
"description": "Label for the question if the token is a privacyIDEA token."
},
"@issuer": {
"description": "Label for the issuer of the token, container... etc.",
"placeholders": {
"name": {
"example": "privacyIDEA"
}
}
},
"@language": {
"description": "Title of language setting group."
},
Expand Down Expand Up @@ -771,6 +779,7 @@
"invalidValueIn": "untranslated",
"isExpotableQuestion": "Lze exportovat?",
"isPiTokenQuestion": "Je to token privacyIDEA?",
"issuer": "Issuer: {name}",
"language": "Jazyk",
"legacySigningErrorMessage": "Token byl vytvořen v zastaralé verzi aplikace, což může vést k problémům při jeho používání.\nPokud problém přetrvává, doporučujeme vytvořit nový push token!",
"legacySigningErrorTitle": "Při použití staršího tokenu došlo k chybě: {tokenLabel}",
Expand Down
9 changes: 9 additions & 0 deletions lib/l10n/app_de.arb
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,14 @@
"@isPiTokenQuestion": {
"description": "Label for the question if the token is a privacyIDEA token."
},
"@issuer": {
"description": "Label for the issuer of the token, container... etc.",
"placeholders": {
"name": {
"example": "privacyIDEA"
}
}
},
"@language": {
"description": "Title of language setting group."
},
Expand Down Expand Up @@ -771,6 +779,7 @@
"invalidValueIn": "untranslated",
"isExpotableQuestion": "Ist exportierbar?",
"isPiTokenQuestion": "Ist ein privacyIDEA-Token?",
"issuer": "Issuer: {name}",
"language": "Sprache",
"legacySigningErrorMessage": "Der Token wurde in einer veralteten Version der App erstellt, was zu Problemen bei der Verwendung führen kann. Es wird empfohlen, einen neuen Push-Token zu erstellen, wenn das Problem weiterhin besteht!",
"legacySigningErrorTitle": "Bei der Verwendung des veralteten Tokens ist ein Fehler aufgetreten: {tokenLabel}",
Expand Down
9 changes: 9 additions & 0 deletions lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,14 @@
"@isPiTokenQuestion": {
"description": "Label for the question if the token is a privacyIDEA token."
},
"@issuer": {
"description": "Label for the issuer of the token, container... etc.",
"placeholders": {
"name": {
"example": "privacyIDEA"
}
}
},
"@language": {
"description": "Title of language setting group."
},
Expand Down Expand Up @@ -771,6 +779,7 @@
"invalidValueIn": "The {type} \"{value}\" is not valid for \"{parameter}\" in \"{map}\"",
"isExpotableQuestion": "Is exportable?",
"isPiTokenQuestion": "It's a privacyIDEA token?",
"issuer": "Issuer: {name}",
"language": "Language",
"legacySigningErrorMessage": "The token was enrolled in a old version of this app, which may cause trouble using it.\nIt is suggested to enroll a new push token if the problem persist!",
"legacySigningErrorTitle": "An error occured while using the legacy token: {tokenLabel}",
Expand Down
9 changes: 9 additions & 0 deletions lib/l10n/app_es.arb
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,14 @@
"@isPiTokenQuestion": {
"description": "Label for the question if the token is a privacyIDEA token."
},
"@issuer": {
"description": "Label for the issuer of the token, container... etc.",
"placeholders": {
"name": {
"example": "privacyIDEA"
}
}
},
"@language": {
"description": "Title of language setting group."
},
Expand Down Expand Up @@ -771,6 +779,7 @@
"invalidValueIn": "untranslated",
"isExpotableQuestion": "¿Es exportable?",
"isPiTokenQuestion": "¿Es un token de privacyIDEA?",
"issuer": "Issuer: {name}",
"language": "Language",
"legacySigningErrorMessage": "El token se creó en una versión obsoleta de la aplicación, lo que puede provocar problemas al utilizarlo.\nSe recomienda crear un nuevo token push si el problema persiste.",
"legacySigningErrorTitle": "Se ha producido un error al utilizar el token obsoleto: {tokenLabel}",
Expand Down
9 changes: 9 additions & 0 deletions lib/l10n/app_fr.arb
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,14 @@
"@isPiTokenQuestion": {
"description": "Label for the question if the token is a privacyIDEA token."
},
"@issuer": {
"description": "Label for the issuer of the token, container... etc.",
"placeholders": {
"name": {
"example": "privacyIDEA"
}
}
},
"@language": {
"description": "Title of language setting group."
},
Expand Down Expand Up @@ -771,6 +779,7 @@
"invalidValueIn": "untranslated",
"isExpotableQuestion": "Est exportable ?",
"isPiTokenQuestion": "C'est un jeton privacyIDEA ?",
"issuer": "Issuer: {name}",
"language": "Langue",
"legacySigningErrorMessage": "Le token a été créé dans une version obsolète de l'application, ce qui peut entraîner des problèmes d'utilisation.\nIl est recommandé de créer un nouveau token push si le problème persiste !",
"legacySigningErrorTitle": "Une erreur s'est produite lors de l'utilisation du jeton obsolète : {tokenLabel}",
Expand Down
9 changes: 9 additions & 0 deletions lib/l10n/app_nl.arb
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,14 @@
"@isPiTokenQuestion": {
"description": "Label for the question if the token is a privacyIDEA token."
},
"@issuer": {
"description": "Label for the issuer of the token, container... etc.",
"placeholders": {
"name": {
"example": "privacyIDEA"
}
}
},
"@language": {
"description": "Title of language setting group."
},
Expand Down Expand Up @@ -771,6 +779,7 @@
"invalidValueIn": "untranslated",
"isExpotableQuestion": "Is exporteerbaar?",
"isPiTokenQuestion": "Is het een privacyIDEA token?",
"issuer": "Issuer: {name}",
"language": "Taal",
"legacySigningErrorMessage": "Het token is aangemaakt in een verouderde versie van de app, wat kan leiden tot problemen bij het gebruik ervan.\nHet wordt aanbevolen om een nieuw push token aan te maken als het probleem zich blijft voordoen!",
"legacySigningErrorTitle": "Er is een fout opgetreden bij het gebruik van het verouderde token: {tokenLabel}",
Expand Down
9 changes: 9 additions & 0 deletions lib/l10n/app_pl.arb
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,14 @@
"@isPiTokenQuestion": {
"description": "Label for the question if the token is a privacyIDEA token."
},
"@issuer": {
"description": "Label for the issuer of the token, container... etc.",
"placeholders": {
"name": {
"example": "privacyIDEA"
}
}
},
"@language": {
"description": "Title of language setting group."
},
Expand Down Expand Up @@ -771,6 +779,7 @@
"invalidValueIn": "untranslated",
"isExpotableQuestion": "Czy można eksportować?",
"isPiTokenQuestion": "To jest token privacyIDEA?",
"issuer": "Issuer: {name}",
"language": "Język",
"legacySigningErrorMessage": "Token został utworzony w nieaktualnej wersji aplikacji, co może prowadzić do problemów podczas korzystania z niego.\nZaleca się utworzenie nowego tokena push, jeśli problem nadal występuje!",
"legacySigningErrorTitle": "Wystąpił błąd podczas korzystania z przestarzałego tokena: {tokenLabel}",
Expand Down
8 changes: 4 additions & 4 deletions lib/model/riverpod_states/token_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@ class TokenState {

PushToken? getTokenBySerial(String serial) => pushTokens.firstWhereOrNull((element) => element.serial == serial);

/// Maps the given tokens to the tokens that are already in the state
/// It ignores the id that is usually used to identify the token
/// Instead it uses the non-changeable values of the token to identify it
/// Like the secret and hash algorithm for OTP tokens, or the serial and public server key for push tokens
/// Maps the given tokens to the tokens that are already in the state.
/// It ignores the id that is usually used to identify the token.
/// Instead it uses the non-changeable values of the token to identify it.
/// Like the secret, hash algorithm, serial and public server key for push tokens.
Map<Token, Token?> getSameTokens(List<Token> tokens) {
final sameTokensMap = <Token, Token?>{};
final stateTokens = this.tokens;
Expand Down
9 changes: 7 additions & 2 deletions lib/model/token_folder.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// ignore_for_file: constant_identifier_names

/*
* privacyIDEA Authenticator
*
Expand Down Expand Up @@ -76,8 +78,11 @@ class TokenFolder with SortableMixin {

factory TokenFolder.fromJson(Map<String, dynamic> json) {
var tokenFolder = _$TokenFolderFromJson(json);
if (tokenFolder.isLocked) tokenFolder = tokenFolder.copyWith(isExpanded: false);
return tokenFolder;
if (tokenFolder.isLocked) {
return tokenFolder.copyWith(isExpanded: false);
} else {
return tokenFolder;
}
}
Map<String, dynamic> toJson() => _$TokenFolderToJson(this);
}
12 changes: 6 additions & 6 deletions lib/utils/customization/theme_customization.dart
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@ class ThemeCustomization {
backgroundColor = backgroundColor ?? const Color(0xffEFEFEF),
foregroundColor = foregroundColor ?? const Color(0xff282828),
shadowColor = shadowColor ?? const Color(0x4C303030),
deleteColor = deleteColor ?? const Color(0xffE04D2D),
renameColor = renameColor ?? const Color(0xff6A8FE5),
lockColor = lockColor ?? const Color(0xffFFD633),
deleteColor = deleteColor ?? const Color(0xffe85e40),
renameColor = renameColor ?? const Color(0xff7f9bdd),
lockColor = lockColor ?? const Color(0xffffd633),
tileIconColor = tileIconColor ?? const Color(0xff757575),
navigationBarColor = navigationBarColor ?? const Color(0xFFFFFFFF),
// From here on the colors have a default value based on another given color so they can be null
Expand Down Expand Up @@ -130,9 +130,9 @@ class ThemeCustomization {
backgroundColor = backgroundColor ?? const Color(0xFF303030),
foregroundColor = foregroundColor ?? const Color(0xffF5F5F5),
shadowColor = shadowColor ?? const Color(0x4CEFEFEF),
deleteColor = deleteColor ?? const Color(0xffCD3C14),
renameColor = renameColor ?? const Color(0xff527EDB),
lockColor = lockColor ?? const Color(0xffFFCC00),
deleteColor = deleteColor ?? const Color(0xffb93f1d),
renameColor = renameColor ?? const Color(0xff4a72c6),
lockColor = lockColor ?? const Color(0xffe4ba11),
tileIconColor = tileIconColor ?? const Color(0xffF5F5F5),
navigationBarColor = navigationBarColor ?? const Color(0xFF282828),
// From here on the colors have a default value based on another given color so they can be null
Expand Down
7 changes: 1 addition & 6 deletions lib/utils/home_widget_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ import '../widgets/home_widgets/home_widget_otp.dart';
import '../widgets/home_widgets/home_widget_unlinked.dart';
import 'globals.dart';
import 'logger.dart';
import 'riverpod/riverpod_providers/generated_providers/token_notifier.dart';
import 'riverpod/riverpod_providers/state_providers/home_widget_provider.dart';

const appGroupId = 'group.authenticator_home_widget_group';
Expand Down Expand Up @@ -79,7 +78,7 @@ class HomeWidgetUtils {
static const _widgetActionSize = Size(24 * 2, 24 * 2);

/// Default duration for showing the OTP
static const _showDuration = Duration(seconds: 15);
static const _showDuration = Duration(seconds: 10);

factory HomeWidgetUtils({TokenRepository? tokenRepository, TokenFolderRepository? tokenFolderRepository}) {
if (kIsWeb || Platform.isIOS) return UnsupportedHomeWidgetUtils(); // Not supported on iOS
Expand All @@ -101,10 +100,6 @@ class HomeWidgetUtils {
static TokenRepository? _tokenRepository;
static TokenFolderRepository? _folderRepository;
static final Mutex _repoMutex = Mutex();
static Future<List<OTPToken>> get _otpTokens async {
final tokens = globalRef?.read(tokenProvider).tokens;
return tokens?.whereType<OTPToken>().toList() ?? (await _loadTokensFromRepo()).whereType<OTPToken>().toList();
}

static Future<OTPToken?> _getTokenOfTokenId(String tokenId) async {
await _repoMutex.acquire();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ class TokenFolderNotifier extends _$TokenFolderNotifier {
_stateMutex.release();
return oldState;
}
state = newState;
_stateMutex.release();
return newState;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ class TokenNotifier extends _$TokenNotifier with ResultHandler {

/// Adds a list of tokens and returns the tokens that could not be added or replaced.
Future<List<Token>> _addOrReplaceTokens(List<Token> tokens) async {
tokens = _removeDuplicates(tokens);
if (tokens.isEmpty) return [];
Logger.debug('Adding ${tokens.length} tokens.', verbose: true);
await _repoMutex.acquire();
Expand Down Expand Up @@ -377,10 +378,10 @@ class TokenNotifier extends _$TokenNotifier with ResultHandler {
Future<List<Token>> addOrReplaceTokens(List<Token> tokens) => _addOrReplaceTokens(tokens);

/// Updates a token and returns the updated token if successful, the old token if not and null if the token does not exist.
Future<T?> updateToken<T extends Token>(T token, T Function(T) updater) async => _updateToken(token, updater);
Future<T?> updateToken<T extends Token>(T token, T Function(T) updater) => _updateToken(token, updater);

/// Updates a list of tokens and returns the updated tokens if successful, the old tokens if not and an empty list if the tokens does not exist.
Future<List<T>> updateTokens<T extends Token>(List<T> tokens, T Function(T) updater) async => _updateTokens(tokens, updater);
Future<List<T>> updateTokens<T extends Token>(List<T> tokens, T Function(T) updater) => _updateTokens(tokens, updater);

/// Increments the counter of a HOTPToken and returns the updated token if successful, the old token if not and null if the token does not exist.
Future<HOTPToken?> incrementCounter(HOTPToken token) => _updateToken(token, (p0) => p0.copyWith(counter: token.counter + 1));
Expand Down Expand Up @@ -437,20 +438,20 @@ class TokenNotifier extends _$TokenNotifier with ResultHandler {
}

/// Minimizing the app needs to cancel all timers and save the state to the repository.
Future<bool> saveStateOnMinimizeApp() async {
Future<bool> onMinimizeApp() {
Logger.info('TokenNotifier: Preparing to minimize app.');
_cancelTimers();
await hideLockedTokens();
return _saveStateToRepo(state);
return hideLockedTokens();
}

Future<List<Token>> hideLockedTokens() async {
final hideLockedTokens = <Token>[];
Future<bool> hideLockedTokens() async {
final lockedTokens = <Token>[];
for (var token in state.tokens) {
if (token.isLocked && !token.isHidden) {
hideLockedTokens.add(token);
lockedTokens.add(token);
}
}
return await updateTokens(hideLockedTokens, (p0) => p0.copyWith(isHidden: true));
return (await updateTokens(lockedTokens, (p0) => p0.copyWith(isHidden: true))).length == lockedTokens.length;
}

/// Removes a token from the state and the repository.
Expand Down Expand Up @@ -800,6 +801,16 @@ class TokenNotifier extends _$TokenNotifier with ResultHandler {
///////////////////////////// Helper Methods ///////////////////////////////////
///////////////////////////////////////////////////////////////////////////// */

List<Token> _removeDuplicates(List<Token> tokens) {
final uniqueTokens = <Token>[];
for (var token in tokens) {
if (!uniqueTokens.any((uniqureToken) => uniqureToken.isSameTokenAs(token))) {
uniqueTokens.add(token);
}
}
return uniqueTokens;
}

Future<void> _showImportTokensPage(
List<ProcessorResult<Token>> tokenResults,
TokenOriginSourceType tokenOriginSourceType,
Expand All @@ -814,9 +825,8 @@ class TokenNotifier extends _$TokenNotifier with ResultHandler {
),
),
);

if (tokensToKeep == null) return;
final tokensWithSourceType = _addSourceType(tokenResults.getData(), tokenOriginSourceType);
final tokensWithSourceType = _addSourceType(tokensToKeep, tokenOriginSourceType);
await addNewTokens(tokensWithSourceType);
}

Expand Down
Loading

0 comments on commit 1d2ab18

Please sign in to comment.