Skip to content

Commit 4518b11

Browse files
Merge pull request #276 from JoE11-y/testnet
feat: add admin routes for contract tasks
2 parents b107770 + 96dff0c commit 4518b11

File tree

5 files changed

+163
-1
lines changed

5 files changed

+163
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
use crate::models::{QuestDocument, QuestTaskDocument, Call};
2+
use crate::utils::verify_quest_auth;
3+
use crate::{models::AppState, utils::get_error};
4+
use crate::middleware::auth::auth_middleware;
5+
use axum::{
6+
extract::{Extension, State},
7+
http::StatusCode,
8+
response::{IntoResponse, Json}
9+
};
10+
use axum_auto_routes::route;
11+
use mongodb::bson::doc;
12+
use mongodb::options::FindOneOptions;
13+
use serde::Deserialize;
14+
use serde_json::json;
15+
use std::sync::Arc;
16+
17+
pub_struct!(Deserialize; CreateContract {
18+
quest_id: i64,
19+
name: String,
20+
desc: String,
21+
href: String,
22+
cta: String,
23+
calls: Vec<Call>
24+
});
25+
26+
#[route(post, "/admin/tasks/contract/create", auth_middleware)]
27+
pub async fn handler(
28+
State(state): State<Arc<AppState>>,
29+
Extension(sub): Extension<String>,
30+
Json(body): Json<CreateContract>,
31+
) -> impl IntoResponse {
32+
let collection = state.db.collection::<QuestTaskDocument>("tasks");
33+
// Get the last id in increasing order
34+
let last_id_filter = doc! {};
35+
let options = FindOneOptions::builder().sort(doc! {"id": -1}).build();
36+
let last_doc = &collection.find_one(last_id_filter, options).await.unwrap();
37+
38+
let quests_collection = state.db.collection::<QuestDocument>("quests");
39+
40+
let res = verify_quest_auth(sub, &quests_collection, &(body.quest_id as i64)).await;
41+
if !res {
42+
return get_error("Error creating task".to_string());
43+
};
44+
45+
let mut next_id = 1;
46+
if let Some(doc) = last_doc {
47+
let last_id = doc.id;
48+
next_id = last_id + 1;
49+
}
50+
51+
let new_document = QuestTaskDocument {
52+
name: body.name.clone(),
53+
desc: body.desc.clone(),
54+
verify_redirect: None,
55+
href: body.href.clone(),
56+
total_amount: None,
57+
quest_id: body.quest_id,
58+
id: next_id,
59+
cta: body.cta.clone(),
60+
verify_endpoint: "quests/verify_contract".to_string(),
61+
verify_endpoint_type: "default".to_string(),
62+
task_type: Some("contract".to_string()),
63+
discord_guild_id: None,
64+
quiz_name: None,
65+
contracts: None,
66+
calls: Some(body.calls),
67+
api_url: None,
68+
regex: None,
69+
};
70+
71+
// insert document to boost collection
72+
return match collection.insert_one(new_document, None).await {
73+
Ok(_) => (
74+
StatusCode::OK,
75+
Json(json!({"message": "Task created successfully"})).into_response(),
76+
)
77+
.into_response(),
78+
Err(_e) => get_error("Error creating tasks".to_string()),
79+
};
80+
}

src/endpoints/admin/contract/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pub mod create_contract;
2+
pub mod update_contract;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
use crate::models::{QuestTaskDocument, Call};
2+
use crate::{models::AppState, utils::get_error};
3+
use crate::middleware::auth::auth_middleware;
4+
use crate::utils::verify_task_auth;
5+
6+
use axum::{
7+
extract::{Extension, State},
8+
http::StatusCode,
9+
response::{IntoResponse, Json},
10+
};
11+
use axum_auto_routes::route;
12+
use mongodb::bson::{doc, to_bson};
13+
use serde::Deserialize;
14+
use serde_json::json;
15+
use std::sync::Arc;
16+
17+
pub_struct!(Deserialize; UpdateContract {
18+
id: i64,
19+
name: Option<String>,
20+
desc: Option<String>,
21+
href: Option<String>,
22+
cta: Option<String>,
23+
calls: Option<Vec<Call>>
24+
});
25+
26+
#[route(post, "/admin/tasks/contract/update", auth_middleware)]
27+
pub async fn handler(
28+
State(state): State<Arc<AppState>>,
29+
Extension(sub): Extension<String>,
30+
Json(body): Json<UpdateContract>,
31+
) -> impl IntoResponse {
32+
33+
let collection = state.db.collection::<QuestTaskDocument>("tasks");
34+
35+
let res = verify_task_auth(sub, &collection, &(body.id as i32)).await;
36+
if !res {
37+
return get_error("Error updating tasks".to_string());
38+
}
39+
40+
// filter to get existing quest
41+
let filter = doc! {
42+
"id": &body.id,
43+
};
44+
45+
let mut update_doc = doc! {};
46+
47+
if let Some(name) = &body.name {
48+
update_doc.insert("name", name);
49+
}
50+
if let Some(desc) = &body.desc {
51+
update_doc.insert("desc", desc);
52+
}
53+
if let Some(href) = &body.href {
54+
update_doc.insert("href", href);
55+
}
56+
57+
if let Some(cta) = &body.cta {
58+
update_doc.insert("cta", cta);
59+
}
60+
61+
if let Some(calls) = &body.calls {
62+
update_doc.insert("calls", to_bson(calls).unwrap());
63+
}
64+
65+
// update quest query
66+
let update = doc! {
67+
"$set": update_doc
68+
};
69+
70+
// insert document to boost collection
71+
return match collection.find_one_and_update(filter, update, None).await {
72+
Ok(_) => (
73+
StatusCode::OK,
74+
Json(json!({"message": "Task updated successfully"})).into_response(),
75+
)
76+
.into_response(),
77+
Err(_e) => get_error("Error updating tasks".to_string()),
78+
};
79+
}

src/endpoints/admin/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ pub mod quiz;
1111
pub mod twitter;
1212
pub mod user;
1313
pub mod custom_api;
14+
pub mod contract;

src/models.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ pub struct CompletedTaskDocument {
107107
timestamp: i64,
108108
}
109109

110-
#[derive(Debug, Serialize, Deserialize)]
110+
#[derive(Clone, Debug, Deserialize, Serialize)]
111111
pub struct Call {
112112
pub contract: String,
113113
pub call_data: Vec<String>,

0 commit comments

Comments
 (0)