Compare commits

..

8 commits

Author SHA1 Message Date
0795d6fa4e Merge pull request 'Add template field to Link because ostatus subscribe schema needs it.' (#4) from template_link_type into master
All checks were successful
/ docker build (push) Successful in 1m46s
/ cargo test (push) Successful in 22s
Reviewed-on: #4
2024-05-07 18:06:20 +02:00
efc7b83930 Add template field to Link because ostatus subscribe schema needs it.
All checks were successful
/ cargo test (push) Successful in 20s
Also fixes a bug where Resource::compress lost every link and adds a lot more tests around that functionality.
2024-05-07 18:04:43 +02:00
8eafcf86b9 Server only docker image, but the action's documentation is apparently wrong.
All checks were successful
/ docker build (push) Successful in 1m22s
/ cargo test (push) Successful in 19s
2024-04-01 16:55:07 +02:00
6cd503711f Server only docker image
All checks were successful
/ cargo test (push) Successful in 20s
2024-04-01 16:53:23 +02:00
a38ab85320 Bump version and update dependencies
All checks were successful
/ docker build (push) Successful in 1m19s
/ cargo test (push) Successful in 20s
2024-04-01 16:31:08 +02:00
12cb4fc254 Add more testing around case-insensitivity and patch an error in merge_records creating duplicates in the database 2024-04-01 16:30:37 +02:00
92c3239c00 Merge pull request 'Slim down tokio features' (#2) from leaner-tokio into master
All checks were successful
/ docker build (push) Successful in 1m14s
/ cargo test (push) Successful in 24s
Reviewed-on: #2
2024-03-18 02:13:02 +01:00
3dbe0eb589 Slim down tokio features
All checks were successful
/ cargo test (push) Successful in 22s
2024-03-18 02:11:01 +01:00
7 changed files with 340 additions and 294 deletions

View file

@ -20,3 +20,8 @@ jobs:
push: true push: true
tags: karcsesz/fingerlink:latest-nano tags: karcsesz/fingerlink:latest-nano
build-args: "editor=nano" build-args: "editor=nano"
- uses: docker/build-push-action@v5
with:
push: true
tags: karcsesz/fingerlink:latest-server
file: Dockerfile.serveonly

369
Cargo.lock generated
View file

@ -113,18 +113,18 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]] [[package]]
name = "axum" name = "axum"
version = "0.7.4" version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1236b4b292f6c4d6dc34604bb5120d85c3fe1d1aa596bd5cc52ca054d13e7b9e" checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"axum-core", "axum-core",
"bytes", "bytes",
"futures-util", "futures-util",
"http 1.0.0", "http",
"http-body 1.0.0", "http-body",
"http-body-util", "http-body-util",
"hyper 1.1.0", "hyper",
"hyper-util", "hyper-util",
"itoa", "itoa",
"matchit", "matchit",
@ -137,7 +137,7 @@ dependencies = [
"serde_json", "serde_json",
"serde_path_to_error", "serde_path_to_error",
"serde_urlencoded", "serde_urlencoded",
"sync_wrapper", "sync_wrapper 1.0.0",
"tokio", "tokio",
"tower", "tower",
"tower-layer", "tower-layer",
@ -154,13 +154,13 @@ dependencies = [
"async-trait", "async-trait",
"bytes", "bytes",
"futures-util", "futures-util",
"http 1.0.0", "http",
"http-body 1.0.0", "http-body",
"http-body-util", "http-body-util",
"mime", "mime",
"pin-project-lite", "pin-project-lite",
"rustversion", "rustversion",
"sync_wrapper", "sync_wrapper 0.1.2",
"tower-layer", "tower-layer",
"tower-service", "tower-service",
"tracing", "tracing",
@ -187,12 +187,6 @@ version = "0.21.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.4.2" version = "2.4.2"
@ -255,9 +249,9 @@ checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.5.3" version = "4.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "949626d00e063efc93b6dca932419ceb5432f99769911c0b995f7e884c778813" checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0"
dependencies = [ dependencies = [
"clap_builder", "clap_builder",
"clap_derive", "clap_derive",
@ -277,9 +271,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_derive" name = "clap_derive"
version = "4.5.3" version = "4.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90239a040c80f5e14809ca132ddc4176ab33d5e17e49691793296e3fcb34d72f" checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64"
dependencies = [ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2",
@ -299,22 +293,6 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "core-foundation"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
[[package]] [[package]]
name = "crc32fast" name = "crc32fast"
version = "1.3.2" version = "1.3.2"
@ -330,21 +308,6 @@ version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a"
[[package]]
name = "encoding_rs"
version = "0.8.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1"
dependencies = [
"cfg-if",
]
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]] [[package]]
name = "errno" name = "errno"
version = "0.3.8" version = "0.3.8"
@ -363,7 +326,7 @@ checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
[[package]] [[package]]
name = "fingerlink" name = "fingerlink"
version = "0.1.0" version = "0.1.1"
dependencies = [ dependencies = [
"axum", "axum",
"clap", "clap",
@ -413,6 +376,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-sink",
] ]
[[package]] [[package]]
@ -447,6 +411,7 @@ checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-io", "futures-io",
"futures-sink",
"futures-task", "futures-task",
"memchr", "memchr",
"pin-project-lite", "pin-project-lite",
@ -471,50 +436,6 @@ version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
[[package]]
name = "h2"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9"
dependencies = [
"bytes",
"fnv",
"futures-core",
"futures-sink",
"futures-util",
"http 0.2.11",
"indexmap",
"slab",
"tokio",
"tokio-util",
"tracing",
]
[[package]]
name = "h2"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31d030e59af851932b72ceebadf4a2b5986dba4c3b99dd2493f8273a0f151943"
dependencies = [
"bytes",
"fnv",
"futures-core",
"futures-sink",
"futures-util",
"http 1.0.0",
"indexmap",
"slab",
"tokio",
"tokio-util",
"tracing",
]
[[package]]
name = "hashbrown"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
[[package]] [[package]]
name = "heck" name = "heck"
version = "0.5.0" version = "0.5.0"
@ -536,17 +457,6 @@ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "http"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb"
dependencies = [
"bytes",
"fnv",
"itoa",
]
[[package]] [[package]]
name = "http" name = "http"
version = "1.0.0" version = "1.0.0"
@ -558,17 +468,6 @@ dependencies = [
"itoa", "itoa",
] ]
[[package]]
name = "http-body"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2"
dependencies = [
"bytes",
"http 0.2.11",
"pin-project-lite",
]
[[package]] [[package]]
name = "http-body" name = "http-body"
version = "1.0.0" version = "1.0.0"
@ -576,7 +475,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643"
dependencies = [ dependencies = [
"bytes", "bytes",
"http 1.0.0", "http",
] ]
[[package]] [[package]]
@ -587,8 +486,8 @@ checksum = "41cb79eb393015dadd30fc252023adb0b2400a0caee0fa2a077e6e21a551e840"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-util", "futures-util",
"http 1.0.0", "http",
"http-body 1.0.0", "http-body",
"pin-project-lite", "pin-project-lite",
] ]
@ -604,30 +503,6 @@ version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "hyper"
version = "0.14.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80"
dependencies = [
"bytes",
"futures-channel",
"futures-core",
"futures-util",
"h2 0.3.24",
"http 0.2.11",
"http-body 0.4.6",
"httparse",
"httpdate",
"itoa",
"pin-project-lite",
"socket2",
"tokio",
"tower-service",
"tracing",
"want",
]
[[package]] [[package]]
name = "hyper" name = "hyper"
version = "1.1.0" version = "1.1.0"
@ -637,28 +512,31 @@ dependencies = [
"bytes", "bytes",
"futures-channel", "futures-channel",
"futures-util", "futures-util",
"h2 0.4.2", "http",
"http 1.0.0", "http-body",
"http-body 1.0.0",
"httparse", "httparse",
"httpdate", "httpdate",
"itoa", "itoa",
"pin-project-lite", "pin-project-lite",
"tokio", "tokio",
"want",
] ]
[[package]] [[package]]
name = "hyper-rustls" name = "hyper-rustls"
version = "0.24.2" version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c"
dependencies = [ dependencies = [
"futures-util", "futures-util",
"http 0.2.11", "http",
"hyper 0.14.28", "hyper",
"hyper-util",
"rustls", "rustls",
"rustls-pki-types",
"tokio", "tokio",
"tokio-rustls", "tokio-rustls",
"tower-service",
] ]
[[package]] [[package]]
@ -668,13 +546,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-channel",
"futures-util", "futures-util",
"http 1.0.0", "http",
"http-body 1.0.0", "http-body",
"hyper 1.1.0", "hyper",
"pin-project-lite", "pin-project-lite",
"socket2", "socket2",
"tokio", "tokio",
"tower",
"tower-service",
"tracing",
] ]
[[package]] [[package]]
@ -687,16 +569,6 @@ dependencies = [
"unicode-normalization", "unicode-normalization",
] ]
[[package]]
name = "indexmap"
version = "2.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177"
dependencies = [
"equivalent",
"hashbrown",
]
[[package]] [[package]]
name = "ipnet" name = "ipnet"
version = "2.9.0" version = "2.9.0"
@ -736,16 +608,6 @@ version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
[[package]]
name = "lock_api"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
dependencies = [
"autocfg",
"scopeguard",
]
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.20" version = "0.4.20"
@ -796,7 +658,7 @@ version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
dependencies = [ dependencies = [
"bitflags 2.4.2", "bitflags",
"cfg-if", "cfg-if",
"cfg_aliases", "cfg_aliases",
"libc", "libc",
@ -843,29 +705,6 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]]
name = "parking_lot"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-targets 0.48.5",
]
[[package]] [[package]]
name = "percent-encoding" name = "percent-encoding"
version = "2.3.1" version = "2.3.1"
@ -928,32 +767,24 @@ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]]
name = "redox_syscall"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
dependencies = [
"bitflags 1.3.2",
]
[[package]] [[package]]
name = "reqwest" name = "reqwest"
version = "0.11.26" version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78bf93c4af7a8bb7d879d51cebe797356ff10ae8516ace542b5182d9dcac10b2" checksum = "2d66674f2b6fb864665eea7a3c1ac4e3dfacd2fda83cf6f935a612e01b0e3338"
dependencies = [ dependencies = [
"async-compression", "async-compression",
"base64", "base64",
"bytes", "bytes",
"encoding_rs", "futures-channel",
"futures-core", "futures-core",
"futures-util", "futures-util",
"h2 0.3.24", "http",
"http 0.2.11", "http-body",
"http-body 0.4.6", "http-body-util",
"hyper 0.14.28", "hyper",
"hyper-rustls", "hyper-rustls",
"hyper-util",
"ipnet", "ipnet",
"js-sys", "js-sys",
"log", "log",
@ -963,11 +794,11 @@ dependencies = [
"pin-project-lite", "pin-project-lite",
"rustls", "rustls",
"rustls-pemfile", "rustls-pemfile",
"rustls-pki-types",
"serde", "serde",
"serde_json", "serde_json",
"serde_urlencoded", "serde_urlencoded",
"sync_wrapper", "sync_wrapper 0.1.2",
"system-configuration",
"tokio", "tokio",
"tokio-rustls", "tokio-rustls",
"tokio-util", "tokio-util",
@ -1006,7 +837,7 @@ version = "0.38.31"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949"
dependencies = [ dependencies = [
"bitflags 2.4.2", "bitflags",
"errno", "errno",
"libc", "libc",
"linux-raw-sys", "linux-raw-sys",
@ -1015,14 +846,16 @@ dependencies = [
[[package]] [[package]]
name = "rustls" name = "rustls"
version = "0.21.10" version = "0.22.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" checksum = "99008d7ad0bbbea527ec27bddbc0e432c5b87d8175178cee68d2eec9c4a1813c"
dependencies = [ dependencies = [
"log", "log",
"ring", "ring",
"rustls-pki-types",
"rustls-webpki", "rustls-webpki",
"sct", "subtle",
"zeroize",
] ]
[[package]] [[package]]
@ -1035,12 +868,19 @@ dependencies = [
] ]
[[package]] [[package]]
name = "rustls-webpki" name = "rustls-pki-types"
version = "0.101.7" version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" checksum = "ecd36cc4259e3e4514335c4a138c6b43171a8d61d8f5c9348f9fc7529416f247"
[[package]]
name = "rustls-webpki"
version = "0.102.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610"
dependencies = [ dependencies = [
"ring", "ring",
"rustls-pki-types",
"untrusted", "untrusted",
] ]
@ -1056,22 +896,6 @@ version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "sct"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414"
dependencies = [
"ring",
"untrusted",
]
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.197" version = "1.0.197"
@ -1094,9 +918,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.114" version = "1.0.115"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",
@ -1180,6 +1004,12 @@ version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01"
[[package]]
name = "subtle"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.48" version = "2.0.48"
@ -1198,25 +1028,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
[[package]] [[package]]
name = "system-configuration" name = "sync_wrapper"
version = "0.5.1" version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" checksum = "384595c11a4e2969895cad5a8c4029115f5ab956a9e5ef4de79d11a426e5f20c"
dependencies = [
"bitflags 1.3.2",
"core-foundation",
"system-configuration-sys",
]
[[package]]
name = "system-configuration-sys"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]] [[package]]
name = "tempfile" name = "tempfile"
@ -1277,16 +1092,15 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.36.0" version = "1.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787"
dependencies = [ dependencies = [
"backtrace", "backtrace",
"bytes", "bytes",
"libc", "libc",
"mio", "mio",
"num_cpus", "num_cpus",
"parking_lot",
"pin-project-lite", "pin-project-lite",
"signal-hook-registry", "signal-hook-registry",
"socket2", "socket2",
@ -1307,11 +1121,12 @@ dependencies = [
[[package]] [[package]]
name = "tokio-rustls" name = "tokio-rustls"
version = "0.24.1" version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f"
dependencies = [ dependencies = [
"rustls", "rustls",
"rustls-pki-types",
"tokio", "tokio",
] ]
@ -1570,21 +1385,23 @@ dependencies = [
[[package]] [[package]]
name = "webpki-roots" name = "webpki-roots"
version = "0.25.4" version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" checksum = "b3de34ae270483955a94f4b21bdaaeb83d508bb84a01435f393818edb0012009"
dependencies = [
"rustls-pki-types",
]
[[package]] [[package]]
name = "which" name = "which"
version = "6.0.0" version = "6.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fa5e0c10bf77f44aac573e498d1a82d5fbd5e91f6fc0a99e7be4b38e85e101c" checksum = "8211e4f58a2b2805adfbefbc07bab82958fc91e3836339b1ab7ae32465dce0d7"
dependencies = [ dependencies = [
"either", "either",
"home", "home",
"once_cell",
"rustix", "rustix",
"windows-sys 0.52.0", "winsafe",
] ]
[[package]] [[package]]
@ -1750,3 +1567,15 @@ dependencies = [
"cfg-if", "cfg-if",
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
[[package]]
name = "winsafe"
version = "0.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904"
[[package]]
name = "zeroize"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d"

View file

@ -1,6 +1,6 @@
[package] [package]
name = "fingerlink" name = "fingerlink"
version = "0.1.0" version = "0.1.1"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -12,18 +12,18 @@ editor = ["reqwest", "tempfile", "which", "nix"]
[dependencies] [dependencies]
qpidfile = { version = "0.9.2", optional = true } qpidfile = { version = "0.9.2", optional = true }
tokio = { version = "1.36.0", features = ["full"], optional = true } tokio = { version = "1.37.0", features = ["rt-multi-thread", "signal"], optional = true }
# dashmap = { version = "5.5.3", features = ["inline"]} # dashmap = { version = "5.5.3", features = ["inline"]}
tracing = "0.1.40" tracing = "0.1.40"
tracing-subscriber = { version = "0.3.18", features = ["fmt"] } tracing-subscriber = { version = "0.3.18", features = ["fmt"] }
serde = { version = "1.0.197", features = ["derive"] } serde = { version = "1.0.197", features = ["derive"] }
serde_json = "1.0.114" serde_json = "1.0.115"
thiserror = "1.0.58" thiserror = "1.0.58"
clap = { version = "4.5.3", features = ["derive"]} clap = { version = "4.5.4", features = ["derive"] }
axum = { version = "0.7.4", optional = true } axum = { version = "0.7.5", optional = true }
reqwest = { version = "0.11.26", optional = true, default-features = false, features = ["rustls-tls", "blocking", "json", "gzip", "brotli", "deflate"] } reqwest = { version = "0.12.2", optional = true, default-features = false, features = ["rustls-tls", "blocking", "json", "gzip", "brotli", "deflate"] }
tempfile = { version = "3.10.1", optional = true } tempfile = { version = "3.10.1", optional = true }
which = { version = "6.0.0", optional = true } which = { version = "6.0.1", optional = true }
nix = { version = "0.28.0", optional = true, default-features = false, features = ["signal"] } nix = { version = "0.28.0", optional = true, default-features = false, features = ["signal"] }
urlencoding = { version = "2.1.3"} urlencoding = { version = "2.1.3"}

24
Dockerfile.serveonly Normal file
View file

@ -0,0 +1,24 @@
FROM rust:latest as builder
LABEL authors="karcsesz"
ARG target=x86_64-unknown-linux-musl
RUN apt update && apt install -y musl-tools musl-dev
RUN update-ca-certificates
RUN rustup target add $target
WORKDIR /fingerlink
COPY . .
RUN cargo build --target $target --release --no-default-features --features server
FROM scratch
ENV PATH="${PATH}:/fingerlink"
WORKDIR /fingerlink
COPY --from=builder /fingerlink/target/x86_64-unknown-linux-musl/release/fingerlink /fingerlink/fingerlink
ENTRYPOINT ["/fingerlink/fingerlink", "serve"]
CMD ["--help"]

View file

@ -46,7 +46,6 @@ impl LookupHandler {
let mut lookup = HashMap::new(); let mut lookup = HashMap::new();
for (index, resource) in resources.0.iter().enumerate() { for (index, resource) in resources.0.iter().enumerate() {
for lookup_to_add in resource.keys() { for lookup_to_add in resource.keys() {
let lookup_to_add = lookup_to_add.to_lowercase();
debug!("Adding {lookup_to_add} for {}", resource.subject); debug!("Adding {lookup_to_add} for {}", resource.subject);
let duplicate = lookup.insert(lookup_to_add.clone(), index); let duplicate = lookup.insert(lookup_to_add.clone(), index);
@ -162,6 +161,23 @@ mod tests {
} }
} }
#[test]
fn successful_case_insensitive_query() {
let data = "[{\"subject\":\"testing\"},{\"subject\":\"more_testing\"}]".as_bytes();
let data = LookupHandler::load_from_reader(data).unwrap();
for subject in ["TESTING", "mOre_testiNg"] {
assert_eq!(
data.lookup(subject),
Some(&Resource {
subject: subject.to_lowercase(),
aliases: None,
properties: None,
links: None,
})
);
}
}
#[test] #[test]
fn successful_alias_query() { fn successful_alias_query() {
let data = "[{\"subject\":\"testing\",\"aliases\":[\"alias1\",\"alias2\"]},{\"subject\":\"red herring\",\"aliases\":[\"alias\",\"1\", \"2\"]}]".as_bytes(); let data = "[{\"subject\":\"testing\",\"aliases\":[\"alias1\",\"alias2\"]},{\"subject\":\"red herring\",\"aliases\":[\"alias\",\"1\", \"2\"]}]".as_bytes();
@ -178,4 +194,21 @@ mod tests {
); );
} }
} }
#[test]
fn successful_case_insensitive_alias_query() {
let data = "[{\"subject\":\"testing\",\"aliases\":[\"alias1\",\"alias2\"]},{\"subject\":\"red herring\",\"aliases\":[\"alias\",\"1\", \"2\"]}]".as_bytes();
let data = LookupHandler::load_from_reader(data).unwrap();
for subject in ["aliAS1", "aLiAs2"] {
assert_eq!(
data.lookup(subject),
Some(&Resource {
subject: "testing".to_string(),
aliases: Some(vec!["alias1".to_string(), "alias2".to_string()]),
properties: None,
links: None,
})
);
}
}
} }

View file

@ -39,16 +39,16 @@ impl Resource {
} }
} }
/// Returns the aliases of the given record. If the `aliases` field is /// Returns the aliases of the given record, converted to lowercase. If the `aliases` field is
/// entirely missing, returns an empty array. /// entirely missing, returns an empty array.
pub fn keys(&self) -> impl Iterator<Item = &String> { pub fn keys(&self) -> impl Iterator<Item=String> + '_ {
let aliases = if let Some(aliases) = &self.aliases { let aliases = if let Some(aliases) = &self.aliases {
aliases.as_slice() aliases.as_slice()
} else { } else {
&[] &[]
}; };
aliases.iter().chain(std::iter::once(&self.subject)) aliases.iter().chain(std::iter::once(&self.subject)).map(|key| key.to_lowercase())
} }
/// Replaces the current `subject` field of the WebFinger resource /// Replaces the current `subject` field of the WebFinger resource
@ -114,6 +114,7 @@ impl Resource {
.map(clone_hashmap_with_option_value_as_complete) .map(clone_hashmap_with_option_value_as_complete)
.unwrap_or_default(), .unwrap_or_default(),
), ),
template: Some(link.template.clone().unwrap_or_default()),
} }
})) }))
}) })
@ -146,6 +147,36 @@ impl Resource {
.links .links
.filter(|links| !links.is_empty()) .filter(|links| !links.is_empty())
.map(|mut links| { .map(|mut links| {
// Collapse default subvalues
for link in &mut links {
if link.media_type.as_ref().map_or(false, String::is_empty) {
link.media_type = None;
}
if link.href.as_ref().map_or(false, String::is_empty) {
link.href = None;
}
if let Some(titles) = &mut link.titles {
titles.retain(|key, value| !key.is_empty() || !value.is_empty())
}
if link.titles.as_ref().map_or(false, HashMap::is_empty) {
link.titles = None;
}
if let Some(properties) = &mut link.properties {
for value in properties.values_mut() {
if value.as_ref().map_or(false, String::is_empty) {
*value = None;
}
}
properties.retain(|key, value| !key.is_empty() || !value.is_none())
}
if link.properties.as_ref().map_or(false, HashMap::is_empty) {
link.properties = None;
}
if link.template.as_ref().map_or(false, String::is_empty) {
link.template = None;
}
}
// Delete completely default links
links.retain(|link| { links.retain(|link| {
// Empty `rel` is invalid, but short-circuiting here would delete records // Empty `rel` is invalid, but short-circuiting here would delete records
// that are only partially edited. Better to store invalid data than to delete // that are only partially edited. Better to store invalid data than to delete
@ -153,22 +184,19 @@ impl Resource {
let mut is_default = link.rel.is_empty(); let mut is_default = link.rel.is_empty();
is_default &= link is_default &= link
.media_type .media_type
.as_ref()
.filter(|media_type| !media_type.is_empty())
.is_none(); .is_none();
is_default &= link.href.as_ref().filter(|href| !href.is_empty()).is_none(); is_default &= link.href.as_ref().filter(|href| !href.is_empty()).is_none();
is_default &= link is_default &= link
.titles .titles
.as_ref()
.filter(|titles| !titles.is_empty())
.is_none(); .is_none();
is_default &= link is_default &= link
.properties .properties
.as_ref() .is_none();
.filter(|titles| !titles.is_empty()) is_default &= link
.template
.is_none(); .is_none();
is_default !is_default
}); });
links links
@ -189,12 +217,15 @@ pub struct Link {
pub titles: Option<HashMap<String, String>>, pub titles: Option<HashMap<String, String>>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub properties: Option<HashMap<String, Option<String>>>, pub properties: Option<HashMap<String, Option<String>>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub template: Option<String>,
} }
#[cfg(test)] #[cfg(test)]
/// Functions to generate data for testing functions that manipulate `Resource` structs /// Functions to generate data for testing functions that manipulate `Resource` structs
pub mod test_data { pub mod test_data {
use crate::schema::resource::Resource; use std::collections::HashMap;
use crate::schema::resource::{Link, Resource};
/// A [`Resource`] with only the `subject` field set /// A [`Resource`] with only the `subject` field set
pub fn barebones_user() -> Resource { pub fn barebones_user() -> Resource {
@ -220,6 +251,100 @@ pub mod test_data {
links: None, links: None,
} }
} }
pub fn example_mastodon_user() -> Resource {
Resource {
subject: "acct:user@example.com".to_string(),
aliases: Some(vec![
"https://example.com/@user".to_string(),
"https://example.com/users/user".to_string()
]),
properties: None,
links: Some(vec![
Link {
rel: "http://webfinger.net/rel/profile-page".to_string(),
media_type: Some("text/html".to_string()),
href: Some("https://example.com/@user".to_string()),
titles: None,
properties: None,
template: None,
},
Link {
rel: "self".to_string(),
media_type: Some("application/activity+json".to_string()),
href: Some("https://example.com/users/user".to_string()),
titles: None,
properties: None,
template: None,
},
Link {
rel: "http://ostatus.org/schema/1.0/subscribe".to_string(),
media_type: None,
href: None,
titles: None,
properties: None,
template: Some("https://example.com/authorize_interaction?uri={uri}".to_string()),
},
Link {
rel: "http://webfinger.net/rel/avatar".to_string(),
media_type: Some("image/png".to_string()),
href: Some("https://example.com/system/accounts/avatars/321/423/112/234/123/527/original/1j2ioff88a9wa.png".to_string()),
titles: None,
properties: None,
template: None,
}
]),
}
}
pub fn example_firefish_user() -> Resource {
Resource {
subject: "acct:user@example.com".to_string(),
aliases: None,
properties: None,
links: Some(vec![
Link {
rel: "self".to_string(),
media_type: Some("application/activity+json".to_string()),
href: Some("https://example.com/users/8fsua89lcieaj".to_string()),
titles: None,
properties: None,
template: None,
},
Link {
rel: "http://webfinger.net/rel/profile-page".to_string(),
media_type: Some("text/html".to_string()),
href: Some("https://example.com/@user".to_string()),
titles: None,
properties: None,
template: None,
},
Link {
rel: "http://ostatus.org/schema/1.0/subscribe".to_string(),
media_type: None,
href: None,
titles: None,
properties: None,
template: Some("https://example.com/authorize-follow?acct={uri}".to_string()),
}
])
}
}
pub fn full_resource() -> Resource {
Resource {
subject: "some_subject".to_string(),
aliases: Some(vec!["ThisIsAnAlias".to_string()]),
properties: Some(HashMap::from_iter(std::iter::once(("property_key".to_string(), Some("property_value".to_string()))))),
links: Some(vec![Link {
rel: "link_relation".to_string(),
media_type: Some("media/type".to_string()),
href: Some("https://example.com/link_href".to_string()),
titles: Some(HashMap::from_iter(std::iter::once(("title_key".to_string(), "title_value".to_string())))),
properties: Some(HashMap::from_iter(std::iter::once(("property_key".to_string(), Some("property_value".to_string()))))),
template: Some("template".to_string()),
}]),
}
}
} }
#[cfg(test)] #[cfg(test)]
@ -288,6 +413,9 @@ mod tests {
test_data::barebones_user(), test_data::barebones_user(),
test_data::user_with_matching_subject_and_alias(), test_data::user_with_matching_subject_and_alias(),
test_data::user_with_single_alias(), test_data::user_with_single_alias(),
test_data::example_firefish_user(),
test_data::example_mastodon_user(),
test_data::full_resource(),
] { ] {
assert_eq!(data, data.as_completely_serializable().compress()); assert_eq!(data, data.as_completely_serializable().compress());
} }

View file

@ -83,10 +83,10 @@ impl ResourceList {
) -> &ResourceList { ) -> &ResourceList {
debug!("Building hashset of already taken queries..."); debug!("Building hashset of already taken queries...");
let unique_check: HashSet<String> = let unique_check: HashSet<String> =
HashSet::from_iter(self.0.iter().flat_map(Resource::keys).cloned()); HashSet::from_iter(self.0.iter().flat_map(Resource::keys));
for record in new_records { for record in new_records {
let record_keys = HashSet::from_iter(record.keys().cloned()); let record_keys = HashSet::from_iter(record.keys());
let collisions = unique_check let collisions = unique_check
.intersection(&record_keys) .intersection(&record_keys)
.collect::<HashSet<_>>(); .collect::<HashSet<_>>();
@ -103,7 +103,7 @@ impl ResourceList {
CollisionHandling::OverwriteSingleSkipMultiple => { CollisionHandling::OverwriteSingleSkipMultiple => {
let mut collided_resources = let mut collided_resources =
self.0.iter().enumerate().filter(|record| { self.0.iter().enumerate().filter(|record| {
record.1.keys().any(|elem| collisions.contains(elem)) record.1.keys().any(|elem| collisions.contains(&elem))
}); });
if let Some((collided_index, collided_resource)) = collided_resources.next() if let Some((collided_index, collided_resource)) = collided_resources.next()
{ {
@ -118,7 +118,7 @@ impl ResourceList {
CollisionHandling::OverwriteMultiple => { CollisionHandling::OverwriteMultiple => {
warn!("Overwriting already existing record(s) with new data..."); warn!("Overwriting already existing record(s) with new data...");
self.0.retain(|record| { self.0.retain(|record| {
if record.keys().any(|elem| collisions.contains(elem)) { if record.keys().any(|elem| collisions.contains(&elem)) {
warn!("Removing {record:?}"); warn!("Removing {record:?}");
false false
} else { } else {
@ -138,4 +138,31 @@ impl ResourceList {
self self
} }
#[cfg(test)]
/// Returns the amount of records stored
fn len(&self) -> usize {
self.0.len()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn check_merge_case_insensitivity() {
let mut base = ResourceList(vec![Resource::new("ThisIsASubject".to_string())]);
base.merge_records(std::iter::once(Resource::new("thisisasubject".to_string())), CollisionHandling::Skip);
assert_eq!(base.len(), 1);
}
#[test]
fn check_merge_case_insensitivity_alt() {
let mut base = Resource::new("ThisIsASubject".to_string());
base.add_new_primary_subject("ThisIsANewPrimarySubject".to_string());
let mut base = ResourceList(vec![base]);
base.merge_records(std::iter::once(Resource::new("thisisasubject".to_string())), CollisionHandling::Skip);
assert_eq!(base.len(), 1);
}
} }