Delete & Post Game Endpoints. Various other changes
This commit is contained in:
parent
790a7dd8ee
commit
07e6df6b64
8 changed files with 493 additions and 107 deletions
src/v3
422
src/v3/mod.rs
422
src/v3/mod.rs
|
@ -1,11 +1,66 @@
|
|||
use std::{vec, collections::HashMap};
|
||||
use std::{collections::HashMap, vec};
|
||||
|
||||
use actix_web::{web::{self, Json}, Responder, get};
|
||||
use actix_web::{
|
||||
delete, get, post, put,
|
||||
web::{self, Json},
|
||||
HttpResponse, Responder,
|
||||
};
|
||||
|
||||
use crate::{AppState, db};
|
||||
use crate::{db, AppState};
|
||||
|
||||
pub(crate) mod schemas;
|
||||
|
||||
fn verify_auth(token: &str, data: &AppState) -> schemas::AuthReturn {
|
||||
let mut auth_return = schemas::AuthReturn {
|
||||
moderator: false,
|
||||
admin: false,
|
||||
};
|
||||
|
||||
if token == data.auth_tokens.admin {
|
||||
auth_return.admin = true;
|
||||
auth_return.moderator = true;
|
||||
} else if token == data.auth_tokens.moderator {
|
||||
auth_return.moderator = true;
|
||||
}
|
||||
|
||||
return auth_return;
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
params(
|
||||
schemas::AuthParams
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "OK", body = AuthReturn),
|
||||
),
|
||||
security(
|
||||
("api_key" = [])
|
||||
),
|
||||
)]
|
||||
#[get("/api/v3/auth")]
|
||||
pub(crate) async fn auth(
|
||||
data: web::Data<AppState>,
|
||||
params: web::Query<schemas::AuthParamsOptional>,
|
||||
) -> impl Responder {
|
||||
let params: schemas::AuthParamsOptional = params.into_inner();
|
||||
|
||||
let mut auth_return = schemas::AuthReturn {
|
||||
moderator: false,
|
||||
admin: false,
|
||||
};
|
||||
|
||||
if let Some(auth_token) = params.token.clone() {
|
||||
if auth_token == data.auth_tokens.admin {
|
||||
auth_return.admin = true;
|
||||
auth_return.moderator = true;
|
||||
} else if auth_token == data.auth_tokens.moderator {
|
||||
auth_return.moderator = true;
|
||||
}
|
||||
}
|
||||
|
||||
Json(auth_return)
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
params(
|
||||
|
||||
|
@ -17,56 +72,53 @@ pub(crate) mod schemas;
|
|||
("api_key" = [])
|
||||
),
|
||||
)]
|
||||
#[get("/full_view_data")]
|
||||
pub(crate) async fn full_view_data(
|
||||
data: web::Data<AppState>
|
||||
) -> impl Responder {
|
||||
#[get("/api/v3/full_view_data")]
|
||||
pub(crate) async fn full_view_data(data: web::Data<AppState>) -> impl Responder {
|
||||
let start = chrono::Local::now(); // DEBUG
|
||||
|
||||
// SQL Queries
|
||||
// TODO: Optimize by utilizing some SQL magic, for now this has to do
|
||||
|
||||
let db_games: Vec<db::schemas::Game> = sqlx::query_as(
|
||||
"SELECT * FROM public.games ORDER BY id",
|
||||
)
|
||||
.fetch_all(&data.db)
|
||||
.await.expect("Error Fetching Data from DB");
|
||||
let db_games: Vec<db::schemas::Game> = sqlx::query_as("SELECT * FROM public.games ORDER BY id")
|
||||
.fetch_all(&data.db)
|
||||
.await
|
||||
.expect("Error Fetching Data from DB");
|
||||
|
||||
let db_groups: Vec<db::schemas::GameGroup> = sqlx::query_as(
|
||||
"SELECT * FROM public.game_groups ORDER BY id",
|
||||
)
|
||||
.fetch_all(&data.db)
|
||||
.await.expect("Error Fetching Data from DB");
|
||||
let db_groups: Vec<db::schemas::GameGroup> =
|
||||
sqlx::query_as("SELECT * FROM public.game_groups ORDER BY id")
|
||||
.fetch_all(&data.db)
|
||||
.await
|
||||
.expect("Error Fetching Data from DB");
|
||||
|
||||
let db_empires: Vec<db::schemas::Empire> = sqlx::query_as(
|
||||
"SELECT * FROM public.empires ORDER BY id",
|
||||
)
|
||||
.fetch_all(&data.db)
|
||||
.await.expect("Error Fetching Data from DB");
|
||||
let db_empires: Vec<db::schemas::Empire> =
|
||||
sqlx::query_as("SELECT * FROM public.empires ORDER BY id")
|
||||
.fetch_all(&data.db)
|
||||
.await
|
||||
.expect("Error Fetching Data from DB");
|
||||
|
||||
let db_ethics: Vec<db::schemas::Ethic> = sqlx::query_as(
|
||||
"SELECT * FROM public.ethics ORDER BY id",
|
||||
)
|
||||
.fetch_all(&data.db)
|
||||
.await.expect("Error Fetching Data from DB");
|
||||
let db_ethics: Vec<db::schemas::Ethic> =
|
||||
sqlx::query_as("SELECT * FROM public.ethics ORDER BY id")
|
||||
.fetch_all(&data.db)
|
||||
.await
|
||||
.expect("Error Fetching Data from DB");
|
||||
|
||||
let db_empire_ethics: Vec<db::schemas::EmpireEthic> = sqlx::query_as(
|
||||
"SELECT * FROM public.empire_ethics ORDER BY empires_id",
|
||||
)
|
||||
.fetch_all(&data.db)
|
||||
.await.expect("Error Fetching Data from DB");
|
||||
let db_empire_ethics: Vec<db::schemas::EmpireEthic> =
|
||||
sqlx::query_as("SELECT * FROM public.empire_ethics ORDER BY empires_id")
|
||||
.fetch_all(&data.db)
|
||||
.await
|
||||
.expect("Error Fetching Data from DB");
|
||||
|
||||
let db_portrait_groups: Vec<db::schemas::PortraitGroup> = sqlx::query_as(
|
||||
"SELECT * FROM public.portrait_groups ORDER BY id",
|
||||
)
|
||||
.fetch_all(&data.db)
|
||||
.await.expect("Error Fetching Data from DB");
|
||||
let db_portrait_groups: Vec<db::schemas::PortraitGroup> =
|
||||
sqlx::query_as("SELECT * FROM public.portrait_groups ORDER BY id")
|
||||
.fetch_all(&data.db)
|
||||
.await
|
||||
.expect("Error Fetching Data from DB");
|
||||
|
||||
let db_portraits: Vec<db::schemas::Portrait> = sqlx::query_as(
|
||||
"SELECT * FROM public.portraits ORDER BY id",
|
||||
)
|
||||
.fetch_all(&data.db)
|
||||
.await.expect("Error Fetching Data from DB");
|
||||
let db_portraits: Vec<db::schemas::Portrait> =
|
||||
sqlx::query_as("SELECT * FROM public.portraits ORDER BY id")
|
||||
.fetch_all(&data.db)
|
||||
.await
|
||||
.expect("Error Fetching Data from DB");
|
||||
|
||||
let mut parsed_data: schemas::FullViewData = schemas::FullViewData {
|
||||
games: HashMap::new(),
|
||||
|
@ -83,7 +135,11 @@ pub(crate) async fn full_view_data(
|
|||
portraits: HashMap::new(),
|
||||
};
|
||||
|
||||
parsed_data.species.entry(species.id).and_modify(|d| *d = new_data.clone()).or_insert(new_data);
|
||||
parsed_data
|
||||
.species
|
||||
.entry(species.id)
|
||||
.and_modify(|d| *d = new_data.clone())
|
||||
.or_insert(new_data);
|
||||
});
|
||||
|
||||
db_portraits.iter().for_each(|portrait| {
|
||||
|
@ -93,7 +149,14 @@ pub(crate) async fn full_view_data(
|
|||
lores: portrait.lores.clone(),
|
||||
};
|
||||
|
||||
parsed_data.species.get_mut(&portrait.group_id).unwrap().portraits.entry(portrait.id).and_modify(|d| *d = new_data.clone()).or_insert(new_data);
|
||||
parsed_data
|
||||
.species
|
||||
.get_mut(&portrait.group_id)
|
||||
.unwrap()
|
||||
.portraits
|
||||
.entry(portrait.id)
|
||||
.and_modify(|d| *d = new_data.clone())
|
||||
.or_insert(new_data);
|
||||
});
|
||||
|
||||
// Games Vector and Children
|
||||
|
@ -105,7 +168,11 @@ pub(crate) async fn full_view_data(
|
|||
groups: HashMap::new(),
|
||||
};
|
||||
|
||||
parsed_data.games.entry(game.id).and_modify(|d| *d = new_data.clone()).or_insert(new_data);
|
||||
parsed_data
|
||||
.games
|
||||
.entry(game.id)
|
||||
.and_modify(|d| *d = new_data.clone())
|
||||
.or_insert(new_data);
|
||||
});
|
||||
|
||||
db_groups.iter().for_each(|group| {
|
||||
|
@ -114,14 +181,21 @@ pub(crate) async fn full_view_data(
|
|||
name: group.name.clone(),
|
||||
};
|
||||
|
||||
parsed_data.games.get_mut(&group.game_id).unwrap().groups.entry(group.id).and_modify(|d| *d = new_data.clone()).or_insert(new_data);
|
||||
parsed_data
|
||||
.games
|
||||
.get_mut(&group.game_id)
|
||||
.unwrap()
|
||||
.groups
|
||||
.entry(group.id)
|
||||
.and_modify(|d| *d = new_data.clone())
|
||||
.or_insert(new_data);
|
||||
});
|
||||
|
||||
db_empires.iter().for_each(|empire| {
|
||||
let new_data = schemas::ChellarisEmpire {
|
||||
id: empire.id,
|
||||
gestalt: empire.gestalt.unwrap_or(false),
|
||||
machine: false, // TODO overwrite this later on with correct data
|
||||
machine: false,
|
||||
group: empire.group_id,
|
||||
empire_portrait: empire.empire_portrait_id,
|
||||
empire_portrait_group: empire.empire_portrait_group_id,
|
||||
|
@ -129,7 +203,14 @@ pub(crate) async fn full_view_data(
|
|||
ethics: HashMap::new(),
|
||||
};
|
||||
|
||||
parsed_data.games.get_mut(&empire.group_game_id).unwrap().empires.entry(empire.id).and_modify(|d| *d = new_data.clone()).or_insert(new_data);
|
||||
parsed_data
|
||||
.games
|
||||
.get_mut(&empire.group_game_id)
|
||||
.unwrap()
|
||||
.empires
|
||||
.entry(empire.id)
|
||||
.and_modify(|d| *d = new_data.clone())
|
||||
.or_insert(new_data);
|
||||
});
|
||||
|
||||
// Ethics Vector
|
||||
|
@ -140,26 +221,259 @@ pub(crate) async fn full_view_data(
|
|||
machine: ethic.machine_ethic,
|
||||
};
|
||||
|
||||
parsed_data.ethics.entry(ethic.id).and_modify(|d| *d = new_data.clone()).or_insert(new_data);
|
||||
parsed_data
|
||||
.ethics
|
||||
.entry(ethic.id)
|
||||
.and_modify(|d| *d = new_data.clone())
|
||||
.or_insert(new_data);
|
||||
});
|
||||
|
||||
println!("{:#?}", parsed_data.ethics); // DEBUG
|
||||
|
||||
db_empire_ethics.iter().for_each(|empire_ethic| {
|
||||
let game_id = empire_ethic.empires_group_game_id;
|
||||
let id = empire_ethic.empires_id;
|
||||
|
||||
let new_data = schemas::EmpireEthic {
|
||||
id: empire_ethic.ethics_id,
|
||||
displayName: parsed_data.ethics[&empire_ethic.ethics_id].displayName.clone(),
|
||||
displayName: parsed_data.ethics[&empire_ethic.ethics_id]
|
||||
.displayName
|
||||
.clone(),
|
||||
machine: parsed_data.ethics[&empire_ethic.ethics_id].machine,
|
||||
fanatic: empire_ethic.ethics_fanatic,
|
||||
};
|
||||
|
||||
parsed_data.games.get_mut(&game_id).unwrap().empires.get_mut(&id).unwrap().ethics.entry(empire_ethic.ethics_id).and_modify(|d| *d = new_data.clone()).or_insert(new_data);
|
||||
if new_data.machine {
|
||||
parsed_data
|
||||
.games
|
||||
.get_mut(&game_id)
|
||||
.unwrap()
|
||||
.empires
|
||||
.get_mut(&id)
|
||||
.unwrap()
|
||||
.machine = true;
|
||||
}
|
||||
|
||||
parsed_data
|
||||
.games
|
||||
.get_mut(&game_id)
|
||||
.unwrap()
|
||||
.empires
|
||||
.get_mut(&id)
|
||||
.unwrap()
|
||||
.ethics
|
||||
.entry(empire_ethic.ethics_id)
|
||||
.and_modify(|d| *d = new_data.clone())
|
||||
.or_insert(new_data);
|
||||
});
|
||||
|
||||
println!("{:?} ms", (chrono::Local::now() - start).to_std().unwrap()); // DEBUG
|
||||
|
||||
|
||||
Json(parsed_data)
|
||||
}
|
||||
|
||||
// Data Fetching Endpoints for Admin/Moderator Menu
|
||||
|
||||
#[utoipa::path(
|
||||
params(),
|
||||
responses(
|
||||
(status = 200, description = "OK", body = HashMap<i32, ChellarisGameLite>),
|
||||
),
|
||||
security(
|
||||
("api_key" = [])
|
||||
),
|
||||
)]
|
||||
#[get("/api/v3/list_games")]
|
||||
pub(crate) async fn list_games(data: web::Data<AppState>) -> impl Responder {
|
||||
// SQL Queries
|
||||
// TODO: Optimize by utilizing some SQL magic, for now this has to do
|
||||
|
||||
let db_games: Vec<db::schemas::Game> = sqlx::query_as("SELECT * FROM public.games ORDER BY id")
|
||||
.fetch_all(&data.db)
|
||||
.await
|
||||
.expect("Error Fetching Data from DB");
|
||||
|
||||
let mut parsed_data: HashMap<i32, schemas::ChellarisGameLite> = HashMap::new();
|
||||
|
||||
// Data processing
|
||||
// Games Vector
|
||||
db_games.iter().for_each(|game| {
|
||||
let new_data = schemas::ChellarisGameLite {
|
||||
id: game.id,
|
||||
name: game.name.clone(),
|
||||
};
|
||||
|
||||
parsed_data
|
||||
.entry(game.id)
|
||||
.and_modify(|d| *d = new_data.clone())
|
||||
.or_insert(new_data);
|
||||
});
|
||||
|
||||
Json(parsed_data)
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
params(
|
||||
schemas::GetGameParam
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "OK", body = HashMap<i32, ChellarisGameLite>),
|
||||
),
|
||||
security(
|
||||
("api_key" = [])
|
||||
),
|
||||
)]
|
||||
#[get("/api/v3/game")]
|
||||
pub(crate) async fn get_game_data(
|
||||
data: web::Data<AppState>,
|
||||
params: web::Query<schemas::GetGameParam>,
|
||||
) -> impl Responder {
|
||||
let params: schemas::GetGameParam = params.into_inner();
|
||||
|
||||
// SQL Queries
|
||||
// TODO: Optimize by utilizing some SQL magic, for now this has to do
|
||||
let db_games: Vec<db::schemas::Game>;
|
||||
if let Some(game_id) = params.game_id {
|
||||
db_games = match sqlx::query_as!(
|
||||
db::schemas::Game,
|
||||
"SELECT * FROM public.games WHERE id = $1 ORDER BY id",
|
||||
game_id as i32
|
||||
)
|
||||
.fetch_one(&data.db)
|
||||
.await
|
||||
{
|
||||
Ok(data) => vec![data],
|
||||
Err(_) => vec![],
|
||||
};
|
||||
} else {
|
||||
db_games = sqlx::query_as("SELECT * FROM public.games ORDER BY id")
|
||||
.fetch_all(&data.db)
|
||||
.await
|
||||
.expect("Error Fetching Data from DB");
|
||||
}
|
||||
|
||||
let mut parsed_data: HashMap<i32, schemas::ChellarisGameLite> = HashMap::new();
|
||||
|
||||
// Data processing
|
||||
// Games Vector
|
||||
db_games.iter().for_each(|game| {
|
||||
let new_data = schemas::ChellarisGameLite {
|
||||
id: game.id,
|
||||
name: game.name.clone(),
|
||||
};
|
||||
|
||||
parsed_data
|
||||
.entry(game.id)
|
||||
.and_modify(|d| *d = new_data.clone())
|
||||
.or_insert(new_data);
|
||||
});
|
||||
|
||||
Json(parsed_data)
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
request_body = PostGameParams,
|
||||
responses(
|
||||
(status = 200, description = "OK", body = ChellarisGameLite),
|
||||
(status = 422, description = "Missing Game Name"),
|
||||
(status = 401, description = "Auth Token Invalid"),
|
||||
),
|
||||
security(
|
||||
("api_key" = [])
|
||||
),
|
||||
)]
|
||||
#[post("/api/v3/game")]
|
||||
pub(crate) async fn create_game(
|
||||
data: web::Data<AppState>,
|
||||
params: web::Json<schemas::PostGameParams>,
|
||||
) -> impl Responder {
|
||||
let params = params.into_inner();
|
||||
|
||||
let user_auth: schemas::AuthReturn = verify_auth(¶ms.auth.token, &data);
|
||||
|
||||
// SQL Queries
|
||||
// TODO: Optimize by utilizing some SQL magic, for now this has to do
|
||||
if user_auth.admin || user_auth.moderator {
|
||||
if params.game_name != "" {
|
||||
let db_game: db::schemas::Game;
|
||||
|
||||
db_game = match sqlx::query_as!(
|
||||
db::schemas::Game,
|
||||
"INSERT INTO public.games(name) VALUES ($1) RETURNING * ",
|
||||
params.game_name
|
||||
)
|
||||
.fetch_one(&data.db)
|
||||
.await
|
||||
{
|
||||
Ok(data) => data,
|
||||
Err(_) => return HttpResponse::UnprocessableEntity().finish(),
|
||||
};
|
||||
|
||||
let parsed_game: schemas::ChellarisGameLite = schemas::ChellarisGameLite {
|
||||
id: db_game.id,
|
||||
name: db_game.name,
|
||||
};
|
||||
|
||||
return HttpResponse::Ok().json(parsed_game);
|
||||
} else {
|
||||
return HttpResponse::UnprocessableEntity().finish();
|
||||
}
|
||||
} else {
|
||||
return HttpResponse::Unauthorized().finish();
|
||||
}
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
params(
|
||||
schemas::DeleteGameParam,
|
||||
),
|
||||
request_body = AuthParams,
|
||||
responses(
|
||||
(status = 200, description = "OK"),
|
||||
(status = 422, description = "Missing Game ID"),
|
||||
(status = 401, description = "Auth Token Invalid"),
|
||||
),
|
||||
security(
|
||||
("api_key" = [])
|
||||
),
|
||||
)]
|
||||
#[delete("/api/v3/game")]
|
||||
pub(crate) async fn delete_game(
|
||||
data: web::Data<AppState>,
|
||||
auth_params: web::Json<schemas::AuthParams>,
|
||||
param: web::Query<schemas::DeleteGameParam>,
|
||||
) -> impl Responder {
|
||||
let auth_params = auth_params.into_inner();
|
||||
let param = param.into_inner();
|
||||
|
||||
let user_auth: schemas::AuthReturn = verify_auth(&auth_params.token, &data);
|
||||
|
||||
// SQL Queries
|
||||
// TODO: Optimize by utilizing some SQL magic, for now this has to do
|
||||
if user_auth.admin || user_auth.moderator {
|
||||
match sqlx::query!(
|
||||
"DELETE FROM public.games WHERE id = $1",
|
||||
param.game_id as i32
|
||||
)
|
||||
.execute(&data.db)
|
||||
.await
|
||||
{
|
||||
Ok(_) => {},
|
||||
Err(_) => return HttpResponse::UnprocessableEntity().finish(),
|
||||
};
|
||||
|
||||
return HttpResponse::Ok().into();
|
||||
} else {
|
||||
return HttpResponse::Unauthorized().finish();
|
||||
}
|
||||
}
|
||||
|
||||
// Data Manipulation Endpoints
|
||||
|
||||
// Moderator & Admin
|
||||
// Add/Update/Remove Empire
|
||||
// Add/Update/Remove Group
|
||||
// Add/Update/Remove Game
|
||||
|
||||
// Admin
|
||||
// Add/Update/Remove Portrait
|
||||
// Add/Update/Remove Species
|
||||
// Add/Update/Remove Ethics
|
||||
|
|
|
@ -4,10 +4,43 @@ use serde::{Serialize, Deserialize};
|
|||
use utoipa::{ToSchema, IntoParams};
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema, Debug, IntoParams)]
|
||||
pub struct AuthParams {
|
||||
pub struct AuthParamsOptional {
|
||||
#[schema(example = "1357")]
|
||||
pub token: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema, Debug, IntoParams)]
|
||||
pub struct AuthParams {
|
||||
#[schema(example = "1357")]
|
||||
pub token: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema, Debug)]
|
||||
pub struct AuthReturn {
|
||||
#[schema(example = false)]
|
||||
pub moderator: bool,
|
||||
#[schema(example = false)]
|
||||
pub admin: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema, Debug, IntoParams)]
|
||||
pub struct GetGameParam {
|
||||
pub game_id: Option<usize>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema, Debug)]
|
||||
pub struct PostGameParams {
|
||||
pub auth: AuthParams,
|
||||
#[schema(example = "Game XY")]
|
||||
pub game_name: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema, Debug, IntoParams)]
|
||||
pub struct DeleteGameParam {
|
||||
#[schema(example = 0)]
|
||||
pub game_id: usize,
|
||||
}
|
||||
|
||||
#[derive(Serialize, ToSchema, Debug, Clone)]
|
||||
pub struct FullViewData {
|
||||
pub games: HashMap<i32, ChellarisGame>,
|
||||
|
@ -23,6 +56,12 @@ pub struct ChellarisGame {
|
|||
pub empires: HashMap<i32, ChellarisEmpire>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, ToSchema, Debug, Clone)]
|
||||
pub struct ChellarisGameLite {
|
||||
pub id: i32,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, ToSchema, Debug, Clone)]
|
||||
pub struct ChellarisGameGroup {
|
||||
pub id: i32,
|
||||
|
@ -68,4 +107,5 @@ pub struct Portrait {
|
|||
pub id: i32,
|
||||
pub hires: String,
|
||||
pub lores: Option<String>,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Reference in a new issue