diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..476f1de --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +.git +.gitignore +deployments +target +xssbook.db \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..541f4f7 --- /dev/null +++ b/LICENSE @@ -0,0 +1,13 @@ + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + Version 2, December 2004 + + Copyright (C) 2004 Sam Hocevar + + 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. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..7c9efce --- /dev/null +++ b/README.md @@ -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 \ No newline at end of file diff --git a/deployments/docker/Dockerfile b/deployments/docker/Dockerfile new file mode 100644 index 0000000..f14b0a6 --- /dev/null +++ b/deployments/docker/Dockerfile @@ -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"] \ No newline at end of file diff --git a/deployments/docker/docker-compose.yml b/deployments/docker/docker-compose.yml new file mode 100644 index 0000000..e58c9f6 --- /dev/null +++ b/deployments/docker/docker-compose.yml @@ -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 diff --git a/src/api/pages.rs b/src/api/pages.rs index b2bef82..7f5bfc3 100644 --- a/src/api/pages.rs +++ b/src/api/pages.rs @@ -14,7 +14,7 @@ async fn login(user: Option) -> Response { if user.is_some() { return Redirect::to("/home").into_response() } 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) -> Response { if user.is_none() { return Redirect::to("/login").into_response() } 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) -> Response { if user.is_none() { return Redirect::to("/login").into_response() } 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) -> Response { if user.is_none() { return Redirect::to("/login").into_response() } else { - return ResponseCode::Success.file("/profile.html").await.unwrap() + return ResponseCode::Success.file("/profile.html").await } } diff --git a/src/main.rs b/src/main.rs index ab5a9cc..ebce57e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ 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 tracing::metadata::LevelFilter; use tracing_subscriber::{prelude::__tracing_subscriber_SubscriberExt, util::SubscriberInitExt, Layer, filter::filter_fn}; @@ -13,9 +13,10 @@ mod types; mod console; async fn serve(req: Request, next: Next) -> Response { - let Ok(file) = ResponseCode::Success.file(&req.uri().to_string()).await else { - return next.run(req).await - }; + let file = ResponseCode::Success.file(&req.uri().to_string()).await; + if file.status() != StatusCode::OK { + return next.run(req).await; + } file } @@ -33,10 +34,7 @@ async fn log(mut req: Request, next: Next) -> Response where } async fn not_found() -> Response { - match ResponseCode::NotFound.file("/404.html").await { - Ok(file) => file, - Err(err) => err - } + ResponseCode::NotFound.file("/404.html").await } #[tokio::main] diff --git a/src/types/response.rs b/src/types/response.rs index de572b2..d10bce9 100644 --- a/src/types/response.rs +++ b/src/types/response.rs @@ -54,21 +54,21 @@ impl ResponseCode { } #[instrument()] - pub async fn file(self, path: &str) -> Result { + pub async fn file(self, path: &str) -> Response { 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 svc = ServeFile::new(path); let Ok(mut res) = svc.oneshot(Request::new(Body::empty())).await else { 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 { - return Err(ResponseCode::NotFound.text("File not found")); + return ResponseCode::NotFound.text("File not found"); } *res.status_mut() = self.code(); - Ok(res.into_response()) + res.into_response() } }