rust-nex/rnex-server/backend-auth/src/admin.rs
red binder 667f434189
All checks were successful
Build and Test / sonic-transformed (push) Successful in 7m20s
Build and Test / mario-tennis (push) Successful in 7m30s
Build and Test / minecraft-wiiu (push) Successful in 7m35s
Build and Test / terraria (push) Successful in 7m58s
Build and Test / wii-sports-club (push) Successful in 8m0s
Build and Test / puyopuyo (push) Successful in 8m2s
Build and Test / splatoon-testfire (push) Successful in 8m55s
Build and Test / splatoon (push) Successful in 8m55s
Build and Test / wii-u-chat (push) Successful in 9m12s
Build and Test / super-mario-maker (push) Successful in 9m14s
Build and Test / friends (push) Successful in 9m16s
Build and Test / fast-racing-neo (push) Successful in 9m26s
feat(grpc): add support for maintenance checks
2026-08-12 04:57:53 +02:00

72 lines
No EOL
2 KiB
Rust

use std::net::SocketAddr;
use rnex_auth::{is_maintenance, set_maintenance};
use rnex_server_api::auth::{
auth_admin_service_server::{AuthAdminService, AuthAdminServiceServer},
MaintenanceState, Empty,
};
use tonic::{Request, Response, Status, transport::Server};
pub struct AdminGrpc {
token: Option<String>,
}
impl AdminGrpc {
pub fn new(token: Option<String>) -> Self {
Self { token }
}
fn authorize<T>(&self, request: &Request<T>) -> Result<(), Status> {
let Some(expected) = &self.token else {
return Ok(());
};
let Some(value) = request.metadata().get("authorization") else {
return Err(Status::unauthenticated("missing authorization header"));
};
let header = value
.to_str()
.map_err(|_| Status::unauthenticated("authorization header must be ASCII"))?;
let supplied = header
.strip_prefix("Bearer ")
.or_else(|| header.strip_prefix("bearer "))
.ok_or_else(|| Status::unauthenticated("authorization header must use Bearer scheme"))?;
if supplied == expected {
Ok(())
} else {
Err(Status::unauthenticated("invalid admin token"))
}
}
}
#[tonic::async_trait]
impl AuthAdminService for AdminGrpc {
async fn set_maintenance(
&self,
request: Request<MaintenanceState>,
) -> Result<Response<Empty>, Status> {
self.authorize(&request)?;
set_maintenance(request.into_inner().enabled);
Ok(Response::new(Empty {}))
}
async fn get_maintenance(
&self,
request: Request<Empty>,
) -> Result<Response<MaintenanceState>, Status> {
self.authorize(&request)?;
Ok(Response::new(MaintenanceState {
enabled: is_maintenance(),
}))
}
}
pub async fn serve(addr: SocketAddr, token: Option<String>) -> Result<(), tonic::transport::Error> {
Server::builder()
.add_service(AuthAdminServiceServer::new(AdminGrpc::new(token)))
.serve(addr)
.await
}