diff options
author | Santo Cariotti <santo@dcariotti.me> | 2024-08-23 22:07:47 +0200 |
---|---|---|
committer | Santo Cariotti <santo@dcariotti.me> | 2024-08-23 22:07:47 +0200 |
commit | cb1aa9668a967fe875e716469ccf936ed8693ad3 (patch) | |
tree | ff06888ed9d2a3a3b7fe2a05d18d80e801db6e15 | |
parent | ecb99e08531ff4d22e1a2204989e848347b3a756 (diff) |
Filter positions by user id
-rw-r--r-- | src/graphql/query.rs | 3 | ||||
-rw-r--r-- | src/graphql/types/position.rs | 50 | ||||
-rw-r--r-- | src/graphql/types/user.rs | 29 |
3 files changed, 70 insertions, 12 deletions
diff --git a/src/graphql/query.rs b/src/graphql/query.rs index a875d25..3d72b2e 100644 --- a/src/graphql/query.rs +++ b/src/graphql/query.rs @@ -23,9 +23,10 @@ impl Query { async fn positions<'ctx>( &self, ctx: &Context<'ctx>, + #[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> { - position::get_positions(ctx, limit, offset).await + position::get_positions(ctx, user_id, limit, offset).await } } diff --git a/src/graphql/types/position.rs b/src/graphql/types/position.rs index bdcb24f..8b2d658 100644 --- a/src/graphql/types/position.rs +++ b/src/graphql/types/position.rs @@ -1,11 +1,11 @@ -use crate::{dates::GraphQLDate, state::AppState}; +use crate::{dates::GraphQLDate, graphql::types::jwt::Authentication, state::AppState}; use async_graphql::{Context, Enum, Object}; use chrono::Utc; use serde::{Deserialize, Serialize}; use std::error::Error; use tokio_postgres::types::{to_sql_checked, FromSql, IsNull, ToSql, Type}; -use super::jwt::Authentication; +use super::user::find_user; #[derive(Enum, Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)] pub enum MovingActivity { @@ -105,6 +105,7 @@ impl Position { pub async fn get_positions<'ctx>( ctx: &Context<'ctx>, + user_id: Option<i32>, limit: Option<i64>, offset: Option<i64>, ) -> Result<Option<Vec<Position>>, String> { @@ -114,14 +115,43 @@ pub async fn get_positions<'ctx>( match auth { Authentication::NotLogged => Err("Unauthorized".to_string()), Authentication::Logged(claims) => { - let rows = client.query(" - SELECT id, user_id, created_at, ST_Y(location::geometry) AS latitude, ST_X(location::geometry) AS longitude, activity - FROM positions - WHERE user_id = $1 - ORDER BY id DESC - LIMIT $2 - OFFSET $3", - &[&claims.user_id, &limit.unwrap_or(20), &offset.unwrap_or(0)]).await.unwrap(); + let rows; + let claim_user = find_user(client, claims.user_id) + .await + .expect("Should not be here"); + + if claim_user.is_admin { + match user_id { + Some(id) => { + rows = client.query(" + SELECT id, user_id, created_at, ST_Y(location::geometry) AS latitude, ST_X(location::geometry) AS longitude, activity + FROM positions + WHERE user_id = $1 + ORDER BY id DESC + LIMIT $2 + OFFSET $3", + &[&id, &limit.unwrap_or(20), &offset.unwrap_or(0)]).await.unwrap(); + } + None => { + rows = client.query(" + SELECT id, user_id, created_at, ST_Y(location::geometry) AS latitude, ST_X(location::geometry) AS longitude, activity + FROM positions + ORDER BY id DESC + LIMIT $1 + OFFSET $2", + &[&limit.unwrap_or(20), &offset.unwrap_or(0)]).await.unwrap(); + } + } + } else { + rows = client.query(" + SELECT id, user_id, created_at, ST_Y(location::geometry) AS latitude, ST_X(location::geometry) AS longitude, activity + FROM positions + WHERE user_id = $1 + ORDER BY id DESC + LIMIT $2 + OFFSET $3", + &[&claim_user.id, &limit.unwrap_or(20), &offset.unwrap_or(0)]).await.unwrap(); + } let positions: Vec<Position> = rows .iter() diff --git a/src/graphql/types/user.rs b/src/graphql/types/user.rs index 21554b9..4ecf086 100644 --- a/src/graphql/types/user.rs +++ b/src/graphql/types/user.rs @@ -1,6 +1,7 @@ -use crate::state::AppState; +use crate::{errors::AppError, state::AppState}; use async_graphql::{Context, Object}; use serde::{Deserialize, Serialize}; +use tokio_postgres::Client; use super::jwt::Authentication; @@ -64,3 +65,29 @@ pub async fn get_users<'ctx>( } } } + +pub async fn find_user(client: &Client, id: i32) -> Result<User, AppError> { + let rows = client + .query( + "SELECT id, email, password, is_admin FROM users WHERE id = $1", + &[&id], + ) + .await + .unwrap(); + + let users: Vec<User> = rows + .iter() + .map(|row| User { + id: row.get("id"), + email: row.get("email"), + password: row.get("password"), + is_admin: row.get("is_admin"), + }) + .collect(); + + if users.len() == 1 { + Ok(users[0].clone()) + } else { + Err(AppError::NotFound("User".to_string())) + } +} |