Skip to content

Commit 5e683d3

Browse files
committed
refactor: add attestation middleware
Signed-off-by: Gustavo Inacio <[email protected]>
1 parent 47a0bf3 commit 5e683d3

File tree

2 files changed

+96
-0
lines changed

2 files changed

+96
-0
lines changed

crates/service/src/middleware.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright 2023-, Edge & Node, GraphOps, and Semiotic Labs.
22
// SPDX-License-Identifier: Apache-2.0
33

4+
mod attestation;
45
pub mod auth;
56
mod inject_allocation;
67
mod inject_attestation_signer;
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// Copyright 2023-, Edge & Node, GraphOps, and Semiotic Labs.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
use std::string::FromUtf8Error;
5+
6+
use axum::{
7+
body::to_bytes,
8+
extract::Request,
9+
middleware::Next,
10+
response::{IntoResponse, Response},
11+
};
12+
use reqwest::StatusCode;
13+
use serde::Serialize;
14+
use thegraph_core::Attestation;
15+
16+
use indexer_attestation::AttestationSigner;
17+
18+
#[derive(Clone)]
19+
pub enum AttestationInput {
20+
Attestable { req: String },
21+
NotAttestable,
22+
}
23+
24+
#[derive(Debug, Serialize)]
25+
pub struct IndexerResponsePayload {
26+
#[serde(rename = "graphQLResponse")]
27+
graphql_response: String,
28+
attestation: Option<Attestation>,
29+
}
30+
31+
/// check if the query can be attestable generates attestation
32+
/// executes query -> return subgraph response: (string, attestable (bool))
33+
/// if attestable && allocation id:
34+
/// - look for signer
35+
/// - create attestation
36+
/// - return response with attestation
37+
/// else:
38+
/// - return with no attestation
39+
///
40+
/// Required AttestationSigner
41+
pub async fn attestation_middleware(
42+
request: Request,
43+
next: Next,
44+
) -> Result<Response, AttestationError> {
45+
let signer = request
46+
.extensions()
47+
.get::<AttestationSigner>()
48+
.cloned()
49+
.ok_or(AttestationError::CouldNotFindSigner)?;
50+
51+
let (parts, graphql_response) = next.run(request).await.into_parts();
52+
let attestation_response = parts.extensions.get::<AttestationInput>();
53+
let bytes = to_bytes(graphql_response, usize::MAX).await?;
54+
let res = String::from_utf8(bytes.into())?;
55+
56+
let attestation = match attestation_response {
57+
Some(AttestationInput::Attestable { req }) => Some(signer.create_attestation(req, &res)),
58+
_ => None,
59+
};
60+
61+
Ok(Response::new(
62+
serde_json::to_string(&IndexerResponsePayload {
63+
graphql_response: res,
64+
attestation,
65+
})?
66+
.into(),
67+
))
68+
}
69+
70+
#[derive(thiserror::Error, Debug)]
71+
pub enum AttestationError {
72+
#[error("Could not find signer for allocation")]
73+
CouldNotFindSigner,
74+
75+
#[error("There was an AxumError: {0}")]
76+
AxumError(#[from] axum::Error),
77+
78+
#[error("There was an error converting the response to UTF-8 string: {0}")]
79+
FromUtf8Error(#[from] FromUtf8Error),
80+
81+
#[error("there was an error while serializing the response: {0}")]
82+
SerializationError(#[from] serde_json::Error),
83+
}
84+
85+
impl IntoResponse for AttestationError {
86+
fn into_response(self) -> Response {
87+
match self {
88+
AttestationError::CouldNotFindSigner
89+
| AttestationError::AxumError(_)
90+
| AttestationError::FromUtf8Error(_)
91+
| AttestationError::SerializationError(_) => StatusCode::INTERNAL_SERVER_ERROR,
92+
}
93+
.into_response()
94+
}
95+
}

0 commit comments

Comments
 (0)