2023-08-30 04:16:43 +02:00
use std ::{ collections ::HashMap , vec } ;
2023-08-26 06:36:12 +02:00
2023-08-30 04:16:43 +02:00
use actix_web ::{
delete , get , post , put ,
web ::{ self , Json } ,
2023-09-03 02:20:26 +02:00
HttpRequest , HttpResponse , Responder ,
2023-08-30 04:16:43 +02:00
} ;
2023-09-08 22:55:17 +02:00
use sqlx ::QueryBuilder ;
2023-08-26 06:36:12 +02:00
2023-09-08 22:55:17 +02:00
use crate ::{ db , AppState } ;
2023-08-26 06:36:12 +02:00
pub ( crate ) mod schemas ;
2023-09-02 20:23:34 +02:00
fn verify_auth ( token : Option < & str > , data : & AppState ) -> schemas ::AuthReturn {
2023-08-30 04:16:43 +02:00
let mut auth_return = schemas ::AuthReturn {
moderator : false ,
admin : false ,
} ;
2023-09-02 20:23:34 +02:00
if let Some ( token ) = token {
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 ;
}
2023-08-30 04:16:43 +02:00
}
return auth_return ;
}
2023-09-02 20:23:34 +02:00
fn get_auth_header < ' a > ( req : & ' a HttpRequest ) -> Option < & ' a str > {
req . headers ( ) . get ( " x-api-key " ) ? . to_str ( ) . ok ( )
}
2023-08-30 04:16:43 +02:00
#[ utoipa::path(
responses (
( status = 200 , description = " OK " , body = AuthReturn ) ,
) ,
security (
( " api_key " = [ ] )
) ,
) ]
#[ get( " /api/v3/auth " ) ]
2023-09-03 02:20:26 +02:00
pub ( crate ) async fn auth ( data : web ::Data < AppState > , req : HttpRequest ) -> impl Responder {
2023-09-02 20:23:34 +02:00
let auth_token = get_auth_header ( & req ) ;
2023-08-30 04:16:43 +02:00
2023-09-02 20:23:34 +02:00
let auth_return = verify_auth ( auth_token , & data ) ;
2023-08-30 04:16:43 +02:00
Json ( auth_return )
}
2023-08-26 06:36:12 +02:00
#[ utoipa::path(
responses (
( status = 200 , description = " OK " , body = FullViewData ) ,
) ,
security (
( " api_key " = [ ] )
) ,
) ]
2023-08-30 04:16:43 +02:00
#[ get( " /api/v3/full_view_data " ) ]
pub ( crate ) async fn full_view_data ( data : web ::Data < AppState > ) -> impl Responder {
2023-08-26 06:36:12 +02:00
// SQL Queries
// TODO: Optimize by utilizing some SQL magic, for now this has to do
2023-08-30 04:16:43 +02:00
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_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_empire_ethics : Vec < db ::schemas ::EmpireEthic > =
2023-09-03 02:20:26 +02:00
sqlx ::query_as ( " SELECT * FROM public.empire_ethics ORDER BY empire_id " )
2023-08-30 04:16:43 +02:00
. 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 " ) ;
2023-08-26 06:36:12 +02:00
let mut parsed_data : schemas ::FullViewData = schemas ::FullViewData {
games : HashMap ::new ( ) ,
ethics : HashMap ::new ( ) ,
2023-09-08 22:55:17 +02:00
phenotypes : HashMap ::new ( ) ,
2023-08-26 06:36:12 +02:00
} ;
// Data processing
// Species Vector
db_portrait_groups . iter ( ) . for_each ( | species | {
2023-09-08 22:55:17 +02:00
let new_data = schemas ::Phenotype {
2023-08-26 06:36:12 +02:00
id : species . id ,
2023-09-03 02:20:26 +02:00
display : species . name . clone ( ) ,
2023-09-08 22:55:17 +02:00
species : HashMap ::new ( ) ,
2023-08-26 06:36:12 +02:00
} ;
2023-08-30 04:16:43 +02:00
parsed_data
2023-09-08 22:55:17 +02:00
. phenotypes
2023-08-30 04:16:43 +02:00
. entry ( species . id )
. and_modify ( | d | * d = new_data . clone ( ) )
. or_insert ( new_data ) ;
2023-08-26 06:36:12 +02:00
} ) ;
db_portraits . iter ( ) . for_each ( | portrait | {
2023-09-08 22:55:17 +02:00
let new_data = schemas ::Species {
2023-08-26 06:36:12 +02:00
id : portrait . id ,
hires : portrait . hires . clone ( ) ,
2023-09-08 22:55:17 +02:00
lores : portrait . lores . clone ( ) ,
2023-08-26 06:36:12 +02:00
} ;
2023-08-30 04:16:43 +02:00
parsed_data
2023-09-08 22:55:17 +02:00
. phenotypes
2023-08-30 04:16:43 +02:00
. get_mut ( & portrait . group_id )
. unwrap ( )
2023-09-08 22:55:17 +02:00
. species
2023-08-30 04:16:43 +02:00
. entry ( portrait . id )
. and_modify ( | d | * d = new_data . clone ( ) )
. or_insert ( new_data ) ;
2023-08-26 06:36:12 +02:00
} ) ;
// Games Vector and Children
db_games . iter ( ) . for_each ( | game | {
2023-09-02 20:23:34 +02:00
let new_data = schemas ::ChellarisGameLegacy {
2023-08-26 06:36:12 +02:00
id : game . id ,
name : game . name . clone ( ) ,
empires : HashMap ::new ( ) ,
groups : HashMap ::new ( ) ,
} ;
2023-08-30 04:16:43 +02:00
parsed_data
. games
. entry ( game . id )
. and_modify ( | d | * d = new_data . clone ( ) )
. or_insert ( new_data ) ;
2023-08-26 06:36:12 +02:00
} ) ;
db_groups . iter ( ) . for_each ( | group | {
2023-09-02 20:23:34 +02:00
let new_data = schemas ::ChellarisGameGroupLegacy {
2023-08-26 06:36:12 +02:00
id : group . id ,
name : group . name . clone ( ) ,
} ;
2023-08-30 04:16:43 +02:00
parsed_data
. games
. get_mut ( & group . game_id )
. unwrap ( )
. groups
. entry ( group . id )
. and_modify ( | d | * d = new_data . clone ( ) )
. or_insert ( new_data ) ;
2023-08-26 06:36:12 +02:00
} ) ;
db_empires . iter ( ) . for_each ( | empire | {
2023-09-03 02:20:26 +02:00
let new_data = schemas ::ChellarisEmpireLegacy {
2023-08-26 06:36:12 +02:00
id : empire . id ,
2023-09-02 20:23:34 +02:00
gestalt : empire . gestalt ,
2023-09-08 22:55:17 +02:00
machine : empire . portrait_group_id . to_string ( ) = = dotenv! ( " MACHINE_GROUP_ID " ) ,
2023-08-26 06:36:12 +02:00
group : empire . group_id ,
2023-09-07 22:00:20 +02:00
portrait_id : empire . portrait_id ,
portrait_group_id : empire . portrait_group_id ,
2023-09-02 20:23:34 +02:00
discord_user : None ,
2023-08-26 06:36:12 +02:00
ethics : HashMap ::new ( ) ,
} ;
2023-08-30 04:16:43 +02:00
parsed_data
. games
2023-09-03 02:20:26 +02:00
. get_mut ( & empire . game_id )
2023-08-30 04:16:43 +02:00
. unwrap ( )
. empires
. entry ( empire . id )
. and_modify ( | d | * d = new_data . clone ( ) )
. or_insert ( new_data ) ;
2023-08-26 06:36:12 +02:00
} ) ;
// Ethics Vector
db_ethics . iter ( ) . for_each ( | ethic | {
let new_data = schemas ::Ethic {
id : ethic . id ,
2023-09-03 02:20:26 +02:00
display : ethic . name . clone ( ) ,
2023-09-08 22:55:17 +02:00
gestalt : ethic . gestalt_ethic ,
2023-08-26 06:36:12 +02:00
} ;
2023-08-30 04:16:43 +02:00
parsed_data
. ethics
. entry ( ethic . id )
. and_modify ( | d | * d = new_data . clone ( ) )
. or_insert ( new_data ) ;
2023-08-26 06:36:12 +02:00
} ) ;
db_empire_ethics . iter ( ) . for_each ( | empire_ethic | {
2023-09-03 02:20:26 +02:00
let game_id = empire_ethic . empire_game_id ;
let id = empire_ethic . empire_id ;
2023-08-26 06:36:12 +02:00
2023-09-03 02:20:26 +02:00
let new_data = schemas ::EmpireEthicLegacy {
2023-09-07 21:54:52 +02:00
ethic_id : empire_ethic . ethics_id ,
2023-09-03 02:20:26 +02:00
display : parsed_data . ethics [ & empire_ethic . ethics_id ] . display . clone ( ) ,
2023-09-08 22:55:17 +02:00
gestalt : parsed_data . ethics [ & empire_ethic . ethics_id ] . gestalt ,
2023-09-03 02:20:26 +02:00
fanatic : empire_ethic . fanatic ,
2023-08-26 06:36:12 +02:00
} ;
2023-09-08 22:55:17 +02:00
if new_data . gestalt {
2023-08-30 04:16:43 +02:00
parsed_data
. games
. get_mut ( & game_id )
. unwrap ( )
. empires
. get_mut ( & id )
. unwrap ( )
2023-09-08 22:55:17 +02:00
. gestalt = true ;
2023-08-30 04:16:43 +02:00
}
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 ) ;
2023-08-26 06:36:12 +02:00
} ) ;
2023-08-30 04:16:43 +02:00
Json ( parsed_data )
}
// Data Fetching Endpoints for Admin/Moderator Menu
2023-09-02 20:23:34 +02:00
// Game Endpoints
2023-08-30 04:16:43 +02:00
#[ utoipa::path(
params ( ) ,
responses (
2023-09-03 02:20:26 +02:00
( status = 200 , description = " OK " , body = HashMap < i32 , ChellarisGameFlat > ) ,
2023-08-30 04:16:43 +02:00
) ,
security (
( " api_key " = [ ] )
) ,
) ]
2023-09-02 20:23:34 +02:00
#[ get( " /api/v3/games " ) ]
2023-08-30 04:16:43 +02:00
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 " ) ;
2023-09-02 20:23:34 +02:00
let mut parsed_data : HashMap < i32 , schemas ::ChellarisGameFlat > = HashMap ::new ( ) ;
2023-08-30 04:16:43 +02:00
// Data processing
// Games Vector
db_games . iter ( ) . for_each ( | game | {
2023-09-02 20:23:34 +02:00
let new_data = schemas ::ChellarisGameFlat {
2023-08-30 04:16:43 +02:00
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 (
2023-09-02 20:23:34 +02:00
( status = 200 , description = " OK " , body = ChellarisGame ) ,
2023-08-30 04:16:43 +02:00
) ,
security (
( " api_key " = [ ] )
) ,
) ]
#[ get( " /api/v3/game " ) ]
pub ( crate ) async fn get_game_data (
data : web ::Data < AppState > ,
2023-09-02 20:23:34 +02:00
path_param : web ::Query < schemas ::GetGameParam > ,
req : HttpRequest ,
2023-08-30 04:16:43 +02:00
) -> impl Responder {
2023-09-02 20:23:34 +02:00
let auth_token = get_auth_header ( & req ) ;
let param = path_param . into_inner ( ) ;
let user_auth : schemas ::AuthReturn = verify_auth ( auth_token . as_deref ( ) , & data ) ;
2023-08-30 04:16:43 +02:00
// SQL Queries
// TODO: Optimize by utilizing some SQL magic, for now this has to do
2023-09-02 20:23:34 +02:00
let db_game : db ::schemas ::Game = match sqlx ::query_as! (
db ::schemas ::Game ,
" SELECT * FROM public.games WHERE id = $1 " ,
param . game_id
)
. fetch_one ( & data . db )
. await
{
Ok ( data ) = > data ,
Err ( _ ) = > return HttpResponse ::UnprocessableEntity ( ) . finish ( ) ,
} ;
let db_empires : Vec < db ::schemas ::Empire > = sqlx ::query_as! (
db ::schemas ::Empire ,
2023-09-03 02:20:26 +02:00
" SELECT * FROM public.empires WHERE game_id = $1 " ,
2023-09-02 20:23:34 +02:00
param . game_id
)
. fetch_all ( & data . db )
. await
. unwrap_or ( vec! [ ] ) ;
let db_groups : Vec < db ::schemas ::GameGroup > = sqlx ::query_as! (
db ::schemas ::GameGroup ,
" SELECT * FROM public.game_groups WHERE game_id = $1 " ,
param . game_id
)
. fetch_all ( & data . db )
. await
. unwrap_or ( vec! [ ] ) ;
// Data Processing
let mut parsed_data : schemas ::ChellarisGame = schemas ::ChellarisGame {
id : db_game . id ,
name : db_game . name ,
empires : HashMap ::new ( ) ,
groups : HashMap ::new ( ) ,
} ;
db_empires . iter ( ) . for_each ( | empire | {
let new_empire = schemas ::ChellarisEmpireFlat {
id : empire . id ,
group : empire . group_id ,
2023-09-03 02:20:26 +02:00
game : empire . game_id ,
name : if user_auth . moderator | | user_auth . admin {
empire . name . clone ( )
} else {
" [REDACTED] " . to_string ( )
} ,
discord_user : if user_auth . moderator | | user_auth . admin {
empire . discord_user . clone ( )
} else {
None
} ,
2023-09-02 20:23:34 +02:00
gestalt : empire . gestalt ,
2023-09-03 02:20:26 +02:00
portrait_id : empire . portrait_id ,
portrait_group_id : empire . portrait_group_id ,
2023-08-30 04:16:43 +02:00
} ;
2023-09-02 20:23:34 +02:00
parsed_data
. empires
. entry ( empire . id )
. and_modify ( | d | * d = new_empire . clone ( ) )
. or_insert ( new_empire ) ;
} ) ;
2023-08-30 04:16:43 +02:00
2023-09-02 20:23:34 +02:00
db_groups . iter ( ) . for_each ( | group | {
let new_group = schemas ::ChellarisGroupFlat {
id : group . id ,
name : group . name . clone ( ) ,
2023-08-30 04:16:43 +02:00
} ;
parsed_data
2023-09-02 20:23:34 +02:00
. groups
. entry ( group . id )
. and_modify ( | d | * d = new_group . clone ( ) )
. or_insert ( new_group ) ;
2023-08-30 04:16:43 +02:00
} ) ;
2023-09-02 20:23:34 +02:00
return HttpResponse ::Ok ( ) . json ( parsed_data ) ;
2023-08-26 06:36:12 +02:00
}
2023-08-30 04:16:43 +02:00
#[ 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 > ,
2023-09-02 20:23:34 +02:00
req : HttpRequest ,
2023-08-30 04:16:43 +02:00
) -> impl Responder {
2023-09-02 20:23:34 +02:00
let auth_token = get_auth_header ( & req ) ;
2023-08-30 04:16:43 +02:00
let params = params . into_inner ( ) ;
2023-09-02 20:23:34 +02:00
let user_auth : schemas ::AuthReturn = verify_auth ( auth_token . as_deref ( ) , & data ) ;
2023-08-30 04:16:43 +02:00
// 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 ( ) ,
} ;
2023-09-02 20:23:34 +02:00
match sqlx ::query! (
" INSERT INTO public.game_groups(name, game_id) VALUES ($1, $2) " ,
2023-09-03 02:20:26 +02:00
" N/A " ,
db_game . id
2023-09-02 20:23:34 +02:00
)
. execute ( & data . db )
. await
{
2023-09-03 02:20:26 +02:00
Ok ( _ ) = > { }
2023-09-02 20:23:34 +02:00
Err ( _ ) = > return HttpResponse ::UnprocessableEntity ( ) . finish ( ) ,
} ;
let parsed_game : schemas ::ChellarisGameFlat = schemas ::ChellarisGameFlat {
2023-08-30 04:16:43 +02:00
id : db_game . id ,
name : db_game . name ,
} ;
return HttpResponse ::Ok ( ) . json ( parsed_game ) ;
} else {
return HttpResponse ::UnprocessableEntity ( ) . finish ( ) ;
}
} else {
return HttpResponse ::Unauthorized ( ) . finish ( ) ;
}
}
2023-09-02 20:23:34 +02:00
#[ utoipa::path(
request_body = UpdateGameParams ,
responses (
( status = 200 , description = " OK " , body = ChellarisGameLite ) ,
( status = 422 , description = " Missing Game Name " ) ,
( status = 401 , description = " Auth Token Invalid " ) ,
) ,
security (
( " api_key " = [ ] )
) ,
) ]
#[ put( " /api/v3/game " ) ]
pub ( crate ) async fn edit_game (
data : web ::Data < AppState > ,
params : web ::Json < schemas ::UpdateGameParams > ,
req : HttpRequest ,
) -> impl Responder {
let auth_token = get_auth_header ( & req ) ;
let params = params . into_inner ( ) ;
let user_auth : schemas ::AuthReturn = verify_auth ( auth_token . as_deref ( ) , & 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 ,
" UPDATE public.games SET name = $1 WHERE id = $2 RETURNING * ; " ,
2023-09-03 02:20:26 +02:00
params . game_name ,
params . game_id
2023-09-02 20:23:34 +02:00
)
. fetch_one ( & data . db )
. await
{
Ok ( data ) = > data ,
Err ( _ ) = > return HttpResponse ::UnprocessableEntity ( ) . finish ( ) ,
} ;
let parsed_game : schemas ::ChellarisGameFlat = schemas ::ChellarisGameFlat {
id : db_game . id ,
name : db_game . name ,
} ;
return HttpResponse ::Ok ( ) . json ( parsed_game ) ;
} else {
return HttpResponse ::UnprocessableEntity ( ) . finish ( ) ;
}
} else {
return HttpResponse ::Unauthorized ( ) . finish ( ) ;
}
}
2023-08-30 04:16:43 +02:00
#[ utoipa::path(
params (
schemas ::DeleteGameParam ,
) ,
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 > ,
2023-09-02 20:23:34 +02:00
req : HttpRequest ,
2023-08-30 04:16:43 +02:00
param : web ::Query < schemas ::DeleteGameParam > ,
) -> impl Responder {
2023-09-02 20:23:34 +02:00
let auth_token = get_auth_header ( & req ) ;
2023-08-30 04:16:43 +02:00
let param = param . into_inner ( ) ;
2023-09-02 20:23:34 +02:00
let user_auth : schemas ::AuthReturn = verify_auth ( auth_token , & data ) ;
2023-08-30 04:16:43 +02:00
// SQL Queries
// TODO: Optimize by utilizing some SQL magic, for now this has to do
if user_auth . admin | | user_auth . moderator {
2023-09-02 20:23:34 +02:00
match sqlx ::query! ( " DELETE FROM public.games WHERE id = $1 " , param . game_id )
. execute ( & data . db )
. await
2023-08-30 04:16:43 +02:00
{
2023-09-02 20:23:34 +02:00
Ok ( _ ) = > { }
Err ( e ) = > {
println! ( " {:#?} " , e ) ;
return HttpResponse ::UnprocessableEntity ( ) . finish ( ) ;
2023-09-03 02:20:26 +02:00
}
2023-09-02 20:23:34 +02:00
} ;
return HttpResponse ::Ok ( ) . into ( ) ;
} else {
return HttpResponse ::Unauthorized ( ) . finish ( ) ;
}
}
// Group Endpoints
#[ utoipa::path(
request_body = PostGroupParams ,
responses (
( status = 200 , description = " OK " , body = ChellarisGroupFlat ) ,
( status = 422 , description = " Missing Game Name " ) ,
( status = 401 , description = " Auth Token Invalid " ) ,
) ,
security (
( " api_key " = [ ] )
) ,
) ]
#[ post( " /api/v3/group " ) ]
pub ( crate ) async fn create_group (
data : web ::Data < AppState > ,
params : web ::Json < schemas ::PostGroupParams > ,
req : HttpRequest ,
) -> impl Responder {
let auth_token = get_auth_header ( & req ) ;
let params = params . into_inner ( ) ;
let user_auth : schemas ::AuthReturn = verify_auth ( auth_token . as_deref ( ) , & 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 . group_name ! = " " {
let db_group : db ::schemas ::GameGroup ;
db_group = match sqlx ::query_as! (
db ::schemas ::GameGroup ,
" INSERT INTO public.game_groups(name, game_id) VALUES ($1, $2) RETURNING * " ,
2023-09-03 02:20:26 +02:00
params . group_name ,
params . game_id
2023-09-02 20:23:34 +02:00
)
. fetch_one ( & data . db )
. await
{
Ok ( data ) = > data ,
Err ( _ ) = > return HttpResponse ::UnprocessableEntity ( ) . finish ( ) ,
} ;
let parsed_group : schemas ::ChellarisGroupFlat = schemas ::ChellarisGroupFlat {
id : db_group . id ,
name : db_group . name ,
} ;
return HttpResponse ::Ok ( ) . json ( parsed_group ) ;
} else {
return HttpResponse ::UnprocessableEntity ( ) . finish ( ) ;
}
} else {
return HttpResponse ::Unauthorized ( ) . finish ( ) ;
}
}
#[ utoipa::path(
request_body = UpdateGroupParams ,
responses (
( status = 200 , description = " OK " , body = ChellarisGroupFlat ) ,
( status = 422 , description = " Missing Game Name " ) ,
( status = 401 , description = " Auth Token Invalid " ) ,
) ,
security (
( " api_key " = [ ] )
) ,
) ]
#[ put( " /api/v3/group " ) ]
pub ( crate ) async fn edit_group (
data : web ::Data < AppState > ,
params : web ::Json < schemas ::UpdateGroupParams > ,
req : HttpRequest ,
) -> impl Responder {
let auth_token = get_auth_header ( & req ) ;
let params = params . into_inner ( ) ;
let user_auth : schemas ::AuthReturn = verify_auth ( auth_token . as_deref ( ) , & 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 . group_name ! = " " {
let db_group : db ::schemas ::GameGroup ;
db_group = match sqlx ::query_as! (
db ::schemas ::GameGroup ,
" UPDATE public.game_groups SET name = $1 WHERE id = $2 AND game_id = $3 RETURNING * ; " ,
params . group_name , params . group_id , params . game_id
)
. fetch_one ( & data . db )
. await
{
Ok ( data ) = > data ,
Err ( _ ) = > return HttpResponse ::UnprocessableEntity ( ) . finish ( ) ,
} ;
let parsed_group : schemas ::ChellarisGroupFlat = schemas ::ChellarisGroupFlat {
id : db_group . id ,
name : db_group . name ,
} ;
return HttpResponse ::Ok ( ) . json ( parsed_group ) ;
} else {
return HttpResponse ::UnprocessableEntity ( ) . finish ( ) ;
}
} else {
return HttpResponse ::Unauthorized ( ) . finish ( ) ;
}
}
#[ utoipa::path(
params (
schemas ::DeleteGroupParams ,
) ,
responses (
( status = 200 , description = " OK " ) ,
( status = 422 , description = " Missing Game ID " ) ,
( status = 401 , description = " Auth Token Invalid " ) ,
) ,
security (
( " api_key " = [ ] )
) ,
) ]
#[ delete( " /api/v3/group " ) ]
pub ( crate ) async fn delete_group (
data : web ::Data < AppState > ,
req : HttpRequest ,
param : web ::Query < schemas ::DeleteGroupParams > ,
) -> impl Responder {
let auth_token = get_auth_header ( & req ) ;
let param = param . into_inner ( ) ;
let user_auth : schemas ::AuthReturn = verify_auth ( 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 {
2023-09-03 02:20:26 +02:00
match sqlx ::query! (
" DELETE FROM public.game_groups WHERE id = $1 AND game_id = $2 AND name != 'N/A' " ,
param . group_id ,
param . game_id
)
. execute ( & data . db )
. await
2023-09-02 20:23:34 +02:00
{
Ok ( _ ) = > { }
2023-08-30 04:16:43 +02:00
Err ( _ ) = > return HttpResponse ::UnprocessableEntity ( ) . finish ( ) ,
} ;
return HttpResponse ::Ok ( ) . into ( ) ;
} else {
return HttpResponse ::Unauthorized ( ) . finish ( ) ;
}
}
2023-09-02 20:23:34 +02:00
// Empire Endpoints
2023-09-07 20:14:51 +02:00
#[ utoipa::path(
params (
schemas ::GetEmpireParams
) ,
responses (
( status = 200 , description = " OK " , body = ChellarisEmpire ) ,
) ,
security (
( " api_key " = [ ] )
) ,
) ]
#[ get( " /api/v3/empire " ) ]
pub ( crate ) async fn get_empire (
data : web ::Data < AppState > ,
params : web ::Query < schemas ::GetEmpireParams > ,
req : HttpRequest ,
) -> impl Responder {
let auth_token = get_auth_header ( & req ) ;
let params = params . into_inner ( ) ;
let user_auth : schemas ::AuthReturn = verify_auth ( auth_token . as_deref ( ) , & data ) ;
// SQL Queries
// TODO: Optimize by utilizing some SQL magic, for now this has to do
if user_auth . admin | | user_auth . moderator {
let db_empire : db ::schemas ::Empire ;
let mut db_empire_query =
QueryBuilder ::< sqlx ::Postgres > ::new ( " SELECT * FROM public.empires WHERE " ) ;
db_empire_query . push ( " id = " ) . push_bind ( params . empire_id ) ;
db_empire_query
. push ( " AND game_id = " )
. push_bind ( params . game_id ) ;
db_empire = match db_empire_query
. build_query_as ::< db ::schemas ::Empire > ( )
. fetch_one ( & data . db )
. await
{
Ok ( data ) = > data ,
Err ( e ) = > {
return HttpResponse ::UnprocessableEntity ( ) . body ( format! ( " {:#?} " , e . to_string ( ) ) )
}
} ;
let mut db_ethics : HashMap < i32 , schemas ::EmpireEthic > = HashMap ::new ( ) ;
let mut db_ethic_query =
QueryBuilder ::< sqlx ::Postgres > ::new ( " SELECT * FROM public.empire_ethics WHERE " ) ;
db_ethic_query
. push ( " empire_id = " )
. push_bind ( params . empire_id ) ;
db_ethic_query
. push ( " AND empire_game_id = " )
. push_bind ( params . game_id ) ;
match db_ethic_query
. build_query_as ::< db ::schemas ::EmpireEthic > ( )
. fetch_all ( & data . db )
. await
{
Ok ( data ) = > {
for ethic in data {
db_ethics . insert (
ethic . ethics_id ,
schemas ::EmpireEthic {
ethic_id : ethic . ethics_id ,
fanatic : ethic . fanatic ,
} ,
) ;
}
}
Err ( e ) = > {
return HttpResponse ::UnprocessableEntity ( ) . body ( format! ( " {:#?} " , e . to_string ( ) ) )
}
} ;
// Empire Ethic Creation
let parsed_empire : schemas ::ChellarisEmpire = schemas ::ChellarisEmpire {
id : db_empire . id ,
group : db_empire . group_id ,
game : db_empire . game_id ,
name : db_empire . name ,
discord_user : db_empire . discord_user ,
2023-09-08 23:06:56 +02:00
machine : db_empire . portrait_group_id . to_string ( ) = = dotenv! ( " MACHINE_GROUP_ID " ) ,
2023-09-07 20:14:51 +02:00
gestalt : db_empire . gestalt ,
portrait_id : db_empire . portrait_id ,
portrait_group_id : db_empire . portrait_group_id ,
ethics : db_ethics ,
} ;
return HttpResponse ::Ok ( ) . json ( parsed_empire ) ;
} else {
return HttpResponse ::Unauthorized ( ) . finish ( ) ;
}
}
2023-09-03 02:20:26 +02:00
#[ utoipa::path(
request_body = PostEmpireParams ,
responses (
( status = 200 , description = " OK " , body = ChellarisEmpireFlat ) ,
( status = 422 , description = " Missing Game Name " ) ,
( status = 401 , description = " Auth Token Invalid " ) ,
) ,
security (
( " api_key " = [ ] )
) ,
) ]
#[ post( " /api/v3/empire " ) ]
pub ( crate ) async fn create_empire (
data : web ::Data < AppState > ,
params : web ::Json < schemas ::PostEmpireParams > ,
req : HttpRequest ,
) -> impl Responder {
let auth_token = get_auth_header ( & req ) ;
let params = params . into_inner ( ) ;
let user_auth : schemas ::AuthReturn = verify_auth ( auth_token . as_deref ( ) , & data ) ;
// SQL Queries
// TODO: Optimize by utilizing some SQL magic, for now this has to do
if user_auth . admin | | user_auth . moderator {
let mut all_params_present = true ;
if params . empire_name = = " " {
all_params_present = false ;
}
if all_params_present {
// Basic Empire Creation
let db_empire : db ::schemas ::Empire ;
let mut db_empire_query =
QueryBuilder ::< sqlx ::Postgres > ::new ( " INSERT INTO public.empires( " ) ;
db_empire_query . push ( " group_id " ) ;
db_empire_query . push ( " , game_id " ) ;
db_empire_query . push ( " , name " ) ;
db_empire_query . push ( " , gestalt " ) ;
db_empire_query . push ( " , portrait_id " ) ;
db_empire_query . push ( " , portrait_group_id " ) ;
db_empire_query . push ( " , discord_user " ) ;
db_empire_query . push ( " ) VALUES ( " ) ;
db_empire_query . push ( " " ) . push_bind ( params . group_id ) ;
db_empire_query . push ( " , " ) . push_bind ( params . game_id ) ;
db_empire_query . push ( " , " ) . push_bind ( params . empire_name ) ;
db_empire_query . push ( " , " ) . push_bind ( params . gestalt ) ;
db_empire_query . push ( " , " ) . push_bind ( params . portrait_id ) ;
db_empire_query
. push ( " , " )
. push_bind ( params . portrait_group_id ) ;
if let Some ( discord_user ) = params . discord_user {
db_empire_query . push ( " , " ) . push_bind ( discord_user ) ;
} else {
let val : Option < String > = None ;
db_empire_query . push ( " , " ) . push_bind ( val ) ;
}
db_empire_query . push ( " ) RETURNING * " ) ;
db_empire = match db_empire_query
. build_query_as ::< db ::schemas ::Empire > ( )
. fetch_one ( & data . db )
. await
{
Ok ( data ) = > data ,
Err ( e ) = > {
return HttpResponse ::UnprocessableEntity ( )
. body ( format! ( " {:#?} " , e . to_string ( ) ) )
}
} ;
let mut db_ethics : HashMap < i32 , schemas ::EmpireEthic > = HashMap ::new ( ) ;
for ethic in params . ethics {
let mut db_ethic_query =
QueryBuilder ::< sqlx ::Postgres > ::new ( " INSERT INTO public.empire_ethics( " ) ;
2023-09-07 20:14:51 +02:00
db_ethic_query . push ( " empire_id " ) . push ( " , empire_game_id " ) ;
2023-09-03 02:20:26 +02:00
db_ethic_query . push ( " , ethics_id " ) . push ( " , fanatic " ) ;
db_ethic_query . push ( " ) VALUES ( " ) ;
db_ethic_query . push ( " " ) . push_bind ( db_empire . id ) ;
db_ethic_query . push ( " , " ) . push_bind ( db_empire . game_id ) ;
db_ethic_query . push ( " , " ) . push_bind ( ethic . ethic_id ) ;
db_ethic_query . push ( " , " ) . push_bind ( ethic . fanatic ) ;
db_ethic_query . push ( " ) RETURNING * " ) ;
match db_ethic_query
. build_query_as ::< db ::schemas ::EmpireEthic > ( )
. fetch_one ( & data . db )
. await
{
Ok ( data ) = > db_ethics . insert (
data . ethics_id ,
schemas ::EmpireEthic {
ethic_id : data . ethics_id ,
fanatic : data . fanatic ,
} ,
) ,
Err ( e ) = > {
return HttpResponse ::UnprocessableEntity ( )
. body ( format! ( " {:#?} " , e . to_string ( ) ) )
}
} ;
}
// Empire Ethic Creation
let parsed_empire : schemas ::ChellarisEmpire = schemas ::ChellarisEmpire {
id : db_empire . id ,
group : db_empire . group_id ,
game : db_empire . game_id ,
name : db_empire . name ,
discord_user : db_empire . discord_user ,
2023-09-08 23:06:56 +02:00
machine : db_empire . portrait_group_id . to_string ( ) = = dotenv! ( " MACHINE_GROUP_ID " ) ,
2023-09-03 02:20:26 +02:00
gestalt : db_empire . gestalt ,
portrait_id : db_empire . portrait_id ,
portrait_group_id : db_empire . portrait_group_id ,
ethics : db_ethics ,
} ;
return HttpResponse ::Ok ( ) . json ( parsed_empire ) ;
} else {
return HttpResponse ::UnprocessableEntity ( ) . finish ( ) ;
}
} else {
return HttpResponse ::Unauthorized ( ) . finish ( ) ;
}
}
#[ utoipa::path(
request_body = UpdateEmpireParams ,
responses (
( status = 200 , description = " OK " , body = ChellarisEmpireFlat ) ,
( status = 422 , description = " Missing Game Name " ) ,
( status = 401 , description = " Auth Token Invalid " ) ,
) ,
security (
( " api_key " = [ ] )
) ,
) ]
#[ put( " /api/v3/empire " ) ]
pub ( crate ) async fn edit_empire (
data : web ::Data < AppState > ,
params : web ::Json < schemas ::UpdateEmpireParams > ,
req : HttpRequest ,
) -> impl Responder {
let auth_token = get_auth_header ( & req ) ;
let params = params . into_inner ( ) ;
let user_auth : schemas ::AuthReturn = verify_auth ( auth_token . as_deref ( ) , & data ) ;
// SQL Queries
// TODO: Optimize by utilizing some SQL magic, for now this has to do
if user_auth . admin | | user_auth . moderator {
let mut any_param_present = false ;
let mut db_empire_query = QueryBuilder ::< sqlx ::Postgres > ::new ( " UPDATE public.empires SET " ) ;
let mut db_empire_separated = db_empire_query . separated ( " , " ) ;
2023-09-09 01:04:01 +02:00
// More often than not does nothing but is required to ensure data is handled properly
db_empire_separated
. push ( " game_id = " )
. push_bind_unseparated ( params . game_id ) ;
2023-09-03 02:20:26 +02:00
if let Some ( new_group ) = params . group_id {
any_param_present = true ;
db_empire_separated
. push ( " group_id = " )
. push_bind_unseparated ( new_group ) ;
}
if let Some ( new_name ) = params . empire_name {
if new_name ! = " " {
any_param_present = true ;
db_empire_separated
. push ( " name = " )
. push_bind_unseparated ( new_name ) ;
}
}
if let Some ( new_gestalt ) = params . gestalt {
any_param_present = true ;
db_empire_separated
. push ( " gestalt = " )
. push_bind_unseparated ( new_gestalt ) ;
}
if let Some ( new_portrait ) = params . portrait_id {
any_param_present = true ;
db_empire_separated
. push ( " portrait_id = " )
. push_bind_unseparated ( new_portrait ) ;
}
if let Some ( new_portrait_group ) = params . portrait_group_id {
any_param_present = true ;
db_empire_separated
. push ( " portrait_group_id = " )
. push_bind_unseparated ( new_portrait_group ) ;
}
if let Some ( new_discord_user ) = params . discord_user {
if new_discord_user ! = " " {
any_param_present = true ;
db_empire_separated
. push ( " discord_user = " )
. push_bind_unseparated ( new_discord_user ) ;
}
}
let db_empire : db ::schemas ::Empire ;
if any_param_present {
db_empire_separated
. push_unseparated ( " WHERE id = " )
. push_bind_unseparated ( params . empire_id ) ;
db_empire_separated
. push_unseparated ( " AND game_id = " )
. push_bind_unseparated ( params . game_id ) ;
db_empire_separated . push_unseparated ( " RETURNING * " ) ;
db_empire = match db_empire_query
. build_query_as ::< db ::schemas ::Empire > ( )
. fetch_one ( & data . db )
. await
{
Ok ( data ) = > data ,
Err ( e ) = > {
return HttpResponse ::UnprocessableEntity ( )
. body ( format! ( " {:#?} " , e . to_string ( ) ) )
}
} ;
} else {
let mut db_empire_query =
QueryBuilder ::< sqlx ::Postgres > ::new ( " SELECT * FROM public.empires " ) ;
db_empire_separated
. push_unseparated ( " WHERE id = " )
. push_bind_unseparated ( params . empire_id ) ;
db_empire_separated
. push_unseparated ( " AND game_id = " )
. push_bind_unseparated ( params . game_id ) ;
db_empire = match db_empire_query
. build_query_as ::< db ::schemas ::Empire > ( )
. fetch_one ( & data . db )
. await
{
Ok ( data ) = > data ,
Err ( e ) = > {
return HttpResponse ::UnprocessableEntity ( )
. body ( format! ( " {:#?} " , e . to_string ( ) ) )
}
} ;
}
let mut ethics_changed = false ;
let mut db_ethics : HashMap < i32 , schemas ::EmpireEthic > = HashMap ::new ( ) ;
if let Some ( new_ethics ) = params . ethics {
if new_ethics . len ( ) ! = 0 {
ethics_changed = true ;
let mut db_ethic_wipe =
QueryBuilder ::< sqlx ::Postgres > ::new ( " DELETE FROM public.empire_ethics " ) ;
2023-09-07 20:14:51 +02:00
db_ethic_wipe
2023-09-03 02:20:26 +02:00
. push ( " WHERE empire_id = " )
. push_bind ( params . empire_id ) ;
db_ethic_wipe
. push ( " AND empire_game_id = " )
. push_bind ( params . game_id ) ;
2023-09-07 20:14:51 +02:00
match db_ethic_wipe . build ( ) . execute ( & data . db ) . await {
Ok ( _ ) = > { }
2023-09-03 02:20:26 +02:00
Err ( e ) = > {
return HttpResponse ::UnprocessableEntity ( )
. body ( format! ( " {:#?} " , e . to_string ( ) ) )
}
} ;
for ethic in new_ethics {
let mut db_ethic_query =
QueryBuilder ::< sqlx ::Postgres > ::new ( " INSERT INTO public.empire_ethics( " ) ;
2023-09-07 20:14:51 +02:00
db_ethic_query . push ( " empire_id " ) . push ( " , empire_game_id " ) ;
2023-09-03 02:20:26 +02:00
db_ethic_query . push ( " , ethics_id " ) . push ( " , fanatic " ) ;
db_ethic_query . push ( " ) VALUES ( " ) ;
db_ethic_query . push ( " " ) . push_bind ( db_empire . id ) ;
db_ethic_query . push ( " , " ) . push_bind ( db_empire . game_id ) ;
db_ethic_query . push ( " , " ) . push_bind ( ethic . ethic_id ) ;
db_ethic_query . push ( " , " ) . push_bind ( ethic . fanatic ) ;
db_ethic_query . push ( " ) RETURNING * " ) ;
match db_ethic_query . build ( ) . execute ( & data . db ) . await {
Ok ( _ ) = > { }
Err ( e ) = > {
return HttpResponse ::UnprocessableEntity ( )
. body ( format! ( " {:#?} " , e . to_string ( ) ) )
}
} ;
}
}
}
let mut db_ethic_query =
QueryBuilder ::< sqlx ::Postgres > ::new ( " SELECT * FROM public.empire_ethics " ) ;
db_ethic_query
. push ( " WHERE empire_id = " )
. push_bind ( params . empire_id ) ;
db_ethic_query
. push ( " AND empire_game_id = " )
. push_bind ( params . game_id ) ;
match db_ethic_query
. build_query_as ::< db ::schemas ::EmpireEthic > ( )
. fetch_all ( & data . db )
. await
{
Ok ( data ) = > data . iter ( ) . for_each ( | db_ethic | {
db_ethics . insert (
db_ethic . ethics_id ,
schemas ::EmpireEthic {
ethic_id : db_ethic . ethics_id ,
fanatic : db_ethic . fanatic ,
} ,
) ;
} ) ,
Err ( e ) = > {
return HttpResponse ::UnprocessableEntity ( ) . body ( format! ( " {:#?} " , e . to_string ( ) ) )
}
} ;
if any_param_present | | ethics_changed {
let parsed_empire : schemas ::ChellarisEmpire = schemas ::ChellarisEmpire {
id : db_empire . id ,
group : db_empire . group_id ,
game : db_empire . game_id ,
name : db_empire . name ,
discord_user : db_empire . discord_user ,
2023-09-08 23:06:56 +02:00
machine : db_empire . portrait_group_id . to_string ( ) = = dotenv! ( " MACHINE_GROUP_ID " ) ,
2023-09-03 02:20:26 +02:00
gestalt : db_empire . gestalt ,
portrait_id : db_empire . portrait_id ,
portrait_group_id : db_empire . portrait_group_id ,
ethics : db_ethics ,
} ;
return HttpResponse ::Ok ( ) . json ( parsed_empire ) ;
} else {
return HttpResponse ::UnprocessableEntity ( ) . finish ( ) ;
}
} else {
return HttpResponse ::Unauthorized ( ) . finish ( ) ;
}
}
#[ utoipa::path(
params (
schemas ::DeleteEmpireParams ,
) ,
responses (
( status = 200 , description = " OK " ) ,
( status = 422 , description = " Missing Game ID " ) ,
( status = 401 , description = " Auth Token Invalid " ) ,
) ,
security (
( " api_key " = [ ] )
) ,
) ]
#[ delete( " /api/v3/empire " ) ]
pub ( crate ) async fn delete_empire (
data : web ::Data < AppState > ,
req : HttpRequest ,
param : web ::Query < schemas ::DeleteEmpireParams > ,
) -> impl Responder {
let auth_token = get_auth_header ( & req ) ;
let param = param . into_inner ( ) ;
let user_auth : schemas ::AuthReturn = verify_auth ( 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 {
match sqlx ::query! (
2023-09-07 20:14:51 +02:00
" DELETE FROM public.empires WHERE id = $1 AND game_id = $2 " ,
2023-09-03 02:20:26 +02:00
param . empire_id ,
param . game_id
)
. execute ( & data . db )
. await
{
Ok ( _ ) = > { }
Err ( _ ) = > return HttpResponse ::UnprocessableEntity ( ) . finish ( ) ,
} ;
return HttpResponse ::Ok ( ) . into ( ) ;
} else {
return HttpResponse ::Unauthorized ( ) . finish ( ) ;
}
}
2023-09-02 20:23:34 +02:00
2023-09-08 22:55:17 +02:00
// Ethics Endpoints
// Data Manipulation Admin Only
#[ utoipa::path(
responses (
( status = 200 , description = " OK " , body = ChellarisEthics ) ,
) ,
) ]
#[ get( " /api/v3/ethics " ) ]
pub ( crate ) async fn get_ethics ( data : web ::Data < AppState > ) -> impl Responder {
// SQL Queries
// TODO: Optimize by utilizing some SQL magic, for now this has to do
let mut db_ethics : HashMap < i32 , schemas ::Ethic > = HashMap ::new ( ) ;
let mut db_ethic_query = QueryBuilder ::< sqlx ::Postgres > ::new ( " SELECT * FROM public.ethics " ) ;
match db_ethic_query
. build_query_as ::< db ::schemas ::Ethic > ( )
. fetch_all ( & data . db )
. await
{
Ok ( data ) = > {
for ethic in data {
db_ethics . insert (
ethic . id ,
schemas ::Ethic {
id : ethic . id ,
gestalt : ethic . gestalt_ethic ,
display : ethic . name ,
} ,
) ;
}
}
Err ( e ) = > return HttpResponse ::UnprocessableEntity ( ) . body ( format! ( " {:#?} " , e . to_string ( ) ) ) ,
} ;
// Empire Ethic Creation
let parsed_data : schemas ::ChellarisEthics = schemas ::ChellarisEthics { ethics : db_ethics } ;
return HttpResponse ::Ok ( ) . json ( parsed_data ) ;
}
// Species & Portrait Endpoints
// Data Manipulation Admin Only
2023-08-30 04:16:43 +02:00
2023-09-08 22:55:17 +02:00
#[ utoipa::path(
responses (
( status = 200 , description = " OK " , body = ChellarisPhenotypes ) ,
) ,
) ]
#[ get( " /api/v3/phenotypes " ) ]
pub ( crate ) async fn get_phenotypes ( data : web ::Data < AppState > ) -> impl Responder {
// SQL Queries
// TODO: Optimize by utilizing some SQL magic, for now this has to do
let mut db_phenotypes : HashMap < i32 , schemas ::Phenotype > = HashMap ::new ( ) ;
let mut db_phenotype_query = QueryBuilder ::< sqlx ::Postgres > ::new ( " SELECT * FROM public.portrait_groups " ) ;
match db_phenotype_query
. build_query_as ::< db ::schemas ::PortraitGroup > ( )
. fetch_all ( & data . db )
. await
{
Ok ( data ) = > {
for phenotype in data {
db_phenotypes . insert (
phenotype . id ,
schemas ::Phenotype {
id : phenotype . id ,
display : phenotype . name ,
species : HashMap ::new ( ) ,
} ,
) ;
}
}
Err ( e ) = > return HttpResponse ::UnprocessableEntity ( ) . body ( format! ( " {:#?} " , e . to_string ( ) ) ) ,
} ;
let mut db_species_query = QueryBuilder ::< sqlx ::Postgres > ::new ( " SELECT * FROM public.portraits " ) ;
match db_species_query
. build_query_as ::< db ::schemas ::Portrait > ( )
. fetch_all ( & data . db )
. await
{
Ok ( data ) = > {
for species in data {
if let Some ( phenotype ) = db_phenotypes . get_mut ( & species . group_id ) {
phenotype . species . insert (
species . id ,
schemas ::Species {
id : species . id ,
hires : species . hires ,
lores : species . lores
}
) ;
}
}
}
Err ( e ) = > return HttpResponse ::UnprocessableEntity ( ) . body ( format! ( " {:#?} " , e . to_string ( ) ) ) ,
} ;
// Empire Ethic Creation
let parsed_data : schemas ::ChellarisPhenotypes = schemas ::ChellarisPhenotypes { phenotypes : db_phenotypes } ;
return HttpResponse ::Ok ( ) . json ( parsed_data ) ;
}