Add admin endpoint for updating games #4

Merged
Zigzagill merged 8 commits from update-functions into main 2026-05-24 05:22:46 +00:00
5 changed files with 161 additions and 9 deletions

83
Cargo.lock generated
View File

@ -587,6 +587,40 @@ dependencies = [
"memchr",
]
[[package]]
name = "darling"
version = "0.20.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.20.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "darling_macro"
version = "0.20.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
dependencies = [
"darling_core",
"quote",
"syn",
]
[[package]]
name = "deranged"
version = "0.5.5"
@ -1029,6 +1063,12 @@ dependencies = [
"stable_deref_trait",
]
[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "http"
version = "0.2.12"
@ -1323,6 +1363,12 @@ dependencies = [
"zerovec",
]
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "idna"
version = "1.1.0"
@ -1376,6 +1422,17 @@ dependencies = [
"hashbrown 0.16.0",
]
[[package]]
name = "inherent"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c727f80bfa4a6c6e2508d2f05b6f4bfce242030bd88ed15ae5331c5b5d30fba7"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "ipnet"
version = "2.11.0"
@ -1554,6 +1611,7 @@ dependencies = [
"r2d2_sqlite",
"reqwest",
"rusqlite",
"sea-query",
"serde",
"serde_json",
"tempfile",
@ -2206,6 +2264,31 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "sea-query"
version = "1.0.0-rc.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7e01d76c67146262612a9db50cbc4b4b3236a96a1f04f1744ef2582234187e2"
dependencies = [
"inherent",
"itoa",
"sea-query-derive",
]
[[package]]
name = "sea-query-derive"
version = "1.0.0-rc.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d88ad44b6ad9788c8b9476b6b91f94c7461d1e19d39cd8ea37838b1e6ff5aa8"
dependencies = [
"darling",
"heck",
"proc-macro2",
"quote",
"syn",
"thiserror",
]
[[package]]
name = "security-framework"
version = "2.11.1"

View File

@ -17,6 +17,7 @@ r2d2 = "0.8.10"
r2d2_sqlite = "0.31.0"
reqwest = "0.12.24"
rusqlite = {version="0.37.0", features=["bundled"]}
sea-query = "1.0.0-rc.34"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.145"
tera = "1.20.1"

View File

@ -1,6 +1,6 @@
#!/usr/bin/env bash
cd $(dirname "$0")
db_file='../storage/mapbattle.db'
sqlite3 "$dbfile" < db.sql
sqlite3 -csv "$dbfile" ".import init_games.csv games"
sqlite3 -csv "$dbfile" ".import init_teams.csv teams"
sqlite3 "$db_file" < db.sql
sqlite3 -csv "$db_file" ".import init_games.csv games"
sqlite3 -csv "$db_file" ".import init_teams.csv teams"

View File

@ -1,6 +1,7 @@
use crate::data::{Game, Player, Team};
use actix_web::{Error, error, web};
use rusqlite::Row;
use sea_query::{Expr, ExprTrait, Query, SqliteQueryBuilder};
use serde_json::{Map, Value};
use std::collections::HashMap;
@ -54,6 +55,21 @@ pub async fn teams(pool: &Pool) -> Result<HashMap<String, Team>, Error> {
.map_err(error::ErrorInternalServerError)
}
pub async fn update_game(
pool: &Pool,
code: String,
start_time: String,
end_time: String,
) -> Result<(), Error> {
let pool = pool.clone();
let conn = web::block(move || pool.get())
.await?
.map_err(error::ErrorInternalServerError)?;
web::block(move || update_game_sqlite(conn, code, start_time, end_time))
.await?
.map_err(error::ErrorInternalServerError)
}
fn get_all_games(conn: Connection, all_teams: HashMap<String, Team>) -> GamesResult {
let mut games_stmt = conn.prepare(GAMES_QUERY)?;
games_stmt
@ -72,6 +88,30 @@ fn get_all_games(conn: Connection, all_teams: HashMap<String, Team>) -> GamesRes
.and_then(Iterator::collect)
}
fn update_game_sqlite(
conn: Connection,
code: String,
start_time: String,
end_time: String,
) -> Result<(), rusqlite::Error> {
let update_query = Query::update()
.table("games")
.values([
("start_time", start_time.into()),
("end_time", end_time.into()),
])
.and_where(Expr::col("code").eq(code))
.to_owned();
let mut update_stmt = conn.prepare(&update_query.to_string(SqliteQueryBuilder))?;
let result = update_stmt.query([]);
match result {
Ok(_) => Ok(()),
Err(error) => Err(error),
}
}
fn get_all_teams(conn: Connection) -> TeamsResult {
let mut teams_stmt = conn.prepare(TEAMS_QUERY)?;
teams_stmt

View File

@ -67,6 +67,13 @@ struct QueryForm {
query: String,
}
#[derive(Deserialize, Debug)]
struct UpdateGameForm {
code: String,
start_time: String,
end_time: String,
}
impl Actor for GamesActor {
type Context = actix::Context<Self>;
}
@ -185,12 +192,32 @@ async fn admin() -> impl Responder {
}

okay it does look like we need to update stuff both in the games object and the db, we should do it in a follow-up though

okay it does look like we need to update stuff both in the games object and the db, we should do it in a follow-up though
#[get("/admin/games")]
Zigzagill marked this conversation as resolved Outdated

should remove this if no longer need it for debugging hehe

should remove this if no longer need it for debugging hehe
async fn list_of_games(games: web::Data<Arc<Mutex<Vec<Game>>>>) -> impl Responder {
let games = games.lock().await;
let games_json = serde_json::to_string(&*games).unwrap();
HttpResponse::Ok()
.content_type("application/json")
.body(games_json)
async fn list_of_games(pool: web::Data<Pool>) -> impl Responder {
let games_result = db::games(&pool).await;
match games_result {
Ok(games) => {
let games_json = serde_json::to_string(&*games).unwrap();
HttpResponse::Ok()
.content_type("application/json")
.body(games_json)
}
Err(err) => HttpResponse::InternalServerError().body(format!("{err}")),
}
}
#[post("/admin/game/update")]
async fn update_game(pool: web::Data<Pool>, form: web::Form<UpdateGameForm>) -> impl Responder {
match db::update_game(
&pool,
form.code.clone(),
form.start_time.clone(),
form.end_time.clone(),
)
.await
{
Ok(_) => HttpResponse::Ok().body("{}"),
Err(err) => HttpResponse::InternalServerError().body(format!("{err:?}")),
}
}
#[post("/admin/query")]
@ -232,6 +259,7 @@ async fn main() -> std::io::Result<()> {
.service(admin_query)
.service(list_of_games)
.service(get_territories)
.service(update_game)
})
.bind(("0.0.0.0", 8080))?
.run()