Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Object Mapping Strategy #3

Merged
merged 40 commits into from
Jan 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
55d39af
Add submodule
symorton Dec 5, 2022
26d6cda
Add git submodule for VC SDK
symorton Dec 5, 2022
75fca95
Create workspace
symorton Dec 5, 2022
810388a
Create test app
symorton Dec 5, 2022
441f873
Fix nit for initial PR
symorton Dec 5, 2022
eaf88b4
Add code owners and pull request template
symorton Dec 5, 2022
5e65489
Add IssuanceRequest and Requirements
symorton Dec 9, 2022
5ee938d
Add Contract
symorton Dec 9, 2022
fd28740
Add Request Handling Protocol
symorton Dec 9, 2022
29bfc51
Add Async Wrapper
symorton Dec 12, 2022
98f8e3a
Add Protocol for Presentation Service and Extend it
symorton Dec 12, 2022
e59e7ff
Add protocol for request handling
symorton Dec 12, 2022
442cf67
Update project file
symorton Dec 12, 2022
a5972a1
Add Verified Id Flow
symorton Dec 12, 2022
2c8751c
Add PinRequirement and CredentialFormat
symorton Dec 12, 2022
f14700d
Fix nits on comments.
symorton Dec 12, 2022
69b3ca2
Remove trait properties from contract.
symorton Dec 12, 2022
fbdaf3f
Merge branch 'symorton/issuanceDataModels' into symorton/requestHandler
symorton Dec 13, 2022
9ad759f
Merge branch 'dev' into symorton/requestHandler
symorton Dec 13, 2022
4c5ec31
Add Extension for PresentationService
symorton Dec 13, 2022
9845e6a
Add Translation Protocols
symorton Dec 14, 2022
82c02fb
Add PresentationService Extension
symorton Dec 14, 2022
e7fb0aa
Add Root of Trust Data Model
symorton Dec 14, 2022
779de17
Small nits on Requirements
symorton Dec 14, 2022
b688d95
Add root of trust to Contract
symorton Dec 14, 2022
b90ad75
Make contracts a internally set var
symorton Dec 14, 2022
d9e4a80
Add a Mapper for IdTokenDescriptor
symorton Dec 14, 2022
7714ffe
Add mapping of AccessTokenDescriptor to AccessTokenRequirement
symorton Dec 14, 2022
2c64110
Update Id and Access Token Mappings
symorton Dec 15, 2022
ffb12d7
Add PresentationServiceable Protocol
symorton Dec 15, 2022
22cc416
Add Async Wrapper Tests
symorton Dec 15, 2022
3a211c4
Remove Request Handler for next PR
symorton Dec 15, 2022
fba07fc
Update project file
symorton Dec 15, 2022
1bf4848
Fix comments on token mappers
symorton Dec 15, 2022
2ad89e7
Add mapping for presentation descriptor to verified id requirement
symorton Dec 15, 2022
34e3749
Add comments for PresentationServiceable protocol
symorton Dec 15, 2022
927c8a0
Fix naming in token mapping tests
symorton Dec 15, 2022
4d889d5
Fix nits for PR
symorton Dec 15, 2022
af04773
Fix small nit in tests
symorton Dec 15, 2022
ac90987
Remove mocked data models and use VC SDK data models instead for testing
symorton Dec 16, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
224 changes: 215 additions & 9 deletions WalletLibrary/WalletLibrary.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import VCEntities

/**
* An extension of the VCEntities.AccessTokenDescriptor class to be able
* to map AccessTokenDescriptor to AccessTokenRequirement.
*/
extension VCEntities.AccessTokenDescriptor: Mappable {

/// Map the access token descriptor to access token requirement.
func map(using mapper: Mapping) throws -> AccessTokenRequirement {

let configuration = try getRequiredProperty(property: configuration, propertyName: "configuration")
let resourceId = try getRequiredProperty(property: resourceId, propertyName: "resourceId")
let scope = try getRequiredProperty(property: oboScope, propertyName: "oboScope")

return AccessTokenRequirement(encrypted: encrypted ?? false,
required: self.required ?? false,
configuration: configuration,
clientId: nil,
resourceId: resourceId,
scope: scope)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import VCEntities

/**
* An extension of the VCEntities.IdTokenDescriptor class to be able
* to map IdTokenDescriptor to IdTokenRequirement.
*/
extension VCEntities.IdTokenDescriptor: Mappable {

/// Map the id token descriptor to the id token requirement.
func map(using mapper: Mapping) throws -> IdTokenRequirement {

guard let configuration = URL(string: configuration) else {
throw MappingError.InvalidProperty(property:"configuration",
in: String(describing: IdTokenDescriptor.self))
}

let redirectUri = try getRequiredProperty(property: redirectURI, propertyName: "redirectURI")
let scope = try getRequiredProperty(property: scope, propertyName: "scope")

return IdTokenRequirement(encrypted: encrypted ?? false,
required: idTokenRequired ?? false,
configuration: configuration,
clientId: clientID,
redirectUri: redirectUri,
scope: scope,
nonce: nil)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import VCEntities

/**
* An extension of the VCEntities.PresentationDescriptor class to be able
* to map PresentationDescriptor to VerifiedIdRequirement.
*/
extension VCEntities.PresentationDescriptor: Mappable {

func map(using mapper: Mapping) throws -> VerifiedIdRequirement {

let acceptedIssuers = issuers?.compactMap { $0.iss } ?? []

var issuanceParams: CredentialIssuanceParams? = nil
if let contracts = contracts,
!contracts.isEmpty {
issuanceParams = CredentialIssuanceParams(acceptedIssuers: acceptedIssuers,
credentialIssuerMetadata: contracts)
}

return VerifiedIdRequirement(encrypted: encrypted ?? false,
required: presentationRequired ?? false,
types: [credentialType],
acceptedIssuers: acceptedIssuers,
purpose: nil,
credentialIssuanceParams: issuanceParams)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import VCEntities
import VCServices

/**
* An extension of the VCServices.PresentationService class.
*/
extension PresentationService: PresentationServiceable {

/// Fetches and validates the presentation request.
func getRequest(url: String) async throws -> VCEntities.PresentationRequest {
return try await AsyncWrapper().wrap { () in
self.getRequest(usingUrl: url)
}()
}

/// Sends the presentation response container and if successful, returns void,
/// If unsuccessful, throws an error.
func send(response: VCEntities.PresentationResponseContainer) async throws -> Void {
let _ = try await AsyncWrapper().wrap { () in
self.send(response: response)
}()
}
}
35 changes: 35 additions & 0 deletions WalletLibrary/WalletLibrary/Protocols/Extensions/Mappable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

/**
* Errors pertaining to mapping one data model to another using the Mappable protocol.
*/
enum MappingError: Error, Equatable {
case PropertyNotPresent(property: String, in: String)
case InvalidProperty(property: String, in: String)
}

/**
* Map the object that conforms to Mappable to object T.
*/
protocol Mappable {
associatedtype T

/// Map the object that conforms to the protocol to another object.
func map(using mapper: Mapping) throws -> T
}

extension Mappable {

/// Helper method to convert an optional property to a required property, else throw an error.
func getRequiredProperty<U>(property: U?, propertyName: String) throws -> U {

guard let requiredProperty = property else {
throw MappingError.PropertyNotPresent(property: propertyName, in: String(describing: Self.self))
}

return requiredProperty
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import VCEntities

/**
* Protocol that handles getting vc sdk presentation requests and sending vc sdk presentation responses.
*/
protocol PresentationServiceable {

/// Fetches and validates the presentation request.
func getRequest(url: String) async throws -> VCEntities.PresentationRequest

/// Sends the presentation response container and if successful, returns void,
/// If unsuccessful, throws an error.
func send(response: PresentationResponseContainer) async throws -> Void
}
11 changes: 11 additions & 0 deletions WalletLibrary/WalletLibrary/Protocols/Utilities/Mapping.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

/**
* Protocol that defines a Mapper used to map one object to another.
*/
protocol Mapping {
func map<T: Mappable>(_ object: T) throws -> T.T
}
3 changes: 3 additions & 0 deletions WalletLibrary/WalletLibrary/Requests/Contract/Contract.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
*/
public struct Contract {

/// Root of Trust such as Linked Domain Verified for the request.
public let rootOfTrust: RootOfTrust

/// information to describe Verified IDs required for issuance.
public let verifiedIdRequirements: [VerifiedIdRequirement]

Expand Down
13 changes: 8 additions & 5 deletions WalletLibrary/WalletLibrary/Requests/IssuanceRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,17 @@ public struct IssuanceRequest: Request {
public let credentialIssuerMetadata: [String]

/// A list of contracts that can be used to issue the verified id.
public let contracts: [Contract]
public internal(set) var contracts: [Contract]

/// Optional pin requirements needed to display a pin for the request.
/// The optional pin requirements needed to display a pin for the request.
public let pinRequirements: PinRequirement?

/// Credential format data that describes requested verified id accepted formats.
let credentialFormats: [CredentialFormat]
/// The credential format data that describes requested verified id accepted formats.
let credentialFormats: [CredentialFormat]?

/// the state that is sent back with issuance completion response.
/// The state that is sent back with issuance completion response.
let state: String

/// The optional raw representation of the request.
let raw: String?
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,19 @@
/**
* Information to describe an access token required for a Verified Id issuance flow.
*/
public struct AccessTokenRequirement {
/// id of the requirement.
let id: String
public struct AccessTokenRequirement: Equatable {

/// if the requirement should be encrypted.
/// If the requirement should be encrypted.
let encrypted: Bool

/// if the requirement is required or not.
/// If the requirement is required or not.
public let required: Bool

/// The configuration url to get Access Token through an authentication library.
public let configuration: String

/// The client id used to get the access token through an authentication library.
public let clientId: String
/// The optional client id used to get the access token through an authentication library.
public let clientId: String?

/// The resource id used to get the access token through an authentication library.
public let resourceId: String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
*/
public struct CredentialFormat {

/// the format of the verified Id requested such as jwt-vc.
/// The format of the verified Id requested such as jwt-vc.
public let format: String

/// types of the requested verified Id.
/// The types of the requested verified Id.
public let types: [String]
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* Parameters used for an Issuance during Presentation flow
* to define information needed for the issuance of the requested Verified Id.
*/
public struct CredentialIssuanceParams {
public struct CredentialIssuanceParams: Equatable {

/// A list of issuers that are accepted.
public let acceptedIssuers: [String]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,12 @@
/**
* Information to describe an id token required for a Verified Id issuance flow.
*/
public struct IdTokenRequirement {
/// id of the requirement.
let id: String

/// if the requirement should be encrypted.
public struct IdTokenRequirement: Equatable {

/// If the requirement should be encrypted.
let encrypted: Bool

/// if the requirement is required or not.
/// If the requirement is required or not.
public let required: Bool

/// The configuration url to get id token through an authentication library.
Expand All @@ -31,6 +29,6 @@ public struct IdTokenRequirement {
/// The nonce acts as an extra level of security and is used as an additional property
/// within the id token request through an authentication library. The nonce will be placed within
/// the id token retrieved and can be used for validation during an issuance request to an issuance service.
public let nonce: String
public internal(set) var nonce: String? = nil
}

Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
*/
public struct PinRequirement {

/// the length of the pin to display.
public let length: String
/// The length of the pin to display.
public let length: Int

/// the type of the pin such as alphanumeric or numeric.
/// The type of the pin such as alphanumeric or numeric.
public let type: String
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,15 @@
/**
* Information to describe a self attested claim required for a Verified Id issuance flow.
*/
public struct SelfAttestedClaimRequirement {
/// id of the requirement.
let id: String
public struct SelfAttestedClaimRequirement: Equatable {

/// if the requirement should be encrypted.
/// If the requirement should be encrypted.
let encrypted: Bool

/// if the requirement is required or not.
/// If the requirement is required or not.
public let required: Bool

/// the claim requested.
/// The claim requested.
public let claim: String
}

Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,24 @@
/**
* Information to describe Verified IDs required.
*/
public struct VerifiedIdRequirement {
/// id of the requirement.
let id: String
public struct VerifiedIdRequirement: Equatable {

/// If requirement must be encrypted.
let encrypted: Bool

/// if the requirement is required or not.
/// If the requirement is required or not.
public let required: Bool

/// the type of the verified Id required.
/// The type of the verified Id required.
public let types: [String]

/// accepted issuers for verified Id required.
/// The accepted issuers for verified Id required.
public let acceptedIssuers: [String]

/// the purpose for the verified Id, developer can display to the user if desired.
/// The purpose for the verified Id, developer can display to the user if desired.
public let purpose: String?

/// optional property for info needed for issuance during presentation flow.
/// An optional property for information needed for issuance during presentation flow.
public let credentialIssuanceParams: CredentialIssuanceParams?

/// TODO: helper method that returns verified id that match the requirement from a list of verified ids.
Expand Down
17 changes: 17 additions & 0 deletions WalletLibrary/WalletLibrary/Requests/RootOfTrust.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

/**
* Root of Trust such as Linked Domain Verified for the request.
*/
public struct RootOfTrust {

/// Whether root of trust is verified or not (for example, if the linked domain check succeeded.
public let verified: Bool

/// The source of the root of trust (could be the well-known endpoint url or a hub perhaps).
public let source: String?

}
Loading