mirror of
https://github.com/nitnelave/lldap.git
synced 2023-04-12 14:25:13 +00:00
server: update actix, inline juniper-actix
This commit is contained in:
parent
07de6062ca
commit
dce73f91ef
1595
Cargo.lock
generated
1595
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -11,3 +11,6 @@ default-members = ["server"]
|
|||||||
[patch.crates-io.opaque-ke]
|
[patch.crates-io.opaque-ke]
|
||||||
git = 'https://github.com/nitnelave/opaque-ke/'
|
git = 'https://github.com/nitnelave/opaque-ke/'
|
||||||
branch = 'zeroize_1.5'
|
branch = 'zeroize_1.5'
|
||||||
|
|
||||||
|
[patch.crates-io.lber]
|
||||||
|
git = 'https://github.com/inejge/ldap3/'
|
||||||
|
@ -5,14 +5,14 @@ name = "lldap"
|
|||||||
version = "0.4.2-alpha"
|
version = "0.4.2-alpha"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix = "0.12"
|
actix = "0.13"
|
||||||
actix-files = "0.6.0-beta.6"
|
actix-files = "0.6"
|
||||||
actix-http = "=3.0.0-beta.9"
|
actix-http = "3"
|
||||||
actix-rt = "2.2.0"
|
actix-rt = "2"
|
||||||
actix-server = "=2.0.0-beta.5"
|
actix-server = "2"
|
||||||
actix-service = "2.0.0"
|
actix-service = "2"
|
||||||
actix-web = "=4.0.0-beta.8"
|
actix-web = "4.3"
|
||||||
actix-web-httpauth = "0.6.0-beta.2"
|
actix-web-httpauth = "0.8"
|
||||||
anyhow = "*"
|
anyhow = "*"
|
||||||
async-trait = "0.1"
|
async-trait = "0.1"
|
||||||
base64 = "0.13"
|
base64 = "0.13"
|
||||||
@ -25,9 +25,9 @@ futures-util = "*"
|
|||||||
hmac = "0.10"
|
hmac = "0.10"
|
||||||
http = "*"
|
http = "*"
|
||||||
itertools = "0.10.1"
|
itertools = "0.10.1"
|
||||||
juniper = "0.15.10"
|
juniper = "0.15"
|
||||||
juniper_actix = "0.4.0"
|
jwt = "0.16"
|
||||||
jwt = "0.13"
|
lber = "0.4.1"
|
||||||
ldap3_proto = ">=0.3.1"
|
ldap3_proto = ">=0.3.1"
|
||||||
log = "*"
|
log = "*"
|
||||||
orion = "0.16"
|
orion = "0.16"
|
||||||
@ -36,12 +36,12 @@ serde = "*"
|
|||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
sha2 = "0.9"
|
sha2 = "0.9"
|
||||||
thiserror = "*"
|
thiserror = "*"
|
||||||
time = "0.2"
|
time = "0.3"
|
||||||
tokio-rustls = "0.23"
|
tokio-rustls = "0.23"
|
||||||
tokio-stream = "*"
|
tokio-stream = "*"
|
||||||
tokio-util = "0.7.3"
|
tokio-util = "0.7.3"
|
||||||
tracing = "*"
|
tracing = "*"
|
||||||
tracing-actix-web = "0.4.0-beta.7"
|
tracing-actix-web = "0.7"
|
||||||
tracing-attributes = "^0.1.21"
|
tracing-attributes = "^0.1.21"
|
||||||
tracing-log = "*"
|
tracing-log = "*"
|
||||||
rustls-pemfile = "1.0.0"
|
rustls-pemfile = "1.0.0"
|
||||||
@ -97,7 +97,7 @@ version = "^0.1.4"
|
|||||||
|
|
||||||
[dependencies.actix-tls]
|
[dependencies.actix-tls]
|
||||||
features = ["default", "rustls"]
|
features = ["default", "rustls"]
|
||||||
version = "=3.0.0-beta.5"
|
version = "3"
|
||||||
|
|
||||||
[dependencies.image]
|
[dependencies.image]
|
||||||
features = ["jpeg"]
|
features = ["jpeg"]
|
||||||
|
@ -451,14 +451,15 @@ where
|
|||||||
#[instrument(skip_all, level = "debug")]
|
#[instrument(skip_all, level = "debug")]
|
||||||
async fn opaque_register_start<Backend>(
|
async fn opaque_register_start<Backend>(
|
||||||
request: actix_web::HttpRequest,
|
request: actix_web::HttpRequest,
|
||||||
mut payload: actix_web::web::Payload,
|
payload: actix_web::web::Payload,
|
||||||
data: web::Data<AppState<Backend>>,
|
data: web::Data<AppState<Backend>>,
|
||||||
) -> TcpResult<registration::ServerRegistrationStartResponse>
|
) -> TcpResult<registration::ServerRegistrationStartResponse>
|
||||||
where
|
where
|
||||||
Backend: BackendHandler + OpaqueHandler + 'static,
|
Backend: BackendHandler + OpaqueHandler + 'static,
|
||||||
{
|
{
|
||||||
use actix_web::FromRequest;
|
use actix_web::FromRequest;
|
||||||
let validation_result = BearerAuth::from_request(&request, &mut payload.0)
|
let inner_payload = &mut payload.into_inner();
|
||||||
|
let validation_result = BearerAuth::from_request(&request, inner_payload)
|
||||||
.await
|
.await
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|bearer| check_if_token_is_valid(&data, bearer.token()).ok())
|
.and_then(|bearer| check_if_token_is_valid(&data, bearer.token()).ok())
|
||||||
@ -468,7 +469,7 @@ where
|
|||||||
let registration_start_request =
|
let registration_start_request =
|
||||||
web::Json::<registration::ClientRegistrationStartRequest>::from_request(
|
web::Json::<registration::ClientRegistrationStartRequest>::from_request(
|
||||||
&request,
|
&request,
|
||||||
&mut payload.0,
|
inner_payload,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| TcpError::BadRequest(format!("{:#?}", e)))?
|
.map_err(|e| TcpError::BadRequest(format!("{:#?}", e)))?
|
||||||
|
@ -11,10 +11,17 @@ use crate::{
|
|||||||
tcp_server::AppState,
|
tcp_server::AppState,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use actix_web::{web, Error, HttpResponse};
|
use actix_web::FromRequest;
|
||||||
|
use actix_web::HttpMessage;
|
||||||
|
use actix_web::{error::JsonPayloadError, web, Error, HttpRequest, HttpResponse};
|
||||||
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
||||||
use juniper::{EmptySubscription, FieldError, RootNode};
|
use juniper::{
|
||||||
use juniper_actix::{graphiql_handler, graphql_handler, playground_handler};
|
http::{
|
||||||
|
graphiql::graphiql_source, playground::playground_source, GraphQLBatchRequest,
|
||||||
|
GraphQLRequest,
|
||||||
|
},
|
||||||
|
EmptySubscription, FieldError, RootNode, ScalarValue,
|
||||||
|
};
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
pub struct Context<Handler: BackendHandler> {
|
pub struct Context<Handler: BackendHandler> {
|
||||||
@ -100,25 +107,129 @@ pub fn export_schema(opts: ExportGraphQLSchemaOpts) -> anyhow::Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn graphiql_route() -> Result<HttpResponse, Error> {
|
async fn graphiql_route() -> Result<HttpResponse, Error> {
|
||||||
graphiql_handler("/api/graphql", None).await
|
let html = graphiql_source("/api/graphql", None);
|
||||||
|
Ok(HttpResponse::Ok()
|
||||||
|
.content_type("text/html; charset=utf-8")
|
||||||
|
.body(html))
|
||||||
}
|
}
|
||||||
async fn playground_route() -> Result<HttpResponse, Error> {
|
async fn playground_route() -> Result<HttpResponse, Error> {
|
||||||
playground_handler("/api/graphql", None).await
|
let html = playground_source("/api/graphql", None);
|
||||||
|
Ok(HttpResponse::Ok()
|
||||||
|
.content_type("text/html; charset=utf-8")
|
||||||
|
.body(html))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Deserialize, Clone, PartialEq, Debug)]
|
||||||
|
struct GetGraphQLRequest {
|
||||||
|
query: String,
|
||||||
|
#[serde(rename = "operationName")]
|
||||||
|
operation_name: Option<String>,
|
||||||
|
variables: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S> From<GetGraphQLRequest> for GraphQLRequest<S>
|
||||||
|
where
|
||||||
|
S: ScalarValue,
|
||||||
|
{
|
||||||
|
fn from(get_req: GetGraphQLRequest) -> Self {
|
||||||
|
let GetGraphQLRequest {
|
||||||
|
query,
|
||||||
|
operation_name,
|
||||||
|
variables,
|
||||||
|
} = get_req;
|
||||||
|
let variables = variables.map(|s| serde_json::from_str(&s).unwrap());
|
||||||
|
Self::new(query, operation_name, variables)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Actix GraphQL Handler for GET requests
|
||||||
|
pub async fn get_graphql_handler<Query, Mutation, Subscription, CtxT, S>(
|
||||||
|
schema: &juniper::RootNode<'static, Query, Mutation, Subscription, S>,
|
||||||
|
context: &CtxT,
|
||||||
|
req: HttpRequest,
|
||||||
|
) -> Result<HttpResponse, Error>
|
||||||
|
where
|
||||||
|
Query: juniper::GraphQLTypeAsync<S, Context = CtxT>,
|
||||||
|
Query::TypeInfo: Sync,
|
||||||
|
Mutation: juniper::GraphQLTypeAsync<S, Context = CtxT>,
|
||||||
|
Mutation::TypeInfo: Sync,
|
||||||
|
Subscription: juniper::GraphQLSubscriptionType<S, Context = CtxT>,
|
||||||
|
Subscription::TypeInfo: Sync,
|
||||||
|
CtxT: Sync,
|
||||||
|
S: ScalarValue + Send + Sync,
|
||||||
|
{
|
||||||
|
let get_req = web::Query::<GetGraphQLRequest>::from_query(req.query_string())?;
|
||||||
|
let req = GraphQLRequest::from(get_req.into_inner());
|
||||||
|
let gql_response = req.execute(schema, context).await;
|
||||||
|
let body_response = serde_json::to_string(&gql_response)?;
|
||||||
|
let mut response = match gql_response.is_ok() {
|
||||||
|
true => HttpResponse::Ok(),
|
||||||
|
false => HttpResponse::BadRequest(),
|
||||||
|
};
|
||||||
|
Ok(response
|
||||||
|
.content_type("application/json")
|
||||||
|
.body(body_response))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Actix GraphQL Handler for POST requests
|
||||||
|
pub async fn post_graphql_handler<Query, Mutation, Subscription, CtxT, S>(
|
||||||
|
schema: &juniper::RootNode<'static, Query, Mutation, Subscription, S>,
|
||||||
|
context: &CtxT,
|
||||||
|
req: HttpRequest,
|
||||||
|
mut payload: actix_http::Payload,
|
||||||
|
) -> Result<HttpResponse, Error>
|
||||||
|
where
|
||||||
|
Query: juniper::GraphQLTypeAsync<S, Context = CtxT>,
|
||||||
|
Query::TypeInfo: Sync,
|
||||||
|
Mutation: juniper::GraphQLTypeAsync<S, Context = CtxT>,
|
||||||
|
Mutation::TypeInfo: Sync,
|
||||||
|
Subscription: juniper::GraphQLSubscriptionType<S, Context = CtxT>,
|
||||||
|
Subscription::TypeInfo: Sync,
|
||||||
|
CtxT: Sync,
|
||||||
|
S: ScalarValue + Send + Sync,
|
||||||
|
{
|
||||||
|
let req = match req.content_type() {
|
||||||
|
"application/json" => {
|
||||||
|
let body = String::from_request(&req, &mut payload).await?;
|
||||||
|
serde_json::from_str::<GraphQLBatchRequest<S>>(&body)
|
||||||
|
.map_err(JsonPayloadError::Deserialize)
|
||||||
|
}
|
||||||
|
"application/graphql" => {
|
||||||
|
let body = String::from_request(&req, &mut payload).await?;
|
||||||
|
Ok(GraphQLBatchRequest::Single(GraphQLRequest::new(
|
||||||
|
body, None, None,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
_ => Err(JsonPayloadError::ContentType),
|
||||||
|
}?;
|
||||||
|
let gql_batch_response = req.execute(schema, context).await;
|
||||||
|
let gql_response = serde_json::to_string(&gql_batch_response)?;
|
||||||
|
let mut response = match gql_batch_response.is_ok() {
|
||||||
|
true => HttpResponse::Ok(),
|
||||||
|
false => HttpResponse::BadRequest(),
|
||||||
|
};
|
||||||
|
Ok(response.content_type("application/json").body(gql_response))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn graphql_route<Handler: BackendHandler + Clone>(
|
async fn graphql_route<Handler: BackendHandler + Clone>(
|
||||||
req: actix_web::HttpRequest,
|
req: actix_web::HttpRequest,
|
||||||
mut payload: actix_web::web::Payload,
|
payload: actix_web::web::Payload,
|
||||||
data: web::Data<AppState<Handler>>,
|
data: web::Data<AppState<Handler>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
use actix_web::FromRequest;
|
let mut inner_payload = payload.into_inner();
|
||||||
let bearer = BearerAuth::from_request(&req, &mut payload.0).await?;
|
let bearer = BearerAuth::from_request(&req, &mut inner_payload).await?;
|
||||||
let validation_result = check_if_token_is_valid(&data, bearer.token())?;
|
let validation_result = check_if_token_is_valid(&data, bearer.token())?;
|
||||||
let context = Context::<Handler> {
|
let context = Context::<Handler> {
|
||||||
handler: data.backend_handler.clone(),
|
handler: data.backend_handler.clone(),
|
||||||
validation_result,
|
validation_result,
|
||||||
};
|
};
|
||||||
graphql_handler(&schema(), &context, req, payload).await
|
let schema = &schema();
|
||||||
|
let context = &context;
|
||||||
|
match *req.method() {
|
||||||
|
actix_http::Method::POST => post_graphql_handler(schema, context, req, inner_payload).await,
|
||||||
|
actix_http::Method::GET => get_graphql_handler(schema, context, req).await,
|
||||||
|
_ => Err(actix_web::error::UrlGenerationError::ResourceNotFound.into()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn configure_endpoint<Backend>(cfg: &mut web::ServiceConfig)
|
pub fn configure_endpoint<Backend>(cfg: &mut web::ServiceConfig)
|
||||||
|
@ -85,7 +85,10 @@ fn http_config<Backend>(
|
|||||||
server_url,
|
server_url,
|
||||||
mail_options,
|
mail_options,
|
||||||
}))
|
}))
|
||||||
.route("/health", web::get().to(|| HttpResponse::Ok().finish()))
|
.route(
|
||||||
|
"/health",
|
||||||
|
web::get().to(|| async { HttpResponse::Ok().finish() }),
|
||||||
|
)
|
||||||
.service(
|
.service(
|
||||||
web::scope("/auth")
|
web::scope("/auth")
|
||||||
.configure(|cfg| auth_service::configure_server::<Backend>(cfg, enable_password_reset)),
|
.configure(|cfg| auth_service::configure_server::<Backend>(cfg, enable_password_reset)),
|
||||||
@ -165,7 +168,7 @@ where
|
|||||||
let jwt_blacklist = jwt_blacklist.clone();
|
let jwt_blacklist = jwt_blacklist.clone();
|
||||||
let server_url = server_url.clone();
|
let server_url = server_url.clone();
|
||||||
let mail_options = mail_options.clone();
|
let mail_options = mail_options.clone();
|
||||||
HttpServiceBuilder::new()
|
HttpServiceBuilder::default()
|
||||||
.finish(map_config(
|
.finish(map_config(
|
||||||
App::new()
|
App::new()
|
||||||
.wrap(tracing_actix_web::TracingLogger::<CustomRootSpanBuilder>::new())
|
.wrap(tracing_actix_web::TracingLogger::<CustomRootSpanBuilder>::new())
|
||||||
|
Loading…
Reference in New Issue
Block a user