summaryrefslogtreecommitdiffstats
path: root/src/graphql/types
diff options
context:
space:
mode:
Diffstat (limited to 'src/graphql/types')
-rw-r--r--src/graphql/types/alert.rs125
-rw-r--r--src/graphql/types/mod.rs1
-rw-r--r--src/graphql/types/position.rs31
3 files changed, 128 insertions, 29 deletions
diff --git a/src/graphql/types/alert.rs b/src/graphql/types/alert.rs
new file mode 100644
index 0000000..006e9ae
--- /dev/null
+++ b/src/graphql/types/alert.rs
@@ -0,0 +1,125 @@
+use crate::{dates::GraphQLDate, graphql::types::jwt::Authentication, state::AppState};
+use async_graphql::{Context, Enum, InputObject, SimpleObject};
+use chrono::Utc;
+use serde::{Deserialize, Serialize};
+use std::error::Error;
+use tokio_postgres::types::{to_sql_checked, FromSql, IsNull, ToSql, Type};
+
+#[derive(Enum, Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
+/// Enumeration which refers to the level of alert
+pub enum LevelAlert {
+ // User in the AREA
+ One,
+
+ // User in the AREA OR < 1km distance
+ Two,
+
+ // User in the AREA OR < 2km distance
+ Three,
+}
+
+impl<'a> FromSql<'a> for LevelAlert {
+ fn from_sql(_ty: &Type, raw: &'a [u8]) -> Result<LevelAlert, Box<dyn Error + Sync + Send>> {
+ match std::str::from_utf8(raw)? {
+ "One" => Ok(LevelAlert::One),
+ "Two" => Ok(LevelAlert::Two),
+ "Three" => Ok(LevelAlert::Three),
+ other => Err(format!("Unknown variant: {}", other).into()),
+ }
+ }
+
+ fn accepts(ty: &Type) -> bool {
+ ty.name() == "level_alert"
+ }
+}
+
+impl ToSql for LevelAlert {
+ fn to_sql(
+ &self,
+ _ty: &Type,
+ out: &mut bytes::BytesMut,
+ ) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
+ let value = match *self {
+ LevelAlert::One => "One",
+ LevelAlert::Two => "Two",
+ LevelAlert::Three => "Three",
+ };
+ out.extend_from_slice(value.as_bytes());
+ Ok(IsNull::No)
+ }
+
+ fn accepts(ty: &Type) -> bool {
+ ty.name() == "level_alert"
+ }
+
+ to_sql_checked!();
+}
+
+#[derive(SimpleObject, Clone, Debug, Serialize, Deserialize)]
+/// Alert struct
+pub struct Alert {
+ pub id: i32,
+ pub user_id: i32,
+ pub created_at: GraphQLDate,
+ pub area: String,
+ pub level: LevelAlert,
+ pub reached_users: i32,
+}
+
+#[derive(InputObject)]
+pub struct Point {
+ pub latitude: f64,
+ pub longitude: f64,
+}
+
+#[derive(InputObject)]
+/// Alert input struct
+pub struct AlertInput {
+ pub points: Vec<Point>,
+ pub level: LevelAlert,
+}
+
+/// Get alerts from the database
+pub async fn get_alerts<'ctx>(
+ ctx: &Context<'ctx>,
+
+ // Optional limit results
+ limit: Option<i64>,
+
+ // Optional offset results. It should be used with limit field.
+ offset: Option<i64>,
+) -> Result<Option<Vec<Alert>>, String> {
+ let state = ctx.data::<AppState>().expect("Can't connect to db");
+ let client = &*state.client;
+ let auth: &Authentication = ctx.data().unwrap();
+ match auth {
+ Authentication::NotLogged => Err("Unauthorized".to_string()),
+ Authentication::Logged(_) => {
+ let rows = client
+ .query(
+ "SELECT id, user_id, created_at, ST_AsText(area) as area, level, reached_users
+ FROM alerts
+ ORDER BY id DESC
+ LIMIT $1
+ OFFSET $2",
+ &[&limit.unwrap_or(20), &offset.unwrap_or(0)],
+ )
+ .await
+ .unwrap();
+
+ let positions: Vec<Alert> = rows
+ .iter()
+ .map(|row| Alert {
+ id: row.get("id"),
+ user_id: row.get("user_id"),
+ created_at: GraphQLDate(Utc::now()),
+ area: row.get("area"),
+ level: row.get("level"),
+ reached_users: row.get("reached_users"),
+ })
+ .collect();
+
+ Ok(Some(positions))
+ }
+ }
+}
diff --git a/src/graphql/types/mod.rs b/src/graphql/types/mod.rs
index a77cf8c..d0f8ead 100644
--- a/src/graphql/types/mod.rs
+++ b/src/graphql/types/mod.rs
@@ -1,3 +1,4 @@
+pub mod alert;
pub mod jwt;
pub mod position;
pub mod user;
diff --git a/src/graphql/types/position.rs b/src/graphql/types/position.rs
index 8610fcb..a9236a6 100644
--- a/src/graphql/types/position.rs
+++ b/src/graphql/types/position.rs
@@ -1,5 +1,5 @@
use crate::{dates::GraphQLDate, graphql::types::jwt::Authentication, state::AppState};
-use async_graphql::{Context, Enum, InputObject, Object};
+use async_graphql::{Context, Enum, InputObject, SimpleObject};
use chrono::Utc;
use serde::{Deserialize, Serialize};
use std::error::Error;
@@ -67,7 +67,7 @@ impl ToSql for MovingActivity {
to_sql_checked!();
}
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(SimpleObject, Clone, Debug, Serialize, Deserialize)]
/// Position struct
pub struct Position {
pub id: i32,
@@ -86,33 +86,6 @@ pub struct PositionInput {
pub moving_activity: MovingActivity,
}
-#[Object]
-impl Position {
- async fn id(&self) -> i32 {
- self.id
- }
-
- async fn user_id(&self) -> i32 {
- self.user_id
- }
-
- async fn created_at(&self) -> GraphQLDate {
- self.created_at.clone()
- }
-
- async fn latitude(&self) -> f64 {
- self.latitude
- }
-
- async fn longitude(&self) -> f64 {
- self.longitude
- }
-
- async fn moving_activity(&self) -> MovingActivity {
- self.moving_activity
- }
-}
-
/// Get positions from the database
pub async fn get_positions<'ctx>(
ctx: &Context<'ctx>,