[INJIMOB-3647] refactor: enhance response structure of credential status check (#2145)

* [INJIMOB-3647] refactor: udpate vc verifier RN module

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3647] refactor: update reverification logic

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3647] refactor: modify status response structure

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3647] refactor: update response resolving of status check in swift bridge

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3647] refactor: update info logs to print status message

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3647] refactor: modify type from map to record

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3647] refactor: remove unnecessary async function

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3647] refactor: Credential summary result structure

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

---------

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>
This commit is contained in:
KiruthikaJeyashankar
2025-11-27 15:33:17 +05:30
committed by GitHub
parent a0b08914e5
commit 5589ceb848
8 changed files with 117 additions and 119 deletions

View File

@@ -29,16 +29,19 @@ class VCVerifierModule: NSObject, RCTBridgeModule {
let verifier = CredentialsVerifier()
let results = try await verifier.getCredentialStatus(credential: credential, format: credentialFormat)
let responseArray = results.map { result in
return [
"status": result.status,
"purpose": result.purpose,
"errorCode": result.error?.errorCode.rawValue,
"errorMessage": result.error?.message,
"statusListVC": result.statusListVC
var response: [String: Any] = [:]
for (purpose, credentialStatusResult) in results {
let error : [String: Any]? = credentialStatusResult.error != nil ? [
"code": credentialStatusResult.error?.errorCode ?? "UNKNOWN_ERROR",
"message": credentialStatusResult.error?.message ?? "An unknown error occurred"
] : nil
response[purpose] = [
"isValid": credentialStatusResult.isValid,
"statusListVC": credentialStatusResult.statusListVC,
"error": error
]
}
resolve(responseArray)
resolve(response)
} catch {
reject("VERIFICATION_FAILED", "Verification threw an error: \(error.localizedDescription)", error)
}

View File

@@ -4,11 +4,11 @@ public struct CredentialsVerifier {
public init() {}
public func getCredentialStatus(credential: String, format: StatusCheckCredentialFormat, statusPurposeList: [String] = []) async throws-> [CredentialStatusResult] {
public func getCredentialStatus(credential: String, format: StatusCheckCredentialFormat, statusPurposeList: [String] = []) async throws-> [String: CredentialStatusResult] {
do {
let verifier = CredentialVerifierFactory().get(format: format)
let credentialStatusArray = try await verifier.checkStatus(credential: credential, statusPurposes: statusPurposeList)
return credentialStatusArray ?? []
let credentialStatuses = try await verifier.checkStatus(credential: credential, statusPurposes: statusPurposeList)
return credentialStatuses ?? [:]
} catch{
throw error
}

View File

@@ -1,5 +1,5 @@
import Foundation
protocol VerifiableCredential {
func checkStatus(credential: String, statusPurposes: [String]?) async throws-> [CredentialStatusResult]?
func checkStatus(credential: String, statusPurposes: [String]?) async throws-> [String: CredentialStatusResult]
}

View File

@@ -4,19 +4,15 @@ import Gzip
// MARK: - Credential Status Result
public struct CredentialStatusResult {
let purpose: String
let status: Int
let valid: Bool
let error: StatusCheckException?
let statusListVC: [String: Any]?
init(purpose: String, status: Int, valid: Bool, error: StatusCheckException?, statusListVC: [String: Any]? = nil) {
self.purpose = purpose
self.status = status
self.valid = valid
self.error = error
self.statusListVC = statusListVC
}
let isValid: Bool
let statusListVC: [String: Any]?
let error: StatusCheckException?
init(isValid: Bool, statusListVC: [String: Any]? = nil, error: StatusCheckException? = nil) {
self.isValid = isValid
self.statusListVC = statusListVC
self.error = error
}
}
// MARK: - Error Types
@@ -24,6 +20,7 @@ public struct CredentialStatusResult {
enum StatusCheckErrorCode: String {
case rangeError = "RANGE_ERROR"
case statusVerificationError = "STATUS_VERIFICATION_ERROR"
case invalidCredentialStatus = "INVALID_CREDENTIAL_STATUS"
case statusRetrievalError = "STATUS_RETRIEVAL_ERROR"
case invalidPurpose = "INVALID_PURPOSE"
case invalidIndex = "INVALID_INDEX"
@@ -33,7 +30,7 @@ enum StatusCheckErrorCode: String {
case unknownError = "UNKNOWN_ERROR"
}
struct StatusCheckException: Error {
public struct StatusCheckException: Error {
let message: String
let errorCode: StatusCheckErrorCode
}
@@ -49,7 +46,7 @@ final class LdpStatusChecker {
self.networkManager = networkManager
}
func getStatuses(credential: String, statusPurposes: [String]? = nil) async throws -> [CredentialStatusResult]? {
func getStatuses(credential: String, statusPurposes: [String]? = nil) async throws -> [String: CredentialStatusResult] {
guard
let data = credential.data(using: .utf8),
let vc = try JSONSerialization.jsonObject(with: data) as? [String: Any]
@@ -58,24 +55,30 @@ final class LdpStatusChecker {
}
let statusField = vc["credentialStatus"]
guard let statusEntries = normalizeStatusField(statusField) else { return nil }
guard let statusEntries = normalizeStatusField(statusField) else { throw StatusCheckException(
message: "No valid credentialStatus entries found",
errorCode: .invalidCredentialStatus
) }
let filteredEntries = filterEntries(statusEntries, statusPurposes)
guard !filteredEntries.isEmpty else { return nil }
var results: [CredentialStatusResult] = []
guard !filteredEntries.isEmpty else {
print("No matching credentialStatus entries found for purposes: \(statusPurposes ?? [])")
return [:]
}
var results: [String: CredentialStatusResult] = [:]
for entry in filteredEntries {
let purpose = (entry["statusPurpose"] as? String)?.lowercased() ?? ""
do {
let result = try await checkStatusEntry(entry: entry, purpose: purpose)
results.append(result)
} catch let error as StatusCheckException {
results.append(.init(purpose: purpose, status: -1, valid: false, error: error))
} catch {
let genericError = StatusCheckException(message: error.localizedDescription, errorCode: .unknownError)
results.append(.init(purpose: purpose, status: -1, valid: false, error: genericError))
}
let purpose = (entry["statusPurpose"] as? String)?.lowercased() ?? ""
do {
let result = try await checkStatusEntry(entry: entry, purpose: purpose)
results[purpose] = result
} catch let error as StatusCheckException {
results[purpose] = CredentialStatusResult(isValid: false, statusListVC: nil, error: error)
} catch {
let genericError = StatusCheckException(message: error.localizedDescription, errorCode: .unknownError)
results[purpose] = CredentialStatusResult(isValid: false, statusListVC: nil, error: genericError)
}
}
return results
}
@@ -171,6 +174,8 @@ final class LdpStatusChecker {
else {
throw StatusCheckException(message: "statusMessage count mismatch", errorCode: .statusVerificationError)
}
print("Status message for purpose '\(purpose): $\(statusMessage)")
}
let bitSet = try decodeEncodedList(encodedList)
@@ -181,7 +186,10 @@ final class LdpStatusChecker {
}
let statusValue = readBits(from: bitSet, start: bitPosition, count: statusSize)
return .init(purpose: purpose, status: statusValue, valid: statusValue == 0, error: nil, statusListVC: statusListVC)
let isValid = (statusValue == 0)
print("Status value for purpose \(purpose) at index \(indexStr): \(statusValue)")
return .init(isValid: isValid, statusListVC: statusListVC, error: nil)
}
private func readBits(from bitSet: [UInt8], start: Int, count: Int) -> Int {

View File

@@ -1,7 +1,7 @@
import Foundation
struct LdpVerifiableCredential: VerifiableCredential {
func checkStatus(credential: String, statusPurposes: [String]?) async throws-> [CredentialStatusResult]? {
func checkStatus(credential: String, statusPurposes: [String]?) async throws-> [String: CredentialStatusResult] {
try await LdpStatusChecker().getStatuses(credential: credential)
}
}