Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 3 additions & 1 deletion app/src/bcsc-theme/api/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ class BCSCService {
}

private async handleRequest(config: InternalAxiosRequestConfig): Promise<InternalAxiosRequestConfig> {
this.logger.info(`Handling request for URL: ${String(config.url)}`)
// skip processing if skipBearerAuth is set in the config
if (config.skipBearerAuth) {
return config
Expand All @@ -203,7 +204,8 @@ class BCSCService {
config.headers.set('Authorization', `Bearer ${this.tokens.access_token}`)
}

this.logger.debug(`${String(config.method)}: ${String(config.url)}`, {})
this.logger.debug(`Sending request to ${String(config.url)} with method ${String(config.method)}`, config as any)

return config
}

Expand Down
9 changes: 7 additions & 2 deletions app/src/bcsc-theme/hooks/useInitializeBcscApi.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,14 @@ const useInitializeBcscApi = () => {
const asyncEffect = async () => {
try {
await client.fetchEndpointsAndConfig(client.baseURL)
logger.debug('Fetched BCSC endpoints and configuration', {
baseURL: client.baseURL,
})
} catch (error) {
logger.error('Failed to fetch BCSC endpoints', {
message: error instanceof Error ? error.message : String(error),
})

dispatch({
type: DispatchAction.BANNER_MESSAGES,
payload: [
Expand All @@ -42,8 +46,9 @@ const useInitializeBcscApi = () => {

try {
await registration.register()
logger.debug('BCSC registration successful')
} catch (error) {
logger.error(`Error during registration: ${error}`)
logger.error(`Error during registration.`, error as Error)
}

try {
Expand All @@ -69,7 +74,7 @@ const useInitializeBcscApi = () => {
dispatch({ type: BCDispatchAction.UPDATE_VERIFIED, payload: [true] })
}
} catch (error) {
logger.error(`Error setting API client tokens: ${error}`)
logger.error(`Error setting API client tokens.`, error as Error)
} finally {
setLoading(false)
}
Expand Down
54 changes: 28 additions & 26 deletions packages/bcsc-core/ios/BcscCore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import CryptoKit
import Foundation
import React


enum AccountSecurityMethod: String {
case pinNoDeviceAuth = "app_pin_no_device_authn"
case pinWithDeviceAuth = "app_pin_has_device_authn"
Expand Down Expand Up @@ -33,6 +34,7 @@ enum DeviceInfoKeys {
@objcMembers
@objc(BcscCore)
class BcscCore: NSObject {
let logger = AppLogger(subsystem: Bundle.main.bundleIdentifier ?? "ca.bc.gov.id.servicescard", category: "BcscCore")
static let generalizedOsName = "iOS"
static let provider = "https://idsit.gov.bc.ca/device/"
static let clientName = "BC Services Wallet"
Expand Down Expand Up @@ -144,7 +146,7 @@ class BcscCore: NSObject {
SecItemDelete(query as CFDictionary)
}

print("BcscCore: Keychain cleared for this app.")
logger.log("Keychain cleared for this app.")
}

// MARK: - Public Methods
Expand Down Expand Up @@ -229,60 +231,60 @@ class BcscCore: NSObject {
let baseId = components.joined(separator: "/") // Reconstruct the base part of the ID
let newKeyId = "\(baseId)/\(numericSuffix)"

print(
"BcscCore: generateKeyPair (private) - Latest key found: \(existingTag). Attempting to generate new incremented key with ID: \(newKeyId)"
logger.log(
"generateKeyPair - Latest key found: \(existingTag). Attempting to generate new incremented key with ID: \(newKeyId)"
)
do {
// Assuming default keyType and keySize are handled by KeyPairManager.generateKeyPair or are acceptable.
_ = try keyPairManager.generateKeyPair(withLabel: newKeyId)
print(
"BcscCore: generateKeyPair (private) - Successfully generated new incremented key with ID: \(newKeyId)"
logger.log(
"generateKeyPair - Successfully generated new incremented key with ID: \(newKeyId)"
)
return newKeyId
} catch {
print(
"BcscCore: generateKeyPair (private) - Failed to generate new incremented key with ID \(newKeyId): \(error.localizedDescription)."
logger.error(
"generateKeyPair - Failed to generate new incremented key with ID \(newKeyId): \(error.localizedDescription)."
)
return nil // Failed to generate the specifically requested incremented key.
}
} else {
// Parsing the existing tag failed (e.g., not in expected format or last part not a number).
// Fallback: generate a completely new key using a fresh initial ID pattern.
print(
"BcscCore: generateKeyPair (private) - Could not parse or increment existing key tag: \(existingTag). Attempting to generate a new key with a fresh initial ID pattern."
logger.warning(
"generateKeyPair - Could not parse or increment existing key tag: \(existingTag). Attempting to generate a new key with a fresh initial ID pattern."
)
// Use the same pattern for the new key ID as in the 'no keys found' case for consistency, but with a new UUID.
let freshGeneratedKeyId = "\(BcscCore.provider)/\(UUID().uuidString)/1"
print(
"BcscCore: generateKeyPair (private) - Attempting to generate a new key with ID: \(freshGeneratedKeyId) due to parsing failure of existing key."
logger.log(
"generateKeyPair - Attempting to generate a new key with ID: \(freshGeneratedKeyId) due to parsing failure of existing key."
)
do {
_ = try keyPairManager.generateKeyPair(withLabel: freshGeneratedKeyId)
print(
"BcscCore: generateKeyPair (private) - Successfully generated new key with ID: \(freshGeneratedKeyId) after parsing failure."
logger.log(
"generateKeyPair - Successfully generated new key with ID: \(freshGeneratedKeyId) after parsing failure."
)
return freshGeneratedKeyId
} catch {
print(
"BcscCore: generateKeyPair (private) - Failed to generate new key with ID \(freshGeneratedKeyId) after parsing failure: \(error.localizedDescription)"
logger.error(
"generateKeyPair - Failed to generate new key with ID \(freshGeneratedKeyId) after parsing failure: \(error.localizedDescription)"
)
return nil
}
}
} else {
// No keys found, attempt to generate a new one
print(
"BcscCore: generateKeyPair (private) - No keys found. Attempting to generate a new key with ID: \(initialKeyId)"
logger.log(
"generateKeyPair - No keys found. Attempting to generate a new key with ID: \(initialKeyId)"
)
do {
_ = try keyPairManager.generateKeyPair(withLabel: initialKeyId) // Assuming default keyType and keySize are handled by this method or are acceptable.
print(
"BcscCore: generateKeyPair (private) - Successfully generated new key with ID: \(initialKeyId)"
logger.log(
"generateKeyPair - Successfully generated new key with ID: \(initialKeyId)"
)
return initialKeyId
} catch {
print(
"BcscCore: generateKeyPair (private) - Failed to generate new key with ID \(initialKeyId): \(error.localizedDescription)"
logger.error(
"generateKeyPair - Failed to generate new key with ID \(initialKeyId): \(error.localizedDescription)"
)
return nil
}
Expand Down Expand Up @@ -375,7 +377,7 @@ class BcscCore: NSObject {

// Add any additional claims
for (key, value) in claims {
print(key, value)
logger.log("\(key), \(value)")
builder.claim(name: key as! String, value: value)
}

Expand All @@ -393,7 +395,7 @@ class BcscCore: NSObject {
_ account: NSDictionary, resolve: @escaping RCTPromiseResolveBlock,
reject: @escaping RCTPromiseRejectBlock
) {
print("BcscCore: setAccount called with account: \(account)")
logger.log("setAccount called with account: \(account)")
let accountID = UUID().uuidString
let storage = StorageService()

Expand Down Expand Up @@ -444,7 +446,7 @@ class BcscCore: NSObject {
)

if success {
print("BcscCore: setAccount - Account successfully stored")
logger.log("setAccount - Account successfully stored")
resolve(nil)
} else {
reject("E_ACCOUNT_STORAGE_FAILED", "Failed to store account data", nil)
Expand Down Expand Up @@ -659,7 +661,7 @@ class BcscCore: NSObject {
]

do {
// print("BcscCore: getDynamicClientRegistrationBody - Client Registration Data: \(clientRegistrationData)")
// logger.log("BcscCore: getDynamicClientRegistrationBody - Client Registration Data: \(clientRegistrationData)")
let jsonData = try JSONSerialization.data(withJSONObject: clientRegistrationData, options: [])
let jsonString = String(data: jsonData, encoding: .utf8) ?? "{}"

Expand Down Expand Up @@ -810,7 +812,7 @@ class BcscCore: NSObject {
return // Error already handled in makeSignedJWT
}

print("signedJWT: \(signedJWT)")
logger.log("signedJWT: \(signedJWT)")

// Encrypt the signed JWT with the provided public key
do {
Expand Down
69 changes: 69 additions & 0 deletions packages/bcsc-core/ios/Logger.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import Foundation
import os

struct AppLogger {
private let subsystem: String
private let category: String

@available(iOS 14.0, *)
private var osLogger: os.Logger {
os.Logger(subsystem: subsystem, category: category)
}

private var legacyLogger: OSLog {
OSLog(subsystem: subsystem, category: category)
}

init(subsystem: String, category: String) {
self.subsystem = subsystem
self.category = category
}

func log(_ message: String) {
if #available(iOS 14.0, *) {
osLogger.log("\(message, privacy: .public)")
} else {
os_log("%{public}s", log: legacyLogger, type: .default, message)
}
}

func info(_ message: String) {
if #available(iOS 14.0, *) {
osLogger.info("\(message, privacy: .public)")
} else {
os_log("%{public}s", log: legacyLogger, type: .info, message)
}
}

func debug(_ message: String) {
if #available(iOS 14.0, *) {
osLogger.debug("\(message, privacy: .public)")
} else {
os_log("%{public}s", log: legacyLogger, type: .debug, message)
}
}

func error(_ message: String) {
if #available(iOS 14.0, *) {
osLogger.error("\(message, privacy: .public)")
} else {
os_log("%{public}s", log: legacyLogger, type: .error, message)
}
}

func warning(_ message: String) {
if #available(iOS 14.0, *) {
osLogger.warning("\(message, privacy: .public)")
} else {
os_log("%{public}s", log: legacyLogger, type: .error, message) // .warning is not available, fallback to .error
}
}

func fault(_ message: String) {
if #available(iOS 14.0, *) {
osLogger.fault("\(message, privacy: .public)")
} else {
os_log("%{public}s", log: legacyLogger, type: .fault, message)
}
}
}
Loading
Loading