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
20 changes: 15 additions & 5 deletions ios/cmuxPackage/Sources/cmuxFeature/MobileAuthComposition.swift
Original file line number Diff line number Diff line change
Expand Up @@ -408,10 +408,17 @@ public struct MobileAuthComposition {
#endif
}

/// - Parameter simulatorSupportDirectory: Where the simulator build keeps
/// its sandboxed token files. Injected so a test can exercise the
/// unresolvable-directory path; production always passes the default.
static func tokenStore(
appNamespace: MobileIOSAppNamespace?,
accessGroup: String?,
legacyProjectID: String
legacyProjectID: String,
simulatorSupportDirectory: URL? = FileManager.default.urls(
for: .applicationSupportDirectory,
in: .userDomainMask
).first
) -> TokenStoreInit {
guard let appNamespace else {
// A malformed or test bundle must not leave StackClientApp without
Expand All @@ -425,10 +432,13 @@ public struct MobileAuthComposition {
// Unsigned simulator apps cannot rely on Keychain entitlements. Keep
// tokens in this simulator app's sandbox so a process restart exercises
// real session restoration. Bundle and Stack project remain isolated.
guard let support = FileManager.default.urls(
for: .applicationSupportDirectory,
in: .userDomainMask
).first else { return .none }
guard let support = simulatorSupportDirectory else {
// Same reasoning as a missing app identity above: .none leaves
// StackClientApp with a NullTokenStore, so the next authenticated
// operation fatalErrors. Losing the session on relaunch is
// recoverable; trapping the process is not.
return .memory
}
let projectComponent = Data(legacyProjectID.utf8).base64EncodedString()
.replacingOccurrences(of: "+", with: "-")
.replacingOccurrences(of: "/", with: "_")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,20 @@ import Testing
}
}

@Test func unresolvableSupportDirectoryFallsBackToMemory() throws {
let namespace = try makeNamespace()
let choice = MobileAuthComposition.tokenStore(
appNamespace: namespace,
accessGroup: nil,
legacyProjectID: "project-a",
simulatorSupportDirectory: nil
)
guard case .memory = choice else {
Issue.record("An unresolvable support directory must not select .none, which traps the SDK")
return
}
}

private func store(
namespace: MobileIOSAppNamespace,
project: String
Expand Down
Loading