1
Fork 0
mirror of https://github.com/Steffo99/distributed-arcade.git synced 2024-11-24 17:14:25 +00:00

Gate POST /board/ with the envvar CREATE_TOKEN

This commit is contained in:
Steffo 2022-11-13 02:05:15 +01:00
parent 610ba76cc4
commit 8c9996e83a
Signed by: steffo
GPG key ID: 6965406171929D01
5 changed files with 42 additions and 10 deletions

1
.gitignore vendored
View file

@ -1,2 +1,3 @@
/target /target
/data /data
/secrets

View file

@ -17,5 +17,6 @@ services:
environment: environment:
REDIS_CONN_STRING: "redis://redis:6379/" REDIS_CONN_STRING: "redis://redis:6379/"
AXUM_HOST_STRING: "0.0.0.0:80" AXUM_HOST_STRING: "0.0.0.0:80"
env_file: "./secrets/distributedarcade.env"
ports: ports:
- "127.0.0.1:30038:80" # Reverse proxy this! - "127.0.0.1:30038:80" # Reverse proxy this!

View file

@ -7,6 +7,7 @@ POST http://localhost:30000/
### Create a board ### Create a board
POST http://localhost:30000/board/ POST http://localhost:30000/board/
Content-Type: application/json Content-Type: application/json
Authorization: Bearer qwertyxyzzy
{ {
"name": "example", "name": "example",

View file

@ -116,6 +116,8 @@ paths:
- using the `Descending` order, higher scores are better ranked than lower scores, like in arcade games or athletics. - using the `Descending` order, higher scores are better ranked than lower scores, like in arcade games or athletics.
**WARNING: Once created, a board cannot be edited or deleted, and its token will not be accessible any longer!** **WARNING: Once created, a board cannot be edited or deleted, and its token will not be accessible any longer!**
Requires an authorization key, set as the `CREATE_TOKEN` environment variable of the server.
tags: ["Board"] tags: ["Board"]
requestBody: requestBody:
required: true required: true
@ -135,6 +137,8 @@ paths:
enum: enum:
- "Ascending" - "Ascending"
- "Descending" - "Descending"
security:
- XCreateToken: []
responses: responses:
201: 201:
description: "Board created successfully" description: "Board created successfully"
@ -152,6 +156,20 @@ paths:
operationId: "putScore" operationId: "putScore"
parameters: parameters:
board: "$response.body/name" board: "$response.body/name"
401:
description: "Missing, invalid or malformed Authorization header"
content:
application/json:
schema:
type: string
example: "Missing Authorization header"
403:
description: "Invalid create token"
content:
application/json:
schema:
type: string
example: "Invalid create token"
409: 409:
description: "Board already exists" description: "Board already exists"
content: content:
@ -257,6 +275,13 @@ paths:
schema: schema:
type: string type: string
example: "Missing Authorization header" example: "Missing Authorization header"
403:
description: "Invalid board token"
content:
application/json:
schema:
type: string
example: "Invalid board token"
502: 502:
$ref: "#/components/responses/RedisCmdFailed" $ref: "#/components/responses/RedisCmdFailed"
504: 504:
@ -265,6 +290,10 @@ paths:
components: components:
securitySchemes: securitySchemes:
XCreateToken:
type: http
scheme: "Bearer"
bearerFormat: "setInEnvVars"
XBoardToken: XBoardToken:
type: http type: http
scheme: "Bearer" scheme: "Bearer"

View file

@ -1,16 +1,17 @@
//! Module defining routes for `/board/`. //! Module defining routes for `/board/`.
use axum::http::StatusCode; use axum::http::{HeaderMap, StatusCode};
use axum::extract::{Extension, Json, Query}; use axum::extract::{Extension, Json, Query};
use redis::AsyncCommands; use redis::AsyncCommands;
use serde::Serialize; use serde::Serialize;
use serde::Deserialize; use serde::Deserialize;
use crate::outcome; use crate::outcome;
use crate::shortcuts::redis::RedisConnectOr504; use crate::shortcuts::redis::RedisConnectOr504;
use crate::shortcuts::token::Generate; use crate::shortcuts::token::{Authorize, Generate};
use crate::utils::sorting::SortingOrder; use crate::utils::sorting::SortingOrder;
use crate::utils::kebab::Skewer; use crate::utils::kebab::Skewer;
use crate::utils::token::SecureToken; use crate::utils::token::SecureToken;
use crate::config;
/// Expected body for [`POST /board/`](route_board_post). /// Expected body for [`POST /board/`](route_board_post).
@ -118,19 +119,18 @@ pub(crate) async fn route_board_get(
/// Handler for `POST /board/`. /// Handler for `POST /board/`.
///
/// Creates a new board, storing the details on [Redis].
///
/// Will refuse to overwrite an already existing board.
///
/// Be aware that once created, boards cannot be deleted, if not manually via `redis-cli`.
///
/// If successful, returns [`StatusCode::CREATED`].
pub(crate) async fn route_board_post( pub(crate) async fn route_board_post(
headers: HeaderMap,
Extension(rclient): Extension<redis::Client>, Extension(rclient): Extension<redis::Client>,
Json(RouteBoardBody {name, order}): Json<RouteBoardBody>, Json(RouteBoardBody {name, order}): Json<RouteBoardBody>,
) -> outcome::RequestResult { ) -> outcome::RequestResult {
let token = headers.get_authorization_or_401("Bearer")?;
if token != config::CREATE_TOKEN.as_str() {
log::trace!("Token does not match, forbidding...");
return Err((StatusCode::FORBIDDEN, outcome::req_error!("Invalid create token")))
}
let name = name.to_kebab_lowercase(); let name = name.to_kebab_lowercase();
log::trace!("Determining the Redis key names..."); log::trace!("Determining the Redis key names...");