Almost no unwraps !
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Lucien Cartier-Tilet 2023-01-16 00:48:09 +01:00
parent dcaa920c51
commit d0a40b7ed8
Signed by: phundrak
GPG Key ID: BD7789E705CB8DCA
4 changed files with 97 additions and 41 deletions

View File

@ -1,6 +1,9 @@
use crate::{db::Database, graphql::Context}; use crate::{
db::{Database, DatabaseError},
graphql::Context,
};
use diesel::prelude::*; use diesel::prelude::*;
use juniper::GraphQLEnum; use juniper::{FieldResult, GraphQLEnum};
use tracing::info; use tracing::info;
use uuid::Uuid; use uuid::Uuid;
@ -8,6 +11,8 @@ use uuid::Uuid;
use super::super::schema; use super::super::schema;
use super::users::User; use super::users::User;
use std::convert::Into;
use schema::{langandagents, langtranslatesto, languages}; use schema::{langandagents, langtranslatesto, languages};
#[derive( #[derive(
@ -65,14 +70,22 @@ impl Language {
&self, &self,
db: &Database, db: &Database,
relationship: AgentLanguageRelation, relationship: AgentLanguageRelation,
) -> Vec<User> { ) -> Result<Vec<User>, DatabaseError> {
use schema::langandagents::dsl; use schema::langandagents::dsl;
match &mut db.conn() { match &mut db.conn() {
Ok(conn) => dsl::langandagents Ok(conn) => Ok(dsl::langandagents
.filter(dsl::language.eq(self.id)) .filter(dsl::language.eq(self.id))
.filter(dsl::relationship.eq(relationship)) .filter(dsl::relationship.eq(relationship))
.load::<LangAndAgent>(conn) .load::<LangAndAgent>(conn)
.unwrap() .map_err(|e| {
DatabaseError::new(
format!(
"Failed to retrieve language relationship: {:?}",
e
),
"Database reading error",
)
})?
.iter() .iter()
.map(|v| { .map(|v| {
use schema::users::dsl; use schema::users::dsl;
@ -89,7 +102,7 @@ impl Language {
None None
} }
}) })
.collect::<Vec<User>>(), .collect::<Vec<User>>()),
Err(e) => { Err(e) => {
panic!("Could not connect to the database: {:?}", e); panic!("Could not connect to the database: {:?}", e);
} }
@ -125,23 +138,32 @@ 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: &Context) -> Vec<Language> { fn target_language(&self, context: &Context) -> FieldResult<Vec<Language>> {
use schema::langtranslatesto::dsl; use schema::langtranslatesto::dsl;
match &mut context.db.conn() { match &mut context.db.conn() {
Ok(conn) => dsl::langtranslatesto Ok(conn) => Ok(dsl::langtranslatesto
.filter(dsl::langfrom.eq(self.id)) .filter(dsl::langfrom.eq(self.id))
.load::<LangTranslatesTo>(conn) .load::<LangTranslatesTo>(conn)
.unwrap() .map_err(|e| {
DatabaseError::new(
format!(
"Failed to retrieve language translations: {:?}",
e
),
"Database reading failure",
)
})?
.into_iter() .into_iter()
.flat_map(|l| { .flat_map(|l| {
use schema::languages::dsl; use schema::languages::dsl;
dsl::languages.find(l.langto).first::<Language>(conn) dsl::languages.find(l.langto).first::<Language>(conn)
}) })
.collect::<Vec<Language>>(), .collect::<Vec<Language>>()),
Err(e) => { Err(e) => Err(DatabaseError::new(
info!("Failed to connect to the database: {:?}", e); format!("Failed to connect to the database: {:?}", e),
Vec::new() "Database connection failure",
} )
.into()),
} }
} }
@ -187,34 +209,43 @@ impl Language {
#[graphql( #[graphql(
description = "User with administrative rights over the language" description = "User with administrative rights over the language"
)] )]
fn owner(&self, context: &Context) -> User { fn owner(&self, context: &Context) -> FieldResult<User> {
use schema::users::dsl; use schema::users::dsl;
match &mut context.db.conn() { match &mut context.db.conn() {
Ok(conn) => dsl::users Ok(conn) => Ok(dsl::users
.find(self.owner.clone()) .find(self.owner.clone())
.first::<User>(conn) .first::<User>(conn)
.unwrap_or_else(|e| { .map_err(|e| {
panic!( DatabaseError::new(
"Failed to retrieve owner {} of language {}: {:?}", format!(
self.owner, self.name, e "Failed to retrieve owner {} of language {}: {:?}",
self.owner, self.name, e
),
"Database reading error",
) )
}), })?),
Err(e) => panic!("Failed to connect to the database: {:?}", e), Err(e) => Err(DatabaseError::new(
format!("Failed to connect to the database: {:?}", e),
"Database connection failure",
)
.into()),
} }
} }
#[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: &Context) -> Vec<User> { fn authors(&self, context: &Context) -> FieldResult<Vec<User>> {
self.relationship(&context.db, AgentLanguageRelation::Author) self.relationship(&context.db, AgentLanguageRelation::Author)
.map_err(Into::into)
} }
#[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: &Context) -> Vec<User> { fn publishers(&self, context: &Context) -> FieldResult<Vec<User>> {
self.relationship(&context.db, AgentLanguageRelation::Publisher) self.relationship(&context.db, AgentLanguageRelation::Publisher)
.map_err(Into::into)
} }
} }

View File

@ -1,3 +1,3 @@
pub mod users;
pub mod languages; pub mod languages;
pub mod users;
pub mod words; pub mod words;

View File

@ -1,7 +1,9 @@
use super::super::schema::{userfollows, users}; use super::super::schema::{userfollows, users};
use diesel::prelude::*; use diesel::prelude::*;
use juniper::FieldResult;
use tracing::debug;
use crate::graphql::Context; use crate::{db::DatabaseError, graphql::Context};
#[derive(Queryable, Insertable, Debug, Clone, PartialEq, Eq)] #[derive(Queryable, Insertable, Debug, Clone, PartialEq, Eq)]
pub struct User { pub struct User {
@ -22,21 +24,45 @@ impl User {
} }
#[graphql(description = "Who the user follows")] #[graphql(description = "Who the user follows")]
pub fn following(&self, context: &Context) -> Vec<User> { pub fn following(&self, context: &Context) -> FieldResult<Vec<User>> {
use super::super::schema::{userfollows, users}; use super::super::schema::{userfollows, users};
let conn = &mut context.db.conn().unwrap(); let conn = &mut context.db.conn().map_err(|e| {
userfollows::dsl::userfollows DatabaseError::new(
format!("Failed to connect to database: {:?}", e),
"Database connection error",
)
})?;
Ok(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)
.unwrap() .map_err(|e| {
.iter() DatabaseError::new(
.map(|f| { format!(
users::dsl::users "Failed to retrieve user follows from database: {:?}",
.find(f.following.clone()) e
.first::<User>(conn) ),
.unwrap() "Database reading error",
}) )
.collect::<Vec<User>>() })?
.iter()
.filter_map(|f| {
match users::dsl::users
.find(f.following.clone())
.first::<User>(conn) {
Ok(val) => Some(val),
Err(e) => {
let err = DatabaseError::new(
format!("Failed to retrieve user {} from database: {:?}",
f.following.clone(),
e),
"Database reading error");
debug!("{}", err);
None
}
}
})
.collect::<Vec<User>>())
} }
} }

View File

@ -18,7 +18,7 @@ pub struct OtherEnvVar {
impl Default for OtherEnvVar { impl Default for OtherEnvVar {
fn default() -> Self { fn default() -> Self {
Self { Self {
admin_key: from_env!("ADMIN_KEY") admin_key: from_env!("ADMIN_KEY"),
} }
} }
} }
@ -28,7 +28,7 @@ pub struct Context {
pub db: Database, pub db: Database,
pub appwrite: APVariables, pub appwrite: APVariables,
pub user_auth: bool, pub user_auth: bool,
pub other_vars: OtherEnvVar pub other_vars: OtherEnvVar,
} }
impl Context { impl Context {
@ -64,7 +64,6 @@ impl Context {
res.user_auth = self.user_auth(auth_token).await; res.user_auth = self.user_auth(auth_token).await;
res res
} }
} }
impl juniper::Context for Context {} impl juniper::Context for Context {}