summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Cargo.lock801
-rw-r--r--Cargo.toml6
-rw-r--r--sellershut.toml16
-rw-r--r--src/entity/user.rs64
-rw-r--r--src/main.rs48
-rw-r--r--src/server.rs14
-rw-r--r--src/server/routes.rs14
-rw-r--r--src/server/routes/users.rs4
-rw-r--r--src/server/routes/users/get_outbox.rs77
-rw-r--r--src/server/routes/users/get_user.rs49
-rw-r--r--src/server/routes/users/webfinger.rs23
-rw-r--r--src/state.rs17
13 files changed, 1069 insertions, 65 deletions
diff --git a/.gitignore b/.gitignore
index e3dc09e..3b539fa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
/target
/docs/book/book
+.env
diff --git a/Cargo.lock b/Cargo.lock
index bf320d7..eaa2246 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -77,6 +77,12 @@ dependencies = [
]
[[package]]
+name = "allocator-api2"
+version = "0.2.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
+
+[[package]]
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -92,6 +98,56 @@ dependencies = [
]
[[package]]
+name = "anstream"
+version = "0.6.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "is_terminal_polyfill",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9"
+dependencies = [
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882"
+dependencies = [
+ "anstyle",
+ "once_cell_polyfill",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
name = "anyhow"
version = "1.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -120,6 +176,15 @@ dependencies = [
]
[[package]]
+name = "atoi"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
name = "autocfg"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -203,7 +268,7 @@ dependencies = [
"miniz_oxide",
"object",
"rustc-demangle",
- "windows-targets",
+ "windows-targets 0.52.6",
]
[[package]]
@@ -223,6 +288,9 @@ name = "bitflags"
version = "2.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
+dependencies = [
+ "serde",
+]
[[package]]
name = "block-buffer"
@@ -310,6 +378,52 @@ dependencies = [
]
[[package]]
+name = "clap"
+version = "4.5.41"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9"
+dependencies = [
+ "clap_builder",
+ "clap_derive",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.5.41"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "clap_lex",
+ "strsim",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.5.41"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.104",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
+
+[[package]]
+name = "colorchoice"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
+
+[[package]]
name = "concurrent-queue"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -319,6 +433,18 @@ dependencies = [
]
[[package]]
+name = "config"
+version = "0.15.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b1eb4fb07bc7f012422df02766c7bd5971effb894f573865642f06fa3265440"
+dependencies = [
+ "pathdiff",
+ "serde",
+ "toml",
+ "winnow",
+]
+
+[[package]]
name = "const-oid"
version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -340,6 +466,21 @@ dependencies = [
]
[[package]]
+name = "crc"
+version = "3.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675"
+dependencies = [
+ "crc-catalog",
+]
+
+[[package]]
+name = "crc-catalog"
+version = "2.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
+
+[[package]]
name = "crossbeam-channel"
version = "0.5.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -358,6 +499,15 @@ dependencies = [
]
[[package]]
+name = "crossbeam-queue"
+version = "0.3.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115"
+dependencies = [
+ "crossbeam-utils",
+]
+
+[[package]]
name = "crossbeam-utils"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -420,6 +570,15 @@ dependencies = [
]
[[package]]
+name = "deranged"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e"
+dependencies = [
+ "powerfmt",
+]
+
+[[package]]
name = "derive_builder"
version = "0.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -459,6 +618,7 @@ dependencies = [
"block-buffer",
"const-oid",
"crypto-common",
+ "subtle",
]
[[package]]
@@ -473,6 +633,12 @@ dependencies = [
]
[[package]]
+name = "dotenvy"
+version = "0.15.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
+
+[[package]]
name = "dyn-clone"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -483,6 +649,9 @@ name = "either"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
+dependencies = [
+ "serde",
+]
[[package]]
name = "enum_delegate"
@@ -515,6 +684,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
+name = "etcetera"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943"
+dependencies = [
+ "cfg-if",
+ "home",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
name = "event-listener"
version = "5.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -536,12 +716,29 @@ dependencies = [
]
[[package]]
+name = "flume"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095"
+dependencies = [
+ "futures-core",
+ "futures-sink",
+ "spin",
+]
+
+[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
+name = "foldhash"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
+
+[[package]]
name = "form_urlencoded"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -593,6 +790,17 @@ dependencies = [
]
[[package]]
+name = "futures-intrusive"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f"
+dependencies = [
+ "futures-core",
+ "lock_api",
+ "parking_lot",
+]
+
+[[package]]
name = "futures-io"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -701,6 +909,59 @@ name = "hashbrown"
version = "0.15.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5"
+dependencies = [
+ "allocator-api2",
+ "equivalent",
+ "foldhash",
+]
+
+[[package]]
+name = "hashlink"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1"
+dependencies = [
+ "hashbrown",
+]
+
+[[package]]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
+[[package]]
+name = "hex"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+
+[[package]]
+name = "hkdf"
+version = "0.12.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
+dependencies = [
+ "hmac",
+]
+
+[[package]]
+name = "hmac"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
+dependencies = [
+ "digest",
+]
+
+[[package]]
+name = "home"
+version = "0.5.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf"
+dependencies = [
+ "windows-sys 0.59.0",
+]
[[package]]
name = "http"
@@ -808,7 +1069,7 @@ dependencies = [
"tokio",
"tokio-rustls",
"tower-service",
- "webpki-roots",
+ "webpki-roots 1.0.1",
]
[[package]]
@@ -1010,6 +1271,12 @@ dependencies = [
]
[[package]]
+name = "is_terminal_polyfill"
+version = "1.70.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
+
+[[package]]
name = "itertools"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1056,6 +1323,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
[[package]]
+name = "libsqlite3-sys"
+version = "0.30.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149"
+dependencies = [
+ "pkg-config",
+ "vcpkg",
+]
+
+[[package]]
name = "litemap"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1112,6 +1389,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
[[package]]
+name = "md-5"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
+dependencies = [
+ "cfg-if",
+ "digest",
+]
+
+[[package]]
name = "memchr"
version = "2.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1193,6 +1480,12 @@ dependencies = [
]
[[package]]
+name = "num-conv"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
+
+[[package]]
name = "num-integer"
version = "0.1.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1238,6 +1531,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
+name = "once_cell_polyfill"
+version = "1.70.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
+
+[[package]]
name = "overload"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1269,10 +1568,16 @@ dependencies = [
"libc",
"redox_syscall",
"smallvec",
- "windows-targets",
+ "windows-targets 0.52.6",
]
[[package]]
+name = "pathdiff"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3"
+
+[[package]]
name = "pem-rfc7468"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1321,6 +1626,12 @@ dependencies = [
]
[[package]]
+name = "pkg-config"
+version = "0.3.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
+
+[[package]]
name = "portable-atomic"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1336,6 +1647,12 @@ dependencies = [
]
[[package]]
+name = "powerfmt"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
+
+[[package]]
name = "ppv-lite86"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1583,7 +1900,7 @@ dependencies = [
"wasm-bindgen-futures",
"wasm-streams",
"web-sys",
- "webpki-roots",
+ "webpki-roots 1.0.1",
]
[[package]]
@@ -1716,6 +2033,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
+name = "secrecy"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e891af845473308773346dc847b2c23ee78fe442e0472ac50e22a18a93d3ae5a"
+dependencies = [
+ "serde",
+ "zeroize",
+]
+
+[[package]]
name = "sellershut"
version = "0.1.0"
dependencies = [
@@ -1723,13 +2050,17 @@ dependencies = [
"anyhow",
"async-trait",
"axum",
+ "clap",
+ "config",
"serde",
+ "sqlx",
"stack-up",
"tokio",
"tower",
"tower-http",
"tracing",
"url",
+ "uuid",
]
[[package]]
@@ -1782,6 +2113,15 @@ dependencies = [
]
[[package]]
+name = "serde_spanned"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "40734c41988f7306bb04f0ecf60ec0f3f1caa34290e4e8ea471dcd3346483b83"
+dependencies = [
+ "serde",
+]
+
+[[package]]
name = "serde_urlencoded"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1794,6 +2134,17 @@ dependencies = [
]
[[package]]
+name = "sha1"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
+[[package]]
name = "sha2"
version = "0.10.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1849,6 +2200,9 @@ name = "smallvec"
version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
+dependencies = [
+ "serde",
+]
[[package]]
name = "socket2"
@@ -1865,6 +2219,9 @@ name = "spin"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
+dependencies = [
+ "lock_api",
+]
[[package]]
name = "spki"
@@ -1877,6 +2234,204 @@ dependencies = [
]
[[package]]
+name = "sqlx"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fefb893899429669dcdd979aff487bd78f4064e5e7907e4269081e0ef7d97dc"
+dependencies = [
+ "sqlx-core",
+ "sqlx-macros",
+ "sqlx-mysql",
+ "sqlx-postgres",
+ "sqlx-sqlite",
+]
+
+[[package]]
+name = "sqlx-core"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee6798b1838b6a0f69c007c133b8df5866302197e404e8b6ee8ed3e3a5e68dc6"
+dependencies = [
+ "base64",
+ "bytes",
+ "crc",
+ "crossbeam-queue",
+ "either",
+ "event-listener",
+ "futures-core",
+ "futures-intrusive",
+ "futures-io",
+ "futures-util",
+ "hashbrown",
+ "hashlink",
+ "indexmap",
+ "log",
+ "memchr",
+ "once_cell",
+ "percent-encoding",
+ "rustls",
+ "serde",
+ "serde_json",
+ "sha2",
+ "smallvec",
+ "thiserror 2.0.12",
+ "time",
+ "tokio",
+ "tokio-stream",
+ "tracing",
+ "url",
+ "uuid",
+ "webpki-roots 0.26.11",
+]
+
+[[package]]
+name = "sqlx-macros"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2d452988ccaacfbf5e0bdbc348fb91d7c8af5bee192173ac3636b5fb6e6715d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "sqlx-core",
+ "sqlx-macros-core",
+ "syn 2.0.104",
+]
+
+[[package]]
+name = "sqlx-macros-core"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19a9c1841124ac5a61741f96e1d9e2ec77424bf323962dd894bdb93f37d5219b"
+dependencies = [
+ "dotenvy",
+ "either",
+ "heck",
+ "hex",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "serde",
+ "serde_json",
+ "sha2",
+ "sqlx-core",
+ "sqlx-mysql",
+ "sqlx-postgres",
+ "sqlx-sqlite",
+ "syn 2.0.104",
+ "tokio",
+ "url",
+]
+
+[[package]]
+name = "sqlx-mysql"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526"
+dependencies = [
+ "atoi",
+ "base64",
+ "bitflags",
+ "byteorder",
+ "bytes",
+ "crc",
+ "digest",
+ "dotenvy",
+ "either",
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-util",
+ "generic-array",
+ "hex",
+ "hkdf",
+ "hmac",
+ "itoa",
+ "log",
+ "md-5",
+ "memchr",
+ "once_cell",
+ "percent-encoding",
+ "rand 0.8.5",
+ "rsa",
+ "serde",
+ "sha1",
+ "sha2",
+ "smallvec",
+ "sqlx-core",
+ "stringprep",
+ "thiserror 2.0.12",
+ "time",
+ "tracing",
+ "uuid",
+ "whoami",
+]
+
+[[package]]
+name = "sqlx-postgres"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46"
+dependencies = [
+ "atoi",
+ "base64",
+ "bitflags",
+ "byteorder",
+ "crc",
+ "dotenvy",
+ "etcetera",
+ "futures-channel",
+ "futures-core",
+ "futures-util",
+ "hex",
+ "hkdf",
+ "hmac",
+ "home",
+ "itoa",
+ "log",
+ "md-5",
+ "memchr",
+ "once_cell",
+ "rand 0.8.5",
+ "serde",
+ "serde_json",
+ "sha2",
+ "smallvec",
+ "sqlx-core",
+ "stringprep",
+ "thiserror 2.0.12",
+ "time",
+ "tracing",
+ "uuid",
+ "whoami",
+]
+
+[[package]]
+name = "sqlx-sqlite"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c2d12fe70b2c1b4401038055f90f151b78208de1f9f89a7dbfd41587a10c3eea"
+dependencies = [
+ "atoi",
+ "flume",
+ "futures-channel",
+ "futures-core",
+ "futures-executor",
+ "futures-intrusive",
+ "futures-util",
+ "libsqlite3-sys",
+ "log",
+ "percent-encoding",
+ "serde",
+ "serde_urlencoded",
+ "sqlx-core",
+ "thiserror 2.0.12",
+ "time",
+ "tracing",
+ "url",
+ "uuid",
+]
+
+[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1888,11 +2443,25 @@ version = "0.1.0"
source = "git+https://github.com/rtkay123/stack-up.git#939ce92c1da43bdfea0387de6716ef1f0713b619"
dependencies = [
"bon",
+ "secrecy",
"serde",
"serde_json",
+ "sqlx",
"thiserror 2.0.12",
"tracing",
"tracing-subscriber",
+ "url",
+]
+
+[[package]]
+name = "stringprep"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1"
+dependencies = [
+ "unicode-bidi",
+ "unicode-normalization",
+ "unicode-properties",
]
[[package]]
@@ -2005,6 +2574,37 @@ dependencies = [
]
[[package]]
+name = "time"
+version = "0.3.41"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40"
+dependencies = [
+ "deranged",
+ "itoa",
+ "num-conv",
+ "powerfmt",
+ "serde",
+ "time-core",
+ "time-macros",
+]
+
+[[package]]
+name = "time-core"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c"
+
+[[package]]
+name = "time-macros"
+version = "0.2.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49"
+dependencies = [
+ "num-conv",
+ "time-core",
+]
+
+[[package]]
name = "tinystr"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2070,6 +2670,17 @@ dependencies = [
]
[[package]]
+name = "tokio-stream"
+version = "0.1.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047"
+dependencies = [
+ "futures-core",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
name = "tokio-util"
version = "0.7.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2083,6 +2694,37 @@ dependencies = [
]
[[package]]
+name = "toml"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed0aee96c12fa71097902e0bb061a5e1ebd766a6636bb605ba401c45c1650eac"
+dependencies = [
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_parser",
+ "winnow",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bade1c3e902f58d73d3f294cd7f20391c1cb2fbcb643b73566bc773971df91e3"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "toml_parser"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97200572db069e74c512a14117b296ba0a80a30123fbbb5aa1f4a348f639ca30"
+dependencies = [
+ "winnow",
+]
+
+[[package]]
name = "tower"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2204,12 +2846,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
[[package]]
+name = "unicode-bidi"
+version = "0.3.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5"
+
+[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
+name = "unicode-normalization"
+version = "0.1.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956"
+dependencies = [
+ "tinyvec",
+]
+
+[[package]]
+name = "unicode-properties"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0"
+
+[[package]]
name = "untrusted"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2234,6 +2897,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]]
+name = "utf8parse"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
+
+[[package]]
name = "uuid"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2251,6 +2920,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
[[package]]
+name = "vcpkg"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
+
+[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2281,6 +2956,12 @@ dependencies = [
]
[[package]]
+name = "wasite"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b"
+
+[[package]]
name = "wasm-bindgen"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2386,6 +3067,15 @@ dependencies = [
[[package]]
name = "webpki-roots"
+version = "0.26.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9"
+dependencies = [
+ "webpki-roots 1.0.1",
+]
+
+[[package]]
+name = "webpki-roots"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8782dd5a41a24eed3a4f40b606249b3e236ca61adf1f25ea4d45c73de122b502"
@@ -2394,6 +3084,16 @@ dependencies = [
]
[[package]]
+name = "whoami"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6994d13118ab492c3c80c1f81928718159254c53c472bf9ce36f8dae4add02a7"
+dependencies = [
+ "redox_syscall",
+ "wasite",
+]
+
+[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2519,11 +3219,20 @@ dependencies = [
[[package]]
name = "windows-sys"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+dependencies = [
+ "windows-targets 0.48.5",
+]
+
+[[package]]
+name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
- "windows-targets",
+ "windows-targets 0.52.6",
]
[[package]]
@@ -2532,7 +3241,22 @@ version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
- "windows-targets",
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
+dependencies = [
+ "windows_aarch64_gnullvm 0.48.5",
+ "windows_aarch64_msvc 0.48.5",
+ "windows_i686_gnu 0.48.5",
+ "windows_i686_msvc 0.48.5",
+ "windows_x86_64_gnu 0.48.5",
+ "windows_x86_64_gnullvm 0.48.5",
+ "windows_x86_64_msvc 0.48.5",
]
[[package]]
@@ -2541,14 +3265,14 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
+ "windows_aarch64_gnullvm 0.52.6",
+ "windows_aarch64_msvc 0.52.6",
+ "windows_i686_gnu 0.52.6",
"windows_i686_gnullvm",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
+ "windows_i686_msvc 0.52.6",
+ "windows_x86_64_gnu 0.52.6",
+ "windows_x86_64_gnullvm 0.52.6",
+ "windows_x86_64_msvc 0.52.6",
]
[[package]]
@@ -2562,18 +3286,36 @@ dependencies = [
[[package]]
name = "windows_aarch64_gnullvm"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
+
+[[package]]
+name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
+
+[[package]]
+name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
+
+[[package]]
+name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
@@ -2586,29 +3328,62 @@ checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
+
+[[package]]
+name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
+
+[[package]]
+name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
+
+[[package]]
+name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
+name = "winnow"
+version = "0.7.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
name = "wit-bindgen-rt"
version = "0.39.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 1bd7537..4dd7120 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,15 +12,19 @@ activitypub_federation = { version = "0.7.0-beta.5", default-features = false, f
anyhow = "1.0.98"
async-trait = "0.1.88"
axum = { version = "0.8.4", features = ["macros"] }
+clap = { version = "4.5.41", features = ["derive"] }
+config = { version = "0.15.13", default-features = false, features = ["toml"] }
serde = { version = "1.0.219", features = ["derive"] }
+sqlx = { version = "0.8.6", features = ["macros", "migrate", "runtime-tokio", "time", "tls-rustls", "uuid"] }
tokio = { version = "1.46.1", features = ["macros", "rt-multi-thread", "signal"] }
tower-http = { version = "0.6.6", features = ["trace"] }
tracing = "0.1.41"
url = "2.5.4"
+uuid = { version = "1.17.0", features = ["v7"] }
[dependencies.stack-up]
git = "https://github.com/rtkay123/stack-up.git"
-features = ["tracing"]
+features = ["api", "postgres", "tracing"]
[dev-dependencies]
tower = { version = "0.5.2", features = ["util"] }
diff --git a/sellershut.toml b/sellershut.toml
new file mode 100644
index 0000000..d1f54ce
--- /dev/null
+++ b/sellershut.toml
@@ -0,0 +1,16 @@
+[application]
+env = "development"
+port = 2210
+
+[monitoring]
+log-level = "sellershut=trace,info"
+
+[database]
+pool_size = 100
+port = 5432
+name = "sellershut"
+host = "localhost"
+password = "password"
+user = "postgres"
+
+# vim:ft=toml
diff --git a/src/entity/user.rs b/src/entity/user.rs
index e136cb3..da22f00 100644
--- a/src/entity/user.rs
+++ b/src/entity/user.rs
@@ -8,36 +8,77 @@ use activitypub_federation::{
};
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
+use stack_up::Services;
use tracing::trace;
use url::Url;
+use uuid::Uuid;
use crate::{error::AppError, state::AppHandle};
#[derive(PartialEq, Clone, Debug)]
pub(crate) struct User {
+ pub id: String,
pub username: String,
pub ap_id: ObjectId<User>,
pub private_key: Option<String>,
pub public_key: String,
pub inbox: Url,
+ pub outbox: Option<Url>,
}
-impl User {
- pub fn new(username: &str) -> Result<Self, AppError> {
- trace!("creating a new user");
- let keys = generate_actor_keypair()?;
- let stub = &format!("http://localhost/users/{username}");
+pub struct DbUser {
+ pub id: String,
+ pub username: String,
+ pub ap_id: String,
+ pub private_key: Option<String>,
+ pub public_key: String,
+ pub inbox: String,
+ pub outbox: Option<String>,
+ pub local: bool,
+}
+impl TryFrom<DbUser> for User {
+ type Error = AppError;
+ fn try_from(value: DbUser) -> Result<Self, Self::Error> {
Ok(Self {
- username: username.to_owned(),
- ap_id: Url::parse(stub)?.into(),
- private_key: Some(keys.private_key),
- public_key: keys.public_key,
- inbox: Url::parse(&format!("{stub}/inbox"))?,
+ id: value.id,
+ username: value.username,
+ ap_id: Url::parse(&value.ap_id)?.into(),
+ private_key: value.private_key,
+ public_key: value.public_key,
+ inbox: Url::parse(&value.inbox)?,
+ outbox: match value.outbox {
+ Some(ref url) => Some(Url::parse(url)?),
+ None => None,
+ },
})
}
}
+impl User {
+ pub async fn new(username: &str, services: &Services) -> Result<Self, AppError> {
+ trace!("creating keypair for new user");
+ let keys = generate_actor_keypair()?;
+ let stub = &format!("http://localhost/users/{username}");
+ let id = Uuid::now_v7();
+
+ trace!(id = ?id, "creating a new user");
+ let user = sqlx::query_as!(
+ DbUser,
+ "insert into account (id, username, ap_id, private_key, public_key, inbox, outbox, local) values ($1, $2, $3, $4, $5, $6, $7, $8) returning *",
+ id,
+ username,
+ stub,
+ keys.private_key,
+ keys.public_key,
+ &format!("{stub}/inbox"),
+ &format!("{stub}/outbox"),
+ true
+ ).fetch_one(&services.postgres).await?;
+ Self::try_from(user)
+ }
+}
+
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Person {
@@ -47,6 +88,8 @@ pub struct Person {
id: ObjectId<User>,
inbox: Url,
public_key: PublicKey,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ outbox: Option<Url>,
}
#[async_trait]
@@ -85,6 +128,7 @@ impl Object for User {
id: self.ap_id.clone(),
inbox: self.inbox.clone(),
public_key: self.public_key(),
+ outbox: self.outbox.clone(),
})
}
diff --git a/src/main.rs b/src/main.rs
index 1e5b259..68aedc4 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -3,19 +3,53 @@ mod error;
mod server;
mod state;
-use stack_up::{Monitoring, tracing::Tracing};
+use std::net::{Ipv6Addr, SocketAddr};
+
+use clap::Parser;
+use stack_up::{Configuration, Services, tracing::Tracing};
use crate::{error::AppError, state::AppState};
+use tracing::{error, info};
+
+/// sellershut
+#[derive(Parser, Debug)]
+#[command(version, about, long_about = None)]
+struct Args {
+ /// Path to config file
+ #[arg(short, long)]
+ config_file: Option<std::path::PathBuf>,
+}
#[tokio::main]
async fn main() -> Result<(), AppError> {
- let _tracing = Tracing::builder().build(&Monitoring {
- log_level: "trace".into(),
- });
+ let args = Args::parse();
+ let config = include_str!("../sellershut.toml");
+
+ let mut config = config::Config::builder()
+ .add_source(config::File::from_str(config, config::FileFormat::Toml));
+
+ if let Some(cf) = args.config_file.as_ref().and_then(|v| v.to_str()) {
+ config = config.add_source(config::File::new(cf, config::FileFormat::Toml));
+ };
+
+ let mut config: Configuration = config.build()?.try_deserialize()?;
+ config.application.name = env!("CARGO_CRATE_NAME").into();
+ config.application.version = env!("CARGO_PKG_VERSION").into();
+
+ let _tracing = Tracing::builder().build(&config.monitoring);
+
+ let services = Services::builder()
+ .postgres(&config.database)
+ .await
+ .inspect_err(|e| error!("database: {e}"))?
+ .build();
+
+ let state = AppState::new(services, &config).await?;
+
+ let addr = SocketAddr::from((Ipv6Addr::UNSPECIFIED, config.application.port));
- let state = AppState::new().await?;
- let listener = tokio::net::TcpListener::bind("127.0.0.1:3000").await?;
- tracing::debug!("listening on {}", listener.local_addr()?);
+ let listener = tokio::net::TcpListener::bind(addr).await?;
+ info!(port = addr.port(), "serving api");
axum::serve(listener, server::router(state)).await?;
Ok(())
diff --git a/src/server.rs b/src/server.rs
index bb2b4d0..85a3e81 100644
--- a/src/server.rs
+++ b/src/server.rs
@@ -13,3 +13,17 @@ pub fn router(state: FederationConfig<AppHandle>) -> Router {
.layer(TraceLayer::new_for_http())
.layer(FederationMiddleware::new(state))
}
+
+#[cfg(test)]
+pub(crate) fn test_config() -> stack_up::Configuration {
+ use stack_up::Configuration;
+
+ let config_path = "sellershut.toml";
+
+ let config = config::Config::builder()
+ .add_source(config::File::new(config_path, config::FileFormat::Toml))
+ .build()
+ .unwrap();
+
+ config.try_deserialize::<Configuration>().unwrap()
+}
diff --git a/src/server/routes.rs b/src/server/routes.rs
index 7751c95..85cc100 100644
--- a/src/server/routes.rs
+++ b/src/server/routes.rs
@@ -14,13 +14,19 @@ mod tests {
body::Body,
http::{Request, StatusCode},
};
+ use sqlx::PgPool;
+ use stack_up::Services;
use tower::ServiceExt;
- use crate::{server, state::AppState};
+ use crate::{
+ server::{self, test_config},
+ state::AppState,
+ };
- #[tokio::test]
- async fn health_check() {
- let state = AppState::new().await.unwrap();
+ #[sqlx::test]
+ async fn health_check(pool: PgPool) {
+ let services = Services { postgres: pool };
+ let state = AppState::new(services, &test_config()).await.unwrap();
let app = server::router(state);
let response = app
diff --git a/src/server/routes/users.rs b/src/server/routes/users.rs
index 2ef49b2..d3ce446 100644
--- a/src/server/routes/users.rs
+++ b/src/server/routes/users.rs
@@ -1,3 +1,4 @@
+pub mod get_outbox;
pub mod get_user;
pub mod webfinger;
@@ -5,6 +6,7 @@ use axum::{Router, routing::get};
pub fn users_router() -> Router {
Router::new()
- .route("/users/{usernme}", get(get_user::http_get_user))
+ .route("/users/{username}", get(get_user::http_get_user))
+ .route("/users/{username}/outbox", get(get_outbox::http_get_outbox))
.route("/.well-known/webfinger", get(webfinger::webfinger))
}
diff --git a/src/server/routes/users/get_outbox.rs b/src/server/routes/users/get_outbox.rs
new file mode 100644
index 0000000..d5a4af5
--- /dev/null
+++ b/src/server/routes/users/get_outbox.rs
@@ -0,0 +1,77 @@
+use activitypub_federation::{
+ axum::json::FederationJson, config::Data, protocol::context::WithContext, traits::Object,
+};
+use axum::{debug_handler, extract::Path, http::StatusCode, response::IntoResponse};
+
+use crate::{error::AppError, state::AppHandle};
+
+#[debug_handler]
+pub async fn http_get_outbox(
+ Path(name): Path<String>,
+ data: Data<AppHandle>,
+) -> Result<impl IntoResponse, AppError> {
+ if let Some(a) = super::get_user::read_user(&name, &data).await? {
+ let json_user = a.into_json(&data).await?;
+ Ok((
+ StatusCode::OK,
+ FederationJson(WithContext::new_default(json_user)),
+ )
+ .into_response())
+ } else {
+ Ok((StatusCode::NOT_FOUND, "").into_response())
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use axum::{
+ body::Body,
+ http::{Request, StatusCode},
+ };
+ use sqlx::PgPool;
+ use stack_up::Services;
+ use tower::ServiceExt;
+
+ use crate::{
+ server::{self, test_config},
+ state::AppState,
+ };
+
+ #[sqlx::test]
+ async fn get_user(pool: PgPool) {
+ let services = Services { postgres: pool };
+ let state = AppState::new(services, &test_config()).await.unwrap();
+ let app = server::router(state);
+
+ let response = app
+ .oneshot(
+ Request::builder()
+ .uri("/users/sellershut")
+ .body(Body::empty())
+ .unwrap(),
+ )
+ .await
+ .unwrap();
+
+ assert_eq!(response.status(), StatusCode::OK);
+ }
+
+ #[sqlx::test]
+ async fn get_user_not_found(pool: PgPool) {
+ let services = Services { postgres: pool };
+ let state = AppState::new(services, &test_config()).await.unwrap();
+ let app = server::router(state);
+
+ let response = app
+ .oneshot(
+ Request::builder()
+ .uri("/users/selut")
+ .body(Body::empty())
+ .unwrap(),
+ )
+ .await
+ .unwrap();
+
+ assert_eq!(response.status(), StatusCode::NOT_FOUND);
+ }
+}
diff --git a/src/server/routes/users/get_user.rs b/src/server/routes/users/get_user.rs
index d86cc26..4079731 100644
--- a/src/server/routes/users/get_user.rs
+++ b/src/server/routes/users/get_user.rs
@@ -2,6 +2,7 @@ use activitypub_federation::{
axum::json::FederationJson, config::Data, protocol::context::WithContext, traits::Object,
};
use axum::{debug_handler, extract::Path, http::StatusCode, response::IntoResponse};
+use tracing::trace;
use crate::{error::AppError, state::AppHandle};
@@ -10,7 +11,7 @@ pub async fn http_get_user(
Path(name): Path<String>,
data: Data<AppHandle>,
) -> Result<impl IntoResponse, AppError> {
- if let Some(a) = read_user(&name, &data).await {
+ if let Some(a) = read_user(&name, &data).await? {
let json_user = a.into_json(&data).await?;
Ok((
StatusCode::OK,
@@ -22,11 +23,26 @@ pub async fn http_get_user(
}
}
-pub async fn read_user(name: &str, data: &Data<AppHandle>) -> Option<crate::entity::user::User> {
- let read = data.users.read().await;
- read.iter()
- .find(|value| value.username.eq(&name))
- .map(ToOwned::to_owned)
+pub async fn read_user(
+ name: &str,
+ data: &Data<AppHandle>,
+) -> Result<Option<crate::entity::user::User>, AppError> {
+ trace!(username = name, "getting user");
+ let read = sqlx::query_as!(
+ crate::entity::user::DbUser,
+ "select * from account where username = $1 and local = $2",
+ name,
+ true
+ )
+ .fetch_optional(&data.services.postgres)
+ .await?;
+
+ let user = read.into_iter().find(|value| value.username.eq(&name));
+ let user = match user {
+ Some(user) => Some(crate::entity::user::User::try_from(user)?),
+ None => None,
+ };
+ Ok(user)
}
#[cfg(test)]
@@ -35,13 +51,19 @@ mod tests {
body::Body,
http::{Request, StatusCode},
};
+ use sqlx::PgPool;
+ use stack_up::Services;
use tower::ServiceExt;
- use crate::{server, state::AppState};
+ use crate::{
+ server::{self, test_config},
+ state::AppState,
+ };
- #[tokio::test]
- async fn get_user() {
- let state = AppState::new().await.unwrap();
+ #[sqlx::test]
+ async fn get_user(pool: PgPool) {
+ let services = Services { postgres: pool };
+ let state = AppState::new(services, &test_config()).await.unwrap();
let app = server::router(state);
let response = app
@@ -57,9 +79,10 @@ mod tests {
assert_eq!(response.status(), StatusCode::OK);
}
- #[tokio::test]
- async fn get_user_not_found() {
- let state = AppState::new().await.unwrap();
+ #[sqlx::test]
+ async fn get_user_not_found(pool: PgPool) {
+ let services = Services { postgres: pool };
+ let state = AppState::new(services, &test_config()).await.unwrap();
let app = server::router(state);
let response = app
diff --git a/src/server/routes/users/webfinger.rs b/src/server/routes/users/webfinger.rs
index 22975c2..8efeda6 100644
--- a/src/server/routes/users/webfinger.rs
+++ b/src/server/routes/users/webfinger.rs
@@ -17,7 +17,7 @@ pub async fn webfinger(
data: Data<AppHandle>,
) -> Result<impl IntoResponse, AppError> {
let name = extract_webfinger_name(&query.resource, &data)?;
- if let Some(db_user) = read_user(name, &data).await {
+ if let Some(db_user) = read_user(name, &data).await? {
Ok((
StatusCode::OK,
Json(build_webfinger_response(
@@ -37,13 +37,19 @@ mod tests {
body::Body,
http::{Request, StatusCode},
};
+ use sqlx::PgPool;
+ use stack_up::Services;
use tower::ServiceExt;
- use crate::{server, state::AppState};
+ use crate::{
+ server::{self, test_config},
+ state::AppState,
+ };
- #[tokio::test]
- async fn webfinger_ok() {
- let state = AppState::new().await.unwrap();
+ #[sqlx::test]
+ async fn webfinger_ok(pool: PgPool) {
+ let services = Services { postgres: pool };
+ let state = AppState::new(services, &test_config()).await.unwrap();
let app = server::router(state);
let response = app
@@ -59,9 +65,10 @@ mod tests {
assert_eq!(response.status(), StatusCode::OK);
}
- #[tokio::test]
- async fn webfinger_err() {
- let state = AppState::new().await.unwrap();
+ #[sqlx::test]
+ async fn webfinger_err(pool: PgPool) {
+ let services = Services { postgres: pool };
+ let state = AppState::new(services, &test_config()).await.unwrap();
let app = server::router(state);
let response = app
diff --git a/src/state.rs b/src/state.rs
index d7c9136..5ced62e 100644
--- a/src/state.rs
+++ b/src/state.rs
@@ -1,7 +1,7 @@
use std::{ops::Deref, sync::Arc};
use activitypub_federation::config::FederationConfig;
-use tokio::sync::RwLock;
+use stack_up::{Configuration, Environment, Services};
use crate::{entity::user::User, error::AppError};
@@ -17,23 +17,24 @@ impl Deref for AppHandle {
}
pub struct AppState {
- pub users: RwLock<Vec<User>>,
+ pub services: Services,
}
impl AppState {
- pub async fn new() -> Result<FederationConfig<AppHandle>, AppError> {
- let user = User::new("sellershut")?;
+ pub async fn new(
+ services: Services,
+ configuration: &Configuration,
+ ) -> Result<FederationConfig<AppHandle>, AppError> {
+ let user = User::new("sellershut", &services).await?;
let domain = "localhost";
let config = FederationConfig::builder()
.domain(domain)
.signed_fetch_actor(&user)
- .app_data(AppHandle(Arc::new(Self {
- users: RwLock::new(vec![user]),
- })))
+ .app_data(AppHandle(Arc::new(Self { services })))
// .url_verifier(Box::new(MyUrlVerifier()))
// TODO: could change this to env variable?
- .debug(cfg!(debug_assertions))
+ .debug(configuration.application.env == Environment::Development)
.build()
.await?;