zixcel_github/
execution.rs1use crate::boundary::{digest, github_name, identifier, reference};
2use crate::{
3 API_RECEIPT_SCHEMA, API_REQUEST_SCHEMA, ConnectorError, GitHubApiReceipt, GitHubApiRequest,
4 GitHubBackend, GitHubBackendReceipt, RequestValidationReport,
5};
6
7const MAX_DOCUMENT_BYTES: usize = 1_048_576;
8
9impl GitHubApiRequest {
10 pub fn validate(&self) -> Result<(), ConnectorError> {
11 if self.schema != API_REQUEST_SCHEMA {
12 return Err(ConnectorError::new(
13 "schema",
14 "unexpected action request schema",
15 ));
16 }
17 identifier("request_id", &self.request_id)?;
18 identifier("operation_id", &self.operation_id)?;
19 reference("connection_ref", &self.connection_ref)?;
20 github_name("owner", &self.owner)?;
21 github_name("repository", &self.repository)?;
22 self.action.validate()
23 }
24}
25
26pub fn parse_api_request_json(source: &[u8]) -> Result<GitHubApiRequest, ConnectorError> {
27 if source.len() > MAX_DOCUMENT_BYTES {
28 return Err(ConnectorError::new("request", "document exceeds 1 MiB"));
29 }
30 let value: GitHubApiRequest = serde_json::from_slice(source)
31 .map_err(|_| ConnectorError::new("request", "invalid closed JSON"))?;
32 value.validate()?;
33 Ok(value)
34}
35
36pub fn validate_api_request(
37 request: &GitHubApiRequest,
38) -> Result<RequestValidationReport, ConnectorError> {
39 request.validate()?;
40 let required = request.action.required_permission();
41 Ok(RequestValidationReport {
42 schema: "zixcel://github/request-validation-result/v1",
43 request_id: request.request_id.clone(),
44 operation_id: request.operation_id.clone(),
45 valid: true,
46 required_permission: required,
47 })
48}
49
50pub fn execute_api_request<B: GitHubBackend>(
51 request: &GitHubApiRequest,
52 backend: &mut B,
53) -> Result<GitHubApiReceipt, ConnectorError> {
54 let report = validate_api_request(request)?;
55 let value = backend.perform(request)?;
56 validate_backend_receipt(&value)?;
57 Ok(GitHubApiReceipt {
58 schema: API_RECEIPT_SCHEMA,
59 request_id: request.request_id.clone(),
60 operation_id: request.operation_id.clone(),
61 owner: request.owner.clone(),
62 repository: request.repository.clone(),
63 permission: report.required_permission,
64 provider_request_id: value.provider_request_id,
65 remote_reference: value.remote_reference,
66 remote_digest_sha256: value.remote_digest_sha256,
67 })
68}
69
70fn validate_backend_receipt(value: &GitHubBackendReceipt) -> Result<(), ConnectorError> {
71 identifier("provider_request_id", &value.provider_request_id)?;
72 reference("remote_reference", &value.remote_reference)?;
73 if let Some(value) = &value.remote_digest_sha256 {
74 digest("remote_digest_sha256", value)?;
75 }
76 Ok(())
77}
78
79pub fn execute_configured_request<B: GitHubBackend>(
81 config: &crate::ConnectorConfig,
82 request: &GitHubApiRequest,
83 backend: &mut B,
84) -> Result<GitHubApiReceipt, ConnectorError> {
85 config.authorize_request(request)?;
86 execute_api_request(request, backend)
87}