Integrate Vantage live map for guild claims [skip ci]
This commit is contained in:
1 parent
52de8c3031
commit
602e7fd0f0
17 files changed
+470
-21
No files matched your search
@@ -61,6 +61,7 @@ fn clip(s: &str, max: usize) -> String {
|
||||
#[derive(Debug, Clone, sqlx::FromRow, Serialize)]
|
||||
pub struct ServerRow {
|
||||
pub instance_id: String,
|
||||
pub map_url: String,
|
||||
pub id: i64,
|
||||
pub name: String,
|
||||
#[serde(skip)]
|
||||
@@ -832,6 +833,8 @@ pub struct ServerInput {
|
||||
allowed_groups: Vec<String>,
|
||||
#[serde(default)]
|
||||
require_launcher: bool,
|
||||
#[serde(default)]
|
||||
map_url: String,
|
||||
}
|
||||
|
||||
fn default_access() -> String {
|
||||
@@ -849,6 +852,18 @@ impl ServerInput {
|
||||
if self.access == "groups" && self.allowed_groups.is_empty() {
|
||||
return Err(AppError::bad_request("pick at least one group"));
|
||||
}
|
||||
if !self.map_url.trim().is_empty() {
|
||||
let url = reqwest::Url::parse(self.map_url.trim()).map_err(|_| AppError::bad_request("map URL must be an absolute URL"))?;
|
||||
if url.scheme() != "https" && !(url.scheme() == "http" && matches!(url.host_str(), Some("localhost" | "127.0.0.1"))) {
|
||||
return Err(AppError::bad_request("map URL must use HTTPS (or localhost for development)"));
|
||||
}
|
||||
if url.username() != "" || url.password().is_some() || url.fragment().is_some() || url.query().is_some() {
|
||||
return Err(AppError::bad_request("map URL cannot contain credentials, query parameters, or a fragment"));
|
||||
}
|
||||
if !matches!(url.path().rsplit('/').next(), Some("manifest.json" | "world.json")) {
|
||||
return Err(AppError::bad_request("map URL must end with manifest.json or world.json"));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -865,7 +880,7 @@ pub async fn create(_: AdminUser, State(state): State<AppState>, Json(input): Js
|
||||
input.validate()?;
|
||||
let token = new_token();
|
||||
let id: i64 = sqlx::query_scalar(
|
||||
"INSERT INTO game_servers (name, token_hash, token_hint, access, allowed_groups, require_launcher, created_at, instance_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?) RETURNING id",
|
||||
"INSERT INTO game_servers (name, token_hash, token_hint, access, allowed_groups, require_launcher, created_at, instance_id, map_url) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING id",
|
||||
)
|
||||
.bind(input.name.trim())
|
||||
.bind(hash_token(&token))
|
||||
@@ -875,6 +890,7 @@ pub async fn create(_: AdminUser, State(state): State<AppState>, Json(input): Js
|
||||
.bind(input.require_launcher)
|
||||
.bind(now())
|
||||
.bind(&input.instance_id)
|
||||
.bind(input.map_url.trim())
|
||||
.fetch_one(&state.db)
|
||||
.await?;
|
||||
let server = get_server(&state, id).await?;
|
||||
@@ -889,12 +905,13 @@ pub async fn update(
|
||||
) -> AppResult<Json<ServerView>> {
|
||||
input.validate()?;
|
||||
get_server(&state, id).await?;
|
||||
sqlx::query("UPDATE game_servers SET name = ?, access = ?, allowed_groups = ?, require_launcher = ?, instance_id = ? WHERE id = ?")
|
||||
sqlx::query("UPDATE game_servers SET name = ?, access = ?, allowed_groups = ?, require_launcher = ?, instance_id = ?, map_url = ? WHERE id = ?")
|
||||
.bind(input.name.trim())
|
||||
.bind(&input.access)
|
||||
.bind(serde_json::to_string(&input.allowed_groups).unwrap_or_else(|_| "[]".into()))
|
||||
.bind(input.require_launcher)
|
||||
.bind(&input.instance_id)
|
||||
.bind(input.map_url.trim())
|
||||
.bind(id)
|
||||
.execute(&state.db)
|
||||
.await?;
|
||||
@@ -1078,6 +1095,7 @@ pub async fn public_servers(State(state): State<AppState>) -> AppResult<Json<Val
|
||||
"id": s.id,
|
||||
"name": s.name,
|
||||
"instance_id": s.instance_id,
|
||||
"map_url": s.map_url,
|
||||
"online": is_online,
|
||||
"players_online": if is_online { s.online_count } else { 0 },
|
||||
"players_max": s.max_players,
|
||||
|
||||
Reference in new issue
Block a user