This commit is contained in:
Tyler Murphy 2023-01-28 13:14:53 -05:00
parent 487d97cb01
commit f3f5e03651
8 changed files with 103 additions and 17 deletions

5
.dockerignore Normal file
View file

@ -0,0 +1,5 @@
.git
.gitignore
deployments
target
xssbook.db

13
LICENSE Normal file
View file

@ -0,0 +1,13 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.

42
README.md Normal file
View file

@ -0,0 +1,42 @@
# xssbook
**description**
who doesn't want to run non free javascript
now with xssbook you can run as much stallman disapprovement as you want
- all inputs on the site are unfiltered
- api calls dont care what you send them as long as they are valid strings
- /console page to see everyones amazing api calls
**installation**
The project is written in rust, so you can build it by running
`cargo build --release`
Make sure where you run the binary from, you also move the public folder to.
Finally, the site runs on port `8080`, so its recommended you put it begind a reverse proxy, or you could use a docker container and remap the outsite port (see below).
**docker**
If you want to run it in a docker container a premade dockerfile is here for you
`docker build -f deployments/docker/Dockerfile -t xssbook .`
There is also a docker-compose.yml file for your reference in the /deployments/docker folder.
The one thing about the docker container is you have to mount the volume
`-v [your directory]/xssbook.db:/data/xssbook.db`
to make the database persistant. Finally, before running the container run
`touch [your directory]/xssbook.db`
since docker will create a folder there otherwise and it won't work.
**license**
This amazing project is licensed under the WTFPL

View file

@ -0,0 +1,18 @@
FROM rust:1.67-buster as builder
WORKDIR /usr/src/xssbook
COPY ./Cargo.toml ./Cargo.toml
COPY ./Cargo.lock ./Cargo.lock
COPY ./src ./src
RUN cargo install --path .
FROM debian:buster-slim
COPY --from=builder /usr/local/cargo/bin/xssbook /usr/local/bin/xssbook
RUN mkdir /data
WORKDIR /data
COPY ./public ./public
EXPOSE 8080
CMD ["/usr/local/bin/xssbook"]

View file

@ -0,0 +1,10 @@
version: "3.9"
services:
ritlug-discord-bot:
container_name: xssbook
image: xssbook
ports:
- 8080:8080
volumes:
- ${PWD}/xssbook.db:/data/xssbook.db

View file

@ -14,7 +14,7 @@ async fn login(user: Option<AuthorizedUser>) -> Response {
if user.is_some() { if user.is_some() {
return Redirect::to("/home").into_response() return Redirect::to("/home").into_response()
} else { } else {
return ResponseCode::Success.file("/login.html").await.unwrap() return ResponseCode::Success.file("/login.html").await
} }
} }
@ -22,7 +22,7 @@ async fn home(user: Option<AuthorizedUser>) -> Response {
if user.is_none() { if user.is_none() {
return Redirect::to("/login").into_response() return Redirect::to("/login").into_response()
} else { } else {
return ResponseCode::Success.file("/home.html").await.unwrap() return ResponseCode::Success.file("/home.html").await
} }
} }
@ -30,7 +30,7 @@ async fn people(user: Option<AuthorizedUser>) -> Response {
if user.is_none() { if user.is_none() {
return Redirect::to("/login").into_response() return Redirect::to("/login").into_response()
} else { } else {
return ResponseCode::Success.file("/people.html").await.unwrap() return ResponseCode::Success.file("/people.html").await
} }
} }
@ -38,7 +38,7 @@ async fn profile(user: Option<AuthorizedUser>) -> Response {
if user.is_none() { if user.is_none() {
return Redirect::to("/login").into_response() return Redirect::to("/login").into_response()
} else { } else {
return ResponseCode::Success.file("/profile.html").await.unwrap() return ResponseCode::Success.file("/profile.html").await
} }
} }

View file

@ -1,5 +1,5 @@
use std::net::SocketAddr; use std::net::SocketAddr;
use axum::{Router, response::Response, http::Request, middleware::{Next, self}, extract::ConnectInfo, RequestExt, body::HttpBody, Extension}; use axum::{Router, response::Response, http::{Request, StatusCode}, middleware::{Next, self}, extract::ConnectInfo, RequestExt, body::HttpBody, Extension};
use tower_cookies::CookieManagerLayer; use tower_cookies::CookieManagerLayer;
use tracing::metadata::LevelFilter; use tracing::metadata::LevelFilter;
use tracing_subscriber::{prelude::__tracing_subscriber_SubscriberExt, util::SubscriberInitExt, Layer, filter::filter_fn}; use tracing_subscriber::{prelude::__tracing_subscriber_SubscriberExt, util::SubscriberInitExt, Layer, filter::filter_fn};
@ -13,9 +13,10 @@ mod types;
mod console; mod console;
async fn serve<B>(req: Request<B>, next: Next<B>) -> Response { async fn serve<B>(req: Request<B>, next: Next<B>) -> Response {
let Ok(file) = ResponseCode::Success.file(&req.uri().to_string()).await else { let file = ResponseCode::Success.file(&req.uri().to_string()).await;
return next.run(req).await if file.status() != StatusCode::OK {
}; return next.run(req).await;
}
file file
} }
@ -33,10 +34,7 @@ async fn log<B>(mut req: Request<B>, next: Next<B>) -> Response where
} }
async fn not_found() -> Response { async fn not_found() -> Response {
match ResponseCode::NotFound.file("/404.html").await { ResponseCode::NotFound.file("/404.html").await
Ok(file) => file,
Err(err) => err
}
} }
#[tokio::main] #[tokio::main]

View file

@ -54,21 +54,21 @@ impl ResponseCode {
} }
#[instrument()] #[instrument()]
pub async fn file(self, path: &str) -> Result<Response> { pub async fn file(self, path: &str) -> Response {
if path.chars().position(|c| c == '.' ).is_none() { if path.chars().position(|c| c == '.' ).is_none() {
return Err(ResponseCode::BadRequest.text("Folders cannot be served")); return ResponseCode::BadRequest.text("Folders cannot be served");
} }
let path = format!("public{}", path); let path = format!("public{}", path);
let svc = ServeFile::new(path); let svc = ServeFile::new(path);
let Ok(mut res) = svc.oneshot(Request::new(Body::empty())).await else { let Ok(mut res) = svc.oneshot(Request::new(Body::empty())).await else {
tracing::error!("Error while fetching file"); tracing::error!("Error while fetching file");
return Err(ResponseCode::InternalServerError.text("Error while fetching file")); return ResponseCode::InternalServerError.text("Error while fetching file");
}; };
if res.status() != StatusCode::OK { if res.status() != StatusCode::OK {
return Err(ResponseCode::NotFound.text("File not found")); return ResponseCode::NotFound.text("File not found");
} }
*res.status_mut() = self.code(); *res.status_mut() = self.code();
Ok(res.into_response()) res.into_response()
} }
} }