diff options
| author | Christian Cleberg <[email protected]> | 2026-04-12 22:16:14 -0500 |
|---|---|---|
| committer | Christian Cleberg <[email protected]> | 2026-04-12 22:16:14 -0500 |
| commit | 7a875798fea9321bad2636040d9be2c30bc0fa8f (patch) | |
| tree | b0569f6413454f423c4ddaa6b25307bc987ef81d /Hutch/Networking/RepositoryACLService.swift | |
| parent | 86bcd9452d3107f68aca085e03e69b02667c0dbb (diff) | |
| download | hutch-7a875798fea9321bad2636040d9be2c30bc0fa8f.tar.gz hutch-7a875798fea9321bad2636040d9be2c30bc0fa8f.tar.bz2 hutch-7a875798fea9321bad2636040d9be2c30bc0fa8f.zip | |
feat: add repository acl management
Implements: https://todo.sr.ht/~ccleberg/hutch/39
Implements: https://todo.sr.ht/~ccleberg/hutch/40
Implements: https://todo.sr.ht/~ccleberg/hutch/41
Diffstat (limited to 'Hutch/Networking/RepositoryACLService.swift')
| -rw-r--r-- | Hutch/Networking/RepositoryACLService.swift | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/Hutch/Networking/RepositoryACLService.swift b/Hutch/Networking/RepositoryACLService.swift new file mode 100644 index 0000000..82a7a38 --- /dev/null +++ b/Hutch/Networking/RepositoryACLService.swift @@ -0,0 +1,106 @@ +import Foundation + +protocol RepositoryACLServicing { + func fetchACLs(repositoryRid: String) async throws -> [RepositoryACLEntry] + func upsertACL(repositoryId: Int, entity: String, mode: AccessMode) async throws -> RepositoryACLEntry + func deleteACL(entryId: Int) async throws +} + +private struct RepositoryACLQueryResponse: Decodable, Sendable { + let repository: RepositoryACLQueryRepository? +} + +private struct RepositoryACLQueryRepository: Decodable, Sendable { + let acls: RepositoryACLPage +} + +private struct RepositoryACLPage: Decodable, Sendable { + let results: [RepositoryACLEntry] +} + +private struct RepositoryACLMutationResponse: Decodable, Sendable { + let updateACL: RepositoryACLEntry +} + +private struct RepositoryACLDeleteResponse: Decodable, Sendable { + let deleteACL: RepositoryACLDeletedEntry +} + +private struct RepositoryACLDeletedEntry: Decodable, Sendable { + let id: Int +} + +struct RepositoryACLService: RepositoryACLServicing { + private let client: SRHTClient + private let service: SRHTService + + init(client: SRHTClient, service: SRHTService) { + self.client = client + self.service = service + } + + func fetchACLs(repositoryRid: String) async throws -> [RepositoryACLEntry] { + let response = try await client.execute( + service: service, + query: Self.aclsQuery, + variables: ["rid": repositoryRid], + responseType: RepositoryACLQueryResponse.self + ) + return response.repository?.acls.results ?? [] + } + + func upsertACL(repositoryId: Int, entity: String, mode: AccessMode) async throws -> RepositoryACLEntry { + let response = try await client.execute( + service: service, + query: Self.upsertACLMutation, + variables: [ + "repoId": repositoryId, + "entity": entity, + "mode": mode.rawValue + ], + responseType: RepositoryACLMutationResponse.self + ) + return response.updateACL + } + + func deleteACL(entryId: Int) async throws { + _ = try await client.execute( + service: service, + query: Self.deleteACLMutation, + variables: ["id": entryId], + responseType: RepositoryACLDeleteResponse.self + ) + } +} + +private extension RepositoryACLService { + static let aclsQuery = """ + query repositoryACLs($rid: ID!) { + repository(rid: $rid) { + acls { + results { + id + mode + entity { canonicalName } + } + } + } + } + """ + + static let upsertACLMutation = """ + mutation updateACL($repoId: Int!, $mode: AccessMode!, $entity: String!) { + updateACL(repoId: $repoId, mode: $mode, entity: $entity) { + id + mode + entity { canonicalName } + } + } + """ + + static let deleteACLMutation = """ + mutation deleteACL($id: Int!) { + deleteACL(id: $id) { id } + } + """ +} |
