From 32c70909c0f73c17a8803c51c7cd31560c4618d7 Mon Sep 17 00:00:00 2001 From: st170001 Date: Tue, 16 Jan 2024 18:55:36 +0100 Subject: [PATCH 1/7] Trying to get product validation to work --- Cargo.toml | 1 + docker-compose-base.yaml | 4 ++- src/app_callback_service.rs | 60 ++++++++++++++++++++++++++++++++++--- src/main.rs | 21 +++++++------ src/mutation.rs | 56 ++++++++++++++++++++++++++++++---- src/query.rs | 11 ++++--- 6 files changed, 129 insertions(+), 24 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c5da113..1df3b52 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,3 +21,4 @@ uuid = { version = "1.6.1", features = ["v4", "serde"] } mongodb-cursor-pagination = "0.3.2" dapr = "0.13.0" tonic = "0.8" +json = "0.12.4" diff --git a/docker-compose-base.yaml b/docker-compose-base.yaml index 5dc9e0a..50449ba 100644 --- a/docker-compose-base.yaml +++ b/docker-compose-base.yaml @@ -32,7 +32,9 @@ services: "--app-id", "wishlist", "--app-port", - "8080", + "50051", + "--app-protocol", + "grpc", "--dapr-http-port", "3500", "-placement-host-address", diff --git a/src/app_callback_service.rs b/src/app_callback_service.rs index bcb021b..63f0158 100644 --- a/src/app_callback_service.rs +++ b/src/app_callback_service.rs @@ -1,9 +1,30 @@ +use json::JsonValue; +use mongodb::Collection; use tonic::{Request, Response, Status}; +use bson::Uuid; use dapr::{appcallback::*, dapr::dapr::proto::runtime::v1::app_callback_server::AppCallback}; -#[derive(Default)] -pub struct AppCallbackService {} +use crate::foreign_types::ProductVariant; + +pub struct AppCallbackService { + pub collection: Collection, +} + +impl AppCallbackService { + /// Add a newly created product variant to MongoDB. + async fn add_product_variant_to_mongodb(&self, product_variant_id: Uuid) -> Result<(), Status> { + let product_variant = ProductVariant { + id: product_variant_id, + }; + match self.collection.insert_one(product_variant, None).await { + Ok(_) => Ok(()), + Err(_) => Err(Status::internal( + "Adding product variant failed in MongoDB.", + )), + } + } +} #[tonic::async_trait] impl AppCallback for AppCallbackService { @@ -39,11 +60,17 @@ impl AppCallback for AppCallbackService { ) -> Result, Status> { let r = request.into_inner(); let data = &r.data; - let data_content_type = &r.data_content_type; let message = String::from_utf8_lossy(data); + let error_message = format!("Expected message to be parsable JSON, got: {}", message); + let message_json = json::parse(&message).map_err(|_| Status::internal(error_message))?; + let product_variant_id_json_value = &message_json["id"]; + let product_variant_id = parse_product_variant_id(product_variant_id_json_value)?; + println!("Message: {}", &message); - println!("Content-Type: {}", &data_content_type); + + self.add_product_variant_to_mongodb(product_variant_id) + .await?; Ok(Response::new(TopicEventResponse::default())) } @@ -64,3 +91,28 @@ impl AppCallback for AppCallbackService { Ok(Response::new(BindingEventResponse::default())) } } + +/// Parses Uuid from JsonValue containing a String. +fn parse_product_variant_id(product_variant_id_json_value: &JsonValue) -> Result { + match product_variant_id_json_value { + json::JsonValue::String(product_variant_id_string) => { + match Uuid::parse_str(product_variant_id_string) { + Ok(product_variant_id_uuid) => Ok(product_variant_id_uuid), + Err(_) => { + let error_message = format!( + "String value in `id` field cannot be parsed as bson::Uuid, got: {}", + product_variant_id_string + ); + Err(Status::internal(error_message))? + } + } + } + _ => { + let error_message = format!( + "`id` field does not exist or does not contain a String value, got: {}", + product_variant_id_json_value + ); + Err(Status::internal(error_message))? + } + } +} diff --git a/src/main.rs b/src/main.rs index 185095f..cbe19b6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -29,6 +29,8 @@ use mutation::Mutation; mod app_callback_service; use app_callback_service::AppCallbackService; +use crate::foreign_types::ProductVariant; + mod base_connection; mod foreign_types; mod mutation_input_structs; @@ -61,12 +63,12 @@ async fn db_connection() -> Client { /// Establishes connection to Dapr. /// /// Adds AppCallbackService which defines pub/sub interaction with Dapr. -async fn dapr_connection() { - let addr = "[::]:50006".parse().unwrap(); - - let callback_service = AppCallbackService::default(); +async fn dapr_connection(db_client: Database) { + let addr = "[::]:50051".parse().unwrap(); + let collection: mongodb::Collection = + db_client.collection::("product_variants"); - println!("AppCallback server listening on: {}", addr); + let callback_service = AppCallbackService { collection }; // Create a gRPC server with the callback_service. TonicServer::builder() @@ -74,6 +76,8 @@ async fn dapr_connection() { .serve(addr) .await .unwrap(); + + println!("AppCallback server listening on: {}", addr); } /// Can be used to insert dummy wishlist data in the MongoDB database. @@ -119,25 +123,24 @@ async fn main() -> std::io::Result<()> { async fn start_service() { let client = db_connection().await; let db_client: Database = client.database("wishlist-database"); - let collection: mongodb::Collection = db_client.collection::("wishlists"); let schema = Schema::build(Query, Mutation, EmptySubscription) - .data(collection) + .data(db_client.clone()) .enable_federation() .finish(); let app = Router::new().route("/", get(graphiql).post_service(GraphQL::new(schema))); - println!("GraphiQL IDE: http://0.0.0.0:8080"); let t1 = tokio::spawn(async { Server::bind(&"0.0.0.0:8080".parse().unwrap()) .serve(app.into_make_service()) .await .unwrap(); + println!("GraphiQL IDE: http://0.0.0.0:8080"); }); let t2 = tokio::spawn(async { - dapr_connection().await; + dapr_connection(db_client).await; }); t1.await.unwrap(); diff --git a/src/mutation.rs b/src/mutation.rs index 76b29ad..34fe209 100644 --- a/src/mutation.rs +++ b/src/mutation.rs @@ -5,7 +5,7 @@ use bson::Bson; use bson::Uuid; use mongodb::{ bson::{doc, DateTime}, - Collection, + Collection, Database, }; use crate::{ @@ -28,7 +28,12 @@ impl Mutation { ctx: &Context<'a>, #[graphql(desc = "AddWishlistInput")] input: AddWishlistInput, ) -> Result { - let collection: &Collection = ctx.data_unchecked::>(); + let db_client = ctx.data_unchecked::(); + let collection: Collection = db_client.collection::("wishlists"); + let product_variant_collection: Collection = + db_client.collection::("product_variants"); + validate_product_variant_ids(&product_variant_collection, &input.product_variant_ids) + .await?; let normalized_product_variants: HashSet = input .product_variant_ids .iter() @@ -60,10 +65,18 @@ impl Mutation { ctx: &Context<'a>, #[graphql(desc = "UpdateWishlistInput")] input: UpdateWishlistInput, ) -> Result { - let collection: &Collection = ctx.data_unchecked::>(); - + let db_client = ctx.data_unchecked::(); + let collection: Collection = db_client.collection::("wishlists"); + let product_variant_collection: Collection = + db_client.collection::("product_variants"); let current_timestamp = DateTime::now(); - update_product_variant_ids(&collection, &input, ¤t_timestamp).await?; + update_product_variant_ids( + &collection, + &product_variant_collection, + &input, + ¤t_timestamp, + ) + .await?; update_name(&collection, &input, ¤t_timestamp).await?; let wishlist = query_wishlist(&collection, input.id).await?; Ok(wishlist) @@ -75,7 +88,8 @@ impl Mutation { ctx: &Context<'a>, #[graphql(desc = "UUID of wishlist to delete.")] id: Uuid, ) -> Result { - let collection: &Collection = ctx.data_unchecked::>(); + let db_client = ctx.data_unchecked::(); + let collection: Collection = db_client.collection::("wishlists"); if let Err(_) = collection.delete_one(doc! {"_id": id }, None).await { let message = format!("Deleting wishlist of id: `{}` failed in MongoDB.", id); return Err(Error::new(message)); @@ -106,10 +120,13 @@ fn uuid_from_bson(bson: Bson) -> Result { /// * `input` - `UpdateWishlistInput`. async fn update_product_variant_ids( collection: &Collection, + product_variant_collection: &Collection, input: &UpdateWishlistInput, current_timestamp: &DateTime, ) -> Result<()> { if let Some(definitely_product_variant_ids) = &input.product_variant_ids { + validate_product_variant_ids(&product_variant_collection, definitely_product_variant_ids) + .await?; let normalized_product_variants: Vec = definitely_product_variant_ids .iter() .map(|id| ProductVariant { id: id.clone() }) @@ -149,3 +166,30 @@ async fn update_name( } Ok(()) } + +/// Checks if product variants are in the system (MongoDB database populated with events). +/// +/// Used before adding or modifying product variants. +async fn validate_product_variant_ids( + collection: &Collection, + product_variant_ids: &HashSet, +) -> Result<()> { + let product_variant_ids_vec: Vec = product_variant_ids.clone().into_iter().collect(); + match collection + .find_one(doc! {"id": { "$in": product_variant_ids_vec } }, None) + .await + { + Ok(maybe_result) => match maybe_result { + Some(result) => { + println!("{:?}", result); + Ok(()) + } + None => Err(Error::new( + "Product variants with the specified UUIDs are not present in the system.", + )), + }, + Err(_) => Err(Error::new( + "Product variants with the specified UUIDs are not present in the system.", + )), + } +} diff --git a/src/query.rs b/src/query.rs index 7c5a84f..db51b9b 100644 --- a/src/query.rs +++ b/src/query.rs @@ -7,7 +7,7 @@ use crate::{ use async_graphql::{Context, Error, Object, Result}; use bson::Document; use bson::Uuid; -use mongodb::{bson::doc, options::FindOptions, Collection}; +use mongodb::{bson::doc, options::FindOptions, Collection, Database}; use mongodb_cursor_pagination::{error::CursorError, FindResult, PaginatedCursor}; /// Describes GraphQL wishlist queries. @@ -27,7 +27,8 @@ impl Query { WishlistOrderInput, >, ) -> Result { - let collection: &Collection = ctx.data_unchecked::>(); + let db_client = ctx.data_unchecked::(); + let collection: Collection = db_client.collection::("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() @@ -56,7 +57,8 @@ impl Query { ctx: &Context<'a>, #[graphql(desc = "UUID of wishlist to retrieve.")] id: Uuid, ) -> Result { - let collection: &Collection = ctx.data_unchecked::>(); + let db_client = ctx.data_unchecked::(); + let collection: Collection = db_client.collection::("wishlists"); query_wishlist(&collection, id).await } @@ -67,7 +69,8 @@ impl Query { ctx: &Context<'a>, #[graphql(key, desc = "UUID of wishlist to retrieve.")] id: Uuid, ) -> Result { - let collection: &Collection = ctx.data_unchecked::>(); + let db_client = ctx.data_unchecked::(); + let collection: Collection = db_client.collection::("wishlists"); query_wishlist(&collection, id).await } } From 3d27e0e954eb148c6756516824f1b54c8296e2b7 Mon Sep 17 00:00:00 2001 From: st170001 Date: Tue, 23 Jan 2024 14:57:18 +0100 Subject: [PATCH 2/7] Validate product variant ids with fold --- src/app_callback_service.rs | 4 ++-- src/foreign_types.rs | 8 ++++---- src/main.rs | 2 +- src/mutation.rs | 29 +++++++++++++++++------------ 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/src/app_callback_service.rs b/src/app_callback_service.rs index 63f0158..f92ab1e 100644 --- a/src/app_callback_service.rs +++ b/src/app_callback_service.rs @@ -13,9 +13,9 @@ pub struct AppCallbackService { impl AppCallbackService { /// Add a newly created product variant to MongoDB. - async fn add_product_variant_to_mongodb(&self, product_variant_id: Uuid) -> Result<(), Status> { + pub async fn add_product_variant_to_mongodb(&self, product_variant_id: Uuid) -> Result<(), Status> { let product_variant = ProductVariant { - id: product_variant_id, + _id: product_variant_id, }; match self.collection.insert_one(product_variant, None).await { Ok(_) => Ok(()), diff --git a/src/foreign_types.rs b/src/foreign_types.rs index 1277227..d9f975a 100644 --- a/src/foreign_types.rs +++ b/src/foreign_types.rs @@ -8,7 +8,7 @@ use std::{cmp::Ordering, hash::Hash}; #[graphql(unresolvable)] pub struct User { /// UUID of the user. - pub id: Uuid, + pub _id: Uuid, } /// Foreign type of a product variant. @@ -16,17 +16,17 @@ pub struct User { #[graphql(unresolvable)] pub struct ProductVariant { /// UUID of the product variant. - pub id: Uuid, + pub _id: Uuid, } impl PartialOrd for ProductVariant { fn partial_cmp(&self, other: &Self) -> Option { - self.id.partial_cmp(&other.id) + self._id.partial_cmp(&other._id) } } impl From for Bson { fn from(value: ProductVariant) -> Self { - Bson::Document(doc!("id": value.id)) + Bson::Document(doc!("id": value._id)) } } diff --git a/src/main.rs b/src/main.rs index cbe19b6..4b9aefb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -85,7 +85,7 @@ async fn dapr_connection(db_client: Database) { async fn insert_dummy_data(collection: &Collection) { let wishlists: Vec = vec![Wishlist { _id: Uuid::new(), - user: User { id: Uuid::new() }, + user: User { _id: Uuid::new() }, internal_product_variants: HashSet::new(), name: String::from("test"), created_at: DateTime::now(), diff --git a/src/mutation.rs b/src/mutation.rs index 34fe209..bd29f03 100644 --- a/src/mutation.rs +++ b/src/mutation.rs @@ -3,6 +3,7 @@ use std::collections::HashSet; use async_graphql::{Context, Error, Object, Result}; use bson::Bson; use bson::Uuid; +use futures::TryStreamExt; use mongodb::{ bson::{doc, DateTime}, Collection, Database, @@ -37,12 +38,12 @@ impl Mutation { let normalized_product_variants: HashSet = input .product_variant_ids .iter() - .map(|id| ProductVariant { id: id.clone() }) + .map(|id| ProductVariant { _id: id.clone() }) .collect(); let current_timestamp = DateTime::now(); let wishlist = Wishlist { _id: Uuid::new(), - user: User { id: input.user_id }, + user: User { _id: input.user_id }, internal_product_variants: normalized_product_variants, name: input.name, created_at: current_timestamp, @@ -129,7 +130,7 @@ async fn update_product_variant_ids( .await?; let normalized_product_variants: Vec = definitely_product_variant_ids .iter() - .map(|id| ProductVariant { id: id.clone() }) + .map(|id| ProductVariant { _id: id.clone() }) .collect(); if let Err(_) = collection.update_one(doc!{"_id": input.id }, doc!{"$set": {"internal_product_variants": normalized_product_variants, "last_updated_at": current_timestamp}}, None).await { let message = format!("Updating product_variant_ids of wishlist of id: `{}` failed in MongoDB.", input.id); @@ -176,17 +177,21 @@ async fn validate_product_variant_ids( ) -> Result<()> { let product_variant_ids_vec: Vec = product_variant_ids.clone().into_iter().collect(); match collection - .find_one(doc! {"id": { "$in": product_variant_ids_vec } }, None) + .find(doc! {"_id": { "$in": &product_variant_ids_vec } }, None) .await { - Ok(maybe_result) => match maybe_result { - Some(result) => { - println!("{:?}", result); - Ok(()) - } - None => Err(Error::new( - "Product variants with the specified UUIDs are not present in the system.", - )), + Ok(cursor) => { + let product_variants: Vec = cursor.try_collect().await?; + dbg!(&product_variants); + product_variant_ids_vec.iter().fold(Ok(()), |_, p| { + match product_variants.contains(&ProductVariant { _id: *p }) { + true => Ok(()), + false => { + let message = format!("Product variant with the UUID: `{}` is not present in the system.", p); + Err(Error::new(message)) + } + } + }) }, Err(_) => Err(Error::new( "Product variants with the specified UUIDs are not present in the system.", From fb576b2ea82cc89dc601dd1baa3cd76488684755 Mon Sep 17 00:00:00 2001 From: st170001 Date: Tue, 23 Jan 2024 15:04:12 +0100 Subject: [PATCH 3/7] Removed dbg --- src/mutation.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mutation.rs b/src/mutation.rs index bd29f03..1cfbc81 100644 --- a/src/mutation.rs +++ b/src/mutation.rs @@ -182,7 +182,6 @@ async fn validate_product_variant_ids( { Ok(cursor) => { let product_variants: Vec = cursor.try_collect().await?; - dbg!(&product_variants); product_variant_ids_vec.iter().fold(Ok(()), |_, p| { match product_variants.contains(&ProductVariant { _id: *p }) { true => Ok(()), From bbd79571da74c573d654784f67bb385d66c01d74 Mon Sep 17 00:00:00 2001 From: st170001 Date: Tue, 23 Jan 2024 19:06:20 +0100 Subject: [PATCH 4/7] Logging for GraphQL and server start messages --- Cargo.toml | 4 +++- src/app_callback_service.rs | 3 ++- src/main.rs | 17 +++++++++++------ 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1df3b52..4f60c7e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -async-graphql = { version = "6.0.11", features = ["bson", "chrono", "uuid"] } +async-graphql = { version = "6.0.11", features = ["bson", "chrono", "uuid", "log"] } async-graphql-axum = "6.0.11" tokio = { version = "1.8", features = ["macros", "rt-multi-thread"] } hyper = "1.0.1" @@ -22,3 +22,5 @@ mongodb-cursor-pagination = "0.3.2" dapr = "0.13.0" tonic = "0.8" json = "0.12.4" +log = "0.4.20" +simple_logger = "4.3.3" \ No newline at end of file diff --git a/src/app_callback_service.rs b/src/app_callback_service.rs index f92ab1e..d972ac3 100644 --- a/src/app_callback_service.rs +++ b/src/app_callback_service.rs @@ -1,4 +1,5 @@ use json::JsonValue; +use log::info; use mongodb::Collection; use tonic::{Request, Response, Status}; @@ -67,7 +68,7 @@ impl AppCallback for AppCallbackService { let product_variant_id_json_value = &message_json["id"]; let product_variant_id = parse_product_variant_id(product_variant_id_json_value)?; - println!("Message: {}", &message); + info!("Event with message was received: {}", &message); self.add_product_variant_to_mongodb(product_variant_id) .await?; diff --git a/src/main.rs b/src/main.rs index 4b9aefb..02786ca 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ use std::{collections::HashSet, env, fs::File, io::Write}; -use async_graphql::{http::GraphiQLSource, EmptySubscription, SDLExportOptions, Schema}; +use simple_logger::SimpleLogger; +use async_graphql::{extensions::Logger, http::GraphiQLSource, EmptySubscription, SDLExportOptions, Schema}; use async_graphql_axum::GraphQL; use axum::{ response::{self, IntoResponse}, @@ -10,6 +11,7 @@ use axum::{ use clap::{arg, command, Parser}; use foreign_types::User; +use log::info; use mongodb::{bson::DateTime, options::ClientOptions, Client, Collection, Database}; use dapr::dapr::dapr::proto::runtime::v1::app_callback_server::AppCallbackServer; @@ -70,14 +72,13 @@ async fn dapr_connection(db_client: Database) { let callback_service = AppCallbackService { collection }; + info!("AppCallback server listening on: {}", addr); // Create a gRPC server with the callback_service. TonicServer::builder() .add_service(AppCallbackServer::new(callback_service)) .serve(addr) .await - .unwrap(); - - println!("AppCallback server listening on: {}", addr); + .unwrap(); } /// Can be used to insert dummy wishlist data in the MongoDB database. @@ -103,8 +104,11 @@ struct Args { generate_schema: bool, } +/// Activates logger and parses argument for optional schema generation. Otherwise starts gRPC and GraphQL server. #[tokio::main] async fn main() -> std::io::Result<()> { + SimpleLogger::new().init().unwrap(); + let args = Args::parse(); if args.generate_schema { let schema = Schema::build(Query, Mutation, EmptySubscription).finish(); @@ -112,7 +116,7 @@ async fn main() -> std::io::Result<()> { let sdl_export_options = SDLExportOptions::new().federation(); let schema_sdl = schema.sdl_with_options(sdl_export_options); file.write_all(schema_sdl.as_bytes())?; - println!("GraphQL schema: ./schemas/wishlist.graphql was successfully generated!"); + info!("GraphQL schema: ./schemas/wishlist.graphql was successfully generated!"); } else { start_service().await; } @@ -125,6 +129,7 @@ async fn start_service() { let db_client: Database = client.database("wishlist-database"); let schema = Schema::build(Query, Mutation, EmptySubscription) + .extension(Logger) .data(db_client.clone()) .enable_federation() .finish(); @@ -132,11 +137,11 @@ async fn start_service() { let app = Router::new().route("/", get(graphiql).post_service(GraphQL::new(schema))); let t1 = tokio::spawn(async { + info!("GraphiQL IDE: http://0.0.0.0:8080"); Server::bind(&"0.0.0.0:8080".parse().unwrap()) .serve(app.into_make_service()) .await .unwrap(); - println!("GraphiQL IDE: http://0.0.0.0:8080"); }); let t2 = tokio::spawn(async { From 6a163f6286dfb7efc7a875fef11edae24f20fa07 Mon Sep 17 00:00:00 2001 From: st170001 Date: Tue, 23 Jan 2024 19:28:02 +0100 Subject: [PATCH 5/7] Reformat --- src/app_callback_service.rs | 5 ++++- src/main.rs | 8 +++++--- src/mutation.rs | 9 ++++++--- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/app_callback_service.rs b/src/app_callback_service.rs index d972ac3..e9873c7 100644 --- a/src/app_callback_service.rs +++ b/src/app_callback_service.rs @@ -14,7 +14,10 @@ pub struct AppCallbackService { impl AppCallbackService { /// Add a newly created product variant to MongoDB. - pub async fn add_product_variant_to_mongodb(&self, product_variant_id: Uuid) -> Result<(), Status> { + pub async fn add_product_variant_to_mongodb( + &self, + product_variant_id: Uuid, + ) -> Result<(), Status> { let product_variant = ProductVariant { _id: product_variant_id, }; diff --git a/src/main.rs b/src/main.rs index 02786ca..8dd57a0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,8 @@ use std::{collections::HashSet, env, fs::File, io::Write}; -use simple_logger::SimpleLogger; -use async_graphql::{extensions::Logger, http::GraphiQLSource, EmptySubscription, SDLExportOptions, Schema}; +use async_graphql::{ + extensions::Logger, http::GraphiQLSource, EmptySubscription, SDLExportOptions, Schema, +}; use async_graphql_axum::GraphQL; use axum::{ response::{self, IntoResponse}, @@ -9,6 +10,7 @@ use axum::{ Router, Server, }; use clap::{arg, command, Parser}; +use simple_logger::SimpleLogger; use foreign_types::User; use log::info; @@ -78,7 +80,7 @@ async fn dapr_connection(db_client: Database) { .add_service(AppCallbackServer::new(callback_service)) .serve(addr) .await - .unwrap(); + .unwrap(); } /// Can be used to insert dummy wishlist data in the MongoDB database. diff --git a/src/mutation.rs b/src/mutation.rs index 1cfbc81..92ef6f6 100644 --- a/src/mutation.rs +++ b/src/mutation.rs @@ -169,7 +169,7 @@ async fn update_name( } /// Checks if product variants are in the system (MongoDB database populated with events). -/// +/// /// Used before adding or modifying product variants. async fn validate_product_variant_ids( collection: &Collection, @@ -186,12 +186,15 @@ async fn validate_product_variant_ids( match product_variants.contains(&ProductVariant { _id: *p }) { true => Ok(()), false => { - let message = format!("Product variant with the UUID: `{}` is not present in the system.", p); + let message = format!( + "Product variant with the UUID: `{}` is not present in the system.", + p + ); Err(Error::new(message)) } } }) - }, + } Err(_) => Err(Error::new( "Product variants with the specified UUIDs are not present in the system.", )), From 15ccc7b0c72c9d146ce57e255fe9b255aadfe440 Mon Sep 17 00:00:00 2001 From: st170001 Date: Tue, 23 Jan 2024 19:33:43 +0100 Subject: [PATCH 6/7] Updated README --- README.md | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 59e9174..263731e 100644 --- a/README.md +++ b/README.md @@ -12,25 +12,22 @@ ### What it can do - CRUD wishlists: - ```rust - pub struct Wishlist { - pub id: Uuid, - pub user_id: Uuid, - pub product_variants: HashSet, - pub name: String, - pub created_at: DateTime, - pub last_updated_at: DateTime, - } - - /// Foreign ProductVariant - pub struct ProductVariant{ - id: Uuid - } - ``` -- Validates all UUIDs input as strings -- Error prop to GraphQL -### Configuration + ```rust + pub struct Wishlist { + pub id: Uuid, + pub user_id: Uuid, + pub product_variants: HashSet, + pub name: String, + pub created_at: DateTime, + pub last_updated_at: DateTime, + } + + /// Foreign ProductVariant + pub struct ProductVariant{ + id: Uuid + } + ``` -- The environment variables `${MONGODB_USERNAME}` and `${MONGODB_PASSWORD}` should be set in production to configure the database credentials. -- `${MONGODB_URL}` can be reconfigured in `.env` for experimentation purposes. \ No newline at end of file +- Validates all UUIDs input as strings +- Error prop to GraphQL From 5966ab0ec91923518b81767624ffc7d6fb8062b5 Mon Sep 17 00:00:00 2001 From: st170001 Date: Tue, 23 Jan 2024 20:58:28 +0100 Subject: [PATCH 7/7] BSON conversion bugfix --- src/foreign_types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/foreign_types.rs b/src/foreign_types.rs index d9f975a..049c754 100644 --- a/src/foreign_types.rs +++ b/src/foreign_types.rs @@ -27,6 +27,6 @@ impl PartialOrd for ProductVariant { impl From for Bson { fn from(value: ProductVariant) -> Self { - Bson::Document(doc!("id": value._id)) + Bson::Document(doc!("_id": value._id)) } }