docker
This commit is contained in:
parent
487d97cb01
commit
f3f5e03651
8 changed files with 103 additions and 17 deletions
5
.dockerignore
Normal file
5
.dockerignore
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
deployments
|
||||||
|
target
|
||||||
|
xssbook.db
|
13
LICENSE
Normal file
13
LICENSE
Normal 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
42
README.md
Normal 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
|
18
deployments/docker/Dockerfile
Normal file
18
deployments/docker/Dockerfile
Normal 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"]
|
10
deployments/docker/docker-compose.yml
Normal file
10
deployments/docker/docker-compose.yml
Normal 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
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
14
src/main.rs
14
src/main.rs
|
@ -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]
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue