Skip to content

Commit

Permalink
Merge pull request #145 from niscy-eudiw/main
Browse files Browse the repository at this point in the history
fixed user pseudonym attribute from age attestation to be decoded cor…
  • Loading branch information
stzouvaras authored Jul 31, 2024
2 parents 3045c44 + ad1cbf5 commit d9c0c0b
Show file tree
Hide file tree
Showing 12 changed files with 144 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -104,26 +104,26 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/eu-digital-identity-wallet/eudi-lib-ios-iso18013-data-model.git",
"state" : {
"revision" : "7bd825a94d78955b7a176cd3ed1058b30d7f266b",
"version" : "0.2.9"
"revision" : "907e5dbdb58fcaf4916507a8fcfff7a79cbd0efd",
"version" : "0.3.0"
}
},
{
"identity" : "eudi-lib-ios-iso18013-data-transfer",
"kind" : "remoteSourceControl",
"location" : "https://github.com/eu-digital-identity-wallet/eudi-lib-ios-iso18013-data-transfer.git",
"state" : {
"revision" : "ceeddd2a37f579212752bfb38e54efa87ec567e3",
"version" : "0.2.9"
"revision" : "380ebcf5e054adf651580faf7cd627052ef3de12",
"version" : "0.3.0"
}
},
{
"identity" : "eudi-lib-ios-iso18013-security",
"kind" : "remoteSourceControl",
"location" : "https://github.com/eu-digital-identity-wallet/eudi-lib-ios-iso18013-security.git",
"state" : {
"revision" : "78aad88df3997a8448e0a2ebe8cd1cd84cb14e35",
"version" : "0.2.2"
"revision" : "8b77e16221f169b5a5de7e81342411c15e46cf37",
"version" : "0.2.3"
}
},
{
Expand Down Expand Up @@ -158,17 +158,17 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/eu-digital-identity-wallet/eudi-lib-ios-wallet-kit.git",
"state" : {
"revision" : "998fcf0a6d318b9add556d28a26438655fe78f8e",
"version" : "0.6.0"
"revision" : "1255b0526f8c4ec082460db1173f2440761480e9",
"version" : "0.6.1"
}
},
{
"identity" : "eudi-lib-ios-wallet-storage",
"kind" : "remoteSourceControl",
"location" : "https://github.com/eu-digital-identity-wallet/eudi-lib-ios-wallet-storage.git",
"state" : {
"revision" : "8ebf1f0cf0edb2854b7b098cd90c32e0da5c9c34",
"version" : "0.2.2"
"revision" : "2fbdcb70dca4d14383b06dc584d1346959fd26f6",
"version" : "0.2.4"
}
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ extension MdocDecodable {
type: self.docType,
title: identifier.isSupported
? identifier.localizedTitle
: self.title ?? identifier.localizedTitle,
: self.displayName ?? identifier.localizedTitle,
createdAt: self.createdAt,
expiresAt: self.getExpiryDate(
parser: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ final class TestDashboardInteractor: EudiTest {
privateKeyType: nil,
privateKey: nil,
createdAt: nil,
displayName: nil,
status: .deferred
)
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ extension MdocDecodable {
.compactMap({$0})
.sorted(by: {$0.order < $1.order})
.decodeGender()
.decodeUserPseudonym()
.mapTrueFalseToLocalizable()
.parseDates(
parser: {
Expand All @@ -119,7 +120,7 @@ extension MdocDecodable {
type: identifier,
documentName: identifier.isSupported
? identifier.localizedTitle
: title ?? identifier.localizedTitle,
: displayName ?? identifier.localizedTitle,
holdersName: bearerName,
holdersImage: getPortrait() ?? Theme.shared.image.user,
createdAt: createdAt,
Expand Down Expand Up @@ -181,6 +182,7 @@ extension MdocDecodable {
private func flattenNested(parent: NameValue, nested: [NameValue]) -> NameValue {
let flat = nested
.decodeGender()
.decodeUserPseudonym()
.mapTrueFalseToLocalizable()
.parseDates(
parser: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,40 @@ final class TestStartupInteractor: EudiTest {
var interactor: StartupInteractor!
var walletKitController: MockWalletKitController!
var quickPinInteractor: MockQuickPinInteractor!
var keyChainController: MockKeyChainController!
var prefsController: MockPrefsController!

override func setUp() {
self.walletKitController = MockWalletKitController()
self.quickPinInteractor = MockQuickPinInteractor()
self.keyChainController = MockKeyChainController()
self.prefsController = MockPrefsController()
self.interactor = StartupInteractorImpl(
walletKitController: walletKitController,
quickPinInteractor: quickPinInteractor
quickPinInteractor: quickPinInteractor,
keyChainController: keyChainController,
prefsController: prefsController
)

stubPrefsControllerSetValue()
stubKeyChainClear()
stubWalletKiControllerClearAllDocuments()
}

override func tearDown() {
self.interactor = nil
self.walletKitController = nil
self.quickPinInteractor = nil
self.keyChainController = nil
self.prefsController = nil
}

func testInitialize_WhenPinIsNotSet_ThenReturnQuickPinAppRoute() async throws {
func testInitialize_WhenIsNotFirstBootAndPinIsNotSet_ThenReturnQuickPinAppRoute() async throws {
// Given
let expectedConfig = QuickPinUiConfig(flow: .set)
stubFetchDocuments(with: [Constants.euPidModel, Constants.isoMdlModel])
stubHasPin(with: false)
stubRunAtLeastOnce()
// When
let route = await interactor.initialize(with: .zero)
// Then
Expand All @@ -58,13 +71,16 @@ final class TestStartupInteractor: EudiTest {
default:
XCTFail("Wrong route \(route)")
}

verifyFirstBootStorageManipulation(count: 0)
}

func testInitialize_WhenPinIsSetAndHasIssuedDocuments_ThenReturnBiometricsAppRouteWithNavigationSuccessDashboard() async throws {
func testInitialize_WhenIsNotFirstBootAndPinIsSetAndHasIssuedDocuments_ThenReturnBiometricsAppRouteWithNavigationSuccessDashboard() async throws {
// Given
let expectedConfig = biometryConfig(with: true)
stubFetchDocuments(with: [Constants.euPidModel, Constants.isoMdlModel])
stubHasPin(with: true)
stubRunAtLeastOnce()
// When
let route = await interactor.initialize(with: .zero)
// Then
Expand All @@ -76,13 +92,16 @@ final class TestStartupInteractor: EudiTest {
default:
XCTFail("Wrong route \(route)")
}

verifyFirstBootStorageManipulation(count: 0)
}

func testInitialize_WhenPinIsSetAndHasNoIssuedDocuments_ThenReturnBiometricsAppRouteWithNavigationSuccessAddDocument() async throws {
func testInitialize_WhenIsNotFirstBootAndPinIsSetAndHasNoIssuedDocuments_ThenReturnBiometricsAppRouteWithNavigationSuccessAddDocument() async throws {
// Given
let expectedConfig = biometryConfig(with: false)
stubFetchDocuments(with: [])
stubHasPin(with: true)
stubRunAtLeastOnce()
// When
let route = await interactor.initialize(with: .zero)
// Then
Expand All @@ -94,21 +113,47 @@ final class TestStartupInteractor: EudiTest {
default:
XCTFail("Wrong route \(route)")
}

verifyFirstBootStorageManipulation(count: 0)
}

func testInitialize_WhenIsFirstBootAndPinIsNotSet_ThenClearDocumentStorageAndReturnQuickPinAppRoute() async throws {
// Given
let expectedConfig = QuickPinUiConfig(flow: .set)
stubFetchDocuments(with: [Constants.euPidModel, Constants.isoMdlModel])
stubHasPin(with: false)
stubRunAtLeastOnce(false)
// When
let route = await interactor.initialize(with: .zero)
// Then
switch route {
case .quickPin(let config):
let receivedConfig = try XCTUnwrap(config as? QuickPinUiConfig)
XCTAssertEqual(receivedConfig, expectedConfig)
break
default:
XCTFail("Wrong route \(route)")
}

verifyFirstBootStorageManipulation(count: 1)
}
}

private extension TestStartupInteractor {

func stubFetchDocuments(with documents: [MdocDecodable]) {
stub(walletKitController) { mock in
when(mock.loadDocuments()).thenDoNothing()
when(mock.fetchAllDocuments()).thenReturn(documents)
}
}

func stubHasPin(with hasPin: Bool) {
stub(quickPinInteractor) { mock in
when(mock.hasPin()).thenReturn(hasPin)
}
}

func biometryConfig(with hasDocuments: Bool) -> UIConfig.Biometry {
return UIConfig.Biometry(
title: .loginTitle,
Expand All @@ -124,4 +169,34 @@ private extension TestStartupInteractor {
shouldInitializeBiometricOnCreate: true
)
}

func stubPrefsControllerSetValue() {
stub(prefsController) { mock in
when(mock.setValue(any(), forKey: any())).thenDoNothing()
}
}

func stubRunAtLeastOnce(_ atLeastOnce: Bool = true) {
stub(prefsController) { mock in
when(mock.getBool(forKey: Prefs.Key.runAtLeastOnce)).thenReturn(atLeastOnce)
}
}

func stubKeyChainClear() {
stub(keyChainController) { mock in
when(mock.clear()).thenDoNothing()
}
}

func stubWalletKiControllerClearAllDocuments() {
stub(walletKitController) { mock in
when(mock.clearAllDocuments()).thenDoNothing()
}
}

func verifyFirstBootStorageManipulation(count: Int) {
verify(prefsController, times(count)).setValue(any(), forKey: Prefs.Key.runAtLeastOnce)
verify(keyChainController, times(count)).clear()
verify(walletKitController, times(count)).clearAllDocuments()
}
}
4 changes: 2 additions & 2 deletions Modules/feature-test/Sources/Utils/Constants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ extension Constants {
issuerSigned: dr.documents!.first!.issuerSigned,
devicePrivateKey: Constants.pk,
docType: dr.documents!.first!.issuerSigned.issuerAuth.mso.docType,
title: "Driving Licence"
displayName: "Driving Licence"
)!

static let euPidModel = GenericMdocModel(
Expand All @@ -51,7 +51,7 @@ extension Constants {
issuerSigned: dr.documents!.last!.issuerSigned,
devicePrivateKey: Constants.pk,
docType: dr.documents!.last!.issuerSigned.issuerAuth.mso.docType,
title: "National ID"
displayName: "National ID"
)!
}

Expand Down
28 changes: 28 additions & 0 deletions Modules/logic-business/Sources/Extension/String+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,12 @@ public extension String? {
}
return self
}
func ifNull(_ fallback: () -> String) -> String {
guard let self = self else {
return fallback()
}
return self
}
}

public extension String {
Expand Down Expand Up @@ -149,3 +155,25 @@ public extension String {
return value
}
}

public extension String {

var decodeBase64: String? {
guard
let data = Data(base64Encoded: self),
let decoded = String(data: data, encoding: .utf8)
else {
return nil
}
return decoded
}

var toBase64: String? {
guard
let data = self.data(using: .utf8)
else {
return nil
}
return data.base64EncodedString()
}
}
2 changes: 1 addition & 1 deletion Modules/logic-core/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ let package = Package(
dependencies: [
.package(
url: "https://github.com/eu-digital-identity-wallet/eudi-lib-ios-wallet-kit.git",
exact: "0.6.0"
exact: "0.6.1"
),
.package(
name: "logic-resources",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ extension WalletKitController {
let displayStrings = wallet.storage.mdocModels
.first(where: { $0.id == documentId })?.displayStrings
.decodeGender()
.decodeUserPseudonym()
.parseDates(parser: parser)
.mapTrueFalseToLocalizable()

Expand Down
16 changes: 16 additions & 0 deletions Modules/logic-core/Sources/Extension/NameValue+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,22 @@ extension Array where Element == NameValue {
}
}

public func decodeUserPseudonym() -> [NameValue] {
self.map { nameValue in
if nameValue.name == "user_pseudonym" {
return NameValue(
name: nameValue.name,
value: nameValue.value.decodeBase64.ifNull { nameValue.value },
ns: nameValue.ns,
order: nameValue.order,
children: nameValue.children
)
} else {
return nameValue
}
}
}

public func mapTrueFalseToLocalizable() -> [NameValue] {
self.map {
if $0.value == "true" || $0.value == "false" {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ extension WalletStorage.Document {
id: self.id,
createdAt: self.createdAt,
docType: self.docType,
title: nil
displayName: self.displayName
)
}
}
2 changes: 1 addition & 1 deletion Modules/logic-core/Sources/Model/DeferrredDocument.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public struct DeferrredDocument: MdocDecodable {
public var devicePrivateKey: CoseKeyPrivate?
public var docType: String
public var nameSpaces: [NameSpace]?
public var title: String?
public var displayName: String?
public var ageOverXX = [Int: Bool]()
public var displayStrings = [NameValue]()
public var displayImages = [NameImage]()
Expand Down

0 comments on commit d9c0c0b

Please sign in to comment.