Skip to content

Commit b107770

Browse files
Merge pull request #272 from GideonBature/testnet
add custom_api directory with create and update
2 parents ca27945 + 33a9fa6 commit b107770

File tree

6 files changed

+167
-3
lines changed

6 files changed

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

src/endpoints/admin/custom_api/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pub mod create_custom_api;
2+
pub mod update_custom_api;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
use crate::models::QuestTaskDocument;
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;
13+
use serde::Deserialize;
14+
use serde_json::json;
15+
use std::sync::Arc;
16+
17+
pub_struct!(Deserialize; UpdateCustomAPI {
18+
id: i64,
19+
name: Option<String>,
20+
desc: Option<String>,
21+
href: Option<String>,
22+
cta: Option<String>,
23+
api_url: Option<String>,
24+
regex: Option<String>,
25+
});
26+
27+
#[route(post, "/admin/tasks/custom_api/update", auth_middleware)]
28+
pub async fn handler(
29+
State(state): State<Arc<AppState>>,
30+
Extension(sub): Extension<String>,
31+
Json(body): Json<UpdateCustomAPI>,
32+
) -> impl IntoResponse {
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+
if let Some(cta) = &body.cta {
57+
update_doc.insert("cta", cta);
58+
}
59+
if let Some(api_url) = &body.api_url {
60+
update_doc.insert("api_url", api_url);
61+
}
62+
if let Some(regex) = &body.regex {
63+
update_doc.insert("regex", regex);
64+
}
65+
66+
// update quest query
67+
let update = doc! {
68+
"$set": update_doc
69+
};
70+
71+
// insert document to boost collection
72+
return match collection.find_one_and_update(filter, update, None).await {
73+
Ok(_) => (
74+
StatusCode::OK,
75+
Json(json!({"message": "Task updated successfully"})).into_response(),
76+
)
77+
.into_response(),
78+
Err(_e) => get_error("Error updating tasks".to_string()),
79+
};
80+
}

src/endpoints/admin/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ pub mod quest_boost;
1010
pub mod quiz;
1111
pub mod twitter;
1212
pub mod user;
13+
pub mod custom_api;

src/endpoints/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ pub mod has_completed_quest;
1616
pub mod leaderboard;
1717
pub mod quest_boost;
1818
pub mod quests;
19-
pub mod unique_page_visit;
19+
pub mod unique_page_visit;

src/models.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,6 @@ pub struct QuestTaskDocument {
126126
pub verify_endpoint: String,
127127
pub href: String,
128128
pub verify_endpoint_type: String,
129-
pub api_url: Option<String>,
130-
pub regex: Option<String>,
131129
pub calls: Option<Vec<Call>>,
132130
#[serde(default)]
133131
pub verify_redirect: Option<String>,
@@ -139,6 +137,8 @@ pub struct QuestTaskDocument {
139137
pub(crate) discord_guild_id: Option<String>,
140138
#[serde(default)]
141139
pub(crate) contracts: Option<Vec<FieldElement>>,
140+
pub api_url: Option<String>,
141+
pub regex: Option<String>,
142142
}
143143

144144
pub_struct!(Serialize; Reward {

0 commit comments

Comments
 (0)