Move context to new file, add to context if user is authentified
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				continuous-integration/drone/push Build is passing
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	continuous-integration/drone/push Build is passing
				
			This commit is contained in:
		
							parent
							
								
									b20fb5f079
								
							
						
					
					
						commit
						05ca82c4e1
					
				@ -18,8 +18,8 @@ pub struct APVariables {
 | 
				
			|||||||
impl APVariables {
 | 
					impl APVariables {
 | 
				
			||||||
    pub async fn check_session(
 | 
					    pub async fn check_session(
 | 
				
			||||||
        &self,
 | 
					        &self,
 | 
				
			||||||
        session_id: String,
 | 
					        session_id: &str,
 | 
				
			||||||
        user_id: String,
 | 
					        user_id: &str,
 | 
				
			||||||
    ) -> Result<bool> {
 | 
					    ) -> Result<bool> {
 | 
				
			||||||
        let client = reqwest::Client::new();
 | 
					        let client = reqwest::Client::new();
 | 
				
			||||||
        let url = format!("{}/users/{}/sessions", self.endpoint, user_id);
 | 
					        let url = format!("{}/users/{}/sessions", self.endpoint, user_id);
 | 
				
			||||||
 | 
				
			|||||||
@ -29,7 +29,7 @@ macro_rules! find_element {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use diesel::prelude::*;
 | 
					use diesel::prelude::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
pub struct Database {
 | 
					pub struct Database {
 | 
				
			||||||
    conn: Pool<ConnectionManager<PgConnection>>,
 | 
					    conn: Pool<ConnectionManager<PgConnection>>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										49
									
								
								src/graphql/context.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/graphql/context.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					use crate::appwrite::APVariables;
 | 
				
			||||||
 | 
					use crate::db::Database;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use tracing::info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Default, Debug, Clone)]
 | 
				
			||||||
 | 
					pub struct Context {
 | 
				
			||||||
 | 
					    pub db: Database,
 | 
				
			||||||
 | 
					    pub appwrite: APVariables,
 | 
				
			||||||
 | 
					    pub user_auth: bool,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Context {
 | 
				
			||||||
 | 
					    /// HTTP header for a user's session
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// This header `Authorization` must be a single string in the
 | 
				
			||||||
 | 
					    /// form `userId;userSessionId` with `userId` and `userSessionId`
 | 
				
			||||||
 | 
					    /// being variables given by Appwrite to users that are logged in.
 | 
				
			||||||
 | 
					    pub async fn user_auth<'r>(&self, auth_token: Option<&'r str>) -> bool {
 | 
				
			||||||
 | 
					        if let Some(token) = auth_token {
 | 
				
			||||||
 | 
					            let key = token.split(';').collect::<Vec<_>>();
 | 
				
			||||||
 | 
					            if key.len() == 2 {
 | 
				
			||||||
 | 
					                let user_id = key[0];
 | 
				
			||||||
 | 
					                let session_id = key[1];
 | 
				
			||||||
 | 
					                match self.appwrite.check_session(session_id, user_id).await {
 | 
				
			||||||
 | 
					                    Ok(val) => val,
 | 
				
			||||||
 | 
					                    Err(e) => {
 | 
				
			||||||
 | 
					                        info!("Error checking user session: {:?}", e);
 | 
				
			||||||
 | 
					                        false
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                info!("Invalid session key: {}", token);
 | 
				
			||||||
 | 
					                false
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            false
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub async fn attach_auth<'r>(&self, auth_token: Option<&'r str>) -> Self {
 | 
				
			||||||
 | 
					        let mut res = self.clone();
 | 
				
			||||||
 | 
					        res.user_auth = self.user_auth(auth_token).await;
 | 
				
			||||||
 | 
					        res
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl juniper::Context for Context {}
 | 
				
			||||||
@ -1,31 +1,50 @@
 | 
				
			|||||||
 | 
					use rocket::request::{FromRequest, Outcome, Request};
 | 
				
			||||||
use rocket::response::content::RawHtml;
 | 
					use rocket::response::content::RawHtml;
 | 
				
			||||||
use rocket::State;
 | 
					use rocket::State;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use tracing::debug;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use juniper::EmptySubscription;
 | 
					use juniper::EmptySubscription;
 | 
				
			||||||
use juniper_rocket::{GraphQLRequest, GraphQLResponse};
 | 
					use juniper_rocket::{GraphQLRequest, GraphQLResponse};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::appwrite::APVariables;
 | 
					pub mod context;
 | 
				
			||||||
use crate::db::Database;
 | 
					pub use context::Context;
 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Default, Debug)]
 | 
					 | 
				
			||||||
pub struct Context {
 | 
					 | 
				
			||||||
    pub db: Database,
 | 
					 | 
				
			||||||
    pub appwrite: APVariables,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl juniper::Context for Context {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
mod query;
 | 
					 | 
				
			||||||
use query::Query;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
mod mutation;
 | 
					mod mutation;
 | 
				
			||||||
use mutation::Mutation;
 | 
					mod query;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Schema =
 | 
					#[derive(Copy, Clone, Debug)]
 | 
				
			||||||
    juniper::RootNode<'static, Query, Mutation, EmptySubscription<Context>>;
 | 
					pub struct UserAuth<'r>(Option<&'r str>);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug)]
 | 
				
			||||||
 | 
					pub enum UserAuthError {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[rocket::async_trait]
 | 
				
			||||||
 | 
					impl<'r> FromRequest<'r> for UserAuth<'r> {
 | 
				
			||||||
 | 
					    type Error = UserAuthError;
 | 
				
			||||||
 | 
					    async fn from_request(
 | 
				
			||||||
 | 
					        request: &'r Request<'_>,
 | 
				
			||||||
 | 
					    ) -> Outcome<Self, Self::Error> {
 | 
				
			||||||
 | 
					        match request.headers().get_one("Authorization") {
 | 
				
			||||||
 | 
					            None => Outcome::Success(UserAuth(None)),
 | 
				
			||||||
 | 
					            Some(key) => Outcome::Success(UserAuth(Some(key))),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub type Schema = juniper::RootNode<
 | 
				
			||||||
 | 
					    'static,
 | 
				
			||||||
 | 
					    query::Query,
 | 
				
			||||||
 | 
					    mutation::Mutation,
 | 
				
			||||||
 | 
					    EmptySubscription<Context>,
 | 
				
			||||||
 | 
					>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn create_schema() -> Schema {
 | 
					pub fn create_schema() -> Schema {
 | 
				
			||||||
    Schema::new(Query {}, Mutation {}, EmptySubscription::default())
 | 
					    Schema::new(
 | 
				
			||||||
 | 
					        query::Query {},
 | 
				
			||||||
 | 
					        mutation::Mutation {},
 | 
				
			||||||
 | 
					        EmptySubscription::default(),
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[rocket::get("/")]
 | 
					#[rocket::get("/")]
 | 
				
			||||||
@ -37,18 +56,26 @@ pub fn graphiql() -> RawHtml<String> {
 | 
				
			|||||||
#[rocket::get("/graphql?<request>")]
 | 
					#[rocket::get("/graphql?<request>")]
 | 
				
			||||||
pub async fn get_graphql_handler(
 | 
					pub async fn get_graphql_handler(
 | 
				
			||||||
    context: &State<Context>,
 | 
					    context: &State<Context>,
 | 
				
			||||||
 | 
					    user_auth: UserAuth<'_>,
 | 
				
			||||||
    request: GraphQLRequest,
 | 
					    request: GraphQLRequest,
 | 
				
			||||||
    schema: &State<Schema>,
 | 
					    schema: &State<Schema>,
 | 
				
			||||||
) -> GraphQLResponse {
 | 
					) -> GraphQLResponse {
 | 
				
			||||||
    request.execute(schema, context).await
 | 
					    debug!("Current context: {:?}", context);
 | 
				
			||||||
 | 
					    request
 | 
				
			||||||
 | 
					        .execute(schema, &(*context).attach_auth(user_auth.0).await)
 | 
				
			||||||
 | 
					        .await
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[allow(clippy::needless_pass_by_value)]
 | 
					#[allow(clippy::needless_pass_by_value)]
 | 
				
			||||||
#[rocket::post("/graphql", data = "<request>")]
 | 
					#[rocket::post("/graphql", data = "<request>")]
 | 
				
			||||||
pub async fn post_graphql_handler(
 | 
					pub async fn post_graphql_handler(
 | 
				
			||||||
    context: &State<Context>,
 | 
					    context: &State<Context>,
 | 
				
			||||||
 | 
					    user_auth: UserAuth<'_>,
 | 
				
			||||||
    request: GraphQLRequest,
 | 
					    request: GraphQLRequest,
 | 
				
			||||||
    schema: &State<Schema>,
 | 
					    schema: &State<Schema>,
 | 
				
			||||||
) -> GraphQLResponse {
 | 
					) -> GraphQLResponse {
 | 
				
			||||||
    request.execute(schema, context).await
 | 
					    debug!("Current context: {:?}", context);
 | 
				
			||||||
 | 
					    request
 | 
				
			||||||
 | 
					        .execute(schema, &(*context).attach_auth(user_auth.0).await)
 | 
				
			||||||
 | 
					        .await
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user