Sources/OrgApp/TrustStore.swift
29 lines · 1192 bytes
1import CryptoKit
2import Foundation
3
4/// Code the user agreed to run (Babel blocks, Lisp table formulas), keyed by file and content
5/// hash: a change to the code asks again, as `org-confirm-babel-evaluate` would.
6@MainActor
7public final class TrustStore {
8 private let file: URL
9 private var hashes: Set<String>
10
11 public init(file: URL = WorkspaceModel.defaultDirectory.appendingPathComponent("trusted.json")) {
12 self.file = file
13 hashes = (try? JSONDecoder().decode(Set<String>.self, from: Data(contentsOf: file))) ?? []
14 }
15
16 static func key(path: String, content: String) -> String {
17 SHA256.hash(data: Data((path + "\u{0}" + content).utf8)).map { String(format: "%02x", $0) }.joined()
18 }
19
20 public func isTrusted(path: String, content: String) -> Bool {
21 hashes.contains(Self.key(path: path, content: content))
22 }
23
24 public func trust(path: String, content: String) {
25 hashes.insert(Self.key(path: path, content: content))
26 try? FileManager.default.createDirectory(at: file.deletingLastPathComponent(), withIntermediateDirectories: true)
27 try? JSONEncoder().encode(hashes).write(to: file, options: .atomic)
28 }
29}