Skip to content

Commit

Permalink
add status request, bump mongodb to ver 3
Browse files Browse the repository at this point in the history
  • Loading branch information
Kirill-K-1 committed Jul 22, 2024
1 parent 3e02d2f commit 12ba51e
Show file tree
Hide file tree
Showing 8 changed files with 181 additions and 43 deletions.
42 changes: 22 additions & 20 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ tracing-subscriber = { version = "0", features = [ "env-filter", "registry" ] }
log = "0"

# Persistence
mongodb = "2"
mongodb = "3"
redis = "0"

# Misc
Expand Down
27 changes: 26 additions & 1 deletion gov-portal-db/src/server.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use axum::{extract::State, routing::post, Json, Router};
use axum::{
extract::State,
routing::{get, post},
Json, Router,
};
use chrono::{DateTime, Utc};
use ethereum_types::Address;
use jsonwebtoken::TokenData;
Expand Down Expand Up @@ -150,6 +154,7 @@ pub async fn start(config: AppConfig, users_manager: Arc<UsersManager>) -> Resul

let app = Router::new()
.route("/token", post(token_route))
.route("/status", get(status_route))
.route("/user", post(user_route))
.route("/users", post(users_route))
.route("/update-user", post(update_user_route))
Expand Down Expand Up @@ -188,6 +193,26 @@ async fn token_route(
res.map(Json)
}

/// Route handler to read User's profile from MongoDB
async fn status_route(
State(state): State<AppState>,
Json(token): Json<SessionToken>,
) -> Result<Json<()>, String> {
tracing::debug!("[/status] Request {token:?}");

let res = state
.users_manager
.mongo_client
.server_status()
.await
.map(|_| ())
.map_err(|e| e.to_string());

tracing::debug!("[/status] Response {res:?}");

res.map(Json)
}

/// Route handler to read User's profile from MongoDB
async fn user_route(
State(state): State<AppState>,
Expand Down
37 changes: 23 additions & 14 deletions gov-portal-db/src/users_manager/mongo_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use serde::Deserialize;
/// MongoDB client
#[derive(Clone)]
pub struct MongoClient {
pub db: mongodb::Database,
/// Collection being accessed by insert/update/query requests
pub collection: Collection<Document>,
/// MongoDB query maximum timeout
Expand Down Expand Up @@ -60,21 +61,32 @@ impl MongoClient {
.await
.and_then(Client::with_options)?;

let collection = initialize_collection(&inner, &config.db, &config.collection).await?;
// Get a handle to a database.
let db = inner.database(&config.db);

let collection = initialize_collection(&db, &config.collection).await?;

Ok(Self {
db,
collection,
req_timeout: std::time::Duration::from_secs(config.request_timeout),
})
}

pub async fn server_status(&self) -> Result<bson::Document, mongodb::error::Error> {
self.db.run_command(bson::doc! { "serverStatus": 1 }).await
}

/// Query request from collection by filter
pub async fn find(
&self,
filter: impl Into<Option<Document>>,
filter: impl Into<Document>,
find_options: impl Into<Option<FindOptions>>,
) -> Result<Cursor<Document>, mongodb::error::Error> {
self.collection.find(filter, find_options).await
self.collection
.find(filter.into())
.with_options(find_options)
.await
}

/// Insert single document to collection
Expand All @@ -84,7 +96,7 @@ impl MongoClient {
doc: impl std::borrow::Borrow<Document>,
options: impl Into<Option<InsertOneOptions>>,
) -> Result<InsertOneResult, mongodb::error::Error> {
self.collection.insert_one(doc, options).await
self.collection.insert_one(doc).with_options(options).await
}

/// Updates single document in collection by filter query
Expand All @@ -94,29 +106,28 @@ impl MongoClient {
update: impl Into<UpdateModifications>,
options: impl Into<Option<UpdateOptions>>,
) -> Result<UpdateResult, mongodb::error::Error> {
self.collection.update_one(query, update, options).await
self.collection
.update_one(query, update)
.with_options(options)
.await
}
}

async fn initialize_collection(
client: &Client,
db_name: &str,
db: &mongodb::Database,
collection_name: &str,
) -> anyhow::Result<Collection<Document>> {
// Get a handle to a database.
let db = client.database(db_name);

// Get a handle to a collection in the database.
let collection = db.collection::<Document>(collection_name);

// Create new collection (if not present in database) and unique index by wallet address
if !db
.list_collection_names(None)
.list_collection_names()
.await?
.into_iter()
.any(|it| it.as_str() == collection_name)
{
db.create_collection(collection_name, None).await?;
db.create_collection(collection_name).await?;
}

let indexes = collection.list_index_names().await?;
Expand All @@ -130,7 +141,6 @@ async fn initialize_collection(
})
.options(Some(IndexOptions::builder().unique(true).build()))
.build(),
None,
)
.await?;
}
Expand All @@ -144,7 +154,6 @@ async fn initialize_collection(
})
.options(Some(IndexOptions::builder().unique(true).build()))
.build(),
None,
)
.await?;
}
Expand Down
55 changes: 49 additions & 6 deletions gov-portal-db/tests/test_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,49 @@ use assert_matches::assert_matches;
use shared::common::{EmailFrom, User, UserProfile, UserProfileStatus, WrappedCid};
use web3::types::Address;

#[tokio::test]
async fn test_server_status() -> Result<(), anyhow::Error> {
let mongo_config = mongo_client::MongoConfig {
url: Some("mongodb://localhost:27017".to_owned()),
db: "AirDAOGovPortal_IntegrationTest".to_owned(),
collection: "Users".to_owned(),
request_timeout: 10,
};

let users_manager = UsersManager::new(
&mongo_config,
UsersManagerConfig {
secret: "IntegrationTestRegistrationSecretForJWT".to_owned(),
lifetime: std::time::Duration::from_secs(600),
user_profile_attributes: UserProfileAttributes::default(),
email_verification: EmailVerificationConfig {
mailer_base_url: "http://mailer".try_into().unwrap(),
send_timeout: std::time::Duration::from_secs(10),
template_url: "https://registration?token={{VERIFICATION_TOKEN}}".to_string(),
from: EmailFrom {
email: "gwg@airdao.io".try_into().unwrap(),
name: "AirDAO Gov Portal".to_string(),
},
subject: "Complete Your Governor Email Verification".to_string(),
},
moderators: vec![],
},
)
.await?;

users_manager
.mongo_client
.collection
.delete_many(bson::doc! {})
.await?;

assert!(users_manager.mongo_client.server_status().await.is_ok());

users_manager.mongo_client.collection.drop().await?;

Ok(())
}

#[tokio::test]
async fn test_upsert_user() -> Result<(), anyhow::Error> {
let mongo_config = mongo_client::MongoConfig {
Expand Down Expand Up @@ -41,7 +84,7 @@ async fn test_upsert_user() -> Result<(), anyhow::Error> {
users_manager
.mongo_client
.collection
.delete_many(bson::doc! {}, None)
.delete_many(bson::doc! {})
.await?;

let addr_1 = Address::from_low_u64_le(1);
Expand Down Expand Up @@ -72,7 +115,7 @@ async fn test_upsert_user() -> Result<(), anyhow::Error> {
.upsert_user(addr_1, "test1@test.com".try_into()?)
.await?;

users_manager.mongo_client.collection.drop(None).await?;
users_manager.mongo_client.collection.drop().await?;

Ok(())
}
Expand Down Expand Up @@ -118,7 +161,7 @@ async fn test_users_endpoint() -> Result<(), anyhow::Error> {
users_manager
.mongo_client
.collection
.delete_many(bson::doc! {}, None)
.delete_many(bson::doc! {})
.await?;

futures_util::future::join_all((1u64..=9).map(|i| {
Expand Down Expand Up @@ -183,7 +226,7 @@ async fn test_users_endpoint() -> Result<(), anyhow::Error> {
]
);

users_manager.mongo_client.collection.drop(None).await?;
users_manager.mongo_client.collection.drop().await?;

Ok(())
}
Expand Down Expand Up @@ -267,7 +310,7 @@ async fn test_complete_profile() -> Result<(), anyhow::Error> {
users_manager
.mongo_client
.collection
.delete_many(bson::doc! {}, None)
.delete_many(bson::doc! {})
.await?;

let quiz_result = quiz.verify_answers(vec![
Expand Down Expand Up @@ -341,7 +384,7 @@ async fn test_complete_profile() -> Result<(), anyhow::Error> {
})
);

users_manager.mongo_client.collection.drop(None).await?;
users_manager.mongo_client.collection.drop().await?;

Ok(())
}
Loading

0 comments on commit 12ba51e

Please sign in to comment.