Compare commits

..

No commits in common. "master" and "v2.0" have entirely different histories.
master ... v2.0

17 changed files with 78 additions and 174 deletions

1
.gitignore vendored
View file

@ -3,7 +3,6 @@
debug/ debug/
target/ target/
result result
.direnv/
# These are backup files generated by rustfmt # These are backup files generated by rustfmt
**/*.rs.bk **/*.rs.bk

2
Cargo.lock generated
View file

@ -1161,7 +1161,7 @@ dependencies = [
[[package]] [[package]]
name = "karton" name = "karton"
version = "2.0.1" version = "2.0.0"
dependencies = [ dependencies = [
"actix-files", "actix-files",
"actix-multipart", "actix-multipart",

View file

@ -1,6 +1,6 @@
[package] [package]
name = "karton" name = "karton"
version = "2.0.1" version = "2.0.0"
edition = "2021" edition = "2021"
authors = ["Jade <jade@schrottkatze.de>", "Daniel Szabo <daniel.szabo99@outlook.com>"] authors = ["Jade <jade@schrottkatze.de>", "Daniel Szabo <daniel.szabo99@outlook.com>"]
license = "BSD-3-Clause" license = "BSD-3-Clause"

View file

@ -1,4 +1,4 @@
FROM docker.io/rust:latest as build FROM rust:latest as build
WORKDIR /app WORKDIR /app
@ -12,7 +12,7 @@ RUN \
cargo build --release cargo build --release
# https://hub.docker.com/r/bitnami/minideb # https://hub.docker.com/r/bitnami/minideb
FROM docker.io/bitnami/minideb:latest FROM bitnami/minideb:latest
# microbin will be in /app # microbin will be in /app
WORKDIR /app WORKDIR /app
@ -28,8 +28,8 @@ COPY --from=build \
# copy built executable # copy built executable
COPY --from=build \ COPY --from=build \
/app/target/release/karton \ /app/target/release/microbin \
/usr/bin/karton /usr/bin/microbin
# Expose webport used for the webserver to the docker runtime # Expose webport used for the webserver to the docker runtime
EXPOSE 8080 EXPOSE 8080

View file

@ -20,52 +20,52 @@ This is a fork of [MicroBin](https://github.com/szabodanika/microbin).
- Styling via [water.css](https://github.com/kognise/water.css) - Styling via [water.css](https://github.com/kognise/water.css)
- Customizable endpoints - Customizable endpoints
## Installation guide ## TODOs:
Karton is available on [Docker hub](https://hub.docker.com/r/schrottkatze/karton), [crates.io](https://crates.io/crates/karton) and using the nix flake. - [x] removed light mode
The only "officially supported" (I will actively debug and search for the problem) method is the last one using nix flakes. - [x] Rebrand
- [x] New name and logo
- [x] New README
- [ ] installation guides
- [ ] Website
- [ ] Official central instance
- [ ] Donation thing?
### Installation via the nix flake - [ ] Distribution
- [ ] nixpkgs
- [x] crates.io
- [ ] Docker
- [ ] Various other distribution specific repositories?
Add the repository to your inputs. - [ ] Quality
- [ ] Tests
- [x] New theme
- [ ] Proper database (_seriously, json isn't a database_)
- [ ] Proper auth and permissions (_so a single user can also use it and send links_)
- [ ] multi-user
- [x] Click logo/name to get to root
- [ ] Customizability
- [ ] Customizable keys (_so you can make fixed pastas_)
- [x] Customizable wordset
- [ ] Non-env/args configurations
- [ ] further endpoint configuration
- [x] customizable `pasta`, `url` and `raw` endpoints
- [ ] simplified media embed endpoints (/file/$id or /embed/$id by default? maybe with compression?)
- [ ] disable remove
- [ ] make root page a redirect and root based redirect
- [ ] easy to customize logo, icon etc.
- [ ] simplified themeing (only colors etc)
- [ ] Features
- [ ] encrypted pastas
- [ ] image embeds
- [x] in pasta view
- [ ] easy to copy image embed url
- [ ] Markdown pastas
```nix
karton.url = "git+https://gitlab.com/obsidianical/microbin.git";
```
```nix
# microbin.nix
{ inputs, config, pkgs, ... }:
{
environment.systemPackages = [ inputs.karton.defaultPackage."x86_64-linux" ];
systemd.services.karton = {
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
environment = {
# set environment variables to configure karton
KARTON_HASH_IDS = "";
KARTON_EDITABLE = "";
KARTON_PRIVATE = "";
KARTON_HIGHLIGHTSYNTAX = "";
# adjust this to your domain
KARTON_PUBLIC_PATH = "https://example.org";
KARTON_QR = "";
# configure endpoints to be shorter
KARTON_URL_EP = "u";
KARTON_RAW_EP = "r";
KARTON_PASTA_EP = "p";
};
script = "${inputs.karton.defaultPackage."x86_64-linux"}/bin/karton";
# register a simple systemd service
serviceConfig = {
Type = "simple";
RootDirectory="/";
WorkingDirectory = "/karton";
};
};
}
```
## Contact ## Contact

54
TODO.md
View file

@ -1,54 +0,0 @@
# TODO lists
these are just rough guides tho
## v2.1
- [ ] customizable endpoints
- [ ] create
- [ ] edit
- [ ] info
- [ ] get pastas
- [ ] remove
- [ ] improve remove endpoint
- [ ] disable it
- [ ] client library
- [ ] request .well-known data
- [ ] support most endpoints
- [ ] karton cli
## v3.0
- [ ] internal rewrite & docs
- [ ] design new frontend
- [ ] switch to yew
- [ ] using client lib
- [ ] theme and general config files
- [ ] unified theme format
- [ ] no env configs anymore if possible
- [ ] proper dbs
- [ ] sqlite
- [ ] postgres
- [ ] apis/endpoints
- [ ] IDs, name IDs AND user/pastaname
- [ ] root (and admin) user for root level pastas
- [ ] status/instance health admin dashboard and ap
- [ ] storage
- [ ] db status
- [ ] how up to date
- [ ] stats (users etc)
- [ ] errors
- [ ] loading speeds, performance monitor?
- [ ] memory use
- [ ] auth
- [ ] general auth
- [ ] oidc
- [ ] permssion system & api keys
- [ ] only allow some other users to open pasta
- [ ] access control and editing
- [ ] password protected pastas too
- [ ] features for pastas
- [ ] pw protection
- [ ] better editor
- [ ] markdown pastas
- [ ] optional, opt-in commenting

View file

@ -21,11 +21,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1677852945, "lastModified": 1676549890,
"narHash": "sha256-liiVJjkBTuBTAkRW3hrI8MbPD2ImYzwUpa7kvteiKhM=", "narHash": "sha256-sq/WcOEAl7gWrrfGkWdnyYazRyTf+enEim/o6LOQzI8=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "f5ffd5787786dde3a8bf648c7a1b5f78c4e01abb", "rev": "8c66bd1b68f4708c90dcc97c6f7052a5a7b33257",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -35,11 +35,11 @@
}, },
"nixpkgs_2": { "nixpkgs_2": {
"locked": { "locked": {
"lastModified": 1677852945, "lastModified": 1676549890,
"narHash": "sha256-liiVJjkBTuBTAkRW3hrI8MbPD2ImYzwUpa7kvteiKhM=", "narHash": "sha256-sq/WcOEAl7gWrrfGkWdnyYazRyTf+enEim/o6LOQzI8=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "f5ffd5787786dde3a8bf648c7a1b5f78c4e01abb", "rev": "8c66bd1b68f4708c90dcc97c6f7052a5a7b33257",
"type": "github" "type": "github"
}, },
"original": { "original": {

View file

@ -14,7 +14,7 @@
{ {
defaultPackage = naersk-lib.buildPackage ./.; defaultPackage = naersk-lib.buildPackage ./.;
devShell = with pkgs; mkShell { devShell = with pkgs; mkShell {
buildInputs = [ cargo rustc rustfmt pre-commit rustPackages.clippy cargo-watch podman ]; buildInputs = [ cargo rustc rustfmt pre-commit rustPackages.clippy cargo-watch ];
RUST_SRC_PATH = rustPlatform.rustLibSrc; RUST_SRC_PATH = rustPlatform.rustLibSrc;
}; };
}); });

View file

@ -5,8 +5,6 @@ use crate::util::misc::is_valid_url;
use crate::util::pasta_id_converter::CONVERTER; use crate::util::pasta_id_converter::CONVERTER;
use crate::{AppState, Pasta, ARGS}; use crate::{AppState, Pasta, ARGS};
use actix_multipart::Multipart; use actix_multipart::Multipart;
use actix_web::http::StatusCode;
use actix_web::web::{BytesMut, BufMut};
use actix_web::{get, web, Error, HttpResponse, Responder}; use actix_web::{get, web, Error, HttpResponse, Responder};
use askama::Template; use askama::Template;
use bytesize::ByteSize; use bytesize::ByteSize;
@ -16,8 +14,6 @@ use rand::Rng;
use std::io::Write; use std::io::Write;
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{SystemTime, UNIX_EPOCH};
use super::errors::ErrorTemplate;
#[derive(Template)] #[derive(Template)]
#[template(path = "index.html")] #[template(path = "index.html")]
struct IndexTemplate<'a> { struct IndexTemplate<'a> {
@ -119,20 +115,12 @@ pub async fn create(
} }
} }
"content" => { "content" => {
let mut content = BytesMut::new(); let mut content = String::from("");
while let Some(chunk) = field.try_next().await? { while let Some(chunk) = field.try_next().await? {
content.put(chunk); content.push_str(std::str::from_utf8(&chunk).unwrap().to_string().as_str());
} }
if !content.is_empty() { if !content.is_empty() {
new_pasta.content = match String::from_utf8(content.to_vec()) { new_pasta.content = content;
Ok(v) => v,
Err(_) => return Ok(HttpResponse::BadRequest()
.content_type("text/html")
.body(ErrorTemplate {
status_code: StatusCode::BAD_REQUEST,
args: &ARGS
}.render().unwrap())),
};
new_pasta.pasta_type = if is_valid_url(new_pasta.content.as_str()) { new_pasta.pasta_type = if is_valid_url(new_pasta.content.as_str()) {
String::from("url") String::from("url")

View file

@ -6,7 +6,6 @@ use crate::util::misc::remove_expired;
use crate::util::pasta_id_converter::CONVERTER; use crate::util::pasta_id_converter::CONVERTER;
use crate::{AppState, Pasta, ARGS}; use crate::{AppState, Pasta, ARGS};
use actix_multipart::Multipart; use actix_multipart::Multipart;
use actix_web::http::StatusCode;
use actix_web::{get, post, web, Error, HttpResponse}; use actix_web::{get, post, web, Error, HttpResponse};
use askama::Template; use askama::Template;
use futures::TryStreamExt; use futures::TryStreamExt;
@ -43,12 +42,9 @@ pub async fn get_edit(data: web::Data<AppState>, id: web::Path<String>) -> HttpR
} }
} }
HttpResponse::NotFound() HttpResponse::Ok()
.content_type("text/html") .content_type("text/html")
.body(ErrorTemplate { .body(ErrorTemplate { args: &ARGS }.render().unwrap())
status_code: StatusCode::NOT_FOUND,
args: &ARGS
}.render().unwrap())
} }
#[post("/edit/{id}")] #[post("/edit/{id}")]
@ -101,10 +97,7 @@ pub async fn post_edit(
} }
} }
Ok(HttpResponse::NotFound() Ok(HttpResponse::Ok()
.content_type("text/html") .content_type("text/html")
.body(ErrorTemplate { .body(ErrorTemplate { args: &ARGS }.render().unwrap()))
status_code: StatusCode::NOT_FOUND,
args: &ARGS
}.render().unwrap()))
} }

View file

@ -1,4 +1,4 @@
use actix_web::{Error, HttpResponse, http::StatusCode}; use actix_web::{Error, HttpResponse};
use askama::Template; use askama::Template;
use crate::args::{Args, ARGS}; use crate::args::{Args, ARGS};
@ -6,15 +6,11 @@ use crate::args::{Args, ARGS};
#[derive(Template)] #[derive(Template)]
#[template(path = "error.html")] #[template(path = "error.html")]
pub struct ErrorTemplate<'a> { pub struct ErrorTemplate<'a> {
pub status_code: StatusCode,
pub args: &'a Args, pub args: &'a Args,
} }
pub async fn not_found() -> Result<HttpResponse, Error> { pub async fn not_found() -> Result<HttpResponse, Error> {
Ok(HttpResponse::NotFound() Ok(HttpResponse::Ok()
.content_type("text/html") .content_type("text/html")
.body(ErrorTemplate { .body(ErrorTemplate { args: &ARGS }.render().unwrap()))
status_code: StatusCode::NOT_FOUND,
args: &ARGS
}.render().unwrap()))
} }

View file

@ -7,7 +7,6 @@ use crate::util::misc::remove_expired;
use crate::AppState; use crate::AppState;
use crate::util::pasta_id_converter::CONVERTER; use crate::util::pasta_id_converter::CONVERTER;
use actix_web::http::StatusCode;
use actix_web::{web, HttpResponse}; use actix_web::{web, HttpResponse};
use askama::Template; use askama::Template;
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{SystemTime, UNIX_EPOCH};
@ -78,12 +77,9 @@ pub async fn getpasta(data: web::Data<AppState>, id: web::Path<String>) -> HttpR
// otherwise // otherwise
// send pasta not found error // send pasta not found error
HttpResponse::NotFound() HttpResponse::Ok()
.content_type("text/html") .content_type("text/html")
.body(ErrorTemplate { .body(ErrorTemplate { args: &ARGS }.render().unwrap())
status_code: StatusCode::NOT_FOUND,
args: &ARGS
}.render().unwrap())
} }
/// Endpoint for redirection. /// Endpoint for redirection.
@ -140,23 +136,17 @@ pub async fn redirecturl(data: web::Data<AppState>, id: web::Path<String>) -> Ht
return response; return response;
// send error if we're trying to open a non-url pasta as a redirect // send error if we're trying to open a non-url pasta as a redirect
} else { } else {
HttpResponse::NotFound() HttpResponse::Ok()
.content_type("text/html") .content_type("text/html")
.body(ErrorTemplate { .body(ErrorTemplate { args: &ARGS }.render().unwrap());
status_code: StatusCode::NOT_FOUND,
args: &ARGS
}.render().unwrap());
} }
} }
// otherwise // otherwise
// send pasta not found error // send pasta not found error
HttpResponse::NotFound() HttpResponse::Ok()
.content_type("text/html") .content_type("text/html")
.body(ErrorTemplate { .body(ErrorTemplate { args: &ARGS }.render().unwrap())
status_code: StatusCode::NOT_FOUND,
args: &ARGS
}.render().unwrap())
} }
/// Endpoint to request pasta as raw file. /// Endpoint to request pasta as raw file.

View file

@ -5,7 +5,6 @@ use crate::util::hashids::to_u64 as hashid_to_u64;
use crate::util::misc::{self, remove_expired}; use crate::util::misc::{self, remove_expired};
use crate::AppState; use crate::AppState;
use crate::util::pasta_id_converter::CONVERTER; use crate::util::pasta_id_converter::CONVERTER;
use actix_web::http::StatusCode;
use actix_web::{get, web, HttpResponse}; use actix_web::{get, web, HttpResponse};
use askama::Template; use askama::Template;
@ -64,10 +63,7 @@ pub async fn getqr(data: web::Data<AppState>, id: web::Path<String>) -> HttpResp
// otherwise // otherwise
// send pasta not found error // send pasta not found error
HttpResponse::NotFound() HttpResponse::Ok()
.content_type("text/html") .content_type("text/html")
.body(ErrorTemplate { .body(ErrorTemplate { args: &ARGS }.render().unwrap())
status_code: StatusCode::NOT_FOUND,
args: &ARGS
}.render().unwrap())
} }

View file

@ -1,4 +1,3 @@
use actix_web::http::StatusCode;
use actix_web::{get, web, HttpResponse}; use actix_web::{get, web, HttpResponse};
use crate::args::ARGS; use crate::args::ARGS;
@ -59,10 +58,7 @@ pub async fn remove(data: web::Data<AppState>, id: web::Path<String>) -> HttpRes
remove_expired(&mut pastas); remove_expired(&mut pastas);
HttpResponse::NotFound() HttpResponse::Ok()
.content_type("text/html") .content_type("text/html")
.body(ErrorTemplate { .body(ErrorTemplate { args: &ARGS }.render().unwrap())
status_code: StatusCode::NOT_FOUND,
args: &ARGS
}.render().unwrap())
} }

View file

@ -155,7 +155,7 @@ impl Pasta {
self.content self.content
.replace('`', "\\`") .replace('`', "\\`")
.replace('$', "\\$") .replace('$', "\\$")
.replace('/', "\\/") .replace("</script", "<\\/script")
} }
} }

View file

@ -1,7 +1,7 @@
{% include "header.html" %} {% include "header.html" %}
<br> <br>
<h2>{{ status_code.as_u16() }}</h2> <h2>404</h2>
<b>{{ status_code.canonical_reason().unwrap_or("Unknown error") }}</b> <b>Not Found</b>
<br> <br>
<br> <br>
<a href="{{ args.public_path }}/"> Go Home</a> <a href="{{ args.public_path }}/"> Go Home</a>

View file

@ -2,7 +2,7 @@
<html> <html>
<head> <head>
<title>{{ args.title }}</title> <title>MicroBin</title>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">