7.4 KiB
Code Submission
This project is a Leptos + Axum app for a multi-step code submission challenge. It exposes a small web UI where users enter a code, accepts challenge submissions for valid codes, and can toggle the server between offline and live mode for SMS-driven challenge flow testing.
Overview
The app supports:
- A home page for entering challenge codes.
- A
/submit/:coderoute that validates supported codes. - A
/managepage to toggle the server between live and offline states. - A
/historypage for successful submission records. - A protected
POST /event/buzzendpoint for challenge code 1, which validates a secret and timing window. - TextBee SMS notifications when the server is live.
This repository is not a generic template anymore; it is a working challenge server with specific code-handling behavior and operational configuration.
Project structure
.
├── Cargo.toml
├── README.md
├── dev.env
├── LICENSE
├── end2end/
│ ├── package.json
│ ├── playwright.config.ts
│ └── tests/
├── public/
│ ├── challenge3.txt
│ ├── challenge3_annotated.txt
│ └── favicon.ico
├── src/
│ ├── app.rs
│ ├── lib.rs
│ ├── main.rs
│ ├── manage.rs
│ ├── secrets.rs
│ └── codes/
│ ├── code1.rs
│ ├── code2.rs
│ ├── code5.rs
│ ├── history.rs
│ └── mod.rs
├── style/
│ └── main.scss
└── target/
Features
Code 1
Code 1 is the timed buzz challenge. It accepts a POST /event/buzz request with:
{
"delay_ms": 6388,
"secret": "<your CODE1_SECRET value>"
}
Behavior:
delay_msmust be a non-negative integer.secretmust matchCODE1_SECRETexactly.- The request is only accepted in the
America/Chicagowindow from 11:00 AM to 1:30 PM inclusive. - The server computes the signed delta from the target of
6430 ms. - Deltas outside the inclusive range
-500to+500are rejected and ignored. - Valid submissions return HTTP
202. - When live, the app sends SMS notifications via TextBee to the configured recipients.
- When offline, it logs the planned SMS actions instead.
The challenge text includes the literal strings CHALLENGE_1_FIRST and CHALLENGE_1_SECOND, which are sent to the configured recipients once the buzz is accepted.
Code 2
The code value is QJ4EAN and is case-insensitive.
On successful submission:
- It records the success in the submission history.
- If the server is live, it sends a TextBee SMS to
RECIPIENT_SELF. - If the server is offline, it logs the notification instead.
Code 5
The code value is V7MK2P and is case-insensitive.
On successful submission:
- It records the success in the submission history.
- If the server is live, it sends a TextBee SMS to
RECIPIENT_SELF. - If the server is offline, it logs the notification instead.
- It shows a completion message without providing a download.
Getting started
Prerequisites
You need Rust, the Leptos toolchain, and the project dependencies.
If you do not have cargo-leptos installed:
cargo install cargo-leptos --locked
If you need the additional tooling required by cargo-leptos:
rustup toolchain install nightly --allow-downgrade
rustup target add wasm32-unknown-unknown
cargo install cargo-generate
npm install -g sass
Then install the end-to-end test dependencies:
cd end2end
npm install
Environment configuration
Copy the sample environment file to .env before starting the app:
Copy-Item dev.env .env
The app loads .env automatically at startup and validates the required values. The expected settings are defined in src/secrets.rs and include:
DEV_SECRET_KEY— required for admin actions such as toggling live/offline mode and accessing submission history.TEXTBEE_API_KEY— required for sending SMS via TextBee.TEXTBEE_DEVICE_ID— optional, selects a specific paired device.RECIPIENT_SELF,RECIPIENT_1,RECIPIENT_2— each must be a valid E.164 phone number.CODE1_SECRET— required and must be at least 32 bytes long.PROD— set totrueto start the server in the live state. Truthy values are1,true,yes, andon(case-insensitive); any other value starts the server offline.
Do not commit secrets or expose them in client-side code.
Run the app
cargo leptos watch
Then open the local app in your browser as directed by cargo-leptos.
Management and admin flow
The app includes a status management page at /manage.
- It shows whether the server is currently live.
- It lets an operator toggle the server status.
- It requires the configured
DEV_SECRET_KEYbefore changing state.
This is how the system can be transitioned between testing/offline and live challenge operation without exposing the settings publicly.
Challenge testing
Test Code 1 with curl
With the server running locally and CODE1_SECRET set in your shell:
curl.exe -X POST http://127.0.0.1:3000/event/buzz -H "Content-Type: application/json" -d '{"delay_ms":6388,"secret":"<your CODE1_SECRET value>"}'
The server calculates 6388 - 6430 = -42 ms, and a valid request returns HTTP 202.
Test Code 1 with Postman
Create a POST request to http://127.0.0.1:3000/event/buzz, select Body > raw > JSON, and send:
{
"delay_ms": 6388,
"secret": "<your CODE1_SECRET value>"
}
Test Code 1 with Node.js
async function main() {
const delayMs = 6388;
const secret = process.env.CODE1_SECRET;
if (!secret) throw new Error("CODE1_SECRET is not set");
const response = await fetch("http://127.0.0.1:3000/event/buzz", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ delay_ms: delayMs, secret }),
});
console.log(response.status, await response.text());
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
When the server is live, a successful test event sends the configured TextBee SMS to the configured recipients. When it is offline, it logs the action instead.
Build, test, and release
Compile for release
cargo leptos build --release
This will generate the server binary in target/release and the site bundle in target/site.
End-to-end tests
cargo leptos end-to-end
cargo leptos end-to-end --release
Cargo-leptos uses Playwright for browser tests and the test files are under end2end/tests.
Remote deployment without the Rust toolchain
After running cargo leptos build --release, the minimum files needed are:
- The server binary in
target/server/release - The
sitedirectory and all files inside it intarget/site
Copy these files to your remote server. The expected directory structure is:
code_submission
site/
Set the appropriate environment variables before starting the binary:
export LEPTOS_OUTPUT_NAME="code_submission"
export LEPTOS_SITE_ROOT="site"
export LEPTOS_SITE_PKG_DIR="pkg"
export LEPTOS_SITE_ADDR="0.0.0.0:3000"
export LEPTOS_RELOAD_PORT="3001"
Then run the server binary.
Licensing
This project is released under the repository's existing license. The default template license is present in LICENSE, and you should replace it with an appropriate license if you intend to distribute this project publicly.