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