2026-07-05 22:13:51 +02:00
|
|
|
use crate::Pool;
|
2025-03-08 00:53:11 +01:00
|
|
|
use crate::account::account::Auth;
|
2025-04-26 20:10:14 +02:00
|
|
|
use crate::error::{Error, Errors};
|
2026-07-05 22:13:51 +02:00
|
|
|
use crate::nnid::oauth::generate_token::create_token;
|
2025-03-08 00:53:11 +01:00
|
|
|
use crate::nnid::oauth::generate_token::token_type::NEX_TOKEN;
|
2025-03-07 15:14:43 +01:00
|
|
|
use crate::xml::Xml;
|
2026-07-05 22:13:51 +02:00
|
|
|
use nex_account::grpc::Pid;
|
|
|
|
|
use reqwest::header::SERVER;
|
|
|
|
|
use rocket::{State, get};
|
|
|
|
|
use serde::Serialize;
|
|
|
|
|
use sqlx::types::ipnetwork::IpNetwork::V4;
|
|
|
|
|
use std::net::Ipv4Addr;
|
2025-03-07 15:14:43 +01:00
|
|
|
|
2026-07-05 22:13:51 +02:00
|
|
|
const NO_IPV4_ERROR: Errors = Errors {
|
|
|
|
|
error: &[Error {
|
|
|
|
|
code: "1022",
|
|
|
|
|
message: "Server is not a valid IPv4 address",
|
|
|
|
|
}],
|
2025-04-26 20:10:14 +02:00
|
|
|
};
|
|
|
|
|
|
2026-07-05 22:13:51 +02:00
|
|
|
const SERVER_ERROR: Errors = Errors {
|
|
|
|
|
error: &[Error {
|
|
|
|
|
code: "9999",
|
|
|
|
|
message: "Internal Server Error",
|
|
|
|
|
}],
|
2026-06-07 13:55:34 +02:00
|
|
|
};
|
|
|
|
|
|
2026-07-05 22:13:51 +02:00
|
|
|
const NO_SERVER_ERROR: Errors = Errors {
|
|
|
|
|
error: &[Error {
|
|
|
|
|
code: "1021",
|
|
|
|
|
message: "The requested game server was not found",
|
|
|
|
|
}],
|
2025-04-26 20:10:14 +02:00
|
|
|
};
|
|
|
|
|
|
2026-07-05 22:13:51 +02:00
|
|
|
const MAINTENANCE_ERROR: Errors = Errors {
|
|
|
|
|
error: &[Error {
|
|
|
|
|
code: "2002",
|
|
|
|
|
message: "The requested game server is under maintenance",
|
|
|
|
|
}],
|
2026-06-07 13:55:34 +02:00
|
|
|
};
|
|
|
|
|
|
2025-03-07 15:14:43 +01:00
|
|
|
#[derive(Serialize)]
|
|
|
|
|
#[serde(rename = "nex_token")]
|
2026-07-05 22:13:51 +02:00
|
|
|
pub struct NexToken {
|
2025-03-07 15:14:43 +01:00
|
|
|
host: Ipv4Addr,
|
|
|
|
|
nex_password: String,
|
|
|
|
|
pid: i32,
|
|
|
|
|
port: u16,
|
2026-07-05 22:13:51 +02:00
|
|
|
token: Box<str>,
|
2025-03-07 15:14:43 +01:00
|
|
|
}
|
|
|
|
|
|
2025-03-09 23:47:46 +01:00
|
|
|
#[derive(Serialize)]
|
|
|
|
|
#[serde(rename = "service_token")]
|
2026-07-05 22:13:51 +02:00
|
|
|
pub struct ServiceToken {
|
|
|
|
|
token: String,
|
2025-03-09 23:47:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[get("/v1/api/provider/service_token/@me")]
|
2026-07-05 22:13:51 +02:00
|
|
|
pub async fn get_service_token(
|
|
|
|
|
pool: &State<Pool>,
|
|
|
|
|
auth: Auth<true, false>,
|
|
|
|
|
) -> Result<Xml<ServiceToken>, Option<Errors<'static>>> {
|
2025-03-09 23:47:46 +01:00
|
|
|
// just gonna put this here as a side note for the future:
|
|
|
|
|
// we could also be using key derivation to derive the nex token as if it were a key
|
|
|
|
|
// that way we could reduce the data the database needs to store and also reduce the transfer
|
|
|
|
|
// cost of sending an entire row from the user table (which is required for the auth code unless
|
|
|
|
|
// we change the way we read in data to essentially having the user object be a proxy for its
|
|
|
|
|
// table row)
|
|
|
|
|
|
|
|
|
|
let pool = pool.inner();
|
|
|
|
|
|
|
|
|
|
let token = create_token(pool, auth.pid, NEX_TOKEN, None).await;
|
|
|
|
|
|
2026-07-05 22:13:51 +02:00
|
|
|
Ok(Xml(ServiceToken { token }))
|
2025-03-09 23:47:46 +01:00
|
|
|
}
|
|
|
|
|
|
2025-03-07 15:14:43 +01:00
|
|
|
#[get("/v1/api/provider/nex_token/@me?<game_server_id>")]
|
2026-07-05 22:13:51 +02:00
|
|
|
pub async fn get_nex_token(
|
|
|
|
|
pool: &State<Pool>,
|
|
|
|
|
auth: Auth<true, false>,
|
|
|
|
|
game_server_id: &str,
|
|
|
|
|
) -> Result<Xml<NexToken>, Option<Errors<'static>>> {
|
2025-03-08 00:53:11 +01:00
|
|
|
// just gonna put this here as a side note for the future:
|
|
|
|
|
// we could also be using key derivation to derive the nex token as if it were a key
|
|
|
|
|
// that way we could reduce the data the database needs to store and also reduce the transfer
|
|
|
|
|
// cost of sending an entire row from the user table (which is required for the auth code unless
|
|
|
|
|
// we change the way we read in data to essentially having the user object be a proxy for its
|
|
|
|
|
// table row)
|
2025-03-09 23:47:46 +01:00
|
|
|
|
2026-06-07 13:55:34 +02:00
|
|
|
let account_level = auth.account_level;
|
|
|
|
|
|
2025-03-08 00:53:11 +01:00
|
|
|
let pool = pool.inner();
|
|
|
|
|
|
2026-06-07 13:55:34 +02:00
|
|
|
let server = match sqlx::query!(
|
|
|
|
|
"select address, port, maintenance_mode from nex_servers where game_server_id = $1 AND server_account_level <= $2",
|
|
|
|
|
game_server_id,
|
|
|
|
|
account_level
|
2025-04-26 20:10:14 +02:00
|
|
|
)
|
2026-06-07 13:55:34 +02:00
|
|
|
.fetch_optional(pool)
|
|
|
|
|
.await
|
|
|
|
|
.expect("database error") {
|
|
|
|
|
Some(row) => row,
|
|
|
|
|
None => return Err(Some(NO_SERVER_ERROR)),
|
|
|
|
|
}; // only crash on db failure (not missing row)
|
2026-07-05 22:13:51 +02:00
|
|
|
|
2026-06-07 13:55:34 +02:00
|
|
|
if server.maintenance_mode {
|
2026-07-05 22:13:51 +02:00
|
|
|
return Err(Some(MAINTENANCE_ERROR));
|
2026-06-07 13:55:34 +02:00
|
|
|
}
|
2025-03-08 00:53:11 +01:00
|
|
|
|
|
|
|
|
let V4(host) = server.address else {
|
2025-04-26 20:10:14 +02:00
|
|
|
return Err(Some(NO_IPV4_ERROR));
|
2025-03-08 00:53:11 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let host = host.ip();
|
|
|
|
|
|
2026-07-05 22:13:51 +02:00
|
|
|
let mut client = nex_account::grpc_client().await.unwrap();
|
|
|
|
|
let Ok(key) = client.get_nex_key_by_pid(Pid { pid: auth.pid }).await else {
|
|
|
|
|
println!("account does not exist on nex-account server");
|
|
|
|
|
return Err(Some(SERVER_ERROR));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let token = nex_account::gen_nexact_token(
|
|
|
|
|
auth.pid,
|
|
|
|
|
key.into_inner()
|
|
|
|
|
.key
|
|
|
|
|
.try_into()
|
|
|
|
|
.map_err(|_| Some(SERVER_ERROR))?,
|
2025-03-08 00:53:11 +01:00
|
|
|
)
|
2026-07-05 22:13:51 +02:00
|
|
|
.expect("NEX_ACCOUNT_KEYPAIR not set");
|
|
|
|
|
|
|
|
|
|
Ok(Xml(NexToken {
|
|
|
|
|
host,
|
|
|
|
|
port: server.port as u16,
|
|
|
|
|
nex_password: auth.nex_password.clone(),
|
|
|
|
|
pid: auth.pid,
|
|
|
|
|
token,
|
|
|
|
|
}))
|
2026-05-02 13:42:03 +02:00
|
|
|
}
|