From 5e7b3a543f744ddd259ab82db7b41ee45f244ffe Mon Sep 17 00:00:00 2001 From: Frank Merkel <138444693+frankmer@users.noreply.github.com> Date: Mon, 9 Dec 2024 11:26:33 +0100 Subject: [PATCH] refactor: update duration validators and improve expiration date handling in token classes --- lib/model/token_container.dart | 6 +++-- lib/model/tokens/day_password_token.dart | 4 ++-- lib/model/tokens/push_token.dart | 10 ++++----- lib/utils/object_validator.dart | 22 +++++++++---------- .../token_container_notifier.dart | 6 +++++ 5 files changed, 28 insertions(+), 20 deletions(-) diff --git a/lib/model/token_container.dart b/lib/model/token_container.dart index 7a4be7d0..164adfb8 100644 --- a/lib/model/token_container.dart +++ b/lib/model/token_container.dart @@ -93,6 +93,8 @@ class TokenContainer with _$TokenContainer { Uri get transferUrl => serverUrl.replace(path: '/container/$serial/rollover'); Uri get unregisterUrl => serverUrl.replace(path: '/container/register/$serial/terminate/client'); + DateTime? get expirationDate => this is TokenContainerUnfinalized ? timestamp.add((this as TokenContainerUnfinalized).ttl) : null; + // example: "pia://container/SMPH00067A2F" // "?issuer=privacyIDEA" // "&ttl=10" @@ -109,10 +111,10 @@ class TokenContainer with _$TokenContainer { map: uriMap, validators: { ISSUER: const ObjectValidator(), - TTL_MINUTES: durationValidator.withDefault(const Duration(minutes: 10)), + TTL_MINUTES: minutesDurationValidator.withDefault(const Duration(minutes: 10)), NONCE: const ObjectValidator(), TIMESTAMP: ObjectValidator(transformer: (v) => DateTime.parse(v)), - FINALIZATION_URL: stringToUrivalidator, + FINALIZATION_URL: uriValidator, SERIAL: const ObjectValidator(), EC_KEY_ALGORITHM: ObjectValidator(transformer: (v) => EcKeyAlgorithm.values.byCurveName(v)), HASH_ALGORITHM: stringToAlgorithmsValidator, diff --git a/lib/model/tokens/day_password_token.dart b/lib/model/tokens/day_password_token.dart index 2dab0d00..f76e84ec 100644 --- a/lib/model/tokens/day_password_token.dart +++ b/lib/model/tokens/day_password_token.dart @@ -166,7 +166,7 @@ class DayPasswordToken extends OTPToken { OTPToken.ALGORITHM: stringToAlgorithmsValidatorNullable, OTPToken.DIGITS: intValidatorNullable, OTPToken.SECRET_BASE32: base32SecretValidatorNullable, - TOTPToken.PERIOD_SECONDS: stringSecondsToDurationValidatorNullable, + TOTPToken.PERIOD_SECONDS: secondsDurationValidatorNullable, }, name: 'DayPasswordToken', ); @@ -196,7 +196,7 @@ class DayPasswordToken extends OTPToken { OTPToken.ALGORITHM: stringToAlgorithmsValidator.withDefault(Algorithms.SHA1), OTPToken.DIGITS: otpAuthDigitsValidatorNullable, OTPToken.SECRET_BASE32: base32Secretvalidator, - TOTPToken.PERIOD_SECONDS: stringSecondsToDurationValidator.withDefault(const Duration(hours: 24)), + TOTPToken.PERIOD_SECONDS: secondsDurationValidator.withDefault(const Duration(hours: 24)), }, name: 'DayPasswordToken', ); diff --git a/lib/model/tokens/push_token.dart b/lib/model/tokens/push_token.dart index 6dbc2c98..75397468 100644 --- a/lib/model/tokens/push_token.dart +++ b/lib/model/tokens/push_token.dart @@ -219,10 +219,10 @@ class PushToken extends Token { Token.ISSUER: const ObjectValidatorNullable(defaultValue: ''), Token.SERIAL: const ObjectValidator(), SSL_VERIFY: boolValidator.withDefault(true), - TTL_MINUTES: durationValidator.withDefault(const Duration(minutes: 3)), + TTL_MINUTES: minutesDurationValidator.withDefault(const Duration(minutes: 3)), ENROLLMENT_CREDENTIAL: const ObjectValidatorNullable(), - ROLLOUT_URL: stringToUrivalidator, - Token.IMAGE: stringToUriValidatorNullable, + ROLLOUT_URL: uriValidator, + Token.IMAGE: uriValidatorNullable, Token.PIN: boolValidatorNullable, VERSION: const ObjectValidator(), }, @@ -285,8 +285,8 @@ class PushToken extends Token { Token.SERIAL: const ObjectValidatorNullable(), SSL_VERIFY: boolValidatorNullable, ENROLLMENT_CREDENTIAL: const ObjectValidatorNullable(), - ROLLOUT_URL: stringToUriValidatorNullable, - Token.IMAGE: stringToUriValidatorNullable, + ROLLOUT_URL: uriValidatorNullable, + Token.IMAGE: uriValidatorNullable, Token.PIN: boolValidator, VERSION: intValidatorNullable, }, diff --git a/lib/utils/object_validator.dart b/lib/utils/object_validator.dart index 06f6c3d7..2b58e867 100644 --- a/lib/utils/object_validator.dart +++ b/lib/utils/object_validator.dart @@ -24,12 +24,6 @@ import '../model/enums/encodings.dart'; import '../model/exception_errors/localized_argument_error.dart'; import 'logger.dart'; -final durationValidatorNullable = durationValidator.nullable(); -final durationValidator = ObjectValidator( - transformer: (v) => Duration(seconds: v is int ? v : int.parse(v)), - allowedValues: (v) => v.inSeconds > 0, -); - final otpAutjPeriodSecondsValidatorNullable = otpAuthPeriodSecondsValidator.nullable(); final otpAuthPeriodSecondsValidator = ObjectValidator( transformer: (v) { @@ -67,14 +61,20 @@ final intValidator = ObjectValidator(transformer: (v) { final intToStringValidator = ObjectValidator(transformer: (v) => (v as int).toString()); final intToStringValidatorNullable = intToStringValidator.nullable(); -final stringSecondsToDurationValidatorNullable = stringSecondsToDurationValidator.nullable(); -final stringSecondsToDurationValidator = ObjectValidator( - transformer: (v) => Duration(seconds: int.parse(v)), +final secondsDurationValidatorNullable = secondsDurationValidator.nullable(); +final secondsDurationValidator = ObjectValidator( + transformer: (v) => v is Duration ? v : Duration(seconds: v is int ? v : int.parse(v)), + allowedValues: (v) => v.inSeconds > 0, +); + +final minutesDurationValidatorNullable = minutesDurationValidator.nullable(); +final minutesDurationValidator = ObjectValidator( + transformer: (v) => v is Duration ? v : Duration(minutes: v is int ? v : int.parse(v)), allowedValues: (v) => v.inSeconds > 0, ); -final stringToUriValidatorNullable = stringToUrivalidator.nullable(); -final stringToUrivalidator = ObjectValidator(transformer: (v) => Uri.parse(v)); +final uriValidatorNullable = uriValidator.nullable(); +final uriValidator = ObjectValidator(transformer: (v) => v is Uri ? v : Uri.parse(v)); final boolValidatorNullable = boolValidator.nullable(); final boolValidator = ObjectValidator(transformer: (v) { diff --git a/lib/utils/riverpod/riverpod_providers/generated_providers/token_container_notifier.dart b/lib/utils/riverpod/riverpod_providers/generated_providers/token_container_notifier.dart index b64b49d1..3196dde2 100644 --- a/lib/utils/riverpod/riverpod_providers/generated_providers/token_container_notifier.dart +++ b/lib/utils/riverpod/riverpod_providers/generated_providers/token_container_notifier.dart @@ -446,6 +446,12 @@ class TokenContainerNotifier extends _$TokenContainerNotifier with ResultHandler _finalizationMutex.release(); throw ArgumentError('Container must not be finalized'); } + if (container.expirationDate != null && container.expirationDate!.isBefore(DateTime.now())) { + showStatusMessage(message: 'Container ${container.serial} has expired and can not be rolled out anymore'); + await deleteContainer(container); + _finalizationMutex.release(); + return; + } Logger.info('Finalizing container ${container.serial}'); try { container = await _generateKeyPair(container);