Skip to content

Commit

Permalink
add shop item support
Browse files Browse the repository at this point in the history
  • Loading branch information
Your Name committed May 22, 2024
1 parent 16065ff commit af95fd0
Show file tree
Hide file tree
Showing 6 changed files with 302 additions and 88 deletions.
208 changes: 208 additions & 0 deletions src/panelapi/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use crate::panelapi::types::{
partners::{CreatePartner, Partner, PartnerAction, PartnerType, Partners},
rpc::RPCWebAction,
rpclogs::RPCLogEntry,
shop_items::{ShopItem, ShopItemAction},
staff_disciplinary::StaffDisciplinaryTypeAction,
staff_positions::StaffPosition,
vote_credit_tiers::{VoteCreditTier, VoteCreditTierAction},
Expand Down Expand Up @@ -103,6 +104,8 @@ pub async fn init_panelapi(pool: PgPool, cache_http: botox::cache::CacheHttpImpl
StaffMemberAction,
StaffDisciplinaryTypeAction,
VoteCreditTierAction,
ShopItem,
ShopItemAction,
BotWhitelistAction,
Link,
))
Expand Down Expand Up @@ -346,6 +349,13 @@ pub enum PanelQuery {
/// Action
action: VoteCreditTierAction,
},
/// Fetch and update/modify shop items
UpdateShopItems {
/// Login token
login_token: String,
/// Action
action: ShopItemAction,
},
/// Fetch and update/modify bot whitelist
UpdateBotWhitelist {
/// Login token
Expand Down Expand Up @@ -3843,6 +3853,204 @@ async fn query(
}
}
}
PanelQuery::UpdateShopItems {
login_token,
action,
} => {
let auth_data = super::auth::check_auth(&state.pool, &login_token)
.await
.map_err(Error::new)?;

let user_perms = get_user_perms(&state.pool, &auth_data.user_id)
.await
.map_err(Error::new)?
.resolve();

match action {
ShopItemAction::List => {
let rows = sqlx::query!(
"SELECT id, name, cents, target_types, benefits, created_at, last_updated, created_by, updated_by, duration, description FROM shop_items ORDER BY created_at DESC"
)
.fetch_all(&state.pool)
.await
.map_err(Error::new)?;

let mut entries = Vec::new();

for row in rows {
entries.push(ShopItem {
id: row.id,
name: row.name,
cents: row.cents,
target_types: row.target_types,
benefits: row.benefits,
created_at: row.created_at,
last_updated: row.last_updated,
created_by: row.created_by,
updated_by: row.updated_by,
duration: row.duration,
description: row.description,
});
}

Ok((StatusCode::OK, Json(entries)).into_response())
}
ShopItemAction::Create {
id,
name,
cents,
target_types,
benefits,
duration,
description,
} => {
if !perms::has_perm(&user_perms, &"shop_items.create".into()) {
return Ok((
StatusCode::FORBIDDEN,
"You do not have permission to create shop items [shop_items.create]"
.to_string(),
)
.into_response());
}

if cents < 0.0 {
return Ok((
StatusCode::BAD_REQUEST,
"Cents cannot be lower than 0".to_string(),
)
.into_response());
}

if duration < 0 {
return Ok((
StatusCode::BAD_REQUEST,
"Duration cannot be lower than 0".to_string(),
)
.into_response());
}

// Insert entry
sqlx::query!(
"INSERT INTO shop_items (id, name, cents, target_types, benefits, created_by, updated_by, duration, description) VALUES ($1, $2, $3, $4, $5, $6, $6, $7, $8)",
id,
name,
cents,
&target_types,
&benefits,
&auth_data.user_id,
duration,
description,
)
.execute(&state.pool)
.await
.map_err(Error::new)?;

Ok((StatusCode::NO_CONTENT, "").into_response())
}
ShopItemAction::Edit {
id,
name,
cents,
target_types,
benefits,
duration,
description,
} => {
if !perms::has_perm(&user_perms, &"shop_items.update".into()) {
return Ok((
StatusCode::FORBIDDEN,
"You do not have permission to update shop items [shop_items.update]"
.to_string(),
)
.into_response());
}

if cents < 0.0 {
return Ok((
StatusCode::BAD_REQUEST,
"Cents cannot be lower than 0".to_string(),
)
.into_response());
}

if duration < 0 {
return Ok((
StatusCode::BAD_REQUEST,
"Duration cannot be lower than 0".to_string(),
)
.into_response());
}

// Check if entry already exists with same id
if sqlx::query!("SELECT COUNT(*) FROM shop_items WHERE id = $1", id)
.fetch_one(&state.pool)
.await
.map_err(Error::new)?
.count
.unwrap_or(0)
== 0
{
return Ok((
StatusCode::BAD_REQUEST,
"Entry with same id does not already exist".to_string(),
)
.into_response());
}

// Update entry
sqlx::query!(
"UPDATE shop_items SET name = $1, cents = $2, target_types = $3, benefits = $4, last_updated = NOW(), updated_by = $5, duration = $6, description = $7 WHERE id = $8",
name,
cents,
&target_types,
&benefits,
&auth_data.user_id,
duration,
description,
id,
)
.execute(&state.pool)
.await
.map_err(Error::new)?;

Ok((StatusCode::NO_CONTENT, "").into_response())
}
ShopItemAction::Delete { id } => {
if !perms::has_perm(&user_perms, &"shop_items.delete".into()) {
return Ok((
StatusCode::FORBIDDEN,
"You do not have permission to delete shop items [shop_items.delete]"
.to_string(),
)
.into_response());
}

// Check if entry already exists with same vesion
if sqlx::query!("SELECT COUNT(*) FROM shop_items WHERE id = $1", id)
.fetch_one(&state.pool)
.await
.map_err(Error::new)?
.count
.unwrap_or(0)
== 0
{
return Ok((
StatusCode::BAD_REQUEST,
"Entry with same id does not already exist".to_string(),
)
.into_response());
}

// Delete entry
sqlx::query!("DELETE FROM shop_items WHERE id = $1", id)
.execute(&state.pool)
.await
.map_err(Error::new)?;

Ok((StatusCode::NO_CONTENT, "").into_response())
}
}
}
PanelQuery::UpdateBotWhitelist {
login_token,
action,
Expand Down
1 change: 1 addition & 0 deletions src/panelapi/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub mod entity;
pub mod partners;
pub mod rpc;
pub mod rpclogs;
pub mod shop_items;
pub mod staff_disciplinary;
pub mod staff_members;
pub mod staff_positions;
Expand Down
90 changes: 90 additions & 0 deletions src/panelapi/types/shop_items.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
use serde::{Deserialize, Serialize};
use strum_macros::{Display, EnumString, EnumVariantNames};
use ts_rs::TS;
use utoipa::ToSchema;

/// Shop items are items that can be purchased by users on the shop
#[derive(Serialize, Deserialize, TS, Clone, ToSchema)]
#[ts(export, export_to = ".generated/ShopItem.ts")]
pub struct ShopItem {
/// The ID of the shop item
pub id: String,
/// The friendly name of the shop item
pub name: String,
/// The description of the shop item
pub description: String,
/// The cents the shop item costs
pub cents: f64,
/// The target type
pub target_types: Vec<String>,
/// The benefits of the shop item
pub benefits: Vec<String>,
/// The number of hours the shop item lasts for
pub duration: i32,
/// The time the shop item was created
pub created_at: chrono::DateTime<chrono::Utc>,
/// The time the shop item was last updated
pub last_updated: chrono::DateTime<chrono::Utc>,
/// Who created the shop item
pub created_by: String,
/// Who last updated the shop item
pub updated_by: String,
}

#[derive(
Serialize,
Deserialize,
ToSchema,
TS,
EnumString,
EnumVariantNames,
Display,
Clone,
PartialEq,
Default,
)]
#[ts(export, export_to = ".generated/ShopItemAction.ts")]
pub enum ShopItemAction {
/// List all current shop items
#[default]
List,
/// Create a new shop item
Create {
/// The ID of the shop item
id: String,
/// The friendly name of the shop item
name: String,
/// The description of the shop item
description: String,
/// The cents the shop item costs
cents: f64,
/// The target type
target_types: Vec<String>,
/// The benefits of the shop item
benefits: Vec<String>,
/// The number of hours the shop item lasts for
duration: i32,
},
/// Edit a shop item
Edit {
/// The ID of the shop item
id: String,
/// The friendly name of the shop item
name: String,
/// The description of the shop item
description: String,
/// The cents the shop item costs
cents: f64,
/// The target type
target_types: Vec<String>,
/// The benefits of the shop item
benefits: Vec<String>,
/// The number of hours the shop item lasts for
duration: i32,
},
/// Deletes a shop item
Delete {
/// The ID of the shop item
id: String,
},
}
18 changes: 0 additions & 18 deletions src/panelapi/types/vote_credit_tiers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,6 @@ pub enum VoteCreditTierAction {
votes: i32,
},
/// Edit vote credit tier
///
/// To edit index, use the `SwapIndex` action
EditTier {
/// The ID of the tier
id: String,
Expand All @@ -83,20 +81,4 @@ pub enum VoteCreditTierAction {
/// The ID of the tier
id: String,
},
/*
/// Swap the index of two vote credit tiers (A and B) such that the indexes change from (Ia, Ib) -> (Ib, Ia)
SwapIndex {
/// Vote Credit Tier A
a: String,
/// Vote Credit Tier B
b: String,
},
/// Sets the new index of a vote credit tier
SetIndex {
/// The ID of the tier
id: String,
/// The new index of the tier
index: i32,
},
*/
}

0 comments on commit af95fd0

Please sign in to comment.