53 lines
1.5 KiB
Swift
53 lines
1.5 KiB
Swift
import Foundation
|
|
|
|
public final class FileCredentialStore: @unchecked Sendable, CredentialStore {
|
|
private struct FileModel: Codable {
|
|
var credentials: [String: String] = [:]
|
|
}
|
|
|
|
private let location: URL
|
|
private let lock = NSLock()
|
|
private var fileModel = FileModel()
|
|
|
|
public init(location: URL) {
|
|
self.location = location
|
|
lock.withLock {
|
|
if let data = try? Data(contentsOf: location),
|
|
let decoded = try? JSONDecoder().decode(FileModel.self, from: data) {
|
|
fileModel = decoded
|
|
}
|
|
}
|
|
}
|
|
|
|
public func get(instanceID: UUID) throws -> String? {
|
|
lock.withLock {
|
|
fileModel.credentials[instanceID.uuidString]
|
|
}
|
|
}
|
|
|
|
public func set(instanceID: UUID, password: String) throws {
|
|
try lock.withLock {
|
|
fileModel.credentials[instanceID.uuidString] = password
|
|
try write()
|
|
}
|
|
}
|
|
|
|
public func remove(instanceID: UUID) throws {
|
|
try lock.withLock {
|
|
fileModel.credentials.removeValue(forKey: instanceID.uuidString)
|
|
try write()
|
|
}
|
|
}
|
|
|
|
private func write() throws {
|
|
let encoder = JSONEncoder()
|
|
encoder.outputFormatting = [.sortedKeys]
|
|
let data = try encoder.encode(fileModel)
|
|
try data.write(to: location, options: [.atomic, .completeFileProtection])
|
|
try FileManager.default.setAttributes(
|
|
[.posixPermissions: 0o600],
|
|
ofItemAtPath: location.path
|
|
)
|
|
}
|
|
}
|