diff --git a/Sources/CertLogic/CertLogic.swift b/Sources/CertLogic/CertLogic.swift index 95343a0..0a956ac 100644 --- a/Sources/CertLogic/CertLogic.swift +++ b/Sources/CertLogic/CertLogic.swift @@ -40,7 +40,7 @@ final public class CertLogicEngine { self.payloadJSON = JSON(parseJSON: payload) var result: [ValidationResult] = [] - let rulesItems = getListOfRulesFor(external: external, issuerCountryCode: external.issueCountryCode) + let rulesItems = getListOfRulesFor(external: external, issuerCountryCode: external.issuerCountryCode) if(rules.count == 0) { result.append(ValidationResult(rule: nil, result: .passed, validationErrors: nil)) return result @@ -137,23 +137,28 @@ final public class CertLogicEngine { rule.region == nil } } + + let groupedGeneralRulesWithInvalidation = generalRulesWithInvalidation.group(by: \.identifier) + let groupedGeneralRulesWithAcceptence = generalRulesWithAcceptence.group(by: \.identifier) - //General Rule with Acceptence type and max Version number - if generalRulesWithAcceptence.count > 0 { - if let maxRules = generalRulesWithAcceptence.max(by: { (ruleOne, ruleTwo) -> Bool in - return ruleOne.versionInt < ruleTwo.versionInt - }) { - returnedRulesItems.append( maxRules) - } + //General Rule with Acceptence type and max Version number grouped by Identifier + groupedGeneralRulesWithInvalidation.keys.forEach { key in + let rules = groupedGeneralRulesWithInvalidation[key] + if let maxRules = rules?.max(by: { (ruleOne, ruleTwo) -> Bool in + return ruleOne.versionInt < ruleTwo.versionInt + }) { + returnedRulesItems.append( maxRules) + } } - //General Rule with Invalidation type and max Version number - if generalRulesWithInvalidation.count > 0 { - if let maxRules = generalRulesWithInvalidation.max(by: { (ruleOne, ruleTwo) -> Bool in - return ruleOne.versionInt < ruleTwo.versionInt - }) { - returnedRulesItems.append( maxRules) - } + groupedGeneralRulesWithAcceptence.keys.forEach { key in + let rules = groupedGeneralRulesWithAcceptence[key] + if let maxRules = rules?.max(by: { (ruleOne, ruleTwo) -> Bool in + return ruleOne.versionInt < ruleTwo.versionInt + }) { + returnedRulesItems.append( maxRules) + } } + var certTypeRulesWithAcceptence = rules.filter { rule in return rule.countryCode.lowercased() == external.countryCode.lowercased() && rule.ruleType == .acceptence && rule.certificateFullType == external.certificationType && external.validationClock >= rule.validFromDate && external.validationClock <= rule.validToDate } @@ -180,22 +185,26 @@ final public class CertLogicEngine { } } - //Rule with CertificationType with Acceptence type and max Version number - if certTypeRulesWithAcceptence.count > 0 { - if let maxRules = certTypeRulesWithAcceptence.max(by: { (ruleOne, ruleTwo) -> Bool in - return ruleOne.versionInt < ruleTwo.versionInt - }) { - returnedRulesItems.append( maxRules) - } + let groupedCertTypeRulesWithAcceptence = certTypeRulesWithAcceptence.group(by: \.identifier) + let groupedCertTypeRulesWithInvalidation = certTypeRulesWithInvalidation.group(by: \.identifier) + + groupedCertTypeRulesWithAcceptence.keys.forEach { key in + let rules = groupedCertTypeRulesWithAcceptence[key] + if let maxRules = rules?.max(by: { (ruleOne, ruleTwo) -> Bool in + return ruleOne.versionInt < ruleTwo.versionInt + }) { + returnedRulesItems.append( maxRules) + } } - //Rule with CertificationType with Invalidation type and max Version number - if certTypeRulesWithInvalidation.count > 0 { - if let maxRules = certTypeRulesWithInvalidation.max(by: { (ruleOne, ruleTwo) -> Bool in - return ruleOne.versionInt < ruleTwo.versionInt - }) { - returnedRulesItems.append( maxRules) - } + groupedCertTypeRulesWithInvalidation.keys.forEach { key in + let rules = groupedCertTypeRulesWithInvalidation[key] + if let maxRules = rules?.max(by: { (ruleOne, ruleTwo) -> Bool in + return ruleOne.versionInt < ruleTwo.versionInt + }) { + returnedRulesItems.append( maxRules) + } } + return returnedRulesItems } @@ -246,7 +255,7 @@ final public class CertLogicEngine { if external.certificationType == .recovery { section = Constants.recoveryEntry } - if external.certificationType == .vacctination { + if external.certificationType == .vaccination { section = Constants.vaccinationEntry } if external.certificationType == .test { @@ -263,7 +272,7 @@ final public class CertLogicEngine { if external.certificationType == .recovery { section = Constants.payloadRecoveryEntry } - if external.certificationType == .vacctination { + if external.certificationType == .vaccination { section = Constants.payloadVaccinationEntry } if external.certificationType == .test { diff --git a/Sources/CertLogic/ExternalParameter.swift b/Sources/CertLogic/ExternalParameter.swift index d1988a0..96a60f0 100644 --- a/Sources/CertLogic/ExternalParameter.swift +++ b/Sources/CertLogic/ExternalParameter.swift @@ -14,7 +14,7 @@ public class ExternalParameter: Codable { public var validationClock: Date public var valueSets: Dictionary public var countryCode: String - public var issueCountryCode: String + public var issuerCountryCode: String public var exp: Date public var iat: Date public var certificationType: CertificateType = .general @@ -22,7 +22,7 @@ public class ExternalParameter: Codable { public var region: String? enum CodingKeys: String, CodingKey { - case validationClock, valueSets, countryCode, exp, iat, issueCountryCode, kid, region + case validationClock, valueSets, countryCode, exp, iat, issuerCountryCode, kid, region } public init(validationClock: Date, @@ -31,16 +31,18 @@ public class ExternalParameter: Codable { exp: Date, iat: Date, certificationType: CertificateType, - issueCountryCode: String, - region: String? = nil) { + issuerCountryCode: String, + region: String? = nil, + kid: String? = nil) { self.validationClock = validationClock self.valueSets = valueSets self.countryCode = countryCode self.exp = exp self.iat = iat self.certificationType = certificationType - self.issueCountryCode = issueCountryCode + self.issuerCountryCode = issuerCountryCode self.region = region + self.kid = kid } required public init(from decoder: Decoder) throws { @@ -50,7 +52,7 @@ public class ExternalParameter: Codable { countryCode = try container.decode(String.self, forKey: .countryCode) exp = try container.decode(Date.self, forKey: .exp) iat = try container.decode(Date.self, forKey: .iat) - issueCountryCode = try container.decode(String.self, forKey: .issueCountryCode) + issuerCountryCode = try container.decode(String.self, forKey: .issuerCountryCode) kid = try? container.decode(String.self, forKey: .kid) region = try? container.decode(String.self, forKey: .region) } diff --git a/Sources/CertLogic/Rule.swift b/Sources/CertLogic/Rule.swift index 2bc9c10..58ee343 100644 --- a/Sources/CertLogic/Rule.swift +++ b/Sources/CertLogic/Rule.swift @@ -17,7 +17,7 @@ public enum RuleType: String { public enum CertificateType: String { case general = "General" - case vacctination = "Vaccination" + case vaccination = "Vaccination" case recovery = "Recovery" case test = "Test" } diff --git a/Sources/CertLogic/Sequence+.swift b/Sources/CertLogic/Sequence+.swift new file mode 100644 index 0000000..fe87048 --- /dev/null +++ b/Sources/CertLogic/Sequence+.swift @@ -0,0 +1,16 @@ +// +// File.swift +// +// +// Created by Alexandr Chernyy on 07.07.2021. +// + +import Foundation + +public extension Sequence { + func group(by keyPath: KeyPath) -> [Key: [Element]] where Key: Hashable { + return Dictionary(grouping: self, by: { + $0[keyPath: keyPath] + }) + } +} diff --git a/Sources/CertLogic/ValidationResult.swift b/Sources/CertLogic/ValidationResult.swift index 3913b20..d932657 100644 --- a/Sources/CertLogic/ValidationResult.swift +++ b/Sources/CertLogic/ValidationResult.swift @@ -9,8 +9,8 @@ import Foundation // MARK: Result type public enum Result: Int { - case passed = 0 - case fail + case fail = 0 + case passed case open }