summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSanto Cariotti <santo@dcariotti.me>2024-09-16 22:40:24 +0200
committerSanto Cariotti <santo@dcariotti.me>2024-09-16 22:40:24 +0200
commit99bb59373b5918b2baf7e70f510d2b0ec1122a28 (patch)
treec44dc2572c520402812fab2c62bf9f96d1cf2628
parentccde4a437999267ae1f62316bebcc09ea7dc027d (diff)
Use `AppState` instead of `String` using some traits
-rw-r--r--src/db.rs2
-rw-r--r--src/errors.rs30
-rw-r--r--src/graphql/query.rs14
-rw-r--r--src/graphql/types/alert.rs78
-rw-r--r--src/graphql/types/jwt.rs5
-rw-r--r--src/graphql/types/notification.rs32
-rw-r--r--src/graphql/types/position.rs43
-rw-r--r--src/graphql/types/user.rs42
-rw-r--r--src/main.rs37
9 files changed, 151 insertions, 132 deletions
diff --git a/src/db.rs b/src/db.rs
index 4a9e9a7..9644138 100644
--- a/src/db.rs
+++ b/src/db.rs
@@ -6,7 +6,7 @@ use tokio_postgres::{Client, NoTls};
pub async fn setup() -> Result<Client, AppError> {
let database_url = &crate::config::CONFIG.database_url;
- let (client, connection) = tokio_postgres::connect(database_url, NoTls).await.unwrap();
+ let (client, connection) = tokio_postgres::connect(database_url, NoTls).await?;
// Spawn a new task to run the connection to the database
tokio::spawn(async move {
diff --git a/src/errors.rs b/src/errors.rs
index 1b9a802..3dda65c 100644
--- a/src/errors.rs
+++ b/src/errors.rs
@@ -1,3 +1,5 @@
+use core::fmt;
+
use axum::{
http::StatusCode,
response::{IntoResponse, Response},
@@ -66,3 +68,31 @@ impl From<std::io::Error> for AppError {
AppError::BadRequest(error.to_string())
}
}
+
+/// Implementation of the `{}` marker for AppError
+impl fmt::Display for AppError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ AppError::Database => write!(f, "Database"),
+ AppError::BadRequest(value) => write!(f, "BadRequest: {}", value),
+ AppError::NotFound(value) => write!(f, "Not found: {}", value),
+ AppError::TokenCreation => write!(f, "Token creation"),
+ AppError::InvalidToken => write!(f, "Invalid Token"),
+ AppError::Unauthorized => write!(f, "Unauthorized"),
+ }
+ }
+}
+
+/// A tokio_postgres error is mapped to an `AppError::Database`
+impl From<tokio_postgres::Error> for AppError {
+ fn from(_: tokio_postgres::Error) -> Self {
+ AppError::Database
+ }
+}
+
+/// A async_graphql error is mapped to an `AppError::BadRequest`
+impl From<async_graphql::Error> for AppError {
+ fn from(value: async_graphql::Error) -> Self {
+ AppError::BadRequest(value.message)
+ }
+}
diff --git a/src/graphql/query.rs b/src/graphql/query.rs
index e3750c9..9e6e0c3 100644
--- a/src/graphql/query.rs
+++ b/src/graphql/query.rs
@@ -1,4 +1,4 @@
-use crate::graphql::types::*;
+use crate::{errors::AppError, graphql::types::*};
use async_graphql::{Context, Object};
/// Query struct
@@ -25,7 +25,7 @@ impl Query {
ctx: &Context<'ctx>,
#[graphql(desc = "Limit results")] limit: Option<i64>,
#[graphql(desc = "Offset results")] offset: Option<i64>,
- ) -> Result<Option<Vec<user::User>>, String> {
+ ) -> Result<Option<Vec<user::User>>, AppError> {
user::query::get_users(ctx, limit, offset).await
}
@@ -42,7 +42,7 @@ impl Query {
&self,
ctx: &Context<'ctx>,
#[graphql(desc = "User to find")] id: i32,
- ) -> Result<user::User, String> {
+ ) -> Result<user::User, AppError> {
user::query::get_user_by_id(ctx, id).await
}
@@ -61,7 +61,7 @@ impl Query {
#[graphql(desc = "Filter by user id")] user_id: Option<i32>,
#[graphql(desc = "Limit results")] limit: Option<i64>,
#[graphql(desc = "Offset results")] offset: Option<i64>,
- ) -> Result<Option<Vec<position::Position>>, String> {
+ ) -> Result<Option<Vec<position::Position>>, AppError> {
position::query::get_positions(ctx, user_id, limit, offset).await
}
@@ -81,7 +81,7 @@ impl Query {
#[graphql(desc = "Filter by moving activity")] moving_activity: Option<
position::MovingActivity,
>,
- ) -> Result<Option<Vec<position::Position>>, String> {
+ ) -> Result<Option<Vec<position::Position>>, AppError> {
position::query::last_positions(ctx, moving_activity).await
}
@@ -100,7 +100,7 @@ impl Query {
#[graphql(desc = "Filter by ID")] id: Option<i32>,
#[graphql(desc = "Limit results")] limit: Option<i64>,
#[graphql(desc = "Offset results")] offset: Option<i64>,
- ) -> Result<Option<Vec<alert::Alert>>, String> {
+ ) -> Result<Option<Vec<alert::Alert>>, AppError> {
alert::query::get_alerts(ctx, id, limit, offset).await
}
@@ -128,7 +128,7 @@ impl Query {
#[graphql(desc = "Filter by alert ID")] alert_id: Option<i32>,
#[graphql(desc = "Limit results")] limit: Option<i64>,
#[graphql(desc = "Offset results")] offset: Option<i64>,
- ) -> Result<Option<Vec<notification::Notification>>, String> {
+ ) -> Result<Option<Vec<notification::Notification>>, AppError> {
notification::query::get_notifications(ctx, seen, id, alert_id, limit, offset).await
}
}
diff --git a/src/graphql/types/alert.rs b/src/graphql/types/alert.rs
index 69e8f31..6d27626 100644
--- a/src/graphql/types/alert.rs
+++ b/src/graphql/types/alert.rs
@@ -1,4 +1,5 @@
use crate::{
+ errors::AppError,
expo,
graphql::types::{
jwt::Authentication,
@@ -61,17 +62,18 @@ pub mod query {
// Optional offset results. It should be used with limit field.
offset: Option<i64>,
- ) -> Result<Option<Vec<Alert>>, String> {
+ ) -> Result<Option<Vec<Alert>>, AppError> {
let state = ctx.data::<AppState>().expect("Can't connect to db");
let client = &*state.client;
- let auth: &Authentication = ctx.data().unwrap();
+ let auth: &Authentication = ctx.data()?;
match auth {
- Authentication::NotLogged => Err("Unauthorized".to_string()),
+ Authentication::NotLogged => Err(AppError::Unauthorized),
Authentication::Logged(_) => {
let rows = match id {
- Some(id) => client
- .query(
- "SELECT id,
+ Some(id) => {
+ client
+ .query(
+ "SELECT id,
user_id,
extract(epoch from created_at)::double precision as created_at,
ST_AsText(area) as area,
@@ -83,13 +85,14 @@ pub mod query {
reached_users
FROM alerts
WHERE id = $1",
- &[&id],
- )
- .await
- .unwrap(),
- None => client
- .query(
- "SELECT id,
+ &[&id],
+ )
+ .await?
+ }
+ None => {
+ client
+ .query(
+ "SELECT id,
user_id,
extract(epoch from created_at)::double precision as created_at,
ST_AsText(area) as area,
@@ -103,10 +106,10 @@ pub mod query {
ORDER BY id DESC
LIMIT $1
OFFSET $2",
- &[&limit.unwrap_or(20), &offset.unwrap_or(0)],
- )
- .await
- .unwrap(),
+ &[&limit.unwrap_or(20), &offset.unwrap_or(0)],
+ )
+ .await?
+ }
};
let alerts: Vec<Alert> = rows
@@ -141,13 +144,13 @@ pub mod mutations {
let state = ctx.data::<AppState>().expect("Can't connect to db");
let client = &*state.client;
- let auth: &Authentication = ctx.data().unwrap();
+ let auth: &Authentication = ctx.data()?;
match auth {
- Authentication::NotLogged => Err(async_graphql::Error::new("Can't find the owner")),
+ Authentication::NotLogged => Err(AppError::NotFound("Owner".to_string()).into()),
Authentication::Logged(claims) => {
- let claim_user = find_user(client, claims.user_id).await.unwrap();
+ let claim_user = find_user(client, claims.user_id).await?;
if !claim_user.is_admin {
- return Err(async_graphql::Error::new("Unauthorized"));
+ return Err(AppError::Unauthorized.into());
}
let points: String = input
@@ -165,19 +168,16 @@ pub mod mutations {
let polygon = format!("ST_MakePolygon(ST_MakeLine(ARRAY[{}]))", points);
let valid_query = format!("SELECT ST_IsValid({}) as is_valid", polygon);
- let rows;
- match client.query(&valid_query, &[]).await {
- Ok(r) => {
- rows = r;
- }
+ let rows = match client.query(&valid_query, &[]).await {
+ Ok(r) => r,
Err(_) => {
- return Err(async_graphql::Error::new("Polygon is not valid"));
+ return Err(AppError::BadRequest("Polygon is not valid".to_string()).into());
}
};
let is_valid: bool = rows[0].get("is_valid");
if !is_valid {
- return Err(async_graphql::Error::new("Polygon is not valid"));
+ return Err(AppError::BadRequest("Polygon is not valid".to_string()).into());
}
let insert_query = format!(
@@ -198,8 +198,7 @@ pub mod mutations {
&insert_query,
&[&claims.user_id, &input.text1, &input.text2, &input.text3],
)
- .await
- .unwrap();
+ .await?;
let mut alert = rows
.iter()
.map(|row| Alert {
@@ -217,7 +216,7 @@ pub mod mutations {
.collect::<Vec<Alert>>()
.first()
.cloned()
- .ok_or_else(|| async_graphql::Error::new("Failed to create alert"))?;
+ .ok_or_else(|| AppError::BadRequest("Failed to create alert".to_string()))?;
struct Level<'a> {
text: &'a str,
@@ -259,8 +258,7 @@ pub mod mutations {
)",
&[&alert.id, &level.distance],
)
- .await
- .unwrap()
+ .await?
.iter()
.map(|row| row.get(0))
.filter(|id| !positions.contains(id))
@@ -274,8 +272,7 @@ pub mod mutations {
*id,
LevelAlert::from_str(level.text).unwrap(),
)
- .await
- .unwrap();
+ .await?;
notification_ids.push(notification);
}
@@ -284,7 +281,7 @@ pub mod mutations {
.map(|i| format!("${}", i))
.collect();
- if placeholders.len() > 0 {
+ if !placeholders.is_empty() {
let query = format!(
"SELECT DISTINCT u.notification_token FROM positions p JOIN users u ON u.id = p.user_id
WHERE p.id IN ({}) AND notification_token IS NOT NULL",
@@ -299,8 +296,7 @@ pub mod mutations {
.map(|id| id as &(dyn tokio_postgres::types::ToSql + Sync))
.collect::<Vec<&(dyn tokio_postgres::types::ToSql + Sync)>>(),
)
- .await
- .unwrap()
+ .await?
.iter()
.map(|row| {
format!("ExponentPushToken[{}]", row.get::<usize, String>(0))
@@ -317,8 +313,7 @@ pub mod mutations {
_ => "Check it out in app!".to_string(),
},
)
- .await
- .unwrap();
+ .await?;
}
positions.extend(position_ids);
@@ -329,8 +324,7 @@ pub mod mutations {
"UPDATE alerts SET reached_users = $1 WHERE id = $2",
&[&alert.reached_users, &alert.id],
)
- .await
- .unwrap();
+ .await?;
if let Err(e) = audio::tts(
alert.text1.clone(),
diff --git a/src/graphql/types/jwt.rs b/src/graphql/types/jwt.rs
index b2a09c3..af4dc72 100644
--- a/src/graphql/types/jwt.rs
+++ b/src/graphql/types/jwt.rs
@@ -139,14 +139,13 @@ pub mod mutations {
"SELECT id FROM users WHERE email = $1 AND password = $2",
&[&input.email, &password],
)
- .await
- .unwrap();
+ .await?;
let id: Vec<i32> = rows.iter().map(|row| row.get(0)).collect();
if id.len() == 1 {
// Create a new claim using the found ID
let claims = Claims::new(id[0]);
- let token = claims.get_token().unwrap();
+ let token = claims.get_token()?;
Ok(AuthBody::new(token, id[0]))
} else {
Err(Error::new("Invalid email or password"))
diff --git a/src/graphql/types/notification.rs b/src/graphql/types/notification.rs
index 1ff7532..88860a7 100644
--- a/src/graphql/types/notification.rs
+++ b/src/graphql/types/notification.rs
@@ -139,12 +139,12 @@ pub mod query {
// Optional offset results. It should be used with limit field.
offset: Option<i64>,
- ) -> Result<Option<Vec<Notification>>, String> {
+ ) -> Result<Option<Vec<Notification>>, AppError> {
let state = ctx.data::<AppState>().expect("Can't connect to db");
let client = &*state.client;
- let auth: &Authentication = ctx.data().unwrap();
+ let auth: &Authentication = ctx.data()?;
match auth {
- Authentication::NotLogged => Err("Unauthorized".to_string()),
+ Authentication::NotLogged => Err(AppError::Unauthorized),
Authentication::Logged(claims) => {
let claim_user = find_user(client, claims.user_id)
.await
@@ -196,29 +196,25 @@ pub mod query {
.query(&format!(
"{base_query} AND n.alert_id = $1 ORDER BY n.id DESC LIMIT $2 OFFSET $3",
), &[&ida, &limit, &offset])
- .await
- .unwrap(),
+ .await?,
Some (ida) =>
client
.query(&format!(
"{base_query} AND p.user_id = $1 AND n.alert_id = $2 ORDER BY n.id DESC LIMIT $3 OFFSET $4",
), &[&claim_user.id, &ida, &limit, &offset])
- .await
- .unwrap(),
+ .await?,
None if claim_user.is_admin => client
.query(
&format!("{base_query} ORDER BY n.id DESC LIMIT $1 OFFSET $2"),
&[&limit, &offset],
)
- .await
- .unwrap(),
+ .await?,
None =>
client.query(
&format!("{base_query} AND p.user_id = $1 ORDER BY n.id DESC LIMIT $2 OFFSET $3"),
&[&claim_user.id, &limit, &offset],
)
- .await
- .unwrap(),
+ .await?,
};
let notifications: Vec<Notification> = rows
@@ -267,9 +263,9 @@ pub mod mutations {
let state = ctx.data::<AppState>().expect("Can't connect to db");
let client = &*state.client;
- let auth: &Authentication = ctx.data().unwrap();
+ let auth: &Authentication = ctx.data()?;
match auth {
- Authentication::NotLogged => Err(async_graphql::Error::new("Can't find the owner")),
+ Authentication::NotLogged => Err(AppError::NotFound("Owner".to_string()).into()),
Authentication::Logged(claims) => {
let user = find_user(client, claims.user_id)
.await
@@ -303,8 +299,7 @@ pub mod mutations {
WHERE n.id = $1
",
&[&input.id])
- .await
- .unwrap()
+ .await?
.iter()
.map(|row| Notification {
id: row.get("id"),
@@ -335,10 +330,10 @@ pub mod mutations {
.collect::<Vec<Notification>>()
.first()
.cloned()
- .ok_or_else(|| async_graphql::Error::new("Failed to get notification"))?;
+ .ok_or_else(|| AppError::NotFound("Notification".to_string()))?;
if notification.position.user_id != user.id {
- return Err(async_graphql::Error::new("Not found"));
+ return Err(AppError::NotFound("Notification".to_string()).into());
}
client
@@ -346,8 +341,7 @@ pub mod mutations {
"UPDATE notifications SET seen = $1 WHERE id = $2",
&[&input.seen, &input.id],
)
- .await
- .unwrap();
+ .await?;
Ok(notification)
}
diff --git a/src/graphql/types/position.rs b/src/graphql/types/position.rs
index 22030c5..cbd0148 100644
--- a/src/graphql/types/position.rs
+++ b/src/graphql/types/position.rs
@@ -1,11 +1,13 @@
-use crate::{graphql::types::jwt::Authentication, state::AppState};
+use crate::{
+ errors::AppError,
+ graphql::types::{jwt::Authentication, user::find_user},
+ state::AppState,
+};
use async_graphql::{Context, Enum, FieldResult, InputObject, SimpleObject};
use serde::{Deserialize, Serialize};
use std::error::Error;
use tokio_postgres::types::{to_sql_checked, FromSql, IsNull, ToSql, Type};
-use super::user::find_user;
-
#[derive(Enum, Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
/// Enumeration which refers to the kind of moving activity
pub enum MovingActivity {
@@ -96,14 +98,17 @@ pub mod query {
// Optional offset results. It should be used with limit field.
offset: Option<i64>,
- ) -> Result<Option<Vec<Position>>, String> {
+ ) -> Result<Option<Vec<Position>>, AppError> {
let state = ctx.data::<AppState>().expect("Can't connect to db");
let client = &*state.client;
- let auth: &Authentication = ctx.data().unwrap();
+ let auth: &Authentication = ctx.data()?;
match auth {
- Authentication::NotLogged => Err("Unauthorized".to_string()),
+ Authentication::NotLogged => Err(AppError::Unauthorized),
Authentication::Logged(claims) => {
let rows;
+ let limit = limit.unwrap_or(20);
+ let offset = offset.unwrap_or(0);
+
let claim_user = find_user(client, claims.user_id)
.await
.expect("Should not be here");
@@ -118,7 +123,7 @@ pub mod query {
ORDER BY id DESC
LIMIT $2
OFFSET $3",
- &[&id, &limit.unwrap_or(20), &offset.unwrap_or(0)]).await.unwrap();
+ &[&id, &limit, &offset]).await?;
}
None => {
rows = client.query("
@@ -127,7 +132,7 @@ pub mod query {
ORDER BY id DESC
LIMIT $1
OFFSET $2",
- &[&limit.unwrap_or(20), &offset.unwrap_or(0)]).await.unwrap();
+ &[&limit, &offset]).await?;
}
}
} else {
@@ -138,7 +143,7 @@ pub mod query {
ORDER BY id DESC
LIMIT $2
OFFSET $3",
- &[&claim_user.id, &limit.unwrap_or(20), &offset.unwrap_or(0)]).await.unwrap();
+ &[&claim_user.id, &limit, &offset]).await?;
}
let positions: Vec<Position> = rows
@@ -165,19 +170,19 @@ pub mod query {
// Optional filter by moving activity
moving_activity: Option<MovingActivity>,
- ) -> Result<Option<Vec<Position>>, String> {
+ ) -> Result<Option<Vec<Position>>, AppError> {
let state = ctx.data::<AppState>().expect("Can't connect to db");
let client = &*state.client;
- let auth: &Authentication = ctx.data().unwrap();
+ let auth: &Authentication = ctx.data()?;
match auth {
- Authentication::NotLogged => Err("Unauthorized".to_string()),
+ Authentication::NotLogged => Err(AppError::Unauthorized),
Authentication::Logged(claims) => {
let claim_user = find_user(client, claims.user_id)
.await
.expect("Should not be here");
if !claim_user.is_admin {
- return Err("Unauthorized".to_string());
+ return Err(AppError::Unauthorized);
}
let rows = client
@@ -187,8 +192,7 @@ pub mod query {
FROM positions ORDER BY user_id, created_at DESC",
&[],
)
- .await
- .unwrap();
+ .await?;
let positions: Vec<Position> = match moving_activity {
Some(activity) => rows
@@ -233,9 +237,11 @@ pub mod mutations {
let state = ctx.data::<AppState>().expect("Can't connect to db");
let client = &*state.client;
- let auth: &Authentication = ctx.data().unwrap();
+ let auth: &Authentication = ctx.data()?;
match auth {
- Authentication::NotLogged => Err(async_graphql::Error::new("Can't find the owner")),
+ Authentication::NotLogged => {
+ Err(AppError::NotFound("Can't find the owner".to_string()).into())
+ }
Authentication::Logged(claims) => {
let rows = client
.query(
@@ -254,8 +260,7 @@ pub mod mutations {
&input.moving_activity,
],
)
- .await
- .unwrap();
+ .await?;
let positions: Vec<Position> = rows
.iter()
diff --git a/src/graphql/types/user.rs b/src/graphql/types/user.rs
index 44cc87c..3361f4a 100644
--- a/src/graphql/types/user.rs
+++ b/src/graphql/types/user.rs
@@ -107,19 +107,19 @@ pub mod query {
limit: Option<i64>,
// Optional offset results. It should be used with limit field.
offset: Option<i64>,
- ) -> Result<Option<Vec<User>>, String> {
+ ) -> Result<Option<Vec<User>>, AppError> {
let state = ctx.data::<AppState>().expect("Can't connect to db");
let client = &*state.client;
- let auth: &Authentication = ctx.data().unwrap();
+ let auth: &Authentication = ctx.data()?;
match auth {
- Authentication::NotLogged => Err("Unauthorized".to_string()),
+ Authentication::NotLogged => Err(AppError::Unauthorized),
Authentication::Logged(claims) => {
let claim_user = find_user(client, claims.user_id)
.await
.expect("Should not be here");
if !claim_user.is_admin {
- return Err("Unauthorized".to_string());
+ return Err(AppError::Unauthorized);
}
let rows = client
@@ -127,8 +127,7 @@ pub mod query {
"SELECT id, email, name, address, is_admin FROM users LIMIT $1 OFFSET $2",
&[&limit.unwrap_or(20), &offset.unwrap_or(0)],
)
- .await
- .unwrap();
+ .await?;
let users: Vec<User> = rows
.iter()
@@ -149,12 +148,12 @@ pub mod query {
}
/// Get users from the database
- pub async fn get_user_by_id<'ctx>(ctx: &Context<'ctx>, id: i32) -> Result<User, String> {
+ pub async fn get_user_by_id<'ctx>(ctx: &Context<'ctx>, id: i32) -> Result<User, AppError> {
let state = ctx.data::<AppState>().expect("Can't connect to db");
let client = &*state.client;
- let auth: &Authentication = ctx.data().unwrap();
+ let auth: &Authentication = ctx.data()?;
match auth {
- Authentication::NotLogged => Err("Unauthorized".to_string()),
+ Authentication::NotLogged => Err(AppError::Unauthorized),
Authentication::Logged(claims) => {
let claim_user = find_user(client, claims.user_id)
.await
@@ -168,10 +167,9 @@ pub mod query {
WHERE id = $1",
&[&id],
)
- .await
- .unwrap();
+ .await?;
} else if claims.user_id != id {
- return Err("Unauthorized".to_string());
+ return Err(AppError::Unauthorized);
} else {
rows = client
.query(
@@ -179,8 +177,7 @@ pub mod query {
WHERE id = $1",
&[&claims.user_id],
)
- .await
- .unwrap();
+ .await?;
}
let users: Vec<User> = rows
@@ -197,7 +194,7 @@ pub mod query {
.collect();
if users.is_empty() {
- return Err("Not found".to_string());
+ return Err(AppError::NotFound("User".to_string()));
}
Ok(users[0].clone())
@@ -217,7 +214,7 @@ pub mod mutations {
let state = ctx.data::<AppState>().expect("Can't connect to db");
let client = &*state.client;
- let auth: &Authentication = ctx.data().unwrap();
+ let auth: &Authentication = ctx.data()?;
match auth {
Authentication::NotLogged => Err(Error::new("Can't find the owner")),
Authentication::Logged(claims) => {
@@ -230,8 +227,7 @@ pub mod mutations {
"UPDATE users SET notification_token = $1 WHERE id = $2",
&[&input.token, &claims.user_id],
)
- .await
- .unwrap();
+ .await?;
Ok(user)
}
@@ -247,7 +243,7 @@ pub mod mutations {
let state = ctx.data::<AppState>().expect("Can't connect to db");
let client = &*state.client;
- let auth: &Authentication = ctx.data().unwrap();
+ let auth: &Authentication = ctx.data()?;
match auth {
Authentication::NotLogged => Err(Error::new("Can't find the owner")),
Authentication::Logged(claims) => {
@@ -268,8 +264,7 @@ pub mod mutations {
"UPDATE users SET email = $1, name = $2, address = $3 WHERE id = $4",
&[&input.email, &input.name, &input.address, &id],
)
- .await
- .unwrap();
+ .await?;
let user = find_user(client, claims.user_id)
.await
@@ -288,7 +283,7 @@ pub mod mutations {
let state = ctx.data::<AppState>().expect("Can't connect to db");
let client = &*state.client;
- let auth: &Authentication = ctx.data().unwrap();
+ let auth: &Authentication = ctx.data()?;
match auth {
Authentication::NotLogged => Err(Error::new("Can't find the owner")),
Authentication::Logged(claims) => {
@@ -310,8 +305,7 @@ pub mod mutations {
"UPDATE users SET password = $1 WHERE id = $2",
&[&password, &user.id],
)
- .await
- .unwrap();
+ .await?;
Ok(user)
}
diff --git a/src/main.rs b/src/main.rs
index 940bb5c..96cdc61 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -17,6 +17,7 @@ use axum::{
routing::{get, post},
Extension, Router,
};
+use errors::AppError;
use tokio::net::TcpListener;
use tower_http::{
classify::ServerErrorsFailureClass,
@@ -28,10 +29,10 @@ use tower_http::{
use tracing::Span;
/// Create the app: setup everything and returns a `Router`
-async fn create_app() -> Router {
+async fn create_app() -> Result<Router, AppError> {
logger::setup();
expo::setup(CONFIG.expo_access_token.clone());
- let dbclient = db::setup().await.unwrap();
+ let dbclient = db::setup().await?;
let state = state::AppState {
client: Arc::new(dbclient),
@@ -45,7 +46,7 @@ async fn create_app() -> Router {
.data(state.clone())
.finish();
- Router::new()
+ Ok(Router::new()
.route("/assets/sounds/:id", get(audio::show_file))
.route(
"/graphql",
@@ -75,24 +76,26 @@ async fn create_app() -> Router {
.allow_headers(vec![header::CONTENT_TYPE, header::AUTHORIZATION])
.allow_origin(Any),
)
- .layer(Extension(state))
+ .layer(Extension(state)))
}
#[tokio::main(flavor = "current_thread")]
async fn main() {
- let app = create_app().await;
+ if let Ok(app) = create_app().await {
+ let host = &CONFIG.allowed_host;
- let host = &CONFIG.allowed_host;
+ let addr = match host.parse::<SocketAddr>() {
+ Ok(addr) => addr,
+ Err(e) => {
+ panic!("`{}` {}", host, e);
+ }
+ };
+ tracing::info!("Listening on {}", addr);
- let addr = match host.parse::<SocketAddr>() {
- Ok(addr) => addr,
- Err(e) => {
- panic!("`{}` {}", host, e);
- }
- };
- tracing::info!("Listening on {}", addr);
-
- axum::serve(TcpListener::bind(&addr).await.unwrap(), app)
- .await
- .unwrap();
+ axum::serve(TcpListener::bind(&addr).await.unwrap(), app)
+ .await
+ .unwrap();
+ } else {
+ tracing::error!("Can't create an application!");
+ }
}