This commit is contained in:
Raphaël Thériault 2020-01-16 02:14:37 -05:00
parent 3f390faba0
commit a70cc866b3
4 changed files with 142 additions and 103 deletions

2
Cargo.lock generated
View File

@ -714,7 +714,7 @@ dependencies = [
[[package]] [[package]]
name = "filite" name = "filite"
version = "0.2.0" version = "0.3.0"
dependencies = [ dependencies = [
"actix-files 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "actix-files 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"actix-identity 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "actix-identity 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@ -1,6 +1,6 @@
[package] [package]
name = "filite" name = "filite"
version = "0.2.0" version = "0.3.0"
authors = ["Raphaël Thériault <raphael_theriault@outlook.com>"] authors = ["Raphaël Thériault <raphael_theriault@outlook.com>"]
edition = "2018" edition = "2018"
description = "A simple, light and standalone pastebin, URL shortener and file-sharing service" description = "A simple, light and standalone pastebin, URL shortener and file-sharing service"

234
README.md
View File

@ -5,6 +5,39 @@ A simple, light and standalone pastebin, URL shortener and file-sharing service
[![GitHub Actions](https://github.com/raftario/filite/workflows/Build/badge.svg)](https://github.com/raftario/filite/actions?workflowID=Build) [![GitHub Actions](https://github.com/raftario/filite/workflows/Build/badge.svg)](https://github.com/raftario/filite/actions?workflowID=Build)
[![Crates.io](https://img.shields.io/crates/v/filite.svg)](https://crates.io/crates/filite) [![Crates.io](https://img.shields.io/crates/v/filite.svg)](https://crates.io/crates/filite)
[Live Example](https://filite.raphaeltheriault.com)
## Table of Contents
- [filite](#filite)
- [Table of Contents](#table-of-contents)
- [Features](#features)
- [What it is](#what-it-is)
- [What it is not](#what-it-is-not)
- [Installation](#installation)
- [Usage](#usage)
- [Planned features](#planned-features)
- [Config](#config)
- [Client tools](#client-tools)
- [ShareX](#sharex)
- [File](#file)
- [Link](#link)
- [Text](#text)
- [Reverse proxy](#reverse-proxy)
- [NGINX](#nginx)
- [Apache](#apache)
- [Programmatic usage](#programmatic-usage)
- [Listing existing entries](#listing-existing-entries)
- [Creating new entries](#creating-new-entries)
- [Files](#files)
- [Links](#links)
- [Texts](#texts)
- [Deleting entries](#deleting-entries)
- [Contributing](#contributing)
- [Requirements](#requirements)
- [Setup](#setup)
- [License](#license)
## Features ## Features
### What it is ### What it is
@ -15,24 +48,20 @@ A simple, light and standalone pastebin, URL shortener and file-sharing service
### What it is not ### What it is not
* A tracking tool. No stats are stored to increase speed and reduce resource usage, if this is what you are looking for this tool is not for you. * A tracking tool. No stats are stored to increase speed, reduce resource usage and maintain simplicity, if this is what you are looking for filite is not for you.
## Installation ## Installation
1. Get the binary either from the [releases page](https://github.com/raftario/filite/releases) or [using Cargo](https://crates.io/crates/filite) 1. Get the binary either from the [releases page](https://github.com/raftario/filite/releases) or [using Cargo](https://crates.io/crates/filite)
2. Run it a first time and follow the instructions 2. Run `filite init` to perform the initial setup (you can do this at any time to reset the config and password)
3. Edit your config file, check the [dedicated section](#config) for details 3. Edit your config file as you see fit (check the [dedicated section](#config) for details)
4. Run the binary again and you're good to go, just browse to http://localhost:8080 (don't forget to replace `8080` with the port specified in your config) 4. Run `filite`
5. Optionally, set up a [reverse proxy](#reverse-proxy)
That's it!
## Usage ## Usage
When asked for a login, use whatever username you want and the password you provided during setup. Usage is pretty straightforward using the web UI, but here are some tips. When asked for a login, use whatever username you want and the password you provided during setup.
* On successful submission, the URL will be copied to clipboard. If copying to clipboard fails, it will be displayed as an alert.
* Press space in the URL input to generate a random one
* If the entered URL is already in use, the input will have a yellow outline
Details for programmatic usage are provided in [the dedicated section](#programmatic-usage). Details for programmatic usage are provided in [the dedicated section](#programmatic-usage).
## Planned features ## Planned features
@ -40,27 +69,25 @@ Details for programmatic usage are provided in [the dedicated section](#programm
* Decent test suite * Decent test suite
* TLS support * TLS support
* Simple admin page * Simple admin page
* systemd service generation * Multiple logins (?)
## Config ## Config
The config follows the following format. Most of the time, the defaults are reasonable.
```toml ```toml
# Port to listen on # Port to listen on
port = 8080 port = 8080
# SQLite database URL # SQLite database connection url
database_url = "database.db" database_url = "database.db"
# Database connection pool size # SQLite database connection pool size
pool_size = 4 pool_size = 4
# Path to the directory where files will be stored, relative or absolute # Directory where to store static files
files_dir = "files" files_dir = "files"
# Highlight.js configuration # Highlight.js configuration
[highlight] [highlight]
# Theme to use # Theme to use
theme = "github" theme = "github"
# Additional languages to import # Additional languages to include
languages = ["rust"] languages = ["rust"]
``` ```
@ -68,8 +95,10 @@ languages = ["rust"]
### ShareX ### ShareX
> To get the value of `AUTORIZATION` convert `<USERNAME>:<PASSWORD>` to base64. - `<AUTHORIZATION>` is the result of encoding `<USERNAME>:<PASSWORD>` to base64
> Don't forget to replace `http://example.com` with your own address. - `<USERNAME>` is an arbitrary username, it doesn't matter
- `<PASSWORD>` is the password entered during setup
- `<ADDRESS>` is the root address where the filite is running, for instance `http://localhost:8080` or `https://filite.raphaeltheriault.com`
#### File #### File
@ -79,13 +108,13 @@ languages = ["rust"]
"Name": "filite (file)", "Name": "filite (file)",
"DestinationType": "ImageUploader, FileUploader", "DestinationType": "ImageUploader, FileUploader",
"RequestMethod": "POST", "RequestMethod": "POST",
"RequestURL": "http://example.com/f", "RequestURL": "<ADDRESS>/f",
"Headers": { "Headers": {
"Authorization": "Basic <AUTORIZATION>" "Authorization": "Basic <AUTORIZATION>"
}, },
"Body": "MultipartFormData", "Body": "MultipartFormData",
"FileFormName": "file", "FileFormName": "file",
"URL": "http://example.com/f/$response$" "URL": "<ADDRESS>/$response$"
} }
``` ```
@ -97,19 +126,19 @@ languages = ["rust"]
"Name": "filite (link)", "Name": "filite (link)",
"DestinationType": "URLShortener", "DestinationType": "URLShortener",
"RequestMethod": "POST", "RequestMethod": "POST",
"RequestURL": "http://example.com/l", "RequestURL": "<ADDRESS>/l",
"Headers": { "Headers": {
"Authorization": "Basic <AUTORIZATION>" "Authorization": "Basic <AUTORIZATION>"
}, },
"Body": "JSON", "Body": "JSON",
"Data": "{\"forward\":\"$input$\"}", "Data": "{\"forward\":\"$input$\"}",
"URL": "http://example.com/l/$response$" "URL": "<ADDRESS>/l/$response$"
} }
``` ```
#### Text #### Text
> You can remove the prompt and always enable syntax highlighting by replacing `$prompt:Highlight|false$` with `true` or `false`. > You can remove the prompt and always enable or disable syntax highlighting by replacing `$prompt:Highlight|false$` with `true` or `false`.
```json ```json
{ {
@ -117,122 +146,139 @@ languages = ["rust"]
"Name": "filite (text)", "Name": "filite (text)",
"DestinationType": "TextUploader", "DestinationType": "TextUploader",
"RequestMethod": "POST", "RequestMethod": "POST",
"RequestURL": "http://example.com/t", "RequestURL": "<ADDRESS>/t",
"Headers": { "Headers": {
"Authorization": "Basic <AUTORIZATION>" "Authorization": "Basic <AUTORIZATION>"
}, },
"Body": "JSON", "Body": "JSON",
"Data": "{\"contents\":\"$input$\",\"highlight\":$prompt:Highlight|false$}", "Data": "{\"contents\":\"$input$\",\"highlight\":$prompt:Highlight|false$}",
"URL": "http://example.com/t/$response$" "URL": "<ADDRESS>/t/$response$"
} }
``` ```
## Reverse proxy ## Reverse proxy
### NGINX - `<DOMAIN>` is the domain the requests will be coming from, for instance `filite.raphaeltheriault.com`
- `<PORT>` is the port on which filite is listening
> Don't forget to replace `8080` with the port specified in your config and `example.com` with your own domain. > Upload limits are set to 10M as an example
### NGINX
```nginx ```nginx
server { server {
listen 80; listen 80;
listen [::]:80; listen [::]:80;
server_name example.com; server_name <DOMAIN>;
location / { location / {
proxy_pass http://localhost:8080; proxy_pass http://localhost:<PORT>;
location /f { location /f {
client_max_body_size 10M; client_max_body_size 10M;
}
} }
}
} }
``` ```
### Apache
```apache
<VirtualHost *:80>
ServerName <DOMAIN>
ProxyPreserveHost On
ProxyPass / http://localhost:<PORT>/
ProxyPassReverse / http://localhost:<PORT>/
<Location "/f">
LimitRequestBody 10000000
</Location>
</VirtualHost>
```
## Programmatic usage ## Programmatic usage
### Posting new elements > All requests that require authentication use HTTP Basic Auth (without taking the username into account).
Send a PUT request with a JSON body following the following schemes. Don't forget to set the `Content-Type` header to `application/json` and the `Authorization` header to a valid value (username isn't important). ### Listing existing entries
#### File It's possible to get an array of all existing entries for each type with an authenticated request.
`PUT /f/id` - `GET /f`
- `GET /l`
- `GET /t`
```json ### Creating new entries
{
"base64": "Base64-encoded file",
"filename": "Filename"
}
```
#### Link There are two ways to create new entries, `PUT` or `POST` requests.
`PUT` lets you choose the ID manually and `POST` assigns a free one automatically, but that's the only difference.
Both methods require authentication.
`PUT /l/id` > `PUT` requests will overwrite any existing entry.
```json
{
"forward": "URL to forward to"
}
```
#### Text
`PUT /t/id`
```json
{
"contents": "Text contents"
}
```
### Getting existing elements
The response will be a JSON array following the following schemes
#### Files #### Files
`GET /f` - `PUT /f/{id}`
- `POST /f`
```json Files are sent as `multipart/form-data`. The field name isn't important but the file name needs to be included. Only one file is treated.
[
{
"id": "ID (URL) as an integer",
"filepath": "Absolute path to the stored file",
"created": "Creation timestamp"
}
]
```
#### Links #### Links
`GET /l` - `PUT /l/{id}`
- `POST /l`
Links are sent as `application/json` according to the following schema.
```json ```json
[ {
{ "$schema": "http://json-schema.org/draft-07/schema#",
"id": "ID (URL) as an integer", "title": "Link",
"forward": "URL to forward to", "type": "object",
"created": "Creation timestamp" "properties": {
"forward": {
"description": "URL this link forwards to",
"type": "string"
} }
] }
}
``` ```
#### Texts #### Texts
`GET /t` - `PUT /t/{id}`
- `POST /t`
Texts are sent as `application/json` according to the following schema.
```json ```json
[ {
{ "$schema": "http://json-schema.org/draft-07/schema#",
"id": "ID (URL) as an integer", "title": "Text",
"contents": "Text contents", "type": "object",
"created": "Creation timestamp" "properties": {
"contents": {
"description": "Text contents",
"type": "string"
},
"highlight": {
"description": "Whether to enable code highlighting or not for that text",
"type": "boolean"
} }
] }
}
``` ```
### Deleting entries
It's possible to delete any entry with an authenticated request.
- `DELETE /f`
- `DELETE /l`
- `DELETE /t`
## Contributing ## Contributing
The project is open to contributions! Before submitting a PR, make sure your changes work both with and without the `dev` feature enabled. The project is open to contributions! Before submitting a PR, make sure your changes work both with and without the `dev` feature enabled.

View File

@ -19,9 +19,7 @@ pub mod files {
#[derive(Insertable)] #[derive(Insertable)]
#[table_name = "files"] #[table_name = "files"]
pub struct NewFile<'a> { pub struct NewFile<'a> {
/// Primary key, its radix 36 value is used as an url
pub id: i32, pub id: i32,
/// Path to the file to serve relative to the static files root
pub filepath: &'a str, pub filepath: &'a str,
} }
} }
@ -45,9 +43,7 @@ pub mod links {
#[derive(Insertable)] #[derive(Insertable)]
#[table_name = "links"] #[table_name = "links"]
pub struct NewLink<'a> { pub struct NewLink<'a> {
/// Primary key, its radix 36 value is used as an url
pub id: i32, pub id: i32,
/// URL this link forwards to
pub forward: &'a str, pub forward: &'a str,
} }
} }
@ -73,11 +69,8 @@ pub mod texts {
#[derive(Insertable)] #[derive(Insertable)]
#[table_name = "texts"] #[table_name = "texts"]
pub struct NewText<'a> { pub struct NewText<'a> {
/// Primary key, its radix 36 value is used as an url
pub id: i32, pub id: i32,
/// Text contents
pub contents: &'a str, pub contents: &'a str,
/// Whether to enable code highlighting or not for that text
pub highlight: bool, pub highlight: bool,
} }
} }