Fragment graphql module, add Appwrite vars to context
This commit is contained in:
parent
34e28384ce
commit
b20fb5f079
@ -26,6 +26,9 @@ uuid = { version = "1.2.2", features = ["v4", "fast-rng", "macro-diagnostics", "
|
|||||||
rocket = "0.5.0-rc.2"
|
rocket = "0.5.0-rc.2"
|
||||||
rocket_cors = { git = "https://github.com/lawliet89/rocket_cors", rev = "c17e814" }
|
rocket_cors = { git = "https://github.com/lawliet89/rocket_cors", rev = "c17e814" }
|
||||||
|
|
||||||
|
# Web requests
|
||||||
|
reqwest = { version = "0.11.13", features = ["serde_json", "json", "gzip"] }
|
||||||
|
|
||||||
# GraphQL
|
# GraphQL
|
||||||
juniper = "0.15.10"
|
juniper = "0.15.10"
|
||||||
juniper_rocket = "0.8.2"
|
juniper_rocket = "0.8.2"
|
||||||
@ -33,3 +36,6 @@ juniper_rocket = "0.8.2"
|
|||||||
# logging
|
# logging
|
||||||
tracing = "0.1.37"
|
tracing = "0.1.37"
|
||||||
tracing-subscriber = "0.3.16"
|
tracing-subscriber = "0.3.16"
|
||||||
|
|
||||||
|
# Error handling
|
||||||
|
color-eyre = "0.6.2"
|
||||||
|
88
src/appwrite.rs
Normal file
88
src/appwrite.rs
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
use color_eyre::eyre::Result;
|
||||||
|
use rocket::serde::Deserialize;
|
||||||
|
|
||||||
|
macro_rules! from_env {
|
||||||
|
($varname:expr) => {
|
||||||
|
std::env::var($varname)
|
||||||
|
.expect(format!("{} must be set!", $varname).as_str())
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq)]
|
||||||
|
pub struct APVariables {
|
||||||
|
pub endpoint: String,
|
||||||
|
pub project: String,
|
||||||
|
pub api_key: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl APVariables {
|
||||||
|
pub async fn check_session(
|
||||||
|
&self,
|
||||||
|
session_id: String,
|
||||||
|
user_id: String,
|
||||||
|
) -> Result<bool> {
|
||||||
|
let client = reqwest::Client::new();
|
||||||
|
let url = format!("{}/users/{}/sessions", self.endpoint, user_id);
|
||||||
|
let response = client
|
||||||
|
.get(url)
|
||||||
|
.header("X-Appwrite-Key", self.api_key.clone())
|
||||||
|
.header("X-Appwrite-Project", self.project.clone())
|
||||||
|
.header("Content-Type", "application/json")
|
||||||
|
.send()
|
||||||
|
.await?
|
||||||
|
.json::<UserSessions>()
|
||||||
|
.await?;
|
||||||
|
Ok(response.sessions.iter().any(|s| s.id == session_id))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for APVariables {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
endpoint: from_env!("APPWRITE_ENDPOINT"),
|
||||||
|
project: from_env!("APPWRITE_PROJECT"),
|
||||||
|
api_key: from_env!("APPWRITE_API_KEY"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug, Clone, PartialEq, Eq, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[serde(crate = "rocket::serde")]
|
||||||
|
struct UserSessions {
|
||||||
|
total: i64,
|
||||||
|
sessions: Vec<Sessions>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug, Clone, PartialEq, Eq, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[serde(crate = "rocket::serde")]
|
||||||
|
struct Sessions {
|
||||||
|
#[serde(rename = "$id")]
|
||||||
|
id: String,
|
||||||
|
#[serde(rename = "$createdAt")]
|
||||||
|
created_at: String,
|
||||||
|
user_id: String,
|
||||||
|
expire: String,
|
||||||
|
provider: String,
|
||||||
|
provider_uid: String,
|
||||||
|
provider_access_token: String,
|
||||||
|
provider_access_token_expiry: String,
|
||||||
|
provider_refresh_token: String,
|
||||||
|
ip: String,
|
||||||
|
os_code: String,
|
||||||
|
os_name: String,
|
||||||
|
os_version: String,
|
||||||
|
client_type: String,
|
||||||
|
client_code: String,
|
||||||
|
client_name: String,
|
||||||
|
client_version: String,
|
||||||
|
client_engine: String,
|
||||||
|
client_engine_version: String,
|
||||||
|
device_name: String,
|
||||||
|
device_brand: String,
|
||||||
|
device_model: String,
|
||||||
|
country_code: String,
|
||||||
|
country_name: String,
|
||||||
|
current: bool,
|
||||||
|
}
|
@ -29,6 +29,7 @@ macro_rules! find_element {
|
|||||||
|
|
||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Database {
|
pub struct Database {
|
||||||
conn: Pool<ConnectionManager<PgConnection>>,
|
conn: Pool<ConnectionManager<PgConnection>>,
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::db::Database;
|
use crate::{db::Database, graphql::Context};
|
||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
use juniper::GraphQLEnum;
|
use juniper::GraphQLEnum;
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
@ -63,11 +63,11 @@ pub struct Language {
|
|||||||
impl Language {
|
impl Language {
|
||||||
fn relationship(
|
fn relationship(
|
||||||
&self,
|
&self,
|
||||||
context: &Database,
|
db: &Database,
|
||||||
relationship: AgentLanguageRelation,
|
relationship: AgentLanguageRelation,
|
||||||
) -> Vec<User> {
|
) -> Vec<User> {
|
||||||
use schema::langandagents::dsl;
|
use schema::langandagents::dsl;
|
||||||
match &mut context.conn() {
|
match &mut db.conn() {
|
||||||
Ok(conn) => dsl::langandagents
|
Ok(conn) => dsl::langandagents
|
||||||
.filter(dsl::language.eq(self.id))
|
.filter(dsl::language.eq(self.id))
|
||||||
.filter(dsl::relationship.eq(relationship))
|
.filter(dsl::relationship.eq(relationship))
|
||||||
@ -97,7 +97,7 @@ impl Language {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[juniper::graphql_object(Context = Database)]
|
#[juniper::graphql_object(Context = Context)]
|
||||||
impl Language {
|
impl Language {
|
||||||
#[graphql(description = "Unique identifier of the language")]
|
#[graphql(description = "Unique identifier of the language")]
|
||||||
fn id(&self) -> String {
|
fn id(&self) -> String {
|
||||||
@ -125,9 +125,9 @@ impl Language {
|
|||||||
name = "targetLanguage",
|
name = "targetLanguage",
|
||||||
description = "Languages in which the current language is translated"
|
description = "Languages in which the current language is translated"
|
||||||
)]
|
)]
|
||||||
fn target_language(&self, context: &Database) -> Vec<Language> {
|
fn target_language(&self, context: &Context) -> Vec<Language> {
|
||||||
use schema::langtranslatesto::dsl;
|
use schema::langtranslatesto::dsl;
|
||||||
match &mut context.conn() {
|
match &mut context.db.conn() {
|
||||||
Ok(conn) => dsl::langtranslatesto
|
Ok(conn) => dsl::langtranslatesto
|
||||||
.filter(dsl::langfrom.eq(self.id))
|
.filter(dsl::langfrom.eq(self.id))
|
||||||
.load::<LangTranslatesTo>(conn)
|
.load::<LangTranslatesTo>(conn)
|
||||||
@ -187,9 +187,9 @@ impl Language {
|
|||||||
#[graphql(
|
#[graphql(
|
||||||
description = "User with administrative rights over the language"
|
description = "User with administrative rights over the language"
|
||||||
)]
|
)]
|
||||||
fn owner(&self, context: &Database) -> User {
|
fn owner(&self, context: &Context) -> User {
|
||||||
use schema::users::dsl;
|
use schema::users::dsl;
|
||||||
match &mut context.conn() {
|
match &mut context.db.conn() {
|
||||||
Ok(conn) => dsl::users
|
Ok(conn) => dsl::users
|
||||||
.find(self.owner.clone())
|
.find(self.owner.clone())
|
||||||
.first::<User>(conn)
|
.first::<User>(conn)
|
||||||
@ -206,15 +206,15 @@ impl Language {
|
|||||||
#[graphql(
|
#[graphql(
|
||||||
description = "People who participate in the elaboration of the language's dictionary"
|
description = "People who participate in the elaboration of the language's dictionary"
|
||||||
)]
|
)]
|
||||||
fn authors(&self, context: &Database) -> Vec<User> {
|
fn authors(&self, context: &Context) -> Vec<User> {
|
||||||
self.relationship(context, AgentLanguageRelation::Author)
|
self.relationship(&context.db, AgentLanguageRelation::Author)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[graphql(
|
#[graphql(
|
||||||
description = "People who can and do redistribute the language's dictionary"
|
description = "People who can and do redistribute the language's dictionary"
|
||||||
)]
|
)]
|
||||||
fn publishers(&self, context: &Database) -> Vec<User> {
|
fn publishers(&self, context: &Context) -> Vec<User> {
|
||||||
self.relationship(context, AgentLanguageRelation::Publisher)
|
self.relationship(&context.db, AgentLanguageRelation::Publisher)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
use super::super::schema::{userfollows, users};
|
use super::super::schema::{userfollows, users};
|
||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
|
|
||||||
use crate::db::Database;
|
use crate::graphql::Context;
|
||||||
|
|
||||||
#[derive(Queryable, Insertable, Debug, Clone, PartialEq, Eq)]
|
#[derive(Queryable, Insertable, Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct User {
|
pub struct User {
|
||||||
pub id: String,
|
id: String,
|
||||||
pub username: String,
|
username: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[juniper::graphql_object(Context = Database)]
|
#[juniper::graphql_object(Context = Context)]
|
||||||
impl User {
|
impl User {
|
||||||
#[graphql(description = "Appwrite ID of the user")]
|
#[graphql(description = "Appwrite ID of the user")]
|
||||||
pub fn id(&self) -> String {
|
pub fn id(&self) -> String {
|
||||||
@ -22,9 +22,9 @@ impl User {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[graphql(description = "Who the user follows")]
|
#[graphql(description = "Who the user follows")]
|
||||||
pub fn following(&self, context: &Database) -> Vec<User> {
|
pub fn following(&self, context: &Context) -> Vec<User> {
|
||||||
use super::super::schema::{userfollows, users};
|
use super::super::schema::{userfollows, users};
|
||||||
let conn = &mut context.conn().unwrap();
|
let conn = &mut context.db.conn().unwrap();
|
||||||
userfollows::dsl::userfollows
|
userfollows::dsl::userfollows
|
||||||
.filter(userfollows::dsl::follower.eq(self.id.clone()))
|
.filter(userfollows::dsl::follower.eq(self.id.clone()))
|
||||||
.load::<UserFollow>(conn)
|
.load::<UserFollow>(conn)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use super::super::schema;
|
use super::super::schema;
|
||||||
use crate::db::Database;
|
use crate::{db::Database, graphql::Context};
|
||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
use juniper::GraphQLEnum;
|
use juniper::GraphQLEnum;
|
||||||
use schema::{wordrelation, words};
|
use schema::{wordrelation, words};
|
||||||
@ -60,11 +60,11 @@ pub struct Word {
|
|||||||
impl Word {
|
impl Word {
|
||||||
fn relationship(
|
fn relationship(
|
||||||
&self,
|
&self,
|
||||||
context: &Database,
|
db: &Database,
|
||||||
relationship: WordRelationship,
|
relationship: WordRelationship,
|
||||||
) -> Vec<Word> {
|
) -> Vec<Word> {
|
||||||
use schema::wordrelation::dsl;
|
use schema::wordrelation::dsl;
|
||||||
match &mut context.conn() {
|
match &mut db.conn() {
|
||||||
Ok(conn) => dsl::wordrelation
|
Ok(conn) => dsl::wordrelation
|
||||||
.filter(dsl::wordsource.eq(self.norm.clone()))
|
.filter(dsl::wordsource.eq(self.norm.clone()))
|
||||||
.filter(dsl::relationship.eq(relationship))
|
.filter(dsl::relationship.eq(relationship))
|
||||||
@ -84,7 +84,7 @@ impl Word {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[juniper::graphql_object(Context = Database)]
|
#[juniper::graphql_object(Context = Context)]
|
||||||
impl Word {
|
impl Word {
|
||||||
#[graphql(description = "Normal form of the word")]
|
#[graphql(description = "Normal form of the word")]
|
||||||
fn norm(&self) -> String {
|
fn norm(&self) -> String {
|
||||||
@ -97,10 +97,10 @@ impl Word {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[graphql(description = "Base form of the current word")]
|
#[graphql(description = "Base form of the current word")]
|
||||||
fn lemma(&self, context: &Database) -> Option<Word> {
|
fn lemma(&self, context: &Context) -> Option<Word> {
|
||||||
use schema::words::dsl;
|
use schema::words::dsl;
|
||||||
match self.lemma.clone() {
|
match self.lemma.clone() {
|
||||||
Some(lemma) => match &mut context.conn() {
|
Some(lemma) => match &mut context.db.conn() {
|
||||||
Ok(conn) => {
|
Ok(conn) => {
|
||||||
match dsl::words.find(lemma.clone()).first::<Word>(conn) {
|
match dsl::words.find(lemma.clone()).first::<Word>(conn) {
|
||||||
Ok(word) => Some(word),
|
Ok(word) => Some(word),
|
||||||
@ -123,9 +123,9 @@ impl Word {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[graphql(description = "Language to which the word belongs")]
|
#[graphql(description = "Language to which the word belongs")]
|
||||||
fn language(&self, context: &Database) -> Language {
|
fn language(&self, context: &Context) -> Language {
|
||||||
use schema::languages::dsl;
|
use schema::languages::dsl;
|
||||||
match &mut context.conn() {
|
match &mut context.db.conn() {
|
||||||
Ok(conn) => {
|
Ok(conn) => {
|
||||||
match dsl::languages.find(self.language).first::<Language>(conn)
|
match dsl::languages.find(self.language).first::<Language>(conn)
|
||||||
{
|
{
|
||||||
@ -185,16 +185,16 @@ impl Word {
|
|||||||
name = "related",
|
name = "related",
|
||||||
description = "Words related to the current word"
|
description = "Words related to the current word"
|
||||||
)]
|
)]
|
||||||
fn related_words(&self, context: &Database) -> Vec<Word> {
|
fn related_words(&self, context: &Context) -> Vec<Word> {
|
||||||
self.relationship(context, WordRelationship::Related)
|
self.relationship(&context.db, WordRelationship::Related)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[graphql(
|
#[graphql(
|
||||||
name = "definitions",
|
name = "definitions",
|
||||||
description = "Words that define the current word"
|
description = "Words that define the current word"
|
||||||
)]
|
)]
|
||||||
fn definitions(&self, context: &Database) -> Vec<Word> {
|
fn definitions(&self, context: &Context) -> Vec<Word> {
|
||||||
self.relationship(context, WordRelationship::Definition)
|
self.relationship(&context.db, WordRelationship::Definition)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
114
src/graphql.rs
114
src/graphql.rs
@ -1,114 +0,0 @@
|
|||||||
use rocket::response::content::RawHtml;
|
|
||||||
use rocket::State;
|
|
||||||
|
|
||||||
use juniper::EmptySubscription;
|
|
||||||
use juniper_rocket::{GraphQLRequest, GraphQLResponse};
|
|
||||||
|
|
||||||
use crate::db::models::{languages::Language, users::User, words::Word};
|
|
||||||
use crate::db::Database;
|
|
||||||
|
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Query;
|
|
||||||
|
|
||||||
#[juniper::graphql_object(Context = Database)]
|
|
||||||
impl Query {
|
|
||||||
#[graphql(
|
|
||||||
name = "allLanguages",
|
|
||||||
description = "Retrieve all languages defined in the database"
|
|
||||||
)]
|
|
||||||
fn all_languages(context: &Database) -> Vec<Language> {
|
|
||||||
context.all_languages().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[graphql(
|
|
||||||
description = "Retrieve a specific language from its name and its owner's id",
|
|
||||||
arguments(
|
|
||||||
name(description = "Name of the language"),
|
|
||||||
owner(description = "ID of the owner of the language")
|
|
||||||
)
|
|
||||||
)]
|
|
||||||
fn language(
|
|
||||||
context: &Database,
|
|
||||||
name: String,
|
|
||||||
owner: String,
|
|
||||||
) -> Option<Language> {
|
|
||||||
context.language(name.as_str(), owner.as_str())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[graphql(
|
|
||||||
description = "Retrieve a specific user from its id",
|
|
||||||
arguments(id(description = "Appwrite ID of a user"))
|
|
||||||
)]
|
|
||||||
fn user(context: &Database, id: String) -> Option<User> {
|
|
||||||
context.user(id.as_str())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[graphql(
|
|
||||||
description = "Retrieve a specific word from its id",
|
|
||||||
arguments(id(description = "Unique identifier of a word"))
|
|
||||||
)]
|
|
||||||
fn word(context: &Database, id: String) -> Option<Word> {
|
|
||||||
context.word_id(id.as_str())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[graphql(
|
|
||||||
description = "Retrieve all words with a set normal form from a set language",
|
|
||||||
arguments(
|
|
||||||
owner(
|
|
||||||
description = "ID of the owner of the language to search a word in"
|
|
||||||
),
|
|
||||||
language(description = "Name of the language to search a word in"),
|
|
||||||
word(description = "Word to search")
|
|
||||||
)
|
|
||||||
)]
|
|
||||||
fn words(
|
|
||||||
context: &Database,
|
|
||||||
language: String,
|
|
||||||
word: String,
|
|
||||||
) -> Vec<Word> {
|
|
||||||
context.words(uuid::Uuid::from_str(&language).unwrap(), word.as_str())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Mutation;
|
|
||||||
|
|
||||||
#[juniper::graphql_object(Context = Database)]
|
|
||||||
impl Mutation {
|
|
||||||
fn api_version() -> String {
|
|
||||||
"0.1".into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type Schema =
|
|
||||||
juniper::RootNode<'static, Query, Mutation, EmptySubscription<Database>>;
|
|
||||||
|
|
||||||
pub fn create_schema() -> Schema {
|
|
||||||
Schema::new(Query {}, Mutation {}, EmptySubscription::default())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[rocket::get("/")]
|
|
||||||
pub fn graphiql() -> RawHtml<String> {
|
|
||||||
let graphql_endpoint_url = "/graphql";
|
|
||||||
juniper_rocket::graphiql_source(graphql_endpoint_url, None)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[rocket::get("/graphql?<request>")]
|
|
||||||
pub async fn get_graphql_handler(
|
|
||||||
context: &State<Database>,
|
|
||||||
request: GraphQLRequest,
|
|
||||||
schema: &State<Schema>,
|
|
||||||
) -> GraphQLResponse {
|
|
||||||
request.execute(schema, context).await
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::needless_pass_by_value)]
|
|
||||||
#[rocket::post("/graphql", data = "<request>")]
|
|
||||||
pub fn post_graphql_handler(
|
|
||||||
context: &State<Database>,
|
|
||||||
request: GraphQLRequest,
|
|
||||||
schema: &State<Schema>,
|
|
||||||
) -> GraphQLResponse {
|
|
||||||
request.execute_sync(schema, context)
|
|
||||||
}
|
|
54
src/graphql/mod.rs
Normal file
54
src/graphql/mod.rs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
use rocket::response::content::RawHtml;
|
||||||
|
use rocket::State;
|
||||||
|
|
||||||
|
use juniper::EmptySubscription;
|
||||||
|
use juniper_rocket::{GraphQLRequest, GraphQLResponse};
|
||||||
|
|
||||||
|
use crate::appwrite::APVariables;
|
||||||
|
use crate::db::Database;
|
||||||
|
|
||||||
|
#[derive(Default, Debug)]
|
||||||
|
pub struct Context {
|
||||||
|
pub db: Database,
|
||||||
|
pub appwrite: APVariables,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl juniper::Context for Context {}
|
||||||
|
|
||||||
|
mod query;
|
||||||
|
use query::Query;
|
||||||
|
|
||||||
|
mod mutation;
|
||||||
|
use mutation::Mutation;
|
||||||
|
|
||||||
|
type Schema =
|
||||||
|
juniper::RootNode<'static, Query, Mutation, EmptySubscription<Context>>;
|
||||||
|
|
||||||
|
pub fn create_schema() -> Schema {
|
||||||
|
Schema::new(Query {}, Mutation {}, EmptySubscription::default())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rocket::get("/")]
|
||||||
|
pub fn graphiql() -> RawHtml<String> {
|
||||||
|
let graphql_endpoint_url = "/graphql";
|
||||||
|
juniper_rocket::graphiql_source(graphql_endpoint_url, None)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rocket::get("/graphql?<request>")]
|
||||||
|
pub async fn get_graphql_handler(
|
||||||
|
context: &State<Context>,
|
||||||
|
request: GraphQLRequest,
|
||||||
|
schema: &State<Schema>,
|
||||||
|
) -> GraphQLResponse {
|
||||||
|
request.execute(schema, context).await
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::needless_pass_by_value)]
|
||||||
|
#[rocket::post("/graphql", data = "<request>")]
|
||||||
|
pub async fn post_graphql_handler(
|
||||||
|
context: &State<Context>,
|
||||||
|
request: GraphQLRequest,
|
||||||
|
schema: &State<Schema>,
|
||||||
|
) -> GraphQLResponse {
|
||||||
|
request.execute(schema, context).await
|
||||||
|
}
|
32
src/graphql/mutation.rs
Normal file
32
src/graphql/mutation.rs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
use super::Context;
|
||||||
|
|
||||||
|
pub struct Mutation;
|
||||||
|
|
||||||
|
#[juniper::graphql_object(Context = Context)]
|
||||||
|
impl Mutation {
|
||||||
|
fn api_version(
|
||||||
|
session_id: Option<String>,
|
||||||
|
user_id: Option<String>,
|
||||||
|
context: &Context,
|
||||||
|
) -> String {
|
||||||
|
"0.1".into()
|
||||||
|
// if session_id.is_some() && user_id.is_some() {
|
||||||
|
// match context
|
||||||
|
// .appwrite
|
||||||
|
// .check_session(session_id.unwrap(), user_id.unwrap())
|
||||||
|
// {
|
||||||
|
// Ok(true) => "0.1 (authentified)".into(),
|
||||||
|
// Ok(false) => "0.1 (not authentified)".into(),
|
||||||
|
// Err(e) => {
|
||||||
|
// info!(
|
||||||
|
// "Error while checking if the user is connected: {:?}",
|
||||||
|
// e
|
||||||
|
// );
|
||||||
|
// "0.1 (auth failed)"
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// "0.1 (not authentified)"
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
65
src/graphql/query.rs
Normal file
65
src/graphql/query.rs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
use super::Context;
|
||||||
|
use crate::db::models::{languages::Language, users::User, words::Word};
|
||||||
|
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Query;
|
||||||
|
|
||||||
|
#[juniper::graphql_object(Context = Context)]
|
||||||
|
impl Query {
|
||||||
|
#[graphql(
|
||||||
|
name = "allLanguages",
|
||||||
|
description = "Retrieve all languages defined in the database"
|
||||||
|
)]
|
||||||
|
fn all_languages(context: &Context) -> Vec<Language> {
|
||||||
|
context.db.all_languages().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[graphql(
|
||||||
|
description = "Retrieve a specific language from its name and its owner's id",
|
||||||
|
arguments(
|
||||||
|
name(description = "Name of the language"),
|
||||||
|
owner(description = "ID of the owner of the language")
|
||||||
|
)
|
||||||
|
)]
|
||||||
|
fn language(
|
||||||
|
context: &Context,
|
||||||
|
name: String,
|
||||||
|
owner: String,
|
||||||
|
) -> Option<Language> {
|
||||||
|
context.db.language(name.as_str(), owner.as_str())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[graphql(
|
||||||
|
description = "Retrieve a specific user from its id",
|
||||||
|
arguments(id(description = "Appwrite ID of a user"))
|
||||||
|
)]
|
||||||
|
fn user(context: &Context, id: String) -> Option<User> {
|
||||||
|
context.db.user(id.as_str())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[graphql(
|
||||||
|
description = "Retrieve a specific word from its id",
|
||||||
|
arguments(id(description = "Unique identifier of a word"))
|
||||||
|
)]
|
||||||
|
fn word(context: &Context, id: String) -> Option<Word> {
|
||||||
|
context.db.word_id(id.as_str())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[graphql(
|
||||||
|
description = "Retrieve all words with a set normal form from a set language",
|
||||||
|
arguments(
|
||||||
|
owner(
|
||||||
|
description = "ID of the owner of the language to search a word in"
|
||||||
|
),
|
||||||
|
language(description = "Name of the language to search a word in"),
|
||||||
|
word(description = "Word to search")
|
||||||
|
)
|
||||||
|
)]
|
||||||
|
fn words(context: &Context, language: String, word: String) -> Vec<Word> {
|
||||||
|
context
|
||||||
|
.db
|
||||||
|
.words(uuid::Uuid::from_str(&language).unwrap(), word.as_str())
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
#![warn(clippy::style, clippy::pedantic)]
|
#![warn(clippy::style, clippy::pedantic)]
|
||||||
|
|
||||||
|
mod appwrite;
|
||||||
mod db;
|
mod db;
|
||||||
mod graphql;
|
mod graphql;
|
||||||
|
|
||||||
@ -49,6 +50,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
create_schema, get_graphql_handler, graphiql, post_graphql_handler,
|
create_schema, get_graphql_handler, graphiql, post_graphql_handler,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
color_eyre::install()?;
|
||||||
setup_logging();
|
setup_logging();
|
||||||
|
|
||||||
info!("Reading environment variables");
|
info!("Reading environment variables");
|
||||||
@ -60,7 +62,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
#[allow(clippy::let_underscore_drop, clippy::no_effect_underscore_binding)]
|
#[allow(clippy::let_underscore_drop, clippy::no_effect_underscore_binding)]
|
||||||
let _ = rocket::build()
|
let _ = rocket::build()
|
||||||
.attach(cors)
|
.attach(cors)
|
||||||
.manage(db::Database::default())
|
.manage(graphql::Context::default())
|
||||||
.manage(create_schema())
|
.manage(create_schema())
|
||||||
.mount(
|
.mount(
|
||||||
"/",
|
"/",
|
||||||
|
Loading…
Reference in New Issue
Block a user