1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
import Foundation
/// A per-repository deploy key (git.sr.ht `SSHKey` under `Repository.deployKeys`).
struct RepositoryDeployKey: Decodable, Sendable, Identifiable, Hashable {
let rid: String
let keyType: String
let fingerprintSHA256: String
let comment: String?
let access: AccessMode
var id: String { rid }
}
private struct DeployKeysQueryResponse: Decodable, Sendable {
let repository: DeployKeysRepository?
}
private struct DeployKeysRepository: Decodable, Sendable {
let deployKeys: DeployKeysPage
}
private struct DeployKeysPage: Decodable, Sendable {
let results: [RepositoryDeployKey]
}
/// `createDeployKey`'s response returns an empty `access` (the stored value is
/// correct — the list query reports it), so we select only `rid` here and let
/// callers reload rather than decode the partial key.
private struct CreateDeployKeyResponse: Decodable, Sendable {}
/// Delete returns the removed key; only success matters here.
private struct DeleteDeployKeyResponse: Decodable, Sendable {}
/// Deploy keys are a git.sr.ht capability (`createDeployKey` / `deleteDeployKey`),
/// owner-only, alongside repository ACLs.
struct RepositoryDeployKeyService: Sendable {
private let client: SRHTClient
init(client: SRHTClient) {
self.client = client
}
func fetchDeployKeys(repositoryRid: String) async throws -> [RepositoryDeployKey] {
let response = try await client.execute(
service: .git,
query: Self.deployKeysQuery,
variables: ["rid": repositoryRid],
responseType: DeployKeysQueryResponse.self
)
return response.repository?.deployKeys.results ?? []
}
func createDeployKey(repositoryRid: String, mode: AccessMode, key: String) async throws {
_ = try await client.execute(
service: .git,
query: Self.createDeployKeyMutation,
variables: ["repo": repositoryRid, "mode": mode.rawValue, "key": key],
responseType: CreateDeployKeyResponse.self
)
}
func deleteDeployKey(rid: String) async throws {
_ = try await client.execute(
service: .git,
query: Self.deleteDeployKeyMutation,
variables: ["rid": rid],
responseType: DeleteDeployKeyResponse.self
)
}
}
private extension RepositoryDeployKeyService {
static let deployKeysQuery = """
query repositoryDeployKeys($rid: ID!) {
repository(rid: $rid) {
deployKeys {
results {
rid
keyType
fingerprintSHA256
comment
access
}
}
}
}
"""
static let createDeployKeyMutation = """
mutation createDeployKey($repo: ID!, $mode: AccessMode!, $key: String!) {
createDeployKey(repo: $repo, mode: $mode, key: $key) { rid }
}
"""
static let deleteDeployKeyMutation = """
mutation deleteDeployKey($rid: ID!) {
deleteDeployKey(rid: $rid) { rid }
}
"""
}
|