Skip to content

Commit

Permalink
Adapt for user specific queries disallowing general wishlist access
Browse files Browse the repository at this point in the history
  • Loading branch information
legendofa committed Jan 24, 2024
1 parent 95cf105 commit ecda058
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 57 deletions.
8 changes: 0 additions & 8 deletions src/foreign_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,6 @@ use bson::{doc, Bson, Uuid};
use serde::{Deserialize, Serialize};
use std::{cmp::Ordering, hash::Hash};

/// Foreign type of a user.
#[derive(Debug, Serialize, Deserialize, Hash, Eq, PartialEq, Clone, SimpleObject)]
#[graphql(unresolvable)]
pub struct User {
/// UUID of the user.
pub _id: Uuid,
}

/// Foreign type of a product variant.
#[derive(Debug, Serialize, Deserialize, Hash, Eq, PartialEq, Copy, Clone, SimpleObject)]
#[graphql(unresolvable)]
Expand Down
6 changes: 4 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use axum::{
use clap::{arg, command, Parser};
use simple_logger::SimpleLogger;

use foreign_types::User;
use log::info;
use mongodb::{bson::DateTime, options::ClientOptions, Client, Collection, Database};

Expand All @@ -33,7 +32,10 @@ use mutation::Mutation;
mod app_callback_service;
use app_callback_service::AppCallbackService;

use crate::foreign_types::ProductVariant;
use foreign_types::ProductVariant;

mod user;
use user::User;

mod base_connection;
mod foreign_types;
Expand Down
3 changes: 2 additions & 1 deletion src/mutation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ use mongodb::{
Collection, Database,
};

use crate::user::User;
use crate::{
foreign_types::{ProductVariant, User},
foreign_types::ProductVariant,
mutation_input_structs::{AddWishlistInput, UpdateWishlistInput},
query::query_wishlist,
wishlist::Wishlist,
Expand Down
50 changes: 8 additions & 42 deletions src/query.rs
Original file line number Diff line number Diff line change
@@ -1,54 +1,20 @@
use crate::{
base_connection::{BaseConnection, FindResultWrapper},
order_datatypes::WishlistOrderInput,
wishlist_connection::WishlistConnection,
Wishlist,
};
use crate::{user::User, Wishlist};
use async_graphql::{Context, Error, Object, Result};
use bson::Document;

use bson::Uuid;
use mongodb::{bson::doc, options::FindOptions, Collection, Database};
use mongodb_cursor_pagination::{error::CursorError, FindResult, PaginatedCursor};
use mongodb::{bson::doc, Collection, Database};

/// Describes GraphQL wishlist queries.
pub struct Query;

#[Object]
impl Query {
/// Retrieves all wishlists.
async fn wishlists<'a>(
/// Retrieve user with wishlists.
async fn user<'a>(
&self,
ctx: &Context<'a>,
#[graphql(desc = "Describes that the `first` N wishlists should be retrieved.")]
first: Option<u32>,
#[graphql(desc = "Describes how many wishlists should be skipped at the beginning.")]
skip: Option<u64>,
#[graphql(desc = "Specifies the order in which wishlists are retrieved.")] order_by: Option<
WishlistOrderInput,
>,
) -> Result<WishlistConnection> {
let db_client = ctx.data_unchecked::<Database>();
let collection: Collection<Wishlist> = db_client.collection::<Wishlist>("wishlists");
let wishlist_order = order_by.unwrap_or_default();
let sorting_doc = doc! {wishlist_order.field.unwrap_or_default().as_str(): i32::from(wishlist_order.direction.unwrap_or_default())};
let find_options = FindOptions::builder()
.skip(skip)
.limit(first.map(|v| i64::from(v)))
.sort(sorting_doc)
.build();
let document_collection = collection.clone_with_type::<Document>();
let maybe_find_results: Result<FindResult<Wishlist>, CursorError> =
PaginatedCursor::new(Some(find_options.clone()), None, None)
.find(&document_collection, None)
.await;
match maybe_find_results {
Ok(find_results) => {
let find_result_wrapper = FindResultWrapper(find_results);
let connection = Into::<BaseConnection<Wishlist>>::into(find_result_wrapper);
Ok(Into::<WishlistConnection>::into(connection))
}
Err(_) => return Err(Error::new("Retrieving wishlists failed in MongoDB.")),
}
#[graphql(desc = "UUID of user to retrieve.")] id: Uuid,
) -> Result<User> {
Ok(User { _id: id })
}

/// Retrieves wishlist of specific id.
Expand Down
60 changes: 60 additions & 0 deletions src/user.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
use async_graphql::{ComplexObject, Context, Error, Result, SimpleObject};
use bson::{doc, Document, Uuid};
use mongodb::{options::FindOptions, Collection, Database};
use mongodb_cursor_pagination::{error::CursorError, FindResult, PaginatedCursor};
use serde::{Deserialize, Serialize};

use crate::{
base_connection::{BaseConnection, FindResultWrapper},
order_datatypes::CommonOrderInput,
wishlist::Wishlist,
wishlist_connection::WishlistConnection,
};

/// Type of a user owning wishlists.
#[derive(Debug, Serialize, Deserialize, Hash, Eq, PartialEq, Clone, SimpleObject)]
#[graphql(complex)]
pub struct User {
/// UUID of the user.
pub _id: Uuid,
}

#[ComplexObject]
impl User {
/// Retrieves wishlists of user.
async fn wishlists<'a>(
&self,
ctx: &Context<'a>,
#[graphql(desc = "Describes that the `first` N wishlists should be retrieved.")]
first: Option<u32>,
#[graphql(desc = "Describes how many wishlists should be skipped at the beginning.")]
skip: Option<u64>,
#[graphql(desc = "Specifies the order in which wishlists are retrieved.")] order_by: Option<
CommonOrderInput,
>,
) -> Result<WishlistConnection> {
let db_client = ctx.data_unchecked::<Database>();
let collection: Collection<Wishlist> = db_client.collection::<Wishlist>("wishlists");
let wishlist_order = order_by.unwrap_or_default();
let sorting_doc = doc! {wishlist_order.field.unwrap_or_default().as_str(): i32::from(wishlist_order.direction.unwrap_or_default())};
let find_options = FindOptions::builder()
.skip(skip)
.limit(first.map(|v| i64::from(v)))
.sort(sorting_doc)
.build();
let document_collection = collection.clone_with_type::<Document>();
let filter = doc! {"user._id": self._id};
let maybe_find_results: Result<FindResult<Wishlist>, CursorError> =
PaginatedCursor::new(Some(find_options.clone()), None, None)
.find(&document_collection, Some(&filter))
.await;
match maybe_find_results {
Ok(find_results) => {
let find_result_wrapper = FindResultWrapper(find_results);
let connection = Into::<BaseConnection<Wishlist>>::into(find_result_wrapper);
Ok(Into::<WishlistConnection>::into(connection))
}
Err(_) => return Err(Error::new("Retrieving wishlists failed in MongoDB.")),
}
}
}
11 changes: 7 additions & 4 deletions src/wishlist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ use bson::Uuid;
use serde::{Deserialize, Serialize};

use crate::{
foreign_types::{ProductVariant, User},
foreign_types::ProductVariant,
order_datatypes::{CommonOrderInput, OrderDirection},
product_variant_connection::ProductVariantConnection,
user::User,
};

/// The Wishlist of a user.
Expand All @@ -37,11 +38,13 @@ impl Wishlist {
/// Retrieves product variants.
async fn product_variants(
&self,
#[graphql(desc = "Describes that the `first` N wishlists should be retrieved.")]
#[graphql(desc = "Describes that the `first` N product variants should be retrieved.")]
first: Option<usize>,
#[graphql(desc = "Describes how many wishlists should be skipped at the beginning.")]
#[graphql(
desc = "Describes how many product variants should be skipped at the beginning."
)]
skip: Option<usize>,
#[graphql(desc = "Specifies the order in which wishlists are retrieved.")] order_by: Option<
#[graphql(desc = "Specifies the order in which product variants are retrieved.")] order_by: Option<
CommonOrderInput,
>,
) -> Result<ProductVariantConnection> {
Expand Down

0 comments on commit ecda058

Please sign in to comment.