diff --git a/swift/ios/Generated/tcfs_file_provider.swift b/swift/ios/Generated/tcfs_file_provider.swift index 185ab39..5f1cd95 100644 --- a/swift/ios/Generated/tcfs_file_provider.swift +++ b/swift/ios/Generated/tcfs_file_provider.swift @@ -563,8 +563,10 @@ public protocol TcfsProviderHandleProtocol : AnyObject { /** * Process a device enrollment invite (from QR code or deep link). + * + * Returns credentials extracted from the invite for auto-configuration. */ - func processEnrollmentInvite(inviteData: String) throws -> AuthResult + func processEnrollmentInvite(inviteData: String) throws -> EnrollmentResult /** * Upload a local file to remote storage. @@ -756,9 +758,11 @@ open func listItems(path: String)throws -> [FileItem] { /** * Process a device enrollment invite (from QR code or deep link). + * + * Returns credentials extracted from the invite for auto-configuration. */ -open func processEnrollmentInvite(inviteData: String)throws -> AuthResult { - return try FfiConverterTypeAuthResult.lift(try rustCallWithError(FfiConverterTypeProviderError.lift) { +open func processEnrollmentInvite(inviteData: String)throws -> EnrollmentResult { + return try FfiConverterTypeEnrollmentResult.lift(try rustCallWithError(FfiConverterTypeProviderError.lift) { uniffi_tcfs_file_provider_fn_method_tcfsproviderhandle_process_enrollment_invite(self.uniffiClonePointer(), FfiConverterString.lower(inviteData),$0 ) @@ -908,6 +912,149 @@ public func FfiConverterTypeAuthResult_lower(_ value: AuthResult) -> RustBuffer } +/** + * Result of a device enrollment via invite. + * + * Contains all credentials needed to configure the new device. + */ +public struct EnrollmentResult { + public var success: Bool + public var errorMessage: String + public var deviceId: String + public var storageEndpoint: String + public var storageBucket: String + public var accessKey: String + public var s3Secret: String + public var remotePrefix: String + public var encryptionPassphrase: String + public var encryptionSalt: String + public var sessionToken: String + + // Default memberwise initializers are never public by default, so we + // declare one manually. + public init(success: Bool, errorMessage: String, deviceId: String, storageEndpoint: String, storageBucket: String, accessKey: String, s3Secret: String, remotePrefix: String, encryptionPassphrase: String, encryptionSalt: String, sessionToken: String) { + self.success = success + self.errorMessage = errorMessage + self.deviceId = deviceId + self.storageEndpoint = storageEndpoint + self.storageBucket = storageBucket + self.accessKey = accessKey + self.s3Secret = s3Secret + self.remotePrefix = remotePrefix + self.encryptionPassphrase = encryptionPassphrase + self.encryptionSalt = encryptionSalt + self.sessionToken = sessionToken + } +} + + + +extension EnrollmentResult: Equatable, Hashable { + public static func ==(lhs: EnrollmentResult, rhs: EnrollmentResult) -> Bool { + if lhs.success != rhs.success { + return false + } + if lhs.errorMessage != rhs.errorMessage { + return false + } + if lhs.deviceId != rhs.deviceId { + return false + } + if lhs.storageEndpoint != rhs.storageEndpoint { + return false + } + if lhs.storageBucket != rhs.storageBucket { + return false + } + if lhs.accessKey != rhs.accessKey { + return false + } + if lhs.s3Secret != rhs.s3Secret { + return false + } + if lhs.remotePrefix != rhs.remotePrefix { + return false + } + if lhs.encryptionPassphrase != rhs.encryptionPassphrase { + return false + } + if lhs.encryptionSalt != rhs.encryptionSalt { + return false + } + if lhs.sessionToken != rhs.sessionToken { + return false + } + return true + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(success) + hasher.combine(errorMessage) + hasher.combine(deviceId) + hasher.combine(storageEndpoint) + hasher.combine(storageBucket) + hasher.combine(accessKey) + hasher.combine(s3Secret) + hasher.combine(remotePrefix) + hasher.combine(encryptionPassphrase) + hasher.combine(encryptionSalt) + hasher.combine(sessionToken) + } +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public struct FfiConverterTypeEnrollmentResult: FfiConverterRustBuffer { + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> EnrollmentResult { + return + try EnrollmentResult( + success: FfiConverterBool.read(from: &buf), + errorMessage: FfiConverterString.read(from: &buf), + deviceId: FfiConverterString.read(from: &buf), + storageEndpoint: FfiConverterString.read(from: &buf), + storageBucket: FfiConverterString.read(from: &buf), + accessKey: FfiConverterString.read(from: &buf), + s3Secret: FfiConverterString.read(from: &buf), + remotePrefix: FfiConverterString.read(from: &buf), + encryptionPassphrase: FfiConverterString.read(from: &buf), + encryptionSalt: FfiConverterString.read(from: &buf), + sessionToken: FfiConverterString.read(from: &buf) + ) + } + + public static func write(_ value: EnrollmentResult, into buf: inout [UInt8]) { + FfiConverterBool.write(value.success, into: &buf) + FfiConverterString.write(value.errorMessage, into: &buf) + FfiConverterString.write(value.deviceId, into: &buf) + FfiConverterString.write(value.storageEndpoint, into: &buf) + FfiConverterString.write(value.storageBucket, into: &buf) + FfiConverterString.write(value.accessKey, into: &buf) + FfiConverterString.write(value.s3Secret, into: &buf) + FfiConverterString.write(value.remotePrefix, into: &buf) + FfiConverterString.write(value.encryptionPassphrase, into: &buf) + FfiConverterString.write(value.encryptionSalt, into: &buf) + FfiConverterString.write(value.sessionToken, into: &buf) + } +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeEnrollmentResult_lift(_ buf: RustBuffer) throws -> EnrollmentResult { + return try FfiConverterTypeEnrollmentResult.lift(buf) +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypeEnrollmentResult_lower(_ value: EnrollmentResult) -> RustBuffer { + return FfiConverterTypeEnrollmentResult.lower(value) +} + + /** * A file item returned by directory enumeration. */ @@ -1679,7 +1826,7 @@ private var initializationResult: InitializationResult = { if (uniffi_tcfs_file_provider_checksum_method_tcfsproviderhandle_list_items() != 37548) { return InitializationResult.apiChecksumMismatch } - if (uniffi_tcfs_file_provider_checksum_method_tcfsproviderhandle_process_enrollment_invite() != 12693) { + if (uniffi_tcfs_file_provider_checksum_method_tcfsproviderhandle_process_enrollment_invite() != 53679) { return InitializationResult.apiChecksumMismatch } if (uniffi_tcfs_file_provider_checksum_method_tcfsproviderhandle_upload_file() != 28793) { diff --git a/swift/ios/HostApp/HostApp.swift b/swift/ios/HostApp/HostApp.swift index c36ceeb..9bae433 100644 --- a/swift/ios/HostApp/HostApp.swift +++ b/swift/ios/HostApp/HostApp.swift @@ -384,6 +384,30 @@ struct ContentView: View { } } } + + Section("Build") { + HStack { + Text("Version") + Spacer() + Text(Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "?") + .foregroundColor(.secondary) + .font(.system(.caption, design: .monospaced)) + } + HStack { + Text("Build") + Spacer() + Text(Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "?") + .foregroundColor(.secondary) + .font(.system(.caption, design: .monospaced)) + } + HStack { + Text("Commit") + Spacer() + Text(Bundle.main.infoDictionary?["GITCommitSHA"] as? String ?? "dev") + .foregroundColor(.secondary) + .font(.system(.caption, design: .monospaced)) + } + } } .navigationTitle("TCFS") } diff --git a/swift/ios/Scripts/xcode-pipeline.sh b/swift/ios/Scripts/xcode-pipeline.sh index ca8099b..2c594a6 100755 --- a/swift/ios/Scripts/xcode-pipeline.sh +++ b/swift/ios/Scripts/xcode-pipeline.sh @@ -50,6 +50,13 @@ fi # ── Step 1: Generate Xcode project ─────────────────────────────────────── if ! $SKIP_ARCHIVE; then + echo "" + echo "==> Stamping git SHA..." + GIT_SHA=$(cd "$REPO_ROOT" && git rev-parse --short HEAD 2>/dev/null || echo "unknown") + # Patch GIT_COMMIT_SHA in project.yml so xcodegen bakes it into the build settings + sed -i '' "s/GIT_COMMIT_SHA: .*/GIT_COMMIT_SHA: \"$GIT_SHA\"/" "$IOS_DIR/project.yml" + echo " SHA: $GIT_SHA" + echo "" echo "==> Generating Xcode project..." cd "$IOS_DIR" diff --git a/swift/ios/project.yml b/swift/ios/project.yml index 45f8adb..125bab7 100644 --- a/swift/ios/project.yml +++ b/swift/ios/project.yml @@ -12,8 +12,9 @@ settings: CODE_SIGN_STYLE: Manual CODE_SIGN_IDENTITY: "Apple Distribution: John Sullivan (QP994XQKNH)" SWIFT_VERSION: "5.10" - MARKETING_VERSION: "0.9.3" - CURRENT_PROJECT_VERSION: "7" + MARKETING_VERSION: "0.9.4" + CURRENT_PROJECT_VERSION: "8" + GIT_COMMIT_SHA: "dev" targets: TCFS: @@ -32,6 +33,7 @@ targets: CFBundleVersion: "$(CURRENT_PROJECT_VERSION)" UILaunchScreen: {} ITSAppUsesNonExemptEncryption: false + GITCommitSHA: "$(GIT_COMMIT_SHA)" NSAppTransportSecurity: NSAllowsLocalNetworking: true NSAllowsArbitraryLoads: true