diff --git a/lib/api/privacy_idea_container_api.dart b/lib/api/privacy_idea_container_api.dart index 322d8532..527bdf49 100644 --- a/lib/api/privacy_idea_container_api.dart +++ b/lib/api/privacy_idea_container_api.dart @@ -115,7 +115,7 @@ class PrivacyIdeaContainerApi { final passphrase = container.passphraseQuestion?.isNotEmpty == true ? await EnterPassphraseDialog.show(await globalContext) : null; final message = '${container.nonce}' '|${container.timestamp.toIso8601String().replaceFirst('Z', '+00:00')}' - '|${container.finalizationUrl}' + '|${container.registrationUrl}' '|${container.serial}' '|${AppInfoUtils.deviceId}' '${passphrase != null ? '|$passphrase' : ''}'; @@ -128,7 +128,7 @@ class PrivacyIdeaContainerApi { CONTAINER_DEVICE_ID: AppInfoUtils.deviceId, CONTAINER_SIGNATURE: signature, }; - return await _ioClient.doPost(url: container.finalizationUrl, body: body, sslVerify: false); //TODO: sslVerify + return await _ioClient.doPost(url: container.registrationUrl, body: body, sslVerify: container.sslVerify); } /* ////////////////////////////// @@ -136,7 +136,7 @@ class PrivacyIdeaContainerApi { ////////////////////////////// */ Future _getChallenge(TokenContainerFinalized container) async { - final initResponse = await _ioClient.doGet(url: container.syncUrl, parameters: {CONTAINER_SERIAL: container.serial}); + final initResponse = await _ioClient.doGet(url: container.syncUrlInit, parameters: {CONTAINER_SERIAL: container.serial}); if (initResponse.statusCode != 200) { final errorResponse = initResponse.asPiErrorResponse(); if (errorResponse != null) throw errorResponse.piServerResultError; @@ -175,7 +175,7 @@ class PrivacyIdeaContainerApi { CONTAINER_DICT_TOKENS: otpAuthMaps, }; final signMessage = - '${challenge.nonce}|${challenge.timeStamp}|${container.serial}|${challenge.finalizeSyncUrl}|$publicKeyBase64|${jsonEncode(containerDict)}'; + '${challenge.nonce}|${challenge.timeStamp}|${container.serial}|${container.syncUrlFinalize}|$publicKeyBase64|${jsonEncode(containerDict)}'; Logger.debug(signMessage); final signature = container.signMessage(signMessage); Logger.debug('Sended container: ${jsonEncode(containerDict)}'); @@ -185,7 +185,7 @@ class PrivacyIdeaContainerApi { CONTAINER_SYNC_DICT_CLIENT: jsonEncode(containerDict), }; - final response = await _ioClient.doPost(url: Uri.parse(challenge.finalizeSyncUrl), body: body); + final response = await _ioClient.doPost(url: container.syncUrlFinalize, body: body); if (response.statusCode != 200) { final piErrorResponse = response.asPiErrorResponse(); if (piErrorResponse != null) throw piErrorResponse.piServerResultError; diff --git a/lib/l10n/app_cs.arb b/lib/l10n/app_cs.arb index b16f6978..7dd6ac70 100644 --- a/lib/l10n/app_cs.arb +++ b/lib/l10n/app_cs.arb @@ -86,6 +86,12 @@ "@container": { "description": "Title for the container view." }, + "@containerDetails": { + "description": "Title of the container details dialog." + }, + "@containerSyncUrl": { + "description": "Title of the container sync url field." + }, "@couldNotSignMessage": { "description": "Tells the user that the message could not be signed." }, @@ -98,9 +104,6 @@ "@creator": { "description": "Label for the creator of the token." }, - "@darkTheme": { - "description": "The dark theme." - }, "@decline": { "description": "Label for e.g. a button. Something gets declined by the user." }, @@ -108,16 +111,18 @@ "description": "Label that describes deleting the token." }, "@deleteContainerDialogTitle": { - "example": { - "serial": "SMPH0008CC47" + "placeholders": { + "serial": { + "example": "SMPH0008CC47" + } } }, + "@details": { + "description": "Title of the details action Button." + }, "@deviceCredentialsRequiredTitle": { "description": "Message showed as a title in a dialog which indicates the user has not set up credentials authentication on their device. It is used on Android side. Maximum 60 characters." }, - "@deviceCredentialsSetupDescription": { - "description": "Message advising the user to go to the settings and configure device credentials on their device. It shows in a dialog on Android side." - }, "@digits": { "description": "Title of the dropdown button where the number of digits for the opt value is selected." }, @@ -200,6 +205,9 @@ } } }, + "@exampleUrl": { + "description": "Shows the user an example of a valid URL." + }, "@failedToFinalizeContainer": { "description": "Error message when finalizing a container failed.", "placeholders": { @@ -209,7 +217,12 @@ } }, "@failedToLoad": { - "description": "Error message when something could not be loaded." + "description": "Error message when something could not be loaded.", + "placeholders": { + "name": { + "example": "token data" + } + } }, "@failedToSyncContainer": { "placeholders": { @@ -221,21 +234,56 @@ "@feedbackPrivacyPolicy2": { "description": "Taping on this should open the privacy policy." }, + "@finalizationState": { + "description": "Title of the finalization state field." + }, "@generatingPhonePart": { "description": "Title of a dialog telling the user that the phone part gets generated right now." }, "@goToSettingsButton": { "description": "Message showed on a button that the user can click to go to settings pages from the current dialog. It is used on both Android and iOS side. Maximum 30 characters." }, - "@goToSettingsDescription": { - "description": "Message advising the user to go to the settings and configure device credentials or biometrics on their device." - }, - "@guide": { - "description": "Button to open the guide screen." - }, "@handshakeFailed": { "description": "Error message when the handshake failed." }, + "@imageUrl": { + "description": "Title of the image url field." + }, + "@importConflictToken": { + "placeholders": { + "count": { + "example": "5" + } + } + }, + "@importExistingToken": { + "placeholders": { + "count": { + "example": "5" + } + } + }, + "@importFailedToken": { + "placeholders": { + "count": { + "example": "5" + } + } + }, + "@importNTokens": { + "placeholders": { + "count": { + "example": "5" + } + } + }, + "@importNewToken": { + "placeholders": { + "count": { + "example": "5" + } + } + }, "@importedVia": { "description": "Label for the import method of the token." }, @@ -246,6 +294,34 @@ } } }, + "@invalidBackupFile": { + "placeholders": { + "appName": { + "example": "privacyIDEA Authenticator" + } + } + }, + "@invalidLink": { + "placeholders": { + "appName": { + "example": "privacyIDEA Authenticator" + } + } + }, + "@invalidQrFile": { + "placeholders": { + "appName": { + "example": "privacyIDEA Authenticator" + } + } + }, + "@invalidQrScan": { + "placeholders": { + "appName": { + "example": "privacyIDEA Authenticator" + } + } + }, "@invalidValue": { "description": "Error message when the value is not valid for the parameter.", "placeholders": { @@ -282,6 +358,9 @@ "@isPiTokenQuestion": { "description": "Label for the question if the token is a privacyIDEA token." }, + "@issuer": { + "description": "Title of the issuer field." + }, "@issuerLabel": { "description": "Label for the issuer of the token, container... etc.", "placeholders": { @@ -304,9 +383,6 @@ } } }, - "@lightTheme": { - "description": "The light theme." - }, "@linkedContainer": { "description": "Label for the linked container serial number." }, @@ -375,13 +451,6 @@ "@ok": { "description": "Button to confirm an action." }, - "@onBoardingTitle1": { - "placeholders": { - "appName": { - "example": "privacyIDEA Authenticator" - } - } - }, "@open": { "description": "Button to open something." }, @@ -400,6 +469,9 @@ }, "type": "text" }, + "@patchNotesDialogTitle": { + "description": "Title of the dialog that shows the patch notes." + }, "@period": { "description": "Title of the dropdown button where the period of the totp token is selected." }, @@ -460,9 +532,6 @@ "@requestPushChallengesPeriodically": { "description": "The description of the polling feature." }, - "@retry": { - "description": "Label for e.g. a button. Something is tried to be done again." - }, "@rolloutStateCompleted": { "description": "Message for the rollout process" }, @@ -559,6 +628,21 @@ "@syncFbTokenFailed": { "description": "Headline for the list of tokens where the synchronization failed." }, + "@syncState": { + "description": "The state of the synchronization of the token" + }, + "@syncStateCompletedDescription": { + "description": "The description of the state when the synchronization is completed" + }, + "@syncStateFailedDescription": { + "description": "The description of the state when the synchronization failed" + }, + "@syncStateNotStartedDescription": { + "description": "The description of the state when the synchronization is not started" + }, + "@syncStateSyncingDescription": { + "description": "The description of the state when the synchronization is currently syncing" + }, "@synchronizePushTokens": { "description": "Title of synchronizing push tokens in settings." }, @@ -568,9 +652,6 @@ "@synchronizingTokens": { "description": "Title of the push synchronization dialog." }, - "@systemTheme": { - "description": "The systems theme." - }, "@theSecretDoesNotFitTheCurrentEncoding": { "description": "Hint telling the user that the secret does not fit the selected encoding." }, diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index 42182f4c..5a1573a6 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -86,6 +86,12 @@ "@container": { "description": "Title for the container view." }, + "@containerDetails": { + "description": "Title of the container details dialog." + }, + "@containerSyncUrl": { + "description": "Title of the container sync url field." + }, "@couldNotSignMessage": { "description": "Tells the user that the message could not be signed." }, @@ -98,9 +104,6 @@ "@creator": { "description": "Label for the creator of the token." }, - "@darkTheme": { - "description": "The dark theme." - }, "@decline": { "description": "Label for e.g. a button. Something gets declined by the user." }, @@ -108,16 +111,18 @@ "description": "Label that describes deleting the token." }, "@deleteContainerDialogTitle": { - "example": { - "serial": "SMPH0008CC47" + "placeholders": { + "serial": { + "example": "SMPH0008CC47" + } } }, + "@details": { + "description": "Title of the details action Button." + }, "@deviceCredentialsRequiredTitle": { "description": "Message showed as a title in a dialog which indicates the user has not set up credentials authentication on their device. It is used on Android side. Maximum 60 characters." }, - "@deviceCredentialsSetupDescription": { - "description": "Message advising the user to go to the settings and configure device credentials on their device. It shows in a dialog on Android side." - }, "@digits": { "description": "Title of the dropdown button where the number of digits for the opt value is selected." }, @@ -200,6 +205,9 @@ } } }, + "@exampleUrl": { + "description": "Shows the user an example of a valid URL." + }, "@failedToFinalizeContainer": { "description": "Error message when finalizing a container failed.", "placeholders": { @@ -209,7 +217,12 @@ } }, "@failedToLoad": { - "description": "Error message when something could not be loaded." + "description": "Error message when something could not be loaded.", + "placeholders": { + "name": { + "example": "token data" + } + } }, "@failedToSyncContainer": { "placeholders": { @@ -221,21 +234,56 @@ "@feedbackPrivacyPolicy2": { "description": "Tapping on this should open the privacy policy." }, + "@finalizationState": { + "description": "Title of the finalization state field." + }, "@generatingPhonePart": { "description": "Title of a dialog telling the user that the phone part gets generated right now." }, "@goToSettingsButton": { "description": "Message showed on a button that the user can click to go to settings pages from the current dialog. It is used on both Android and iOS side. Maximum 30 characters." }, - "@goToSettingsDescription": { - "description": "Message advising the user to go to the settings and configure device credentials or biometrics on their device." - }, - "@guide": { - "description": "Button to open the guide screen." - }, "@handshakeFailed": { "description": "Error message when the handshake failed." }, + "@imageUrl": { + "description": "Title of the image url field." + }, + "@importConflictToken": { + "placeholders": { + "count": { + "example": "5" + } + } + }, + "@importExistingToken": { + "placeholders": { + "count": { + "example": "5" + } + } + }, + "@importFailedToken": { + "placeholders": { + "count": { + "example": "5" + } + } + }, + "@importNTokens": { + "placeholders": { + "count": { + "example": "5" + } + } + }, + "@importNewToken": { + "placeholders": { + "count": { + "example": "5" + } + } + }, "@importedVia": { "description": "Label for the import method of the token." }, @@ -246,6 +294,34 @@ } } }, + "@invalidBackupFile": { + "placeholders": { + "appName": { + "example": "privacyIDEA Authenticator" + } + } + }, + "@invalidLink": { + "placeholders": { + "appName": { + "example": "privacyIDEA Authenticator" + } + } + }, + "@invalidQrFile": { + "placeholders": { + "appName": { + "example": "privacyIDEA Authenticator" + } + } + }, + "@invalidQrScan": { + "placeholders": { + "appName": { + "example": "privacyIDEA Authenticator" + } + } + }, "@invalidValue": { "description": "Error message when the value is not valid for the parameter.", "placeholders": { @@ -282,6 +358,9 @@ "@isPiTokenQuestion": { "description": "Label for the question if the token is a privacyIDEA token." }, + "@issuer": { + "description": "Title of the issuer field." + }, "@issuerLabel": { "description": "Label for the issuer of the token, container... etc.", "placeholders": { @@ -304,9 +383,6 @@ } } }, - "@lightTheme": { - "description": "The light theme." - }, "@linkedContainer": { "description": "Label for the linked container serial number." }, @@ -375,13 +451,6 @@ "@ok": { "description": "Button to confirm an action." }, - "@onBoardingTitle1": { - "placeholders": { - "appName": { - "example": "privacyIDEA Authenticator" - } - } - }, "@open": { "description": "Button to open something." }, @@ -400,6 +469,9 @@ }, "type": "text" }, + "@patchNotesDialogTitle": { + "description": "Title of the dialog that shows the patch notes." + }, "@period": { "description": "Title of the dropdown button where the period of the totp token is selected." }, @@ -460,9 +532,6 @@ "@requestPushChallengesPeriodically": { "description": "The description of the polling feature." }, - "@retry": { - "description": "Label for e.g. a button. Something is tried to be done again." - }, "@rolloutStateCompleted": { "description": "Message for the rollout process" }, @@ -559,6 +628,21 @@ "@syncFbTokenFailed": { "description": "Headline for the list of tokens where the synchronization failed." }, + "@syncState": { + "description": "The state of the synchronization of the token" + }, + "@syncStateCompletedDescription": { + "description": "The description of the state when the synchronization is completed" + }, + "@syncStateFailedDescription": { + "description": "The description of the state when the synchronization failed" + }, + "@syncStateNotStartedDescription": { + "description": "The description of the state when the synchronization is not started" + }, + "@syncStateSyncingDescription": { + "description": "The description of the state when the synchronization is currently syncing" + }, "@synchronizePushTokens": { "description": "Title of synchronizing push tokens in settings." }, @@ -568,9 +652,6 @@ "@synchronizingTokens": { "description": "Title of the push synchronization dialog." }, - "@systemTheme": { - "description": "The systems theme." - }, "@theSecretDoesNotFitTheCurrentEncoding": { "description": "Hint telling the user that the secret does not fit the selected encoding." }, diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index e9cf05f5..1d91cc1a 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -349,7 +349,7 @@ } }, "@failedToLoad": { - "description": "description", + "description": "Error message when something could not be loaded.", "placeholders": { "name": { "example": "token data" @@ -618,6 +618,9 @@ "@isExpotableQuestion": { "description": "Label for the question if the token is exportable." }, + "@isPiTokenQuestion": { + "description": "Label for the question if the token is a privacyIDEA token." + }, "@issuer": { "description": "Title of the issuer field." }, @@ -793,6 +796,9 @@ "@patchNotesBugFixes": { "description": "description" }, + "@patchNotesDialogTitle": { + "description": "Title of the dialog that shows the patch notes." + }, "@patchNotesImprovements": { "description": "description" }, @@ -1235,6 +1241,7 @@ "confirmation": "Confirmation", "connectionFailed": "Connection failed.", "container": "Container", + "containerAlreadyExists": "Container already exists", "containerDetails": "Container details", "containerSerial": "Container Serial", "containerSyncUrl": "Container Sync Url", @@ -1449,6 +1456,7 @@ "rename": "Rename", "renameToken": "Rename token", "renameTokenFolder": "Rename folder", + "replace": "Replace", "requestInfo": "Sent by {issuer} for your account: \"{account}\"", "requestPushChallengesPeriodically": "Request push challenges from the server periodically. Enable this if push challenges are not received normally.", "requestTriggerdByUserQuestion": "Was this request triggered by you?", diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 2d9c83fd..1a9dac17 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -86,9 +86,15 @@ "@container": { "description": "Title for the container view." }, + "@containerDetails": { + "description": "Title of the container details dialog." + }, "@containerSerial": { "description": "description" }, + "@containerSyncUrl": { + "description": "Title of the container sync url field." + }, "@couldNotSignMessage": { "description": "Tells the user that the message could not be signed." }, @@ -101,9 +107,6 @@ "@creator": { "description": "Label for the creator of the token." }, - "@darkTheme": { - "description": "The dark theme." - }, "@decline": { "description": "Label for e.g. a button. Something gets declined by the user." }, @@ -111,16 +114,18 @@ "description": "Label that describes deleting the token." }, "@deleteContainerDialogTitle": { - "example": { - "serial": "SMPH0008CC47" + "placeholders": { + "serial": { + "example": "SMPH0008CC47" + } } }, + "@details": { + "description": "Title of the details action Button." + }, "@deviceCredentialsRequiredTitle": { "description": "Message showed as a title in a dialog which indicates the user has not set up credentials authentication on their device. It is used on Android side. Maximum 60 characters." }, - "@deviceCredentialsSetupDescription": { - "description": "Message advising the user to go to the settings and configure device credentials on their device. It shows in a dialog on Android side." - }, "@digits": { "description": "Title of the dropdown button where the number of digits for the opt value is selected." }, @@ -203,6 +208,9 @@ } } }, + "@exampleUrl": { + "description": "Shows the user an example of a valid URL." + }, "@failedToFinalizeContainer": { "description": "Error message when finalizing a container failed.", "placeholders": { @@ -212,7 +220,12 @@ } }, "@failedToLoad": { - "description": "Error message when something could not be loaded." + "description": "Error message when something could not be loaded.", + "placeholders": { + "name": { + "example": "token data" + } + } }, "@failedToSyncContainer": { "placeholders": { @@ -224,21 +237,56 @@ "@feedbackPrivacyPolicy2": { "description": "Taping on this should open the privacy policy." }, + "@finalizationState": { + "description": "Title of the finalization state field." + }, "@generatingPhonePart": { "description": "Title of a dialog telling the user that the phone part gets generated right now." }, "@goToSettingsButton": { "description": "Message showed on a button that the user can click to go to settings pages from the current dialog. It is used on both Android and iOS side. Maximum 30 characters." }, - "@goToSettingsDescription": { - "description": "Message advising the user to go to the settings and configure device credentials or biometrics on their device." - }, - "@guide": { - "description": "Button to open the guide screen." - }, "@handshakeFailed": { "description": "Error message when the handshake failed." }, + "@imageUrl": { + "description": "Title of the image url field." + }, + "@importConflictToken": { + "placeholders": { + "count": { + "example": "5" + } + } + }, + "@importExistingToken": { + "placeholders": { + "count": { + "example": "5" + } + } + }, + "@importFailedToken": { + "placeholders": { + "count": { + "example": "5" + } + } + }, + "@importNTokens": { + "placeholders": { + "count": { + "example": "5" + } + } + }, + "@importNewToken": { + "placeholders": { + "count": { + "example": "5" + } + } + }, "@importedVia": { "description": "Label for the import method of the token." }, @@ -249,6 +297,34 @@ } } }, + "@invalidBackupFile": { + "placeholders": { + "appName": { + "example": "privacyIDEA Authenticator" + } + } + }, + "@invalidLink": { + "placeholders": { + "appName": { + "example": "privacyIDEA Authenticator" + } + } + }, + "@invalidQrFile": { + "placeholders": { + "appName": { + "example": "privacyIDEA Authenticator" + } + } + }, + "@invalidQrScan": { + "placeholders": { + "appName": { + "example": "privacyIDEA Authenticator" + } + } + }, "@invalidValue": { "description": "Error message when the value is not valid for the parameter.", "placeholders": { @@ -285,6 +361,9 @@ "@isPiTokenQuestion": { "description": "Label for the question if the token is a privacyIDEA token." }, + "@issuer": { + "description": "Title of the issuer field." + }, "@issuerLabel": { "description": "Label for the issuer of the token, container... etc.", "placeholders": { @@ -307,9 +386,6 @@ } } }, - "@lightTheme": { - "description": "The light theme." - }, "@linkedContainer": { "description": "Label for the linked container serial number." }, @@ -378,13 +454,6 @@ "@ok": { "description": "Button to confirm an action." }, - "@onBoardingTitle1": { - "placeholders": { - "appName": { - "example": "privacyIDEA Authenticator" - } - } - }, "@open": { "description": "Button to open something." }, @@ -403,6 +472,9 @@ }, "type": "text" }, + "@patchNotesDialogTitle": { + "description": "Title of the dialog that shows the patch notes." + }, "@period": { "description": "Title of the dropdown button where the period of the totp token is selected." }, @@ -463,9 +535,6 @@ "@requestPushChallengesPeriodically": { "description": "The description of the polling feature." }, - "@retry": { - "description": "Label for e.g. a button. Something is tried to be done again." - }, "@rolloutStateCompleted": { "description": "Message for the rollout process" }, @@ -562,6 +631,21 @@ "@syncFbTokenFailed": { "description": "Headline for the list of tokens where the synchronization failed." }, + "@syncState": { + "description": "The state of the synchronization of the token" + }, + "@syncStateCompletedDescription": { + "description": "The description of the state when the synchronization is completed" + }, + "@syncStateFailedDescription": { + "description": "The description of the state when the synchronization failed" + }, + "@syncStateNotStartedDescription": { + "description": "The description of the state when the synchronization is not started" + }, + "@syncStateSyncingDescription": { + "description": "The description of the state when the synchronization is currently syncing" + }, "@synchronizePushTokens": { "description": "Title of synchronizing push tokens in settings." }, @@ -571,9 +655,6 @@ "@synchronizingTokens": { "description": "Title of the push synchronization dialog." }, - "@systemTheme": { - "description": "The systems theme." - }, "@theSecretDoesNotFitTheCurrentEncoding": { "description": "Hint telling the user that the secret does not fit the selected encoding." }, diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb index 963adf2a..16327f82 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -86,6 +86,12 @@ "@container": { "description": "Title for the container view." }, + "@containerDetails": { + "description": "Title of the container details dialog." + }, + "@containerSyncUrl": { + "description": "Title of the container sync url field." + }, "@couldNotSignMessage": { "description": "Tells the user that the message could not be signed." }, @@ -98,9 +104,6 @@ "@creator": { "description": "Label for the creator of the token." }, - "@darkTheme": { - "description": "The dark theme." - }, "@decline": { "description": "Label for e.g. a button. Something gets declined by the user." }, @@ -108,16 +111,18 @@ "description": "Label that describes deleting the token." }, "@deleteContainerDialogTitle": { - "example": { - "serial": "SMPH0008CC47" + "placeholders": { + "serial": { + "example": "SMPH0008CC47" + } } }, + "@details": { + "description": "Title of the details action Button." + }, "@deviceCredentialsRequiredTitle": { "description": "Message showed as a title in a dialog which indicates the user has not set up credentials authentication on their device. It is used on Android side. Maximum 60 characters." }, - "@deviceCredentialsSetupDescription": { - "description": "Message advising the user to go to the settings and configure device credentials on their device. It shows in a dialog on Android side." - }, "@digits": { "description": "Title of the dropdown button where the number of digits for the opt value is selected." }, @@ -200,6 +205,9 @@ } } }, + "@exampleUrl": { + "description": "Shows the user an example of a valid URL." + }, "@failedToFinalizeContainer": { "description": "Error message when finalizing a container failed.", "placeholders": { @@ -209,7 +217,12 @@ } }, "@failedToLoad": { - "description": "Error message when something could not be loaded." + "description": "Error message when something could not be loaded.", + "placeholders": { + "name": { + "example": "token data" + } + } }, "@failedToSyncContainer": { "placeholders": { @@ -221,21 +234,56 @@ "@feedbackPrivacyPolicy2": { "description": "Taping on this should open the privacy policy." }, + "@finalizationState": { + "description": "Title of the finalization state field." + }, "@generatingPhonePart": { "description": "Title of a dialog telling the user that the phone part gets generated right now." }, "@goToSettingsButton": { "description": "Message showed on a button that the user can click to go to settings pages from the current dialog. It is used on both Android and iOS side. Maximum 30 characters." }, - "@goToSettingsDescription": { - "description": "Message advising the user to go to the settings and configure device credentials or biometrics on their device." - }, - "@guide": { - "description": "Button to open the guide screen." - }, "@handshakeFailed": { "description": "Error message when the handshake failed." }, + "@imageUrl": { + "description": "Title of the image url field." + }, + "@importConflictToken": { + "placeholders": { + "count": { + "example": "5" + } + } + }, + "@importExistingToken": { + "placeholders": { + "count": { + "example": "5" + } + } + }, + "@importFailedToken": { + "placeholders": { + "count": { + "example": "5" + } + } + }, + "@importNTokens": { + "placeholders": { + "count": { + "example": "5" + } + } + }, + "@importNewToken": { + "placeholders": { + "count": { + "example": "5" + } + } + }, "@importedVia": { "description": "Label for the import method of the token." }, @@ -246,6 +294,34 @@ } } }, + "@invalidBackupFile": { + "placeholders": { + "appName": { + "example": "privacyIDEA Authenticator" + } + } + }, + "@invalidLink": { + "placeholders": { + "appName": { + "example": "privacyIDEA Authenticator" + } + } + }, + "@invalidQrFile": { + "placeholders": { + "appName": { + "example": "privacyIDEA Authenticator" + } + } + }, + "@invalidQrScan": { + "placeholders": { + "appName": { + "example": "privacyIDEA Authenticator" + } + } + }, "@invalidValue": { "description": "Error message when the value is not valid for the parameter.", "placeholders": { @@ -282,6 +358,9 @@ "@isPiTokenQuestion": { "description": "Label for the question if the token is a privacyIDEA token." }, + "@issuer": { + "description": "Title of the issuer field." + }, "@issuerLabel": { "description": "Label for the issuer of the token, container... etc.", "placeholders": { @@ -304,9 +383,6 @@ } } }, - "@lightTheme": { - "description": "The light theme." - }, "@linkedContainer": { "description": "Label for the linked container serial number." }, @@ -375,13 +451,6 @@ "@ok": { "description": "Button to confirm an action." }, - "@onBoardingTitle1": { - "placeholders": { - "appName": { - "example": "privacyIDEA Authenticator" - } - } - }, "@open": { "description": "Button to open something." }, @@ -400,6 +469,9 @@ }, "type": "text" }, + "@patchNotesDialogTitle": { + "description": "Title of the dialog that shows the patch notes." + }, "@period": { "description": "Title of the dropdown button where the period of the totp token is selected." }, @@ -460,9 +532,6 @@ "@requestPushChallengesPeriodically": { "description": "The description of the polling feature." }, - "@retry": { - "description": "Label for e.g. a button. Something is tried to be done again." - }, "@rolloutStateCompleted": { "description": "Message for the rollout process" }, @@ -559,6 +628,21 @@ "@syncFbTokenFailed": { "description": "Headline for the list of tokens where the synchronization failed." }, + "@syncState": { + "description": "The state of the synchronization of the token" + }, + "@syncStateCompletedDescription": { + "description": "The description of the state when the synchronization is completed" + }, + "@syncStateFailedDescription": { + "description": "The description of the state when the synchronization failed" + }, + "@syncStateNotStartedDescription": { + "description": "The description of the state when the synchronization is not started" + }, + "@syncStateSyncingDescription": { + "description": "The description of the state when the synchronization is currently syncing" + }, "@synchronizePushTokens": { "description": "Title of synchronizing push tokens in settings." }, @@ -568,9 +652,6 @@ "@synchronizingTokens": { "description": "Title of the push synchronization dialog." }, - "@systemTheme": { - "description": "The systems theme." - }, "@theSecretDoesNotFitTheCurrentEncoding": { "description": "Hint telling the user that the secret does not fit the selected encoding." }, diff --git a/lib/l10n/app_nl.arb b/lib/l10n/app_nl.arb index 4ec6fafd..95d83c1a 100644 --- a/lib/l10n/app_nl.arb +++ b/lib/l10n/app_nl.arb @@ -86,6 +86,12 @@ "@container": { "description": "Title for the container view." }, + "@containerDetails": { + "description": "Title of the container details dialog." + }, + "@containerSyncUrl": { + "description": "Title of the container sync url field." + }, "@couldNotSignMessage": { "description": "Tells the user that the message could not be signed." }, @@ -98,9 +104,6 @@ "@creator": { "description": "Label for the creator of the token." }, - "@darkTheme": { - "description": "The dark theme." - }, "@decline": { "description": "Label for e.g. a button. Something gets declined by the user." }, @@ -108,16 +111,18 @@ "description": "Label that describes deleting the token." }, "@deleteContainerDialogTitle": { - "example": { - "serial": "SMPH0008CC47" + "placeholders": { + "serial": { + "example": "SMPH0008CC47" + } } }, + "@details": { + "description": "Title of the details action Button." + }, "@deviceCredentialsRequiredTitle": { "description": "Message showed as a title in a dialog which indicates the user has not set up credentials authentication on their device. It is used on Android side. Maximum 60 characters." }, - "@deviceCredentialsSetupDescription": { - "description": "Message advising the user to go to the settings and configure device credentials on their device. It shows in a dialog on Android side." - }, "@digits": { "description": "Title of the dropdown button where the number of digits for the opt value is selected." }, @@ -200,6 +205,9 @@ } } }, + "@exampleUrl": { + "description": "Shows the user an example of a valid URL." + }, "@failedToFinalizeContainer": { "description": "Error message when finalizing a container failed.", "placeholders": { @@ -208,6 +216,14 @@ } } }, + "@failedToLoad": { + "description": "Error message when something could not be loaded.", + "placeholders": { + "name": { + "example": "token data" + } + } + }, "@failedToSyncContainer": { "placeholders": { "serial": { @@ -218,21 +234,56 @@ "@feedbackPrivacyPolicy2": { "description": "Hierop tikken moet het privacybeleid openen." }, + "@finalizationState": { + "description": "Title of the finalization state field." + }, "@generatingPhonePart": { "description": "Title of a dialog telling the user that the phone part gets generated right now." }, "@goToSettingsButton": { "description": "Message showed on a button that the user can click to go to settings pages from the current dialog. It is used on both Android and iOS side. Maximum 30 characters." }, - "@goToSettingsDescription": { - "description": "Message advising the user to go to the settings and configure device credentials or biometrics on their device." - }, - "@guide": { - "description": "Button to open the guide screen." - }, "@handshakeFailed": { "description": "Error message when the handshake failed." }, + "@imageUrl": { + "description": "Title of the image url field." + }, + "@importConflictToken": { + "placeholders": { + "count": { + "example": "5" + } + } + }, + "@importExistingToken": { + "placeholders": { + "count": { + "example": "5" + } + } + }, + "@importFailedToken": { + "placeholders": { + "count": { + "example": "5" + } + } + }, + "@importNTokens": { + "placeholders": { + "count": { + "example": "5" + } + } + }, + "@importNewToken": { + "placeholders": { + "count": { + "example": "5" + } + } + }, "@importedVia": { "description": "Label for the import method of the token." }, @@ -243,6 +294,34 @@ } } }, + "@invalidBackupFile": { + "placeholders": { + "appName": { + "example": "privacyIDEA Authenticator" + } + } + }, + "@invalidLink": { + "placeholders": { + "appName": { + "example": "privacyIDEA Authenticator" + } + } + }, + "@invalidQrFile": { + "placeholders": { + "appName": { + "example": "privacyIDEA Authenticator" + } + } + }, + "@invalidQrScan": { + "placeholders": { + "appName": { + "example": "privacyIDEA Authenticator" + } + } + }, "@invalidValue": { "description": "Error message when the value is not valid for the parameter.", "placeholders": { @@ -279,6 +358,9 @@ "@isPiTokenQuestion": { "description": "Label for the question if the token is a privacyIDEA token." }, + "@issuer": { + "description": "Title of the issuer field." + }, "@issuerLabel": { "description": "Label for the issuer of the token, container... etc.", "placeholders": { @@ -301,9 +383,6 @@ } } }, - "@lightTheme": { - "description": "The light theme." - }, "@linkedContainer": { "description": "Label for the linked container serial number." }, @@ -372,13 +451,6 @@ "@ok": { "description": "Button to confirm an action." }, - "@onBoardingTitle1": { - "placeholders": { - "appName": { - "example": "privacyIDEA Authenticator" - } - } - }, "@open": { "description": "Button to open something." }, @@ -397,6 +469,9 @@ }, "type": "text" }, + "@patchNotesDialogTitle": { + "description": "Title of the dialog that shows the patch notes." + }, "@period": { "description": "Title of the dropdown button where the period of the totp token is selected." }, @@ -457,9 +532,6 @@ "@requestPushChallengesPeriodically": { "description": "The description of the polling feature." }, - "@retry": { - "description": "Label for e.g. a button. Something is tried to be done again." - }, "@rolloutStateCompleted": { "description": "Message for the rollout process" }, @@ -556,6 +628,21 @@ "@syncFbTokenFailed": { "description": "Headline for the list of tokens where the synchronization failed." }, + "@syncState": { + "description": "The state of the synchronization of the token" + }, + "@syncStateCompletedDescription": { + "description": "The description of the state when the synchronization is completed" + }, + "@syncStateFailedDescription": { + "description": "The description of the state when the synchronization failed" + }, + "@syncStateNotStartedDescription": { + "description": "The description of the state when the synchronization is not started" + }, + "@syncStateSyncingDescription": { + "description": "The description of the state when the synchronization is currently syncing" + }, "@synchronizePushTokens": { "description": "Title of synchronizing push tokens in settings." }, diff --git a/lib/l10n/app_pl.arb b/lib/l10n/app_pl.arb index 3d4554d6..501e2706 100644 --- a/lib/l10n/app_pl.arb +++ b/lib/l10n/app_pl.arb @@ -86,6 +86,12 @@ "@container": { "description": "Title for the container view." }, + "@containerDetails": { + "description": "Title of the container details dialog." + }, + "@containerSyncUrl": { + "description": "Title of the container sync url field." + }, "@couldNotSignMessage": { "description": "Tells the user that the message could not be signed." }, @@ -98,9 +104,6 @@ "@creator": { "description": "Label for the creator of the token." }, - "@darkTheme": { - "description": "The dark theme." - }, "@decline": { "description": "Label for e.g. a button. Something gets declined by the user." }, @@ -108,16 +111,18 @@ "description": "Label that describes deleting the token." }, "@deleteContainerDialogTitle": { - "example": { - "serial": "SMPH0008CC47" + "placeholders": { + "serial": { + "example": "SMPH0008CC47" + } } }, + "@details": { + "description": "Title of the details action Button." + }, "@deviceCredentialsRequiredTitle": { "description": "Message showed as a title in a dialog which indicates the user has not set up credentials authentication on their device. It is used on Android side. Maximum 60 characters." }, - "@deviceCredentialsSetupDescription": { - "description": "Message advising the user to go to the settings and configure device credentials on their device. It shows in a dialog on Android side." - }, "@digits": { "description": "Title of the dropdown button where the number of digits for the opt value is selected." }, @@ -200,6 +205,9 @@ } } }, + "@exampleUrl": { + "description": "Shows the user an example of a valid URL." + }, "@failedToFinalizeContainer": { "description": "Error message when finalizing a container failed.", "placeholders": { @@ -208,6 +216,14 @@ } } }, + "@failedToLoad": { + "description": "Error message when something could not be loaded.", + "placeholders": { + "name": { + "example": "token data" + } + } + }, "@failedToSyncContainer": { "placeholders": { "serial": { @@ -218,18 +234,56 @@ "@feedbackPrivacyPolicy2": { "description": "Tapnięcie na to powinno otworzyć politykę prywatności." }, + "@finalizationState": { + "description": "Title of the finalization state field." + }, "@generatingPhonePart": { "description": "Title of a dialog telling the user that the phone part gets generated right now." }, "@goToSettingsButton": { "description": "Message showed on a button that the user can click to go to settings pages from the current dialog. It is used on both Android and iOS side. Maximum 30 characters." }, - "@goToSettingsDescription": { - "description": "Message advising the user to go to the settings and configure device credentials or biometrics on their device." - }, "@handshakeFailed": { "description": "Error message when the handshake failed." }, + "@imageUrl": { + "description": "Title of the image url field." + }, + "@importConflictToken": { + "placeholders": { + "count": { + "example": "5" + } + } + }, + "@importExistingToken": { + "placeholders": { + "count": { + "example": "5" + } + } + }, + "@importFailedToken": { + "placeholders": { + "count": { + "example": "5" + } + } + }, + "@importNTokens": { + "placeholders": { + "count": { + "example": "5" + } + } + }, + "@importNewToken": { + "placeholders": { + "count": { + "example": "5" + } + } + }, "@importedVia": { "description": "Label for the import method of the token." }, @@ -240,6 +294,34 @@ } } }, + "@invalidBackupFile": { + "placeholders": { + "appName": { + "example": "privacyIDEA Authenticator" + } + } + }, + "@invalidLink": { + "placeholders": { + "appName": { + "example": "privacyIDEA Authenticator" + } + } + }, + "@invalidQrFile": { + "placeholders": { + "appName": { + "example": "privacyIDEA Authenticator" + } + } + }, + "@invalidQrScan": { + "placeholders": { + "appName": { + "example": "privacyIDEA Authenticator" + } + } + }, "@invalidValue": { "description": "Error message when the value is not valid for the parameter.", "placeholders": { @@ -276,6 +358,9 @@ "@isPiTokenQuestion": { "description": "Label for the question if the token is a privacyIDEA token." }, + "@issuer": { + "description": "Title of the issuer field." + }, "@issuerLabel": { "description": "Label for the issuer of the token, container... etc.", "placeholders": { @@ -298,9 +383,6 @@ } } }, - "@lightTheme": { - "description": "The light theme." - }, "@linkedContainer": { "description": "Label for the linked container serial number." }, @@ -369,13 +451,6 @@ "@ok": { "description": "Button to confirm an action." }, - "@onBoardingTitle1": { - "placeholders": { - "appName": { - "example": "privacyIDEA Authenticator" - } - } - }, "@open": { "description": "Button to open something." }, @@ -394,6 +469,9 @@ }, "type": "text" }, + "@patchNotesDialogTitle": { + "description": "Title of the dialog that shows the patch notes." + }, "@period": { "description": "Title of the dropdown button where the period of the totp token is selected." }, @@ -454,9 +532,6 @@ "@requestPushChallengesPeriodically": { "description": "The description of the polling feature." }, - "@retry": { - "description": "Label for e.g. a button. Something is tried to be done again." - }, "@rolloutStateCompleted": { "description": "Message for the rollout process" }, @@ -553,6 +628,21 @@ "@syncFbTokenFailed": { "description": "Headline for the list of tokens where the synchronization failed." }, + "@syncState": { + "description": "The state of the synchronization of the token" + }, + "@syncStateCompletedDescription": { + "description": "The description of the state when the synchronization is completed" + }, + "@syncStateFailedDescription": { + "description": "The description of the state when the synchronization failed" + }, + "@syncStateNotStartedDescription": { + "description": "The description of the state when the synchronization is not started" + }, + "@syncStateSyncingDescription": { + "description": "The description of the state when the synchronization is currently syncing" + }, "@synchronizePushTokens": { "description": "Title of synchronizing push tokens in settings." }, @@ -562,9 +652,6 @@ "@synchronizingTokens": { "description": "Title of the push synchronization dialog." }, - "@systemTheme": { - "description": "The systems theme." - }, "@theSecretDoesNotFitTheCurrentEncoding": { "description": "Hint telling the user that the secret does not fit the selected encoding." }, diff --git a/lib/model/api_results/pi_server_results/pi_server_result_value.dart b/lib/model/api_results/pi_server_results/pi_server_result_value.dart index f73550a7..306e6920 100644 --- a/lib/model/api_results/pi_server_results/pi_server_result_value.dart +++ b/lib/model/api_results/pi_server_results/pi_server_result_value.dart @@ -47,7 +47,7 @@ sealed class PiServerResultValue extends PiServerResult { } class ContainerFinalizationChallenge extends PiServerResultValue { - final String finalizeSyncUrl; + // final String finalizeSyncUrl; final String keyAlgorithm; final String nonce; final String timeStamp; @@ -55,7 +55,7 @@ class ContainerFinalizationChallenge extends PiServerResultValue { get timeAsDatetime => DateTime.parse(timeStamp); const ContainerFinalizationChallenge({ - required this.finalizeSyncUrl, + // required this.finalizeSyncUrl, required this.keyAlgorithm, required this.nonce, required this.timeStamp, @@ -65,7 +65,7 @@ class ContainerFinalizationChallenge extends PiServerResultValue { final map = validateMap( map: json, validators: { - CONTAINER_SYNC_URL: const ObjectValidator(), + // CONTAINER_SYNC_URL: const ObjectValidator(), CONTAINER_SYNC_KEY_ALGORITHM: const ObjectValidator(), CONTAINER_SYNC_NONCE: const ObjectValidator(), CONTAINER_SYNC_TIMESTAMP: const ObjectValidator(), @@ -73,7 +73,7 @@ class ContainerFinalizationChallenge extends PiServerResultValue { name: 'ContainerChallenge#fromJson', ); return ContainerFinalizationChallenge( - finalizeSyncUrl: map[CONTAINER_SYNC_URL] as String, + // finalizeSyncUrl: map[CONTAINER_SYNC_URL] as String, keyAlgorithm: map[CONTAINER_SYNC_KEY_ALGORITHM] as String, nonce: map[CONTAINER_SYNC_NONCE] as String, timeStamp: map[CONTAINER_SYNC_TIMESTAMP] as String, @@ -83,11 +83,11 @@ class ContainerFinalizationChallenge extends PiServerResultValue { class ContainerFinalizationResponse extends PiServerResultValue { final ECPublicKey publicServerKey; - final Uri syncUrl; + final Uri serverUrl; const ContainerFinalizationResponse({ required this.publicServerKey, - required this.syncUrl, + required this.serverUrl, }); static ContainerFinalizationResponse fromJson(Map json) { @@ -101,7 +101,7 @@ class ContainerFinalizationResponse extends PiServerResultValue { ); return ContainerFinalizationResponse( publicServerKey: map[CONTAINER_SYNC_PUBLIC_SERVER_KEY] as ECPublicKey, - syncUrl: map[CONTAINER_SYNC_URL] as Uri, + serverUrl: map[CONTAINER_SYNC_URL] as Uri, ); } } diff --git a/lib/model/riverpod_states/token_container_state.dart b/lib/model/riverpod_states/token_container_state.dart index 9dfab092..145ceb51 100644 --- a/lib/model/riverpod_states/token_container_state.dart +++ b/lib/model/riverpod_states/token_container_state.dart @@ -61,4 +61,6 @@ class TokenContainerState with _$TokenContainerState { if (container is TokenContainerFinalized) return container.syncState; return null; } + + TokenContainer? currentOfSerial(String serial) => containerList.firstWhereOrNull((container) => container.serial == serial); } diff --git a/lib/model/token_container.dart b/lib/model/token_container.dart index 30bfa6a9..b47a8c2b 100644 --- a/lib/model/token_container.dart +++ b/lib/model/token_container.dart @@ -45,6 +45,10 @@ class TokenContainer with _$TokenContainer { static const eccUtils = EccUtils(); const TokenContainer._(); + Uri get registrationUrl => serverUrl.replace(path: '/container/register/finalize'); + Uri get syncUrlInit => serverUrl.replace(path: '/container/sync/$serial/init'); + Uri get syncUrlFinalize => serverUrl.replace(path: '/container/sync/$serial/finalize'); + // example: pia://container/SMPH00134123 // ?issuer=privacyIDEA // &nonce=887197025f5fa59b50f33c15196eb97ee651a5d1 @@ -66,6 +70,7 @@ class TokenContainer with _$TokenContainer { CONTAINER_EC_KEY_ALGORITHM: ObjectValidator(transformer: (v) => EcKeyAlgorithm.values.byCurveName(v)), CONTAINER_HASH_ALGORITHM: stringToAlgorithmsValidator, CONTAINER_PASSPHRASE_QUESTION: const ObjectValidatorNullable(), + CONTAINER_SSL_VERIFY: stringToBoolValidator, }, name: 'Container', ); @@ -73,10 +78,11 @@ class TokenContainer with _$TokenContainer { issuer: uriMap[CONTAINER_ISSUER], nonce: uriMap[CONTAINER_NONCE], timestamp: uriMap[CONTAINER_TIMESTAMP], - finalizationUrl: uriMap[CONTAINER_FINALIZATION_URL], + serverUrl: uriMap[CONTAINER_FINALIZATION_URL], serial: uriMap[CONTAINER_SERIAL], ecKeyAlgorithm: uriMap[CONTAINER_EC_KEY_ALGORITHM], hashAlgorithm: uriMap[CONTAINER_HASH_ALGORITHM], + sslVerify: uriMap[CONTAINER_SSL_VERIFY], passphraseQuestion: uriMap[CONTAINER_PASSPHRASE_QUESTION], ); } @@ -85,11 +91,11 @@ class TokenContainer with _$TokenContainer { required String issuer, required String nonce, required DateTime timestamp, - required Uri finalizationUrl, - Uri? syncUrl, + required Uri serverUrl, required String serial, required EcKeyAlgorithm ecKeyAlgorithm, required Algorithms hashAlgorithm, + required bool sslVerify, @Default('privacyIDEA') String serverName, @Default(RolloutState.completed) RolloutState finalizationState, String? passphraseQuestion, @@ -102,10 +108,11 @@ class TokenContainer with _$TokenContainer { required String issuer, required String nonce, required DateTime timestamp, - required Uri syncUrl, + required Uri serverUrl, required String serial, required EcKeyAlgorithm ecKeyAlgorithm, required Algorithms hashAlgorithm, + required bool sslVerify, @Default('privacyIDEA') String serverName, @Default(RolloutState.completed) RolloutState finalizationState, @Default(SyncState.notStarted) SyncState syncState, @@ -118,7 +125,6 @@ class TokenContainer with _$TokenContainer { TokenContainerFinalized? finalize({ ECPublicKey? publicServerKey, AsymmetricKeyPair? clientKeyPair, - Uri? syncUrl, }) { if (this is TokenContainerFinalized) return this as TokenContainerFinalized; if (publicServerKey == null && this.publicServerKey == null) { @@ -129,18 +135,16 @@ class TokenContainer with _$TokenContainer { Logger.warning('Unable to finalize without client key pair'); return null; } - if (syncUrl == null && this.syncUrl == null) { - Logger.warning('Unable to finalize without sync url'); - return null; - } + return TokenContainerFinalized( issuer: issuer, nonce: nonce, timestamp: timestamp, - syncUrl: syncUrl ?? this.syncUrl!, serial: serial, + serverUrl: serverUrl, ecKeyAlgorithm: ecKeyAlgorithm, hashAlgorithm: hashAlgorithm, + sslVerify: sslVerify, passphraseQuestion: passphraseQuestion, finalizationState: RolloutState.completed, publicServerKey: this.publicServerKey ?? eccUtils.serializeECPublicKey(publicServerKey!), @@ -172,8 +176,7 @@ class TokenContainer with _$TokenContainer { 'issuer: $issuer, ' 'nonce: $nonce, ' 'timestamp: $timestamp, ' - '${(this is TokenContainerUnfinalized) ? 'finalizationUrl: ${(this as TokenContainerUnfinalized).finalizationUrl}, ' : ''}' - 'syncUrl: $syncUrl, ' + 'serverUrl: $serverUrl, ' 'serial: $serial, ' 'ecKeyAlgorithm: $ecKeyAlgorithm, ' 'hashAlgorithm: $hashAlgorithm, ' diff --git a/lib/model/token_container.freezed.dart b/lib/model/token_container.freezed.dart index 58f6f3c6..1ce57c02 100644 --- a/lib/model/token_container.freezed.dart +++ b/lib/model/token_container.freezed.dart @@ -32,10 +32,11 @@ mixin _$TokenContainer { String get issuer => throw _privateConstructorUsedError; String get nonce => throw _privateConstructorUsedError; DateTime get timestamp => throw _privateConstructorUsedError; - Uri? get syncUrl => throw _privateConstructorUsedError; + Uri get serverUrl => throw _privateConstructorUsedError; String get serial => throw _privateConstructorUsedError; EcKeyAlgorithm get ecKeyAlgorithm => throw _privateConstructorUsedError; Algorithms get hashAlgorithm => throw _privateConstructorUsedError; + bool get sslVerify => throw _privateConstructorUsedError; String get serverName => throw _privateConstructorUsedError; RolloutState get finalizationState => throw _privateConstructorUsedError; String? get passphraseQuestion => throw _privateConstructorUsedError; @@ -48,11 +49,11 @@ mixin _$TokenContainer { String issuer, String nonce, DateTime timestamp, - Uri finalizationUrl, - Uri? syncUrl, + Uri serverUrl, String serial, EcKeyAlgorithm ecKeyAlgorithm, Algorithms hashAlgorithm, + bool sslVerify, String serverName, RolloutState finalizationState, String? passphraseQuestion, @@ -64,10 +65,11 @@ mixin _$TokenContainer { String issuer, String nonce, DateTime timestamp, - Uri syncUrl, + Uri serverUrl, String serial, EcKeyAlgorithm ecKeyAlgorithm, Algorithms hashAlgorithm, + bool sslVerify, String serverName, RolloutState finalizationState, SyncState syncState, @@ -84,11 +86,11 @@ mixin _$TokenContainer { String issuer, String nonce, DateTime timestamp, - Uri finalizationUrl, - Uri? syncUrl, + Uri serverUrl, String serial, EcKeyAlgorithm ecKeyAlgorithm, Algorithms hashAlgorithm, + bool sslVerify, String serverName, RolloutState finalizationState, String? passphraseQuestion, @@ -100,10 +102,11 @@ mixin _$TokenContainer { String issuer, String nonce, DateTime timestamp, - Uri syncUrl, + Uri serverUrl, String serial, EcKeyAlgorithm ecKeyAlgorithm, Algorithms hashAlgorithm, + bool sslVerify, String serverName, RolloutState finalizationState, SyncState syncState, @@ -120,11 +123,11 @@ mixin _$TokenContainer { String issuer, String nonce, DateTime timestamp, - Uri finalizationUrl, - Uri? syncUrl, + Uri serverUrl, String serial, EcKeyAlgorithm ecKeyAlgorithm, Algorithms hashAlgorithm, + bool sslVerify, String serverName, RolloutState finalizationState, String? passphraseQuestion, @@ -136,10 +139,11 @@ mixin _$TokenContainer { String issuer, String nonce, DateTime timestamp, - Uri syncUrl, + Uri serverUrl, String serial, EcKeyAlgorithm ecKeyAlgorithm, Algorithms hashAlgorithm, + bool sslVerify, String serverName, RolloutState finalizationState, SyncState syncState, @@ -191,10 +195,11 @@ abstract class $TokenContainerCopyWith<$Res> { {String issuer, String nonce, DateTime timestamp, - Uri syncUrl, + Uri serverUrl, String serial, EcKeyAlgorithm ecKeyAlgorithm, Algorithms hashAlgorithm, + bool sslVerify, String serverName, RolloutState finalizationState, String? passphraseQuestion, @@ -221,10 +226,11 @@ class _$TokenContainerCopyWithImpl<$Res, $Val extends TokenContainer> Object? issuer = null, Object? nonce = null, Object? timestamp = null, - Object? syncUrl = null, + Object? serverUrl = null, Object? serial = null, Object? ecKeyAlgorithm = null, Object? hashAlgorithm = null, + Object? sslVerify = null, Object? serverName = null, Object? finalizationState = null, Object? passphraseQuestion = freezed, @@ -245,9 +251,9 @@ class _$TokenContainerCopyWithImpl<$Res, $Val extends TokenContainer> ? _value.timestamp : timestamp // ignore: cast_nullable_to_non_nullable as DateTime, - syncUrl: null == syncUrl - ? _value.syncUrl! - : syncUrl // ignore: cast_nullable_to_non_nullable + serverUrl: null == serverUrl + ? _value.serverUrl + : serverUrl // ignore: cast_nullable_to_non_nullable as Uri, serial: null == serial ? _value.serial @@ -261,6 +267,10 @@ class _$TokenContainerCopyWithImpl<$Res, $Val extends TokenContainer> ? _value.hashAlgorithm : hashAlgorithm // ignore: cast_nullable_to_non_nullable as Algorithms, + sslVerify: null == sslVerify + ? _value.sslVerify + : sslVerify // ignore: cast_nullable_to_non_nullable + as bool, serverName: null == serverName ? _value.serverName : serverName // ignore: cast_nullable_to_non_nullable @@ -302,11 +312,11 @@ abstract class _$$TokenContainerUnfinalizedImplCopyWith<$Res> {String issuer, String nonce, DateTime timestamp, - Uri finalizationUrl, - Uri? syncUrl, + Uri serverUrl, String serial, EcKeyAlgorithm ecKeyAlgorithm, Algorithms hashAlgorithm, + bool sslVerify, String serverName, RolloutState finalizationState, String? passphraseQuestion, @@ -332,11 +342,11 @@ class __$$TokenContainerUnfinalizedImplCopyWithImpl<$Res> Object? issuer = null, Object? nonce = null, Object? timestamp = null, - Object? finalizationUrl = null, - Object? syncUrl = freezed, + Object? serverUrl = null, Object? serial = null, Object? ecKeyAlgorithm = null, Object? hashAlgorithm = null, + Object? sslVerify = null, Object? serverName = null, Object? finalizationState = null, Object? passphraseQuestion = freezed, @@ -357,14 +367,10 @@ class __$$TokenContainerUnfinalizedImplCopyWithImpl<$Res> ? _value.timestamp : timestamp // ignore: cast_nullable_to_non_nullable as DateTime, - finalizationUrl: null == finalizationUrl - ? _value.finalizationUrl - : finalizationUrl // ignore: cast_nullable_to_non_nullable + serverUrl: null == serverUrl + ? _value.serverUrl + : serverUrl // ignore: cast_nullable_to_non_nullable as Uri, - syncUrl: freezed == syncUrl - ? _value.syncUrl - : syncUrl // ignore: cast_nullable_to_non_nullable - as Uri?, serial: null == serial ? _value.serial : serial // ignore: cast_nullable_to_non_nullable @@ -377,6 +383,10 @@ class __$$TokenContainerUnfinalizedImplCopyWithImpl<$Res> ? _value.hashAlgorithm : hashAlgorithm // ignore: cast_nullable_to_non_nullable as Algorithms, + sslVerify: null == sslVerify + ? _value.sslVerify + : sslVerify // ignore: cast_nullable_to_non_nullable + as bool, serverName: null == serverName ? _value.serverName : serverName // ignore: cast_nullable_to_non_nullable @@ -412,11 +422,11 @@ class _$TokenContainerUnfinalizedImpl extends TokenContainerUnfinalized { {required this.issuer, required this.nonce, required this.timestamp, - required this.finalizationUrl, - this.syncUrl, + required this.serverUrl, required this.serial, required this.ecKeyAlgorithm, required this.hashAlgorithm, + required this.sslVerify, this.serverName = 'privacyIDEA', this.finalizationState = RolloutState.completed, this.passphraseQuestion, @@ -437,9 +447,7 @@ class _$TokenContainerUnfinalizedImpl extends TokenContainerUnfinalized { @override final DateTime timestamp; @override - final Uri finalizationUrl; - @override - final Uri? syncUrl; + final Uri serverUrl; @override final String serial; @override @@ -447,6 +455,8 @@ class _$TokenContainerUnfinalizedImpl extends TokenContainerUnfinalized { @override final Algorithms hashAlgorithm; @override + final bool sslVerify; + @override @JsonKey() final String serverName; @override @@ -473,14 +483,15 @@ class _$TokenContainerUnfinalizedImpl extends TokenContainerUnfinalized { (identical(other.nonce, nonce) || other.nonce == nonce) && (identical(other.timestamp, timestamp) || other.timestamp == timestamp) && - (identical(other.finalizationUrl, finalizationUrl) || - other.finalizationUrl == finalizationUrl) && - (identical(other.syncUrl, syncUrl) || other.syncUrl == syncUrl) && + (identical(other.serverUrl, serverUrl) || + other.serverUrl == serverUrl) && (identical(other.serial, serial) || other.serial == serial) && (identical(other.ecKeyAlgorithm, ecKeyAlgorithm) || other.ecKeyAlgorithm == ecKeyAlgorithm) && (identical(other.hashAlgorithm, hashAlgorithm) || other.hashAlgorithm == hashAlgorithm) && + (identical(other.sslVerify, sslVerify) || + other.sslVerify == sslVerify) && (identical(other.serverName, serverName) || other.serverName == serverName) && (identical(other.finalizationState, finalizationState) || @@ -502,11 +513,11 @@ class _$TokenContainerUnfinalizedImpl extends TokenContainerUnfinalized { issuer, nonce, timestamp, - finalizationUrl, - syncUrl, + serverUrl, serial, ecKeyAlgorithm, hashAlgorithm, + sslVerify, serverName, finalizationState, passphraseQuestion, @@ -530,11 +541,11 @@ class _$TokenContainerUnfinalizedImpl extends TokenContainerUnfinalized { String issuer, String nonce, DateTime timestamp, - Uri finalizationUrl, - Uri? syncUrl, + Uri serverUrl, String serial, EcKeyAlgorithm ecKeyAlgorithm, Algorithms hashAlgorithm, + bool sslVerify, String serverName, RolloutState finalizationState, String? passphraseQuestion, @@ -546,10 +557,11 @@ class _$TokenContainerUnfinalizedImpl extends TokenContainerUnfinalized { String issuer, String nonce, DateTime timestamp, - Uri syncUrl, + Uri serverUrl, String serial, EcKeyAlgorithm ecKeyAlgorithm, Algorithms hashAlgorithm, + bool sslVerify, String serverName, RolloutState finalizationState, SyncState syncState, @@ -563,11 +575,11 @@ class _$TokenContainerUnfinalizedImpl extends TokenContainerUnfinalized { issuer, nonce, timestamp, - finalizationUrl, - syncUrl, + serverUrl, serial, ecKeyAlgorithm, hashAlgorithm, + sslVerify, serverName, finalizationState, passphraseQuestion, @@ -583,11 +595,11 @@ class _$TokenContainerUnfinalizedImpl extends TokenContainerUnfinalized { String issuer, String nonce, DateTime timestamp, - Uri finalizationUrl, - Uri? syncUrl, + Uri serverUrl, String serial, EcKeyAlgorithm ecKeyAlgorithm, Algorithms hashAlgorithm, + bool sslVerify, String serverName, RolloutState finalizationState, String? passphraseQuestion, @@ -599,10 +611,11 @@ class _$TokenContainerUnfinalizedImpl extends TokenContainerUnfinalized { String issuer, String nonce, DateTime timestamp, - Uri syncUrl, + Uri serverUrl, String serial, EcKeyAlgorithm ecKeyAlgorithm, Algorithms hashAlgorithm, + bool sslVerify, String serverName, RolloutState finalizationState, SyncState syncState, @@ -616,11 +629,11 @@ class _$TokenContainerUnfinalizedImpl extends TokenContainerUnfinalized { issuer, nonce, timestamp, - finalizationUrl, - syncUrl, + serverUrl, serial, ecKeyAlgorithm, hashAlgorithm, + sslVerify, serverName, finalizationState, passphraseQuestion, @@ -636,11 +649,11 @@ class _$TokenContainerUnfinalizedImpl extends TokenContainerUnfinalized { String issuer, String nonce, DateTime timestamp, - Uri finalizationUrl, - Uri? syncUrl, + Uri serverUrl, String serial, EcKeyAlgorithm ecKeyAlgorithm, Algorithms hashAlgorithm, + bool sslVerify, String serverName, RolloutState finalizationState, String? passphraseQuestion, @@ -652,10 +665,11 @@ class _$TokenContainerUnfinalizedImpl extends TokenContainerUnfinalized { String issuer, String nonce, DateTime timestamp, - Uri syncUrl, + Uri serverUrl, String serial, EcKeyAlgorithm ecKeyAlgorithm, Algorithms hashAlgorithm, + bool sslVerify, String serverName, RolloutState finalizationState, SyncState syncState, @@ -671,11 +685,11 @@ class _$TokenContainerUnfinalizedImpl extends TokenContainerUnfinalized { issuer, nonce, timestamp, - finalizationUrl, - syncUrl, + serverUrl, serial, ecKeyAlgorithm, hashAlgorithm, + sslVerify, serverName, finalizationState, passphraseQuestion, @@ -730,11 +744,11 @@ abstract class TokenContainerUnfinalized extends TokenContainer { {required final String issuer, required final String nonce, required final DateTime timestamp, - required final Uri finalizationUrl, - final Uri? syncUrl, + required final Uri serverUrl, required final String serial, required final EcKeyAlgorithm ecKeyAlgorithm, required final Algorithms hashAlgorithm, + required final bool sslVerify, final String serverName, final RolloutState finalizationState, final String? passphraseQuestion, @@ -752,9 +766,8 @@ abstract class TokenContainerUnfinalized extends TokenContainer { String get nonce; @override DateTime get timestamp; - Uri get finalizationUrl; @override - Uri? get syncUrl; + Uri get serverUrl; @override String get serial; @override @@ -762,6 +775,8 @@ abstract class TokenContainerUnfinalized extends TokenContainer { @override Algorithms get hashAlgorithm; @override + bool get sslVerify; + @override String get serverName; @override RolloutState get finalizationState; @@ -795,10 +810,11 @@ abstract class _$$TokenContainerFinalizedImplCopyWith<$Res> {String issuer, String nonce, DateTime timestamp, - Uri syncUrl, + Uri serverUrl, String serial, EcKeyAlgorithm ecKeyAlgorithm, Algorithms hashAlgorithm, + bool sslVerify, String serverName, RolloutState finalizationState, SyncState syncState, @@ -825,10 +841,11 @@ class __$$TokenContainerFinalizedImplCopyWithImpl<$Res> Object? issuer = null, Object? nonce = null, Object? timestamp = null, - Object? syncUrl = null, + Object? serverUrl = null, Object? serial = null, Object? ecKeyAlgorithm = null, Object? hashAlgorithm = null, + Object? sslVerify = null, Object? serverName = null, Object? finalizationState = null, Object? syncState = null, @@ -850,9 +867,9 @@ class __$$TokenContainerFinalizedImplCopyWithImpl<$Res> ? _value.timestamp : timestamp // ignore: cast_nullable_to_non_nullable as DateTime, - syncUrl: null == syncUrl - ? _value.syncUrl - : syncUrl // ignore: cast_nullable_to_non_nullable + serverUrl: null == serverUrl + ? _value.serverUrl + : serverUrl // ignore: cast_nullable_to_non_nullable as Uri, serial: null == serial ? _value.serial @@ -866,6 +883,10 @@ class __$$TokenContainerFinalizedImplCopyWithImpl<$Res> ? _value.hashAlgorithm : hashAlgorithm // ignore: cast_nullable_to_non_nullable as Algorithms, + sslVerify: null == sslVerify + ? _value.sslVerify + : sslVerify // ignore: cast_nullable_to_non_nullable + as bool, serverName: null == serverName ? _value.serverName : serverName // ignore: cast_nullable_to_non_nullable @@ -905,10 +926,11 @@ class _$TokenContainerFinalizedImpl extends TokenContainerFinalized { {required this.issuer, required this.nonce, required this.timestamp, - required this.syncUrl, + required this.serverUrl, required this.serial, required this.ecKeyAlgorithm, required this.hashAlgorithm, + required this.sslVerify, this.serverName = 'privacyIDEA', this.finalizationState = RolloutState.completed, this.syncState = SyncState.notStarted, @@ -930,7 +952,7 @@ class _$TokenContainerFinalizedImpl extends TokenContainerFinalized { @override final DateTime timestamp; @override - final Uri syncUrl; + final Uri serverUrl; @override final String serial; @override @@ -938,6 +960,8 @@ class _$TokenContainerFinalizedImpl extends TokenContainerFinalized { @override final Algorithms hashAlgorithm; @override + final bool sslVerify; + @override @JsonKey() final String serverName; @override @@ -967,12 +991,15 @@ class _$TokenContainerFinalizedImpl extends TokenContainerFinalized { (identical(other.nonce, nonce) || other.nonce == nonce) && (identical(other.timestamp, timestamp) || other.timestamp == timestamp) && - (identical(other.syncUrl, syncUrl) || other.syncUrl == syncUrl) && + (identical(other.serverUrl, serverUrl) || + other.serverUrl == serverUrl) && (identical(other.serial, serial) || other.serial == serial) && (identical(other.ecKeyAlgorithm, ecKeyAlgorithm) || other.ecKeyAlgorithm == ecKeyAlgorithm) && (identical(other.hashAlgorithm, hashAlgorithm) || other.hashAlgorithm == hashAlgorithm) && + (identical(other.sslVerify, sslVerify) || + other.sslVerify == sslVerify) && (identical(other.serverName, serverName) || other.serverName == serverName) && (identical(other.finalizationState, finalizationState) || @@ -996,10 +1023,11 @@ class _$TokenContainerFinalizedImpl extends TokenContainerFinalized { issuer, nonce, timestamp, - syncUrl, + serverUrl, serial, ecKeyAlgorithm, hashAlgorithm, + sslVerify, serverName, finalizationState, syncState, @@ -1024,11 +1052,11 @@ class _$TokenContainerFinalizedImpl extends TokenContainerFinalized { String issuer, String nonce, DateTime timestamp, - Uri finalizationUrl, - Uri? syncUrl, + Uri serverUrl, String serial, EcKeyAlgorithm ecKeyAlgorithm, Algorithms hashAlgorithm, + bool sslVerify, String serverName, RolloutState finalizationState, String? passphraseQuestion, @@ -1040,10 +1068,11 @@ class _$TokenContainerFinalizedImpl extends TokenContainerFinalized { String issuer, String nonce, DateTime timestamp, - Uri syncUrl, + Uri serverUrl, String serial, EcKeyAlgorithm ecKeyAlgorithm, Algorithms hashAlgorithm, + bool sslVerify, String serverName, RolloutState finalizationState, SyncState syncState, @@ -1057,10 +1086,11 @@ class _$TokenContainerFinalizedImpl extends TokenContainerFinalized { issuer, nonce, timestamp, - syncUrl, + serverUrl, serial, ecKeyAlgorithm, hashAlgorithm, + sslVerify, serverName, finalizationState, syncState, @@ -1077,11 +1107,11 @@ class _$TokenContainerFinalizedImpl extends TokenContainerFinalized { String issuer, String nonce, DateTime timestamp, - Uri finalizationUrl, - Uri? syncUrl, + Uri serverUrl, String serial, EcKeyAlgorithm ecKeyAlgorithm, Algorithms hashAlgorithm, + bool sslVerify, String serverName, RolloutState finalizationState, String? passphraseQuestion, @@ -1093,10 +1123,11 @@ class _$TokenContainerFinalizedImpl extends TokenContainerFinalized { String issuer, String nonce, DateTime timestamp, - Uri syncUrl, + Uri serverUrl, String serial, EcKeyAlgorithm ecKeyAlgorithm, Algorithms hashAlgorithm, + bool sslVerify, String serverName, RolloutState finalizationState, SyncState syncState, @@ -1110,10 +1141,11 @@ class _$TokenContainerFinalizedImpl extends TokenContainerFinalized { issuer, nonce, timestamp, - syncUrl, + serverUrl, serial, ecKeyAlgorithm, hashAlgorithm, + sslVerify, serverName, finalizationState, syncState, @@ -1130,11 +1162,11 @@ class _$TokenContainerFinalizedImpl extends TokenContainerFinalized { String issuer, String nonce, DateTime timestamp, - Uri finalizationUrl, - Uri? syncUrl, + Uri serverUrl, String serial, EcKeyAlgorithm ecKeyAlgorithm, Algorithms hashAlgorithm, + bool sslVerify, String serverName, RolloutState finalizationState, String? passphraseQuestion, @@ -1146,10 +1178,11 @@ class _$TokenContainerFinalizedImpl extends TokenContainerFinalized { String issuer, String nonce, DateTime timestamp, - Uri syncUrl, + Uri serverUrl, String serial, EcKeyAlgorithm ecKeyAlgorithm, Algorithms hashAlgorithm, + bool sslVerify, String serverName, RolloutState finalizationState, SyncState syncState, @@ -1165,10 +1198,11 @@ class _$TokenContainerFinalizedImpl extends TokenContainerFinalized { issuer, nonce, timestamp, - syncUrl, + serverUrl, serial, ecKeyAlgorithm, hashAlgorithm, + sslVerify, serverName, finalizationState, syncState, @@ -1224,10 +1258,11 @@ abstract class TokenContainerFinalized extends TokenContainer { {required final String issuer, required final String nonce, required final DateTime timestamp, - required final Uri syncUrl, + required final Uri serverUrl, required final String serial, required final EcKeyAlgorithm ecKeyAlgorithm, required final Algorithms hashAlgorithm, + required final bool sslVerify, final String serverName, final RolloutState finalizationState, final SyncState syncState, @@ -1247,7 +1282,7 @@ abstract class TokenContainerFinalized extends TokenContainer { @override DateTime get timestamp; @override - Uri get syncUrl; + Uri get serverUrl; @override String get serial; @override @@ -1255,6 +1290,8 @@ abstract class TokenContainerFinalized extends TokenContainer { @override Algorithms get hashAlgorithm; @override + bool get sslVerify; + @override String get serverName; @override RolloutState get finalizationState; diff --git a/lib/model/token_container.g.dart b/lib/model/token_container.g.dart index 0085bcba..47eccd4f 100644 --- a/lib/model/token_container.g.dart +++ b/lib/model/token_container.g.dart @@ -12,13 +12,12 @@ _$TokenContainerUnfinalizedImpl _$$TokenContainerUnfinalizedImplFromJson( issuer: json['issuer'] as String, nonce: json['nonce'] as String, timestamp: DateTime.parse(json['timestamp'] as String), - finalizationUrl: Uri.parse(json['finalizationUrl'] as String), - syncUrl: - json['syncUrl'] == null ? null : Uri.parse(json['syncUrl'] as String), + serverUrl: Uri.parse(json['serverUrl'] as String), serial: json['serial'] as String, ecKeyAlgorithm: $enumDecode(_$EcKeyAlgorithmEnumMap, json['ecKeyAlgorithm']), hashAlgorithm: $enumDecode(_$AlgorithmsEnumMap, json['hashAlgorithm']), + sslVerify: json['sslVerify'] as bool, serverName: json['serverName'] as String? ?? 'privacyIDEA', finalizationState: $enumDecodeNullable( _$RolloutStateEnumMap, json['finalizationState']) ?? @@ -36,11 +35,11 @@ Map _$$TokenContainerUnfinalizedImplToJson( 'issuer': instance.issuer, 'nonce': instance.nonce, 'timestamp': instance.timestamp.toIso8601String(), - 'finalizationUrl': instance.finalizationUrl.toString(), - 'syncUrl': instance.syncUrl?.toString(), + 'serverUrl': instance.serverUrl.toString(), 'serial': instance.serial, 'ecKeyAlgorithm': _$EcKeyAlgorithmEnumMap[instance.ecKeyAlgorithm]!, 'hashAlgorithm': _$AlgorithmsEnumMap[instance.hashAlgorithm]!, + 'sslVerify': instance.sslVerify, 'serverName': instance.serverName, 'finalizationState': _$RolloutStateEnumMap[instance.finalizationState]!, 'passphraseQuestion': instance.passphraseQuestion, @@ -120,11 +119,12 @@ _$TokenContainerFinalizedImpl _$$TokenContainerFinalizedImplFromJson( issuer: json['issuer'] as String, nonce: json['nonce'] as String, timestamp: DateTime.parse(json['timestamp'] as String), - syncUrl: Uri.parse(json['syncUrl'] as String), + serverUrl: Uri.parse(json['serverUrl'] as String), serial: json['serial'] as String, ecKeyAlgorithm: $enumDecode(_$EcKeyAlgorithmEnumMap, json['ecKeyAlgorithm']), hashAlgorithm: $enumDecode(_$AlgorithmsEnumMap, json['hashAlgorithm']), + sslVerify: json['sslVerify'] as bool, serverName: json['serverName'] as String? ?? 'privacyIDEA', finalizationState: $enumDecodeNullable( _$RolloutStateEnumMap, json['finalizationState']) ?? @@ -144,10 +144,11 @@ Map _$$TokenContainerFinalizedImplToJson( 'issuer': instance.issuer, 'nonce': instance.nonce, 'timestamp': instance.timestamp.toIso8601String(), - 'syncUrl': instance.syncUrl.toString(), + 'serverUrl': instance.serverUrl.toString(), 'serial': instance.serial, 'ecKeyAlgorithm': _$EcKeyAlgorithmEnumMap[instance.ecKeyAlgorithm]!, 'hashAlgorithm': _$AlgorithmsEnumMap[instance.hashAlgorithm]!, + 'sslVerify': instance.sslVerify, 'serverName': instance.serverName, 'finalizationState': _$RolloutStateEnumMap[instance.finalizationState]!, 'syncState': _$SyncStateEnumMap[instance.syncState]!, diff --git a/lib/utils/identifiers.dart b/lib/utils/identifiers.dart index b5d42a43..9931c60f 100644 --- a/lib/utils/identifiers.dart +++ b/lib/utils/identifiers.dart @@ -119,6 +119,7 @@ const String CONTAINER_SERIAL = 'serial'; const String CONTAINER_EC_KEY_ALGORITHM = 'key_algorithm'; const String CONTAINER_HASH_ALGORITHM = 'hash_algorithm'; const String CONTAINER_PASSPHRASE_QUESTION = 'passphrase'; +const String CONTAINER_SSL_VERIFY = 'ssl_verify'; const String CONTAINER_CONTAINER_SERIAL = 'container_serial'; const String CONTAINER_PUBLIC_CLIENT_KEY = 'public_client_key'; diff --git a/lib/utils/object_validator.dart b/lib/utils/object_validator.dart index a5f0fcd9..dbeb61b7 100644 --- a/lib/utils/object_validator.dart +++ b/lib/utils/object_validator.dart @@ -124,10 +124,11 @@ Map validateMap({required Map map, required Map final newValue = validator.transform(mapEntry); if (newValue != null) validatedMap[key] = newValue; } else { + Logger.debug('All keys: ${map.keys}'); throw LocalizedArgumentError( localizedMessage: name != null - ? (localizations, value, key) => localizations.valueNotAllowedIn(value.runtimeType.toString(), value.toString(), key, name) - : (localizations, value, key) => localizations.valueNotAllowed(value.runtimeType.toString(), value.toString(), key), + ? (localizations, value, key) => localizations.valueNotAllowedIn(name, key, value.runtimeType.toString(), value.toString()) + : (localizations, value, key) => localizations.valueNotAllowed(key, value.runtimeType.toString(), value.toString()), unlocalizedMessage: 'The ${mapEntry.runtimeType} "$mapEntry" is not an allowed value for "$key"', invalidValue: mapEntry.toString(), name: key, @@ -135,9 +136,10 @@ Map validateMap({required Map map, required Map } } else { if (mapEntry == null) { + Logger.debug('All keys: ${map.keys}'); throw LocalizedArgumentError( localizedMessage: name != null - ? (localizations, value, key) => localizations.missingRequiredParameterIn(key, name) + ? (localizations, value, key) => localizations.missingRequiredParameterIn(name, key) : (localizations, value, key) => localizations.missingRequiredParameter(key), unlocalizedMessage: 'Map does not contain required key "$key"', invalidValue: mapEntry.toString(), 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 f29c9d08..31355b68 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 @@ -40,6 +40,7 @@ import '../../../../l10n/app_localizations.dart'; import '../../../../model/api_results/pi_server_results/pi_server_result_value.dart'; import '../../../../model/enums/rollout_state.dart'; import '../../../../model/enums/sync_state.dart'; +import '../../../../model/exception_errors/localized_argument_error.dart'; import '../../../../model/exception_errors/response_error.dart'; import '../../../../model/pi_server_response.dart'; import '../../../../model/riverpod_states/token_container_state.dart'; @@ -49,7 +50,6 @@ import '../../../../repo/secure_token_container_repository.dart'; import '../../../../widgets/dialog_widgets/add_container_progress_dialog.dart'; import '../../../../widgets/dialog_widgets/container_already_exists_dialog.dart'; import '../../../ecc_utils.dart'; -import '../../../../model/exception_errors/localized_argument_error.dart'; import '../../../logger.dart'; part 'token_container_notifier.g.dart'; @@ -341,7 +341,16 @@ class TokenContainerNotifier extends _$TokenContainerNotifier with ResultHandler final newContainerList = containerContainers.where((element) => !stateContainersSerials.contains(element.serial)).toList(); final existingContainers = containerContainers.where((element) => stateContainersSerials.contains(element.serial)).toList(); Logger.info('Handling processor results: adding Container'); - if (existingContainers.isNotEmpty) await _showContainerAlreadyExistsDialog(existingContainers); + final replaceContainers = []; + if (existingContainers.isNotEmpty) { + replaceContainers.addAll(await _showContainerAlreadyExistsDialog(existingContainers) ?? []); + } + + if (replaceContainers.isNotEmpty) { + await deleteContainerList(replaceContainers); + newContainerList.addAll(replaceContainers); + } + if (newContainerList.isNotEmpty) _showAddContainerProgressDialog(newContainerList); final stateAfterAdding = await addContainerList(newContainerList); final failedToAdd = []; @@ -436,9 +445,8 @@ class TokenContainerNotifier extends _$TokenContainerNotifier with ResultHandler showAsyncDialog(builder: (context) => AddContainerProgressDialog(serials), barrierDismissible: false); } - Future _showContainerAlreadyExistsDialog(List containers) { - final serials = containers.map((e) => e.serial).toList(); - return showAsyncDialog(builder: (context) => ContainerAlreadyExistsDialog(serials), barrierDismissible: false); + Future?> _showContainerAlreadyExistsDialog(List containers) { + return showAsyncDialog>(builder: (context) => ContainerAlreadyExistsDialog(containers), barrierDismissible: false); } /// Finalization substep 1: Generate key pair @@ -523,7 +531,7 @@ class TokenContainerNotifier extends _$TokenContainerNotifier with ResultHandler rethrow; } - container = await updateContainer(container, (c) => c.copyWith(finalizationState: RolloutState.parsingResponseCompleted, syncUrl: resultValue.syncUrl)); + container = await updateContainer(container, (c) => c.copyWith(finalizationState: RolloutState.parsingResponseCompleted, serverUrl: resultValue.serverUrl)); if (container == null) throw StateError('Container was removed'); return resultValue.publicServerKey; } diff --git a/lib/utils/riverpod/riverpod_providers/generated_providers/token_container_notifier.g.dart b/lib/utils/riverpod/riverpod_providers/generated_providers/token_container_notifier.g.dart index 391dab50..06b20e73 100644 --- a/lib/utils/riverpod/riverpod_providers/generated_providers/token_container_notifier.g.dart +++ b/lib/utils/riverpod/riverpod_providers/generated_providers/token_container_notifier.g.dart @@ -7,7 +7,7 @@ part of 'token_container_notifier.dart'; // ************************************************************************** String _$tokenContainerNotifierHash() => - r'ab2f1d98b00a7cbe7c295c517f1b70a55d0c088a'; + r'a1e6ccff90db9591bcf1de7af6fa8b01f3b29d93'; /// Copied from Dart SDK class _SystemHash { diff --git a/lib/views/container_view/container_view.dart b/lib/views/container_view/container_view.dart index 0a5b8385..4a8a7845 100644 --- a/lib/views/container_view/container_view.dart +++ b/lib/views/container_view/container_view.dart @@ -20,6 +20,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:privacyidea_authenticator/views/main_view/main_view_widgets/main_view_navigation_buttons/qr_scanner_button.dart'; import '../../l10n/app_localizations.dart'; @@ -47,11 +48,13 @@ class ContainerView extends ConsumerView { floatingActionButton: const QrScannerButton(), floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat, body: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - for (var containerCredential in container) ContainerWidget(container: containerCredential), - ], + child: SlidableAutoCloseBehavior( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + for (var containerCredential in container) ContainerWidget(container: containerCredential), + ], + ), ), ), ); diff --git a/lib/views/container_view/container_widgets/container_actions/details_container_action_dialog.dart b/lib/views/container_view/container_widgets/container_actions/details_container_action_dialog.dart index 7c998f0d..8cc12b3e 100644 --- a/lib/views/container_view/container_widgets/container_actions/details_container_action_dialog.dart +++ b/lib/views/container_view/container_widgets/container_actions/details_container_action_dialog.dart @@ -46,7 +46,7 @@ class _DetailsContainerDialogState extends ConsumerState @override void initState() { super.initState(); - controller = TextEditingController(text: widget.container.syncUrl.toString()); + controller = TextEditingController(text: widget.container.serverUrl.toString()); } @override @@ -93,7 +93,7 @@ class _DetailsContainerDialogState extends ConsumerState TextButton( onPressed: Uri.tryParse(controller.text) != null ? () { - ref.read(tokenContainerProvider.notifier).updateContainer(widget.container, (c) => c.copyWith(syncUrl: Uri.parse(controller.text))); + ref.read(tokenContainerProvider.notifier).updateContainer(widget.container, (c) => c.copyWith(serverUrl: Uri.parse(controller.text))); Navigator.of(context).pop(); } : null, diff --git a/lib/views/container_view/container_widgets/container_widget.dart b/lib/views/container_view/container_widgets/container_widget.dart index 08463fbd..2ef7d33e 100644 --- a/lib/views/container_view/container_widgets/container_widget.dart +++ b/lib/views/container_view/container_widgets/container_widget.dart @@ -41,16 +41,18 @@ class ContainerWidget extends ConsumerWidget { }); @override - Widget build(BuildContext context, WidgetRef ref) => ClipRRect( - child: PiSliable( - groupTag: groupTag, - identifier: container.serial, - actions: [ - DeleteContainerAction(container: container, key: Key('${container.serial}-DeleteContainerAction')), - DetailsContainerAction(container: container, key: Key('${container.serial}-EditContainerAction')), - ], - stack: stack, - child: ContainerWidgetTile(container: container), - ), - ); + Widget build(BuildContext context, WidgetRef ref) => isPreview + ? ContainerWidgetTile(container: container) + : ClipRRect( + child: PiSliable( + groupTag: groupTag, + identifier: container.serial, + actions: [ + DeleteContainerAction(container: container, key: Key('${container.serial}-DeleteContainerAction')), + DetailsContainerAction(container: container, key: Key('${container.serial}-EditContainerAction')), + ], + stack: stack, + child: ContainerWidgetTile(container: container), + ), + ); } diff --git a/lib/views/container_view/container_widgets/container_widget_tile.dart b/lib/views/container_view/container_widgets/container_widget_tile.dart index f3f2036e..fa81c408 100644 --- a/lib/views/container_view/container_widgets/container_widget_tile.dart +++ b/lib/views/container_view/container_widgets/container_widget_tile.dart @@ -61,7 +61,7 @@ class ContainerWidgetTile extends ConsumerWidget { padding: const EdgeInsets.only(left: 4.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.max, + mainAxisSize: MainAxisSize.min, children: [ for (var line in [ AppLocalizations.of(context)!.issuerLabel(container.issuer), diff --git a/lib/widgets/dialog_widgets/container_already_exists_dialog.dart b/lib/widgets/dialog_widgets/container_already_exists_dialog.dart index 86d624c8..ce84bb4b 100644 --- a/lib/widgets/dialog_widgets/container_already_exists_dialog.dart +++ b/lib/widgets/dialog_widgets/container_already_exists_dialog.dart @@ -19,39 +19,67 @@ */ import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:privacyidea_authenticator/l10n/app_localizations.dart'; +import 'package:privacyidea_authenticator/model/token_container.dart'; +import 'package:privacyidea_authenticator/views/container_view/container_widgets/container_widget.dart'; +import 'package:privacyidea_authenticator/widgets/button_widgets/cooldown_button.dart'; import 'package:privacyidea_authenticator/widgets/dialog_widgets/default_dialog.dart'; -class ContainerAlreadyExistsDialog extends StatelessWidget { - final List serials; +import '../../utils/riverpod/riverpod_providers/generated_providers/token_container_notifier.dart'; - const ContainerAlreadyExistsDialog(this.serials, {super.key}); +class ContainerAlreadyExistsDialog extends ConsumerStatefulWidget { + final List containers; + + const ContainerAlreadyExistsDialog(this.containers, {super.key}); + + @override + ConsumerState createState() => _ContainerAlreadyExistsDialogState(); +} + +class _ContainerAlreadyExistsDialogState extends ConsumerState { + late final List unhandledContainers; + final List replaceContainers = []; + + @override + void initState() { + unhandledContainers = widget.containers; + super.initState(); + } @override Widget build(BuildContext context) { + final container = unhandledContainers.firstOrNull; + if (container == null) return SizedBox.shrink(); + final currentContainer = ref.watch(tokenContainerProvider).valueOrNull?.currentOf(container); + if (currentContainer == null) return SizedBox.shrink(); + final appLocalizations = AppLocalizations.of(context)!; return DefaultDialog( - title: Text('Container already exists'), - content: SizedBox( - width: double.maxFinite, - child: ListView.builder( - shrinkWrap: true, - itemCount: serials.length, - itemBuilder: (context, index) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text('Serial: ${serials[index]}'), - if (index != serials.length - 1) const Divider(), - ], - ); - }, - ), - ), + title: Text(appLocalizations.containerAlreadyExists), + content: ContainerWidget(container: currentContainer, isPreview: true), actions: [ TextButton( - onPressed: () => Navigator.of(context).pop(), - child: Text('OK'), + onPressed: () => _dismiss(container), + child: Text(appLocalizations.dismiss), + ), + CooldownButton( + onPressed: () => _replace(currentContainer, container), + child: Text(appLocalizations.replace), ), ], ); } + + void _dismiss(TokenContainer container) { + setState(() => unhandledContainers.remove(container)); + if (unhandledContainers.isEmpty) Navigator.of(context).pop(replaceContainers); + } + + Future _replace(TokenContainer oldContainer, TokenContainer newContainer) async { + setState(() { + unhandledContainers.remove(newContainer); + replaceContainers.add(newContainer); + }); + if (unhandledContainers.isEmpty && mounted) Navigator.of(context).pop(replaceContainers); + } }