This commit is contained in:
Julian 2023-04-28 18:31:51 +00:00
parent 164811388f
commit 1db02076f3
Signed by: NotNite
GPG Key ID: BD91A5402CCEB08A
7 changed files with 383 additions and 8 deletions

7
Cargo.lock generated
View File

@ -228,6 +228,9 @@ name = "either"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
dependencies = [
"serde",
]
[[package]]
name = "encoding_rs"
@ -1087,6 +1090,7 @@ dependencies = [
"percent-encoding",
"rustls",
"rustls-pemfile",
"serde",
"sha2",
"smallvec",
"sqlformat",
@ -1107,9 +1111,12 @@ dependencies = [
"dotenvy",
"either",
"heck",
"hex",
"once_cell",
"proc-macro2",
"quote",
"serde",
"serde_json",
"sha2",
"sqlx-core",
"sqlx-rt",

View File

@ -1,10 +1,11 @@
[package]
name = "u"
description = "blazingly-fast super-concurrent webscale file server"
authors = ["NotNite <hi@notnite.com>"]
license = "MIT"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "1.0.69"
async-trait = "0.1.65"
@ -14,7 +15,7 @@ hyper = "0.14.24"
mime_guess = "2.0.4"
nanoid = "0.4.0"
serde = { version = "1.0.152", features = ["derive"] }
sqlx = { version = "0.6.2", features = ["sqlite", "runtime-tokio-rustls"] }
sqlx = { version = "0.6.2", features = ["sqlite", "runtime-tokio-rustls", "offline"] }
tokio = { version = "1.26.0", features = ["full"] }
tokio-stream = { version = "0.1.12", features = ["net"] }
tower = "0.4.13"

View File

@ -35,7 +35,7 @@ requirements:
```sh
export U_API_KEY="..."
export U_HOST="https://.../"
export U_HOST="https://..."
export U_REVOCATION_KEY_PATH="$HOME/.u_revocation_keys"
./upload.sh /path/to/file

141
flake.lock Normal file
View File

@ -0,0 +1,141 @@
{
"nodes": {
"crane": {
"inputs": {
"flake-compat": "flake-compat",
"flake-utils": "flake-utils",
"nixpkgs": [
"nixpkgs"
],
"rust-overlay": "rust-overlay"
},
"locked": {
"lastModified": 1681680516,
"narHash": "sha256-EB8Adaeg4zgcYDJn9sR6UMjN/OHdIiMMK19+3LmmXQY=",
"owner": "ipetkov",
"repo": "crane",
"rev": "54b63c8eae4c50172cb50b612946ff1d2bc1c75c",
"type": "github"
},
"original": {
"owner": "ipetkov",
"repo": "crane",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1673956053,
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-utils": {
"locked": {
"lastModified": 1678901627,
"narHash": "sha256-U02riOqrKKzwjsxc/400XnElV+UtPUQWpANPlyazjH0=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "93a2b84fc4b70d9e089d029deacc3583435c2ed6",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_2": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1681202837,
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "cfacdce06f30d2b68473a46042957675eebb3401",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1682566018,
"narHash": "sha256-HPzPRFiy2o/7k7mtnwfM1E6NVZHiFbPdmYCMoIpkHO4=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "8e3b64db39f2aaa14b35ee5376bd6a2e707cadc2",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"crane": "crane",
"flake-utils": "flake-utils_2",
"nixpkgs": "nixpkgs"
}
},
"rust-overlay": {
"inputs": {
"flake-utils": [
"crane",
"flake-utils"
],
"nixpkgs": [
"crane",
"nixpkgs"
]
},
"locked": {
"lastModified": 1680488274,
"narHash": "sha256-0vYMrZDdokVmPQQXtFpnqA2wEgCCUXf5a3dDuDVshn0=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "7ec2ff598a172c6e8584457167575b3a1a5d80d8",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

129
flake.nix Normal file
View File

@ -0,0 +1,129 @@
{
description = "blazingly-fast super-concurrent webscale file server";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
crane.url = "github:ipetkov/crane";
crane.inputs.nixpkgs.follows = "nixpkgs";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, crane, flake-utils }:
let
description = "blazingly-fast super-concurrent webscale file server";
src = ./.;
packages = flake-utils.lib.eachDefaultSystem (system:
let
pkgs = nixpkgs.legacyPackages."${system}";
craneLib = crane.lib.${system};
in rec {
packages.u = craneLib.buildPackage {
pname = "u";
version = "0.1.0";
# Don't use cleanCargoSource here, as it removes sqlx-data.json
src = src;
doCheck = false;
};
apps.u = flake-utils.lib.mkApp {
name = "u";
drv = packages.u;
};
packages.u-upload = pkgs.stdenv.mkDerivation rec {
name = "u-upload";
src =
(pkgs.writeScriptBin "u-upload" (builtins.readFile ./upload.sh));
buildInputs = with pkgs; [ curl jq xclip ];
nativeBuildInputs = with pkgs; [ makeWrapper ];
installPhase = ''
mkdir -p $out/bin
cp bin/u-upload $out/bin
wrapProgram $out/bin/u-upload \
--prefix PATH : ${pkgs.lib.makeBinPath buildInputs}
'';
};
devShell = pkgs.mkShell {
inputsFrom = [ packages.u ];
nativeBuildInputs = with pkgs; [
rustc
cargo
rust-analyzer
sqlx-cli
packages.u-upload
];
};
});
in packages // {
nixosModule = { config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.u;
pkg = self.packages.${pkgs.system}.u;
in {
options.services.u = {
enable = mkEnableOption description;
user = mkOption {
type = types.str;
default = "u";
};
group = mkOption {
type = types.str;
default = "u";
};
port = mkOption {
type = types.int;
default = 8075;
};
};
config = mkIf cfg.enable {
systemd.services.u = {
description = description;
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
preStart = ''
cat > /var/lib/u/.env <<EOF
DATABASE_URL="sqlite:/var/lib/u/u.db"
U_PORT="${toString cfg.port}"
U_FILES_DIR="/var/lib/u/files"
EOF
# Create and migrate the database
${pkgs.sqlx-cli}/bin/sqlx database create
${pkgs.sqlx-cli}/bin/sqlx migrate run --source "${src}/migrations"
'';
script = "${pkg}/bin/u";
serviceConfig = {
User = cfg.user;
Group = cfg.group;
Restart = "always";
WorkingDirectory = "/var/lib/u";
};
};
users = {
users = mkIf (cfg.user == "u") {
u = {
home = "/var/lib/u";
createHome = true;
group = cfg.group;
isSystemUser = true;
};
};
groups = mkIf (cfg.group == "u") { u = { }; };
};
};
};
};
}

97
sqlx-data.json Normal file
View File

@ -0,0 +1,97 @@
{
"db": "SQLite",
"311dd7c05c12408abfbe7dab000687defe924e52d2ca2ed3c7d95bc4a2db039c": {
"describe": {
"columns": [],
"nullable": [],
"parameters": {
"Right": 1
}
},
"query": "insert into api_keys (key, admin) values ($1, false)"
},
"695d9690323bef0cba686448a5053968ebbb5720a7ca5b62a7f4538c972424d2": {
"describe": {
"columns": [],
"nullable": [],
"parameters": {
"Right": 1
}
},
"query": "insert into api_keys (key, admin) values ($1, true)"
},
"8d43fd96f18e00d562d44d710cc0f5bb2ab40f724d5cbcfcbd960ba9450f0a2d": {
"describe": {
"columns": [
{
"name": "admin",
"ordinal": 0,
"type_info": "Bool"
}
],
"nullable": [
false
],
"parameters": {
"Right": 0
}
},
"query": "select admin from api_keys where admin = true"
},
"906d2325e07efbaac3e84fd07994afc0b8720fb34baecb314f7e2123a83961dc": {
"describe": {
"columns": [
{
"name": "admin",
"ordinal": 0,
"type_info": "Bool"
}
],
"nullable": [
false
],
"parameters": {
"Right": 1
}
},
"query": "select admin from api_keys where key = $1"
},
"c0a48d1ace5682569cfd52d74396193c6b34e463d1a1dfe1e6027f6f94f7befa": {
"describe": {
"columns": [],
"nullable": [],
"parameters": {
"Right": 2
}
},
"query": "insert into files (id, revocation_key) values ($1, $2)"
},
"c450bea1caa31e3fc498d3eeadc25fa27d90ad83be87e89e336f56cdb7adb628": {
"describe": {
"columns": [
{
"name": "revocation_key",
"ordinal": 0,
"type_info": "Text"
}
],
"nullable": [
false
],
"parameters": {
"Right": 1
}
},
"query": "select revocation_key from files where id = $1"
},
"d0982a4445b0d5dceb424bfabdc21a88ff2c85042590e1cccd789a4cd7bc735c": {
"describe": {
"columns": [],
"nullable": [],
"parameters": {
"Right": 1
}
},
"query": "delete from files where id = $1"
}
}

View File

@ -1,15 +1,15 @@
#!/usr/bin/env sh
set -eux
set -eu
path=$1
extension=$(echo "$path" | cut -d'.' -f2)
data=$(curl -F file=@$path -H "Authorization: $U_API_KEY" "$U_HOST/api/upload")
data=$(curl -F file=@"$path" -H "Authorization: $U_API_KEY" "$U_HOST/api/upload")
image_id=$(echo "$data" | jq -r .id)
image_revocation_key=$(echo "$data" | jq -r .revocation_key)
echo "$image_id $image_revocation_key" >> $U_REVOCATION_KEY_PATH
echo "$image_id $image_revocation_key" >> "$U_REVOCATION_KEY_PATH"
image_url="https://u.n2.pm/i/$image_id.$extension"
image_url="$U_HOST/i/$image_id.$extension"
echo "$image_url"
echo "$image_url" | xclip -selection clipboard