Compare commits
No commits in common. "main" and "fix-delete-user" have entirely different histories.
main
...
fix-delete
2
.gitignore
vendored
2
.gitignore
vendored
@ -20,5 +20,3 @@ search_index
|
||||
__pycache__
|
||||
.vscode/
|
||||
*-journal
|
||||
.direnv/
|
||||
build.log*
|
||||
|
11
CHANGELOG.md
11
CHANGELOG.md
@ -8,16 +8,11 @@
|
||||
|
||||
- Add 'My feed' to i18n timeline name (#1084)
|
||||
- Bidirectional support for user page header (#1092)
|
||||
- Add non anonymous bind to LDAP server, taken from https://git.joinplu.me/Plume/Plume/src/branch/ldap-non-anon PR
|
||||
|
||||
### Changed
|
||||
|
||||
- Use blog title as slug (#1094, #1126, #1127)
|
||||
- Bump Rust to nightly 2022-07-19 (#1119)
|
||||
- Force LDAP simple bind with *cn* rdn instead of *uid*
|
||||
- Update rust-toolchain to nightly-2023-04-14
|
||||
- Update chrono from 0.4.0 to 0.4.31
|
||||
- Update scheduled-thread-pool from 0.2.6 to 0.2.7
|
||||
|
||||
### Fixed
|
||||
|
||||
@ -27,12 +22,6 @@
|
||||
- Allow empty avatar for remote users (#1129)
|
||||
- Percent encode blog FQN for federation interoperability (#1129)
|
||||
- The same to `preferredUsername` (#1129)
|
||||
- Deprecation warnings during build process(see rust crate updates)
|
||||
- Server error 500 creating new blog with white spaces inside title. Bug reported on https://git.joinplu.me/Plume/Plume/issues/1152
|
||||
- Show _Subscribe_ button in column format instead of row format in screen smaller than 600px. https://git.lainoa.eus/aitzol/Plume/commit/db8cc6e7e8351a5d74f7ce0399126e13493c62d9
|
||||
### To do
|
||||
|
||||
- Choose rdn via environment variables for LDAP simple bind
|
||||
|
||||
## [[0.7.2]] - 2022-05-11
|
||||
|
||||
|
530
Cargo.lock
generated
530
Cargo.lock
generated
@ -126,19 +126,6 @@ dependencies = [
|
||||
"version_check 0.9.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"getrandom 0.2.8",
|
||||
"once_cell",
|
||||
"version_check 0.9.4",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.20"
|
||||
@ -161,12 +148,6 @@ dependencies = [
|
||||
"url 2.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "android-tzdata"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
@ -231,8 +212,8 @@ version = "0.1.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d1d8ab452a3936018a687b20e6f7cf5363d713b732b8884001317b0e48aa3"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.75",
|
||||
"quote 1.0.35",
|
||||
"proc-macro2 1.0.49",
|
||||
"quote 1.0.23",
|
||||
"syn 1.0.107",
|
||||
]
|
||||
|
||||
@ -246,7 +227,7 @@ dependencies = [
|
||||
"derive_builder",
|
||||
"diligent-date-parser",
|
||||
"never",
|
||||
"quick-xml 0.27.1",
|
||||
"quick-xml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -260,20 +241,6 @@ dependencies = [
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "attohttpc"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fcf00bc6d5abb29b5f97e3c61a90b6d3caa12f3faf897d4a3e3607c050a35a7"
|
||||
dependencies = [
|
||||
"http 0.2.8",
|
||||
"log 0.4.17",
|
||||
"native-tls",
|
||||
"serde 1.0.152",
|
||||
"serde_json",
|
||||
"url 2.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
@ -300,32 +267,6 @@ version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "aws-creds"
|
||||
version = "0.34.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3776743bb68d4ad02ba30ba8f64373f1be4e082fe47651767171ce75bb2f6cf5"
|
||||
dependencies = [
|
||||
"attohttpc",
|
||||
"dirs",
|
||||
"log 0.4.17",
|
||||
"quick-xml 0.26.0",
|
||||
"rust-ini 0.18.0",
|
||||
"serde 1.0.152",
|
||||
"thiserror",
|
||||
"time 0.3.17",
|
||||
"url 2.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-region"
|
||||
version = "0.25.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "056557a61427d0e5ba29dd931031c8ffed4ee7a550e7cd55692a9d8deb0a9dba"
|
||||
dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.1.8"
|
||||
@ -448,25 +389,6 @@ dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block_on_proc"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b872f3528eeeb4370ee73b51194dc1cd93680c2d0eb6c7a223889038d2c1a167"
|
||||
dependencies = [
|
||||
"quote 1.0.35",
|
||||
"syn 1.0.107",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blowfish"
|
||||
version = "0.9.1"
|
||||
@ -572,17 +494,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.31"
|
||||
version = "0.4.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
|
||||
checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-integer",
|
||||
"num-traits 0.2.15",
|
||||
"serde 1.0.152",
|
||||
"time 0.1.45",
|
||||
"wasm-bindgen",
|
||||
"windows-targets",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -655,7 +578,7 @@ checksum = "19b076e143e1d9538dde65da30f8481c2a6c44040edb8e02b9bf1351edb92ce3"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"nom 5.1.2",
|
||||
"rust-ini 0.13.0",
|
||||
"rust-ini",
|
||||
"serde 1.0.152",
|
||||
"serde-hjson",
|
||||
"serde_json",
|
||||
@ -713,10 +636,10 @@ dependencies = [
|
||||
"aes-gcm",
|
||||
"base64 0.13.1",
|
||||
"hkdf",
|
||||
"hmac 0.10.1",
|
||||
"hmac",
|
||||
"percent-encoding 2.2.0",
|
||||
"rand 0.8.5",
|
||||
"sha2 0.9.9",
|
||||
"sha2",
|
||||
"time 0.1.45",
|
||||
]
|
||||
|
||||
@ -999,8 +922,8 @@ dependencies = [
|
||||
"cc",
|
||||
"codespan-reporting",
|
||||
"once_cell",
|
||||
"proc-macro2 1.0.75",
|
||||
"quote 1.0.35",
|
||||
"proc-macro2 1.0.49",
|
||||
"quote 1.0.23",
|
||||
"scratch",
|
||||
"syn 1.0.107",
|
||||
]
|
||||
@ -1017,8 +940,8 @@ version = "1.0.85"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e7e2adeb6a0d4a282e581096b06e1791532b7d576dcde5ccd9382acf55db8e6"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.75",
|
||||
"quote 1.0.35",
|
||||
"proc-macro2 1.0.49",
|
||||
"quote 1.0.23",
|
||||
"syn 1.0.107",
|
||||
]
|
||||
|
||||
@ -1040,8 +963,8 @@ checksum = "a784d2ccaf7c98501746bf0be29b2022ba41fd62a2e622af997a03e9f972859f"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2 1.0.75",
|
||||
"quote 1.0.35",
|
||||
"proc-macro2 1.0.49",
|
||||
"quote 1.0.23",
|
||||
"strsim 0.10.0",
|
||||
"syn 1.0.107",
|
||||
]
|
||||
@ -1053,7 +976,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7618812407e9402654622dd402b0a89dff9ba93badd6540781526117b92aab7e"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote 1.0.35",
|
||||
"quote 1.0.23",
|
||||
"syn 1.0.107",
|
||||
]
|
||||
|
||||
@ -1115,8 +1038,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"proc-macro2 1.0.75",
|
||||
"quote 1.0.35",
|
||||
"proc-macro2 1.0.49",
|
||||
"quote 1.0.23",
|
||||
"syn 1.0.107",
|
||||
]
|
||||
|
||||
@ -1194,8 +1117,8 @@ version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.75",
|
||||
"quote 1.0.35",
|
||||
"proc-macro2 1.0.49",
|
||||
"quote 1.0.23",
|
||||
"syn 1.0.107",
|
||||
]
|
||||
|
||||
@ -1218,17 +1141,6 @@ dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
|
||||
dependencies = [
|
||||
"block-buffer 0.10.4",
|
||||
"crypto-common",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diligent-date-parser"
|
||||
version = "0.1.4"
|
||||
@ -1238,32 +1150,6 @@ dependencies = [
|
||||
"chrono",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs"
|
||||
version = "4.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
|
||||
dependencies = [
|
||||
"dirs-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"redox_users",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dlv-list"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257"
|
||||
|
||||
[[package]]
|
||||
name = "dotenv"
|
||||
version = "0.15.0"
|
||||
@ -1409,8 +1295,8 @@ version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.75",
|
||||
"quote 1.0.35",
|
||||
"proc-macro2 1.0.49",
|
||||
"quote 1.0.23",
|
||||
"syn 1.0.107",
|
||||
"synstructure",
|
||||
]
|
||||
@ -1630,8 +1516,8 @@ version = "0.3.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.75",
|
||||
"quote 1.0.35",
|
||||
"proc-macro2 1.0.49",
|
||||
"quote 1.0.23",
|
||||
"syn 1.0.107",
|
||||
]
|
||||
|
||||
@ -1717,8 +1603,8 @@ checksum = "649db3b5cda06091ea6aacb9f66f7002dfe885505b324b8ed795261253ffc2b3"
|
||||
dependencies = [
|
||||
"gettext",
|
||||
"gettext-utils",
|
||||
"proc-macro2 1.0.75",
|
||||
"quote 1.0.35",
|
||||
"proc-macro2 1.0.49",
|
||||
"quote 1.0.23",
|
||||
"syn 1.0.107",
|
||||
]
|
||||
|
||||
@ -1877,12 +1763,6 @@ dependencies = [
|
||||
"ahash 0.7.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
@ -1894,9 +1774,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.3.9"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
||||
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hex"
|
||||
@ -1910,8 +1793,8 @@ version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51ab2f639c231793c5f6114bdb9bbe50a7dbbfcd7c7c6bd8475dec2d991e964f"
|
||||
dependencies = [
|
||||
"digest 0.9.0",
|
||||
"hmac 0.10.1",
|
||||
"digest",
|
||||
"hmac",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1921,16 +1804,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15"
|
||||
dependencies = [
|
||||
"crypto-mac",
|
||||
"digest 0.9.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hmac"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
|
||||
dependencies = [
|
||||
"digest 0.10.6",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1952,8 +1826,8 @@ dependencies = [
|
||||
"log 0.4.17",
|
||||
"mac",
|
||||
"markup5ever",
|
||||
"proc-macro2 1.0.75",
|
||||
"quote 1.0.35",
|
||||
"proc-macro2 1.0.49",
|
||||
"quote 1.0.23",
|
||||
"syn 1.0.107",
|
||||
]
|
||||
|
||||
@ -2675,17 +2549,6 @@ version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
|
||||
|
||||
[[package]]
|
||||
name = "maybe-async"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f1b8c13cb1f814b634a96b2c725449fe7ed464a7b8781de8688be5ffbd3f305"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.75",
|
||||
"quote 1.0.35",
|
||||
"syn 1.0.107",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "maybe-uninit"
|
||||
version = "2.0.0"
|
||||
@ -2748,8 +2611,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9753f12909fd8d923f75ae5c3258cae1ed3c8ec052e1b38c93c21a6d157f789c"
|
||||
dependencies = [
|
||||
"migrations_internals",
|
||||
"proc-macro2 1.0.75",
|
||||
"quote 1.0.35",
|
||||
"proc-macro2 1.0.49",
|
||||
"quote 1.0.23",
|
||||
"syn 1.0.107",
|
||||
]
|
||||
|
||||
@ -2778,15 +2641,6 @@ dependencies = [
|
||||
"unicase 2.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minidom"
|
||||
version = "0.15.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e9ce45d459e358790a285e7609ff5ae4cfab88b75f237e8838e62029dda397b"
|
||||
dependencies = [
|
||||
"rxml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
@ -3113,11 +2967,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.16.0"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
|
||||
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
|
||||
dependencies = [
|
||||
"hermit-abi 0.3.9",
|
||||
"hermit-abi 0.2.6",
|
||||
"libc",
|
||||
]
|
||||
|
||||
@ -3185,8 +3039,8 @@ version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.75",
|
||||
"quote 1.0.35",
|
||||
"proc-macro2 1.0.49",
|
||||
"quote 1.0.23",
|
||||
"syn 1.0.107",
|
||||
]
|
||||
|
||||
@ -3209,16 +3063,6 @@ dependencies = [
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ordered-multimap"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccd746e37177e1711c20dd619a1620f34f5c8b569c53590a72dedd5344d8924a"
|
||||
dependencies = [
|
||||
"dlv-list",
|
||||
"hashbrown 0.12.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "overload"
|
||||
version = "0.1.1"
|
||||
@ -3379,8 +3223,8 @@ version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.75",
|
||||
"quote 1.0.35",
|
||||
"proc-macro2 1.0.49",
|
||||
"quote 1.0.23",
|
||||
"syn 1.0.107",
|
||||
]
|
||||
|
||||
@ -3424,7 +3268,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "plume"
|
||||
version = "0.7.3-dev-fork"
|
||||
version = "0.7.3-dev"
|
||||
dependencies = [
|
||||
"activitystreams",
|
||||
"atom_syndication",
|
||||
@ -3540,7 +3384,6 @@ name = "plume-models"
|
||||
version = "0.7.2"
|
||||
dependencies = [
|
||||
"activitystreams",
|
||||
"ahash 0.8.6",
|
||||
"ammonia",
|
||||
"assert-json-diff",
|
||||
"bcrypt",
|
||||
@ -3550,7 +3393,6 @@ dependencies = [
|
||||
"diesel_migrations",
|
||||
"glob",
|
||||
"guid-create",
|
||||
"heck",
|
||||
"itertools 0.10.5",
|
||||
"lazy_static",
|
||||
"ldap3",
|
||||
@ -3567,7 +3409,6 @@ dependencies = [
|
||||
"riker",
|
||||
"rocket",
|
||||
"rocket_i18n",
|
||||
"rust-s3",
|
||||
"scheduled-thread-pool",
|
||||
"serde 1.0.152",
|
||||
"serde_derive",
|
||||
@ -3620,8 +3461,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2 1.0.75",
|
||||
"quote 1.0.35",
|
||||
"proc-macro2 1.0.49",
|
||||
"quote 1.0.23",
|
||||
"syn 1.0.107",
|
||||
"version_check 0.9.4",
|
||||
]
|
||||
@ -3632,8 +3473,8 @@ version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.75",
|
||||
"quote 1.0.35",
|
||||
"proc-macro2 1.0.49",
|
||||
"quote 1.0.23",
|
||||
"version_check 0.9.4",
|
||||
]
|
||||
|
||||
@ -3678,9 +3519,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.75"
|
||||
version = "1.0.49"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "907a61bd0f64c2f29cd1cf1dc34d05176426a3f504a78010f08416ddb7b13708"
|
||||
checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@ -3711,16 +3552,6 @@ version = "1.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.26.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f50b1c63b38611e7d4d7f68b82d3ad0cc71a2ad2e7f61fc10f1328d917c93cd"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"serde 1.0.152",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.27.1"
|
||||
@ -3751,11 +3582,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.35"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.75",
|
||||
"proc-macro2 1.0.49",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4005,17 +3836,6 @@ dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
|
||||
dependencies = [
|
||||
"getrandom 0.2.8",
|
||||
"redox_syscall 0.2.16",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.7.0"
|
||||
@ -4147,7 +3967,6 @@ dependencies = [
|
||||
"tokio 1.24.1",
|
||||
"tokio-native-tls",
|
||||
"tokio-socks",
|
||||
"tokio-util 0.7.4",
|
||||
"tower-service",
|
||||
"url 2.3.1",
|
||||
"wasm-bindgen",
|
||||
@ -4340,50 +4159,6 @@ version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e52c148ef37f8c375d49d5a73aa70713125b7f19095948a923f80afdeb22ec2"
|
||||
|
||||
[[package]]
|
||||
name = "rust-ini"
|
||||
version = "0.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6d5f2436026b4f6e79dc829837d467cc7e9a55ee40e750d716713540715a2df"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"ordered-multimap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-s3"
|
||||
version = "0.33.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b2ac5ff6acfbe74226fa701b5ef793aaa054055c13ebb7060ad36942956e027"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"aws-creds",
|
||||
"aws-region",
|
||||
"base64 0.13.1",
|
||||
"block_on_proc",
|
||||
"bytes 1.3.0",
|
||||
"cfg-if 1.0.0",
|
||||
"futures 0.3.25",
|
||||
"hex",
|
||||
"hmac 0.12.1",
|
||||
"http 0.2.8",
|
||||
"log 0.4.17",
|
||||
"maybe-async",
|
||||
"md5",
|
||||
"minidom",
|
||||
"percent-encoding 2.2.0",
|
||||
"quick-xml 0.26.0",
|
||||
"reqwest 0.11.13",
|
||||
"serde 1.0.152",
|
||||
"serde_derive",
|
||||
"sha2 0.10.6",
|
||||
"thiserror",
|
||||
"time 0.3.17",
|
||||
"tokio 1.24.1",
|
||||
"tokio-stream",
|
||||
"url 2.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-stemmers"
|
||||
version = "1.2.0"
|
||||
@ -4409,25 +4184,6 @@ dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rxml"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a071866b8c681dc2cfffa77184adc32b57b0caad4e620b6292609703bceb804"
|
||||
dependencies = [
|
||||
"bytes 1.3.0",
|
||||
"pin-project-lite 0.2.9",
|
||||
"rxml_validation",
|
||||
"smartstring",
|
||||
"tokio 1.24.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rxml_validation"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53bc79743f9a66c2fb1f951cd83735f275d46bfe466259fbc5897bb60a0d00ee"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.12"
|
||||
@ -4461,9 +4217,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "scheduled-thread-pool"
|
||||
version = "0.2.7"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3cbc66816425a074528352f5789333ecff06ca41b36b0b0efdfbb29edc391a19"
|
||||
checksum = "977a7519bff143a44f842fd07e80ad1329295bd71686457f18e496736f4bf9bf"
|
||||
dependencies = [
|
||||
"parking_lot 0.12.1",
|
||||
]
|
||||
@ -4552,8 +4308,8 @@ version = "1.0.152"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.75",
|
||||
"quote 1.0.35",
|
||||
"proc-macro2 1.0.49",
|
||||
"quote 1.0.23",
|
||||
"syn 1.0.107",
|
||||
]
|
||||
|
||||
@ -4607,24 +4363,13 @@ version = "0.9.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800"
|
||||
dependencies = [
|
||||
"block-buffer 0.9.0",
|
||||
"block-buffer",
|
||||
"cfg-if 1.0.0",
|
||||
"cpufeatures",
|
||||
"digest 0.9.0",
|
||||
"digest",
|
||||
"opaque-debug",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cpufeatures",
|
||||
"digest 0.10.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sharded-slab"
|
||||
version = "0.1.4"
|
||||
@ -4642,8 +4387,8 @@ checksum = "e63e6744142336dfb606fe2b068afa2e1cca1ee6a5d8377277a92945d81fa331"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"itertools 0.8.2",
|
||||
"proc-macro2 1.0.75",
|
||||
"quote 1.0.35",
|
||||
"proc-macro2 1.0.49",
|
||||
"quote 1.0.23",
|
||||
"syn 1.0.107",
|
||||
]
|
||||
|
||||
@ -4714,15 +4459,6 @@ version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
|
||||
|
||||
[[package]]
|
||||
name = "smartstring"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e714dff2b33f2321fdcd475b71cec79781a692d846f37f415fb395a1d2bcd48e"
|
||||
dependencies = [
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "snap"
|
||||
version = "1.1.0"
|
||||
@ -4814,8 +4550,8 @@ checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988"
|
||||
dependencies = [
|
||||
"phf_generator",
|
||||
"phf_shared",
|
||||
"proc-macro2 1.0.75",
|
||||
"quote 1.0.35",
|
||||
"proc-macro2 1.0.49",
|
||||
"quote 1.0.23",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4875,19 +4611,8 @@ version = "1.0.107"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.75",
|
||||
"quote 1.0.35",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.48"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.75",
|
||||
"quote 1.0.35",
|
||||
"proc-macro2 1.0.49",
|
||||
"quote 1.0.23",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
@ -4897,8 +4622,8 @@ version = "0.12.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.75",
|
||||
"quote 1.0.35",
|
||||
"proc-macro2 1.0.49",
|
||||
"quote 1.0.23",
|
||||
"syn 1.0.107",
|
||||
"unicode-xid 0.2.4",
|
||||
]
|
||||
@ -5120,8 +4845,8 @@ version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.75",
|
||||
"quote 1.0.35",
|
||||
"proc-macro2 1.0.49",
|
||||
"quote 1.0.23",
|
||||
"syn 1.0.107",
|
||||
]
|
||||
|
||||
@ -5307,8 +5032,8 @@ version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e44da00bfc73a25f814cd8d7e57a68a5c31b74b3152a0a1d1f590c97ed06265a"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.75",
|
||||
"quote 1.0.35",
|
||||
"proc-macro2 1.0.49",
|
||||
"quote 1.0.23",
|
||||
"syn 1.0.107",
|
||||
]
|
||||
|
||||
@ -5318,8 +5043,8 @@ version = "1.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.75",
|
||||
"quote 1.0.35",
|
||||
"proc-macro2 1.0.49",
|
||||
"quote 1.0.23",
|
||||
"syn 1.0.107",
|
||||
]
|
||||
|
||||
@ -5509,8 +5234,8 @@ version = "0.1.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.75",
|
||||
"quote 1.0.35",
|
||||
"proc-macro2 1.0.49",
|
||||
"quote 1.0.23",
|
||||
"syn 1.0.107",
|
||||
]
|
||||
|
||||
@ -5752,8 +5477,8 @@ dependencies = [
|
||||
"if_chain",
|
||||
"lazy_static",
|
||||
"proc-macro-error",
|
||||
"proc-macro2 1.0.75",
|
||||
"quote 1.0.35",
|
||||
"proc-macro2 1.0.49",
|
||||
"quote 1.0.23",
|
||||
"regex",
|
||||
"syn 1.0.107",
|
||||
"validator_types",
|
||||
@ -5765,7 +5490,7 @@ version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2ddf34293296847abfc1493b15c6e2f5d3cd19f57ad7d22673bf4c6278da329"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.75",
|
||||
"proc-macro2 1.0.49",
|
||||
"syn 1.0.107",
|
||||
]
|
||||
|
||||
@ -5876,8 +5601,8 @@ dependencies = [
|
||||
"bumpalo",
|
||||
"log 0.4.17",
|
||||
"once_cell",
|
||||
"proc-macro2 1.0.75",
|
||||
"quote 1.0.35",
|
||||
"proc-macro2 1.0.49",
|
||||
"quote 1.0.23",
|
||||
"syn 1.0.107",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
@ -5900,7 +5625,7 @@ version = "0.2.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
|
||||
dependencies = [
|
||||
"quote 1.0.35",
|
||||
"quote 1.0.23",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
@ -5910,8 +5635,8 @@ version = "0.2.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.75",
|
||||
"quote 1.0.35",
|
||||
"proc-macro2 1.0.49",
|
||||
"quote 1.0.23",
|
||||
"syn 1.0.107",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
@ -6016,42 +5741,21 @@ version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.42.0",
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc 0.42.0",
|
||||
"windows_i686_gnu 0.42.0",
|
||||
"windows_i686_msvc 0.42.0",
|
||||
"windows_x86_64_gnu 0.42.0",
|
||||
"windows_x86_64_gnullvm 0.42.0",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc 0.42.0",
|
||||
]
|
||||
|
||||
[[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]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
|
||||
|
||||
[[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_msvc"
|
||||
version = "0.36.1"
|
||||
@ -6064,12 +5768,6 @@ version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.36.1"
|
||||
@ -6082,12 +5780,6 @@ version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
|
||||
|
||||
[[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_msvc"
|
||||
version = "0.36.1"
|
||||
@ -6100,12 +5792,6 @@ version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.36.1"
|
||||
@ -6118,24 +5804,12 @@ version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
|
||||
|
||||
[[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_gnullvm"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
|
||||
|
||||
[[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_msvc"
|
||||
version = "0.36.1"
|
||||
@ -6148,12 +5822,6 @@ version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.6.2"
|
||||
@ -6236,26 +5904,6 @@ version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.7.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.7.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.75",
|
||||
"quote 1.0.35",
|
||||
"syn 2.0.48",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeroize"
|
||||
version = "1.5.7"
|
||||
|
15
Cargo.toml
15
Cargo.toml
@ -1,9 +1,9 @@
|
||||
[package]
|
||||
authors = ["Plume contributors"]
|
||||
name = "plume"
|
||||
version = "0.7.3-dev-fork"
|
||||
repository = "https://git.lainoa.eus/aitzol/Plume"
|
||||
edition = "2021"
|
||||
version = "0.7.3-dev"
|
||||
repository = "https://github.com/Plume-org/Plume"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
atom_syndication = "0.12.0"
|
||||
@ -14,11 +14,11 @@ gettext-macros = "0.6.1"
|
||||
gettext-utils = "0.1.0"
|
||||
guid-create = "0.2"
|
||||
lettre_email = "0.9.2"
|
||||
num_cpus = "1.16.0"
|
||||
num_cpus = "1.10"
|
||||
rocket = "0.4.11"
|
||||
rocket_contrib = { version = "0.4.11", features = ["json"] }
|
||||
rocket_i18n = "0.4.1"
|
||||
scheduled-thread-pool = "0.2.7"
|
||||
scheduled-thread-pool = "0.2.6"
|
||||
serde = "1.0.137"
|
||||
serde_json = "1.0.81"
|
||||
shrinkwraprs = "0.3.0"
|
||||
@ -35,7 +35,7 @@ path = "src/main.rs"
|
||||
|
||||
[dependencies.chrono]
|
||||
features = ["serde"]
|
||||
version = "0.4.31"
|
||||
version = "0.4"
|
||||
|
||||
[dependencies.ctrlc]
|
||||
features = ["termination"]
|
||||
@ -68,13 +68,12 @@ ructe = "0.15.0"
|
||||
rsass = "0.26"
|
||||
|
||||
[features]
|
||||
default = ["postgres", "s3"]
|
||||
default = ["postgres"]
|
||||
postgres = ["plume-models/postgres", "diesel/postgres"]
|
||||
sqlite = ["plume-models/sqlite", "diesel/sqlite"]
|
||||
debug-mailer = []
|
||||
test = []
|
||||
search-lindera = ["plume-models/search-lindera"]
|
||||
s3 = ["plume-models/s3"]
|
||||
|
||||
[workspace]
|
||||
members = ["plume-api", "plume-cli", "plume-models", "plume-common", "plume-front", "plume-macro"]
|
||||
|
@ -30,7 +30,8 @@ FROM debian:stable-slim
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
ca-certificates \
|
||||
libpq5
|
||||
libpq5 \
|
||||
libssl1.1
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
|
@ -228,7 +228,7 @@ main .article-meta {
|
||||
fill: currentColor;
|
||||
}
|
||||
.action.liked:hover svg.feather {
|
||||
background: transparentize($red, 0.75);
|
||||
background: transparentize($red, 0.75)
|
||||
color: $red;
|
||||
}
|
||||
}
|
||||
@ -252,7 +252,7 @@ main .article-meta {
|
||||
background: $primary;
|
||||
}
|
||||
.action.reshared:hover svg.feather {
|
||||
background: transparentize($primary, 0.75);
|
||||
background: transparentize($primary, 0.75)
|
||||
color: $primary;
|
||||
}
|
||||
}
|
||||
|
116
flake.lock
116
flake.lock
@ -1,116 +0,0 @@
|
||||
{
|
||||
"nodes": {
|
||||
"flake-utils": {
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"flake-utils_2": {
|
||||
"inputs": {
|
||||
"systems": "systems_2"
|
||||
},
|
||||
"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": 1683408522,
|
||||
"narHash": "sha256-9kcPh6Uxo17a3kK3XCHhcWiV1Yu1kYj22RHiymUhMkU=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "897876e4c484f1e8f92009fd11b7d988a121a4e7",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"rust-overlay": "rust-overlay"
|
||||
}
|
||||
},
|
||||
"rust-overlay": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils_2",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1683857898,
|
||||
"narHash": "sha256-pyVY4UxM6zUX97g6bk6UyCbZGCWZb2Zykrne8YxacRA=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "4e7fba3f37f5e184ada0ef3cf1e4d8ef450f240b",
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"systems_2": {
|
||||
"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
|
||||
}
|
60
flake.nix
60
flake.nix
@ -1,60 +0,0 @@
|
||||
{
|
||||
description = "Developpment shell for Plume including nightly Rust compiler";
|
||||
|
||||
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
inputs.rust-overlay = {
|
||||
url = "github:oxalica/rust-overlay";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
inputs.flake-utils.url = "github:numtide/flake-utils";
|
||||
|
||||
outputs = { self, nixpkgs, flake-utils, rust-overlay, ... }:
|
||||
flake-utils.lib.eachDefaultSystem (system:
|
||||
let
|
||||
overlays = [ (import rust-overlay) ];
|
||||
pkgs = import nixpkgs { inherit system overlays; };
|
||||
inputs = with pkgs; [
|
||||
(rust-bin.nightly.latest.default.override {
|
||||
targets = [ "wasm32-unknown-unknown" ];
|
||||
})
|
||||
wasm-pack
|
||||
openssl
|
||||
pkg-config
|
||||
gettext
|
||||
postgresql
|
||||
sqlite
|
||||
];
|
||||
in {
|
||||
packages.default = pkgs.rustPlatform.buildRustPackage {
|
||||
pname = "plume";
|
||||
version = "0.7.3-dev";
|
||||
|
||||
src = ./.;
|
||||
|
||||
cargoLock = {
|
||||
lockFile = ./Cargo.lock;
|
||||
outputHashes = {
|
||||
"pulldown-cmark-0.8.0" = "sha256-lpfoRDuY3zJ3QmUqJ5k9OL0MEdGDpwmpJ+u5BCj2kIA=";
|
||||
"rocket_csrf-0.1.2" = "sha256-WywZfMiwZqTPfSDcAE7ivTSYSaFX+N9fjnRsLSLb9wE=";
|
||||
};
|
||||
};
|
||||
buildNoDefaultFeatures = true;
|
||||
buildFeatures = ["postgresql" "s3"];
|
||||
|
||||
nativeBuildInputs = inputs;
|
||||
|
||||
buildPhase = ''
|
||||
wasm-pack build --target web --release plume-front
|
||||
cargo build --no-default-features --features postgresql,s3 --path .
|
||||
cargo build --no-default-features --features postgresql,s3 --path plume-cli
|
||||
'';
|
||||
installPhase = ''
|
||||
cargo install --no-default-features --features postgresql,s3 --path . --target-dir $out
|
||||
cargo install --no-default-features --features postgresql,s3 --path plume-cli --target-dir $out
|
||||
'';
|
||||
};
|
||||
devShells.default = pkgs.mkShell {
|
||||
packages = inputs;
|
||||
};
|
||||
});
|
||||
}
|
@ -24,4 +24,3 @@ path = "../plume-models"
|
||||
postgres = ["plume-models/postgres", "diesel/postgres"]
|
||||
sqlite = ["plume-models/sqlite", "diesel/sqlite"]
|
||||
search-lindera = ["plume-models/search-lindera"]
|
||||
s3 = ["plume-models/s3"]
|
||||
|
@ -28,7 +28,7 @@ futures = "0.3.25"
|
||||
|
||||
[dependencies.chrono]
|
||||
features = ["serde"]
|
||||
version = "0.4.31"
|
||||
version = "0.4"
|
||||
|
||||
[dependencies.pulldown-cmark]
|
||||
default-features = false
|
||||
|
@ -16,9 +16,8 @@ openssl = "0.10.40"
|
||||
rocket = "0.4.11"
|
||||
rocket_i18n = "0.4.1"
|
||||
reqwest = "0.11.11"
|
||||
scheduled-thread-pool = "0.2.7"
|
||||
scheduled-thread-pool = "0.2.6"
|
||||
serde = "1.0.137"
|
||||
rust-s3 = { version = "0.33.0", optional = true, features = ["blocking"] }
|
||||
serde_derive = "1.0"
|
||||
serde_json = "1.0.81"
|
||||
tantivy = "0.13.3"
|
||||
@ -36,12 +35,10 @@ once_cell = "1.12.0"
|
||||
lettre = "0.9.6"
|
||||
native-tls = "0.2.10"
|
||||
activitystreams = "=0.7.0-alpha.20"
|
||||
ahash = "=0.8.6"
|
||||
heck = "0.4.1"
|
||||
|
||||
[dependencies.chrono]
|
||||
features = ["serde"]
|
||||
version = "0.4.31"
|
||||
version = "0.4"
|
||||
|
||||
[dependencies.diesel]
|
||||
features = ["r2d2", "chrono"]
|
||||
@ -64,4 +61,3 @@ diesel_migrations = "1.3.0"
|
||||
postgres = ["diesel/postgres", "plume-macro/postgres" ]
|
||||
sqlite = ["diesel/sqlite", "plume-macro/sqlite" ]
|
||||
search-lindera = ["lindera-tantivy"]
|
||||
s3 = ["rust-s3"]
|
||||
|
@ -5,7 +5,7 @@ use rocket::{
|
||||
Outcome,
|
||||
};
|
||||
|
||||
/// Wrapper around User to use as a request guard on pages exclusively reserved to admins.
|
||||
/// Wrapper around User to use as a request guard on pages reserved to admins.
|
||||
pub struct Admin(pub User);
|
||||
|
||||
impl<'a, 'r> FromRequest<'a, 'r> for Admin {
|
||||
@ -21,23 +21,6 @@ impl<'a, 'r> FromRequest<'a, 'r> for Admin {
|
||||
}
|
||||
}
|
||||
|
||||
/// Same as `Admin` but it forwards to next guard if the user is not an admin.
|
||||
/// It's useful when there are multiple implementations of routes for admin and moderator.
|
||||
pub struct InclusiveAdmin(pub User);
|
||||
|
||||
impl<'a, 'r> FromRequest<'a, 'r> for InclusiveAdmin {
|
||||
type Error = ();
|
||||
|
||||
fn from_request(request: &'a Request<'r>) -> request::Outcome<InclusiveAdmin, ()> {
|
||||
let user = request.guard::<User>()?;
|
||||
if user.is_admin() {
|
||||
Outcome::Success(InclusiveAdmin(user))
|
||||
} else {
|
||||
Outcome::Forward(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Same as `Admin` but for moderators.
|
||||
pub struct Moderator(pub User);
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
use heck::ToUpperCamelCase;
|
||||
use crate::{
|
||||
instance::*, medias::Media, posts::Post, safe_string::SafeString, schema::blogs, users::User,
|
||||
Connection, Error, PlumeRocket, Result, CONFIG, ITEMS_PER_PAGE,
|
||||
@ -103,18 +102,9 @@ impl Blog {
|
||||
find_by!(blogs, find_by_ap_url, ap_url as &str);
|
||||
find_by!(blogs, find_by_name, actor_id as &str, instance_id as i32);
|
||||
|
||||
/// Remove non alphanumeric characters and CamelCase a string
|
||||
pub fn slug(title: &str) -> String {
|
||||
title.to_upper_camel_case()
|
||||
.chars()
|
||||
.filter(|c| c.is_alphanumeric())
|
||||
.collect()
|
||||
}
|
||||
/*
|
||||
pub fn slug(title: &str) -> &str {
|
||||
title
|
||||
}
|
||||
*/
|
||||
|
||||
pub fn get_instance(&self, conn: &Connection) -> Result<Instance> {
|
||||
Instance::get(conn, self.instance_id)
|
||||
|
@ -136,7 +136,7 @@ impl Comment {
|
||||
|id| Comment::get(conn, id).map(|comment| comment.ap_url.unwrap_or_default()),
|
||||
)?);
|
||||
note.set_published(
|
||||
OffsetDateTime::from_unix_timestamp_nanos(self.creation_date.timestamp_nanos_opt().unwrap().into())
|
||||
OffsetDateTime::from_unix_timestamp_nanos(self.creation_date.timestamp_nanos().into())
|
||||
.expect("OffsetDateTime"),
|
||||
);
|
||||
note.set_attributed_to(author.into_id().parse::<IriString>()?);
|
||||
|
@ -6,9 +6,6 @@ use rocket::Config as RocketConfig;
|
||||
use std::collections::HashSet;
|
||||
use std::env::{self, var};
|
||||
|
||||
#[cfg(feature = "s3")]
|
||||
use s3::{Bucket, Region, creds::Credentials};
|
||||
|
||||
#[cfg(not(test))]
|
||||
const DB_NAME: &str = "plume";
|
||||
#[cfg(test)]
|
||||
@ -30,23 +27,13 @@ pub struct Config {
|
||||
pub mail: Option<MailConfig>,
|
||||
pub ldap: Option<LdapConfig>,
|
||||
pub proxy: Option<ProxyConfig>,
|
||||
pub s3: Option<S3Config>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn proxy(&self) -> Option<&reqwest::Proxy> {
|
||||
self.proxy.as_ref().map(|p| &p.proxy)
|
||||
}
|
||||
}
|
||||
|
||||
fn string_to_bool(val: &str, name: &str) -> bool {
|
||||
match val {
|
||||
"1" | "true" | "TRUE" => true,
|
||||
"0" | "false" | "FALSE" => false,
|
||||
_ => panic!("Invalid configuration: {} is not boolean", name),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum InvalidRocketConfig {
|
||||
Env,
|
||||
@ -293,7 +280,6 @@ pub struct LdapConfig {
|
||||
pub tls: bool,
|
||||
pub user_name_attr: String,
|
||||
pub mail_attr: String,
|
||||
pub user: Option<(String, String)>,
|
||||
}
|
||||
|
||||
fn get_ldap_config() -> Option<LdapConfig> {
|
||||
@ -302,29 +288,23 @@ fn get_ldap_config() -> Option<LdapConfig> {
|
||||
match (addr, base_dn) {
|
||||
(Some(addr), Some(base_dn)) => {
|
||||
let tls = var("LDAP_TLS").unwrap_or_else(|_| "false".to_owned());
|
||||
let tls = string_to_bool(&tls, "LDAP_TLS");
|
||||
let tls = match tls.as_ref() {
|
||||
"1" | "true" | "TRUE" => true,
|
||||
"0" | "false" | "FALSE" => false,
|
||||
_ => panic!("Invalid LDAP configuration : tls"),
|
||||
};
|
||||
let user_name_attr = var("LDAP_USER_NAME_ATTR").unwrap_or_else(|_| "cn".to_owned());
|
||||
let mail_attr = var("LDAP_USER_MAIL_ATTR").unwrap_or_else(|_| "mail".to_owned());
|
||||
//2023-12-30
|
||||
let user = var("LDAP_USER").ok();
|
||||
let password = var("LDAP_PASSWORD").ok();
|
||||
let user = match (user, password) {
|
||||
(Some(user), Some(password)) => Some((user, password)),
|
||||
(None, None) => None,
|
||||
_ => panic!("Invalid LDAP configuration both or neither of LDAP_USER and LDAP_PASSWORD must be set")
|
||||
};
|
||||
//
|
||||
Some(LdapConfig {
|
||||
addr,
|
||||
base_dn,
|
||||
tls,
|
||||
user_name_attr,
|
||||
mail_attr,
|
||||
user,
|
||||
})
|
||||
}
|
||||
(None, None) => None,
|
||||
_ => {
|
||||
(_, _) => {
|
||||
panic!("Invalid LDAP configuration : both LDAP_ADDR and LDAP_BASE_DN must be set")
|
||||
}
|
||||
}
|
||||
@ -369,104 +349,6 @@ fn get_proxy_config() -> Option<ProxyConfig> {
|
||||
})
|
||||
}
|
||||
|
||||
pub struct S3Config {
|
||||
pub bucket: String,
|
||||
pub access_key_id: String,
|
||||
pub access_key_secret: String,
|
||||
|
||||
// region? If not set, default to us-east-1
|
||||
pub region: String,
|
||||
// hostname for s3. If not set, default to $region.amazonaws.com
|
||||
pub hostname: String,
|
||||
// may be useful when using self hosted s3. Won't work with recent AWS buckets
|
||||
pub path_style: bool,
|
||||
// http or https
|
||||
pub protocol: String,
|
||||
|
||||
// download directly from s3 to user, wihout going through Plume. Require public read on bucket
|
||||
pub direct_download: bool,
|
||||
// use this hostname for downloads, can be used with caching proxy in front of s3 (expected to
|
||||
// be reachable through https)
|
||||
pub alias: Option<String>,
|
||||
}
|
||||
|
||||
impl S3Config {
|
||||
#[cfg(feature = "s3")]
|
||||
pub fn get_bucket(&self) -> Bucket {
|
||||
let region = Region::Custom {
|
||||
region: self.region.clone(),
|
||||
endpoint: format!("{}://{}", self.protocol, self.hostname),
|
||||
};
|
||||
let credentials = Credentials {
|
||||
access_key: Some(self.access_key_id.clone()),
|
||||
secret_key: Some(self.access_key_secret.clone()),
|
||||
security_token: None,
|
||||
session_token: None,
|
||||
expiration: None,
|
||||
};
|
||||
|
||||
let bucket = Bucket::new(&self.bucket, region, credentials).unwrap();
|
||||
if self.path_style {
|
||||
bucket.with_path_style()
|
||||
} else {
|
||||
bucket
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_s3_config() -> Option<S3Config> {
|
||||
let bucket = var("S3_BUCKET").ok();
|
||||
let access_key_id = var("AWS_ACCESS_KEY_ID").ok();
|
||||
let access_key_secret = var("AWS_SECRET_ACCESS_KEY").ok();
|
||||
if bucket.is_none() && access_key_id.is_none() && access_key_secret.is_none() {
|
||||
return None;
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "s3"))]
|
||||
panic!("S3 support is not enabled in this build");
|
||||
|
||||
#[cfg(feature = "s3")]
|
||||
{
|
||||
if bucket.is_none() || access_key_id.is_none() || access_key_secret.is_none() {
|
||||
panic!("Invalid S3 configuration: some required values are set, but not others");
|
||||
}
|
||||
let bucket = bucket.unwrap();
|
||||
let access_key_id = access_key_id.unwrap();
|
||||
let access_key_secret = access_key_secret.unwrap();
|
||||
|
||||
let region = var("S3_REGION").unwrap_or_else(|_| "us-east-1".to_owned());
|
||||
let hostname = var("S3_HOSTNAME").unwrap_or_else(|_| format!("{}.amazonaws.com", region));
|
||||
|
||||
let protocol = var("S3_PROTOCOL").unwrap_or_else(|_| "https".to_owned());
|
||||
if protocol != "http" && protocol != "https" {
|
||||
panic!("Invalid S3 configuration: invalid protocol {}", protocol);
|
||||
}
|
||||
|
||||
let path_style = var("S3_PATH_STYLE").unwrap_or_else(|_| "false".to_owned());
|
||||
let path_style = string_to_bool(&path_style, "S3_PATH_STYLE");
|
||||
let direct_download = var("S3_DIRECT_DOWNLOAD").unwrap_or_else(|_| "false".to_owned());
|
||||
let direct_download = string_to_bool(&direct_download, "S3_DIRECT_DOWNLOAD");
|
||||
|
||||
let alias = var("S3_ALIAS_HOST").ok();
|
||||
|
||||
if direct_download && protocol == "http" && alias.is_none() {
|
||||
panic!("S3 direct download is disabled because bucket is accessed through plain HTTP. Use HTTPS or set an alias hostname (S3_ALIAS_HOST).");
|
||||
}
|
||||
|
||||
Some(S3Config {
|
||||
bucket,
|
||||
access_key_id,
|
||||
access_key_secret,
|
||||
region,
|
||||
hostname,
|
||||
protocol,
|
||||
path_style,
|
||||
direct_download,
|
||||
alias,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref CONFIG: Config = Config {
|
||||
base_url: var("BASE_URL").unwrap_or_else(|_| format!(
|
||||
@ -498,6 +380,5 @@ lazy_static! {
|
||||
mail: get_mail_config(),
|
||||
ldap: get_ldap_config(),
|
||||
proxy: get_proxy_config(),
|
||||
s3: get_s3_config(),
|
||||
};
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ use activitystreams::activity::{Announce, Create, Delete, Follow, Like, Undo, Up
|
||||
|
||||
use crate::{
|
||||
comments::Comment,
|
||||
db_conn::DbConn,
|
||||
follows, likes,
|
||||
posts::{Post, PostUpdate},
|
||||
reshares::Reshare,
|
||||
|
@ -69,8 +69,6 @@ pub enum Error {
|
||||
Webfinger,
|
||||
Expired,
|
||||
UserAlreadyExists,
|
||||
#[cfg(feature = "s3")]
|
||||
S3(s3::error::S3Error),
|
||||
}
|
||||
|
||||
impl From<bcrypt::BcryptError> for Error {
|
||||
@ -172,13 +170,6 @@ impl From<request::Error> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "s3")]
|
||||
impl From<s3::error::S3Error> for Error {
|
||||
fn from(err: s3::error::S3Error) -> Error {
|
||||
Error::S3(err)
|
||||
}
|
||||
}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
/// Adds a function to a model, that returns the first
|
||||
|
@ -16,9 +16,6 @@ use std::{
|
||||
use tracing::warn;
|
||||
use url::Url;
|
||||
|
||||
#[cfg(feature = "s3")]
|
||||
use crate::config::S3Config;
|
||||
|
||||
const REMOTE_MEDIA_DIRECTORY: &str = "remote";
|
||||
|
||||
#[derive(Clone, Identifiable, Queryable, AsChangeset)]
|
||||
@ -108,7 +105,7 @@ impl Media {
|
||||
.file_path
|
||||
.rsplit_once('.')
|
||||
.map(|x| x.1)
|
||||
.unwrap_or("")
|
||||
.expect("Media::category: extension error")
|
||||
.to_lowercase()
|
||||
{
|
||||
"png" | "jpg" | "jpeg" | "gif" | "svg" => MediaCategory::Image,
|
||||
@ -154,99 +151,26 @@ impl Media {
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns full file path for medias stored in the local media directory.
|
||||
pub fn local_path(&self) -> Option<PathBuf> {
|
||||
if self.file_path.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
if CONFIG.s3.is_some() {
|
||||
#[cfg(feature="s3")]
|
||||
unreachable!("Called Media::local_path() but media are stored on S3");
|
||||
#[cfg(not(feature="s3"))]
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
let relative_path = self
|
||||
.file_path
|
||||
.trim_start_matches(&CONFIG.media_directory)
|
||||
.trim_start_matches(path::MAIN_SEPARATOR)
|
||||
.trim_start_matches("static/media/");
|
||||
|
||||
Some(Path::new(&CONFIG.media_directory).join(relative_path))
|
||||
}
|
||||
|
||||
/// Returns the relative URL to access this file, which is also the key at which
|
||||
/// it is stored in the S3 bucket if we are using S3 storage.
|
||||
/// Does not start with a '/', it is of the form "static/media/<...>"
|
||||
pub fn relative_url(&self) -> Option<String> {
|
||||
if self.file_path.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let relative_path = self
|
||||
.file_path
|
||||
.trim_start_matches(&CONFIG.media_directory)
|
||||
.replace(path::MAIN_SEPARATOR, "/");
|
||||
|
||||
let relative_path = relative_path
|
||||
.trim_start_matches('/')
|
||||
.trim_start_matches("static/media/");
|
||||
|
||||
Some(format!("static/media/{}", relative_path))
|
||||
}
|
||||
|
||||
/// Returns a public URL through which this media file can be accessed
|
||||
pub fn url(&self) -> Result<String> {
|
||||
if self.is_remote {
|
||||
Ok(self.remote_url.clone().unwrap_or_default())
|
||||
} else {
|
||||
let relative_url = self.relative_url().unwrap_or_default();
|
||||
|
||||
#[cfg(feature="s3")]
|
||||
if CONFIG.s3.as_ref().map(|x| x.direct_download).unwrap_or(false) {
|
||||
let s3_url = match CONFIG.s3.as_ref().unwrap() {
|
||||
S3Config { alias: Some(alias), .. } => {
|
||||
format!("https://{}/{}", alias, relative_url)
|
||||
}
|
||||
S3Config { path_style: true, hostname, bucket, .. } => {
|
||||
format!("https://{}/{}/{}",
|
||||
hostname,
|
||||
bucket,
|
||||
relative_url
|
||||
)
|
||||
}
|
||||
S3Config { path_style: false, hostname, bucket, .. } => {
|
||||
format!("https://{}.{}/{}",
|
||||
bucket,
|
||||
hostname,
|
||||
relative_url
|
||||
)
|
||||
}
|
||||
};
|
||||
return Ok(s3_url);
|
||||
}
|
||||
|
||||
let file_path = self.file_path.replace(path::MAIN_SEPARATOR, "/").replacen(
|
||||
&CONFIG.media_directory,
|
||||
"static/media",
|
||||
1,
|
||||
); // "static/media" from plume::routs::plume_media_files()
|
||||
Ok(ap_url(&format!(
|
||||
"{}/{}",
|
||||
Instance::get_local()?.public_domain,
|
||||
relative_url
|
||||
&file_path
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn delete(&self, conn: &Connection) -> Result<()> {
|
||||
if !self.is_remote {
|
||||
if CONFIG.s3.is_some() {
|
||||
#[cfg(not(feature="s3"))]
|
||||
unreachable!();
|
||||
|
||||
#[cfg(feature = "s3")]
|
||||
CONFIG.s3.as_ref().unwrap().get_bucket()
|
||||
.delete_object_blocking(&self.relative_url().ok_or(Error::NotFound)?)?;
|
||||
} else {
|
||||
fs::remove_file(self.local_path().ok_or(Error::NotFound)?)?;
|
||||
}
|
||||
fs::remove_file(self.file_path.as_str())?;
|
||||
}
|
||||
diesel::delete(self)
|
||||
.execute(conn)
|
||||
@ -287,60 +211,22 @@ impl Media {
|
||||
.url()
|
||||
.and_then(|url| url.to_as_uri())
|
||||
.ok_or(Error::MissingApProperty)?;
|
||||
let path = determine_mirror_file_path(&remote_url);
|
||||
let parent = path.parent().ok_or(Error::InvalidValue)?;
|
||||
if !parent.is_dir() {
|
||||
DirBuilder::new().recursive(true).create(parent)?;
|
||||
}
|
||||
|
||||
let file_path = if CONFIG.s3.is_some() {
|
||||
#[cfg(not(feature="s3"))]
|
||||
unreachable!();
|
||||
let mut dest = fs::File::create(path.clone())?;
|
||||
// TODO: conditional GET
|
||||
request::get(
|
||||
remote_url.as_str(),
|
||||
User::get_sender(),
|
||||
CONFIG.proxy().cloned(),
|
||||
)?
|
||||
.copy_to(&mut dest)?;
|
||||
|
||||
#[cfg(feature = "s3")]
|
||||
{
|
||||
use rocket::http::ContentType;
|
||||
|
||||
let dest = determine_mirror_s3_path(&remote_url);
|
||||
|
||||
let media = request::get(
|
||||
remote_url.as_str(),
|
||||
User::get_sender(),
|
||||
CONFIG.proxy().cloned(),
|
||||
)?;
|
||||
|
||||
let content_type = media
|
||||
.headers()
|
||||
.get(reqwest::header::CONTENT_TYPE)
|
||||
.and_then(|x| x.to_str().ok())
|
||||
.and_then(ContentType::parse_flexible)
|
||||
.unwrap_or(ContentType::Binary);
|
||||
|
||||
let bytes = media.bytes()?;
|
||||
|
||||
let bucket = CONFIG.s3.as_ref().unwrap().get_bucket();
|
||||
bucket.put_object_with_content_type_blocking(
|
||||
&dest,
|
||||
&bytes,
|
||||
&content_type.to_string()
|
||||
)?;
|
||||
|
||||
dest
|
||||
}
|
||||
} else {
|
||||
let path = determine_mirror_file_path(&remote_url);
|
||||
let parent = path.parent().ok_or(Error::InvalidValue)?;
|
||||
if !parent.is_dir() {
|
||||
DirBuilder::new().recursive(true).create(parent)?;
|
||||
}
|
||||
|
||||
let mut dest = fs::File::create(path.clone())?;
|
||||
// TODO: conditional GET
|
||||
request::get(
|
||||
remote_url.as_str(),
|
||||
User::get_sender(),
|
||||
CONFIG.proxy().cloned(),
|
||||
)?
|
||||
.copy_to(&mut dest)?;
|
||||
path.to_str().ok_or(Error::InvalidValue)?.to_string()
|
||||
};
|
||||
|
||||
Media::find_by_file_path(conn, &file_path)
|
||||
Media::find_by_file_path(conn, path.to_str().ok_or(Error::InvalidValue)?)
|
||||
.and_then(|mut media| {
|
||||
let mut updated = false;
|
||||
|
||||
@ -381,7 +267,7 @@ impl Media {
|
||||
Media::insert(
|
||||
conn,
|
||||
NewMedia {
|
||||
file_path,
|
||||
file_path: path.to_str().ok_or(Error::InvalidValue)?.to_string(),
|
||||
alt_text: image
|
||||
.content()
|
||||
.and_then(|content| content.to_as_string())
|
||||
@ -421,10 +307,12 @@ impl Media {
|
||||
}
|
||||
|
||||
fn determine_mirror_file_path(url: &str) -> PathBuf {
|
||||
let mut file_path = Path::new(&CONFIG.media_directory).join(REMOTE_MEDIA_DIRECTORY);
|
||||
|
||||
match Url::parse(url) {
|
||||
Ok(url) if url.has_host() => {
|
||||
let mut file_path = Path::new(&super::CONFIG.media_directory).join(REMOTE_MEDIA_DIRECTORY);
|
||||
Url::parse(url)
|
||||
.map(|url| {
|
||||
if !url.has_host() {
|
||||
return;
|
||||
}
|
||||
file_path.push(url.host_str().unwrap());
|
||||
for segment in url.path_segments().expect("FIXME") {
|
||||
file_path.push(segment);
|
||||
@ -432,54 +320,19 @@ fn determine_mirror_file_path(url: &str) -> PathBuf {
|
||||
// TODO: handle query
|
||||
// HINT: Use characters which must be percent-encoded in path as separator between path and query
|
||||
// HINT: handle extension
|
||||
}
|
||||
other => {
|
||||
if let Err(err) = other {
|
||||
warn!("Failed to parse url: {} {}", &url, err);
|
||||
} else {
|
||||
warn!("Error without a host: {}", &url);
|
||||
}
|
||||
})
|
||||
.unwrap_or_else(|err| {
|
||||
warn!("Failed to parse url: {} {}", &url, err);
|
||||
let ext = url
|
||||
.rsplit('.')
|
||||
.next()
|
||||
.map(ToOwned::to_owned)
|
||||
.unwrap_or_else(|| String::from("png"));
|
||||
file_path.push(format!("{}.{}", GUID::rand(), ext));
|
||||
}
|
||||
}
|
||||
});
|
||||
file_path
|
||||
}
|
||||
|
||||
#[cfg(feature="s3")]
|
||||
fn determine_mirror_s3_path(url: &str) -> String {
|
||||
match Url::parse(url) {
|
||||
Ok(url) if url.has_host() => {
|
||||
format!("static/media/{}/{}/{}",
|
||||
REMOTE_MEDIA_DIRECTORY,
|
||||
url.host_str().unwrap(),
|
||||
url.path().trim_start_matches('/'),
|
||||
)
|
||||
}
|
||||
other => {
|
||||
if let Err(err) = other {
|
||||
warn!("Failed to parse url: {} {}", &url, err);
|
||||
} else {
|
||||
warn!("Error without a host: {}", &url);
|
||||
}
|
||||
let ext = url
|
||||
.rsplit('.')
|
||||
.next()
|
||||
.map(ToOwned::to_owned)
|
||||
.unwrap_or_else(|| String::from("png"));
|
||||
format!("static/media/{}/{}.{}",
|
||||
REMOTE_MEDIA_DIRECTORY,
|
||||
GUID::rand(),
|
||||
ext,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) mod tests {
|
||||
use super::*;
|
||||
|
@ -373,7 +373,7 @@ impl Post {
|
||||
}))?;
|
||||
article.set_source(source);
|
||||
article.set_published(
|
||||
OffsetDateTime::from_unix_timestamp_nanos(self.creation_date.timestamp_nanos_opt().unwrap().into())
|
||||
OffsetDateTime::from_unix_timestamp_nanos(self.creation_date.timestamp_nanos().into())
|
||||
.expect("OffsetDateTime"),
|
||||
);
|
||||
article.set_summary(&*self.subtitle);
|
||||
|
@ -221,8 +221,7 @@ impl Timeline {
|
||||
|
||||
pub fn add_to_all_timelines(conn: &Connection, post: &Post, kind: Kind<'_>) -> Result<()> {
|
||||
let timelines = timeline_definition::table
|
||||
//.load::<Self>(conn.deref())
|
||||
.load::<Self>(conn)
|
||||
.load::<Self>(conn.deref())
|
||||
.map_err(Error::from)?;
|
||||
|
||||
for t in timelines {
|
||||
|
@ -169,7 +169,7 @@ impl User {
|
||||
}
|
||||
|
||||
for comment in Comment::list_by_author(conn, self.id)? {
|
||||
let delete_activity = comment.build_delete(conn)?;
|
||||
let delete_activity = comment.build_delete(&conn)?;
|
||||
crate::inbox::inbox(
|
||||
conn,
|
||||
serde_json::to_value(&delete_activity).map_err(Error::from)?,
|
||||
@ -342,42 +342,6 @@ impl User {
|
||||
bcrypt::hash(pass, 10).map_err(Error::from)
|
||||
}
|
||||
|
||||
// [[ LDAP non anonymous bind copied from ....
|
||||
fn ldap_preconn(ldap_conn: &mut LdapConn) -> Result<()> {
|
||||
let ldap = CONFIG.ldap.as_ref().unwrap();
|
||||
|
||||
if let Some((user, password)) = ldap.user.as_ref() {
|
||||
let bind = ldap_conn
|
||||
.simple_bind(user, password)
|
||||
.map_err(|_| Error::NotFound)?;
|
||||
|
||||
if bind.success().is_err() {
|
||||
return Err(Error::NotFound);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn search_dn(ldap_conn: &mut LdapConn, fil: &str) -> Result<String> {
|
||||
let mut cn: String = String::new();
|
||||
let ldap = CONFIG.ldap.as_ref().unwrap();
|
||||
let (rs, _res) = ldap_conn.search(
|
||||
&ldap.base_dn,
|
||||
Scope::Subtree,
|
||||
fil,
|
||||
vec!["cn"]
|
||||
)
|
||||
.map_err(|_| Error::NotFound)?
|
||||
.success()
|
||||
.map_err(|_| Error::NotFound)?;
|
||||
for entry in rs {
|
||||
println!("{:?}", SearchEntry::construct(entry.clone()).dn);
|
||||
cn = SearchEntry::construct(entry).dn;
|
||||
}
|
||||
|
||||
Ok(cn.to_owned())
|
||||
}
|
||||
|
||||
fn ldap_register(conn: &Connection, name: &str, password: &str) -> Result<User> {
|
||||
if CONFIG.ldap.is_none() {
|
||||
return Err(Error::NotFound);
|
||||
@ -385,12 +349,7 @@ impl User {
|
||||
let ldap = CONFIG.ldap.as_ref().unwrap();
|
||||
|
||||
let mut ldap_conn = LdapConn::new(&ldap.addr).map_err(|_| Error::NotFound)?;
|
||||
|
||||
User::ldap_preconn(&mut ldap_conn)?;
|
||||
|
||||
let _filter = format!("(&(objectClass=*)(uid={}))", name).to_owned();
|
||||
let ldap_name = User::search_dn(&mut ldap_conn, &_filter).unwrap();
|
||||
//let ldap_name = format!("{}={},{}", ldap.user_name_attr, name, ldap.base_dn);
|
||||
let ldap_name = format!("{}={},{}", ldap.user_name_attr, name, ldap.base_dn);
|
||||
let bind = ldap_conn
|
||||
.simple_bind(&ldap_name, password)
|
||||
.map_err(|_| Error::NotFound)?;
|
||||
@ -436,18 +395,10 @@ impl User {
|
||||
} else {
|
||||
return false;
|
||||
};
|
||||
if User::ldap_preconn(&mut conn).is_err() {
|
||||
return false;
|
||||
}
|
||||
//
|
||||
let _filter = format!("(&(objectClass=*)(uid={}))", &self.username).to_owned();
|
||||
let name = User::search_dn(&mut conn, &_filter).unwrap();
|
||||
/*
|
||||
let name = format!(
|
||||
"{}={},{}",
|
||||
ldap.user_name_attr, &self.username, ldap.base_dn
|
||||
);
|
||||
*/
|
||||
if let Ok(bind) = conn.simple_bind(&name, password) {
|
||||
bind.success().is_ok()
|
||||
} else {
|
||||
@ -494,7 +445,7 @@ impl User {
|
||||
}
|
||||
// if no user was found, and we were unable to auto-register from ldap
|
||||
// fake-verify a password, and return an error.
|
||||
let other = User::get(&*conn, 1)
|
||||
let other = User::get(conn, 1)
|
||||
.expect("No user is registered")
|
||||
.hashed_password;
|
||||
other.map(|pass| bcrypt::verify(password, &pass));
|
||||
@ -502,7 +453,7 @@ impl User {
|
||||
}
|
||||
}
|
||||
}
|
||||
// ... ldap-non-anon PR https://git.joinplu.me/Plume/Plume/src/branch/ldap-non-anon ]].
|
||||
|
||||
pub fn reset_password(&self, conn: &Connection, pass: &str) -> Result<()> {
|
||||
diesel::update(self)
|
||||
.set(users::hashed_password.eq(User::hash_pass(pass)?))
|
||||
|
1052
po/plume/af.po
1052
po/plume/af.po
File diff suppressed because it is too large
Load Diff
1036
po/plume/ar.po
1036
po/plume/ar.po
File diff suppressed because it is too large
Load Diff
1039
po/plume/bg.po
1039
po/plume/bg.po
File diff suppressed because it is too large
Load Diff
1150
po/plume/ca.po
1150
po/plume/ca.po
File diff suppressed because it is too large
Load Diff
1062
po/plume/cs.po
1062
po/plume/cs.po
File diff suppressed because it is too large
Load Diff
884
po/plume/cy.po
884
po/plume/cy.po
File diff suppressed because it is too large
Load Diff
1052
po/plume/da.po
1052
po/plume/da.po
File diff suppressed because it is too large
Load Diff
1006
po/plume/de.po
1006
po/plume/de.po
File diff suppressed because it is too large
Load Diff
1052
po/plume/el.po
1052
po/plume/el.po
File diff suppressed because it is too large
Load Diff
1052
po/plume/en.po
1052
po/plume/en.po
File diff suppressed because it is too large
Load Diff
1159
po/plume/eo.po
1159
po/plume/eo.po
File diff suppressed because it is too large
Load Diff
973
po/plume/es.po
973
po/plume/es.po
File diff suppressed because it is too large
Load Diff
1125
po/plume/eu.po
1125
po/plume/eu.po
File diff suppressed because it is too large
Load Diff
996
po/plume/fa.po
996
po/plume/fa.po
File diff suppressed because it is too large
Load Diff
1258
po/plume/fi.po
1258
po/plume/fi.po
File diff suppressed because it is too large
Load Diff
1143
po/plume/fr.po
1143
po/plume/fr.po
File diff suppressed because it is too large
Load Diff
1091
po/plume/gl.po
1091
po/plume/gl.po
File diff suppressed because it is too large
Load Diff
1063
po/plume/he.po
1063
po/plume/he.po
File diff suppressed because it is too large
Load Diff
1060
po/plume/hi.po
1060
po/plume/hi.po
File diff suppressed because it is too large
Load Diff
1135
po/plume/hr.po
1135
po/plume/hr.po
File diff suppressed because it is too large
Load Diff
1052
po/plume/hu.po
1052
po/plume/hu.po
File diff suppressed because it is too large
Load Diff
1041
po/plume/it.po
1041
po/plume/it.po
File diff suppressed because it is too large
Load Diff
1113
po/plume/ja.po
1113
po/plume/ja.po
File diff suppressed because it is too large
Load Diff
1048
po/plume/ko.po
1048
po/plume/ko.po
File diff suppressed because it is too large
Load Diff
1002
po/plume/nb.po
1002
po/plume/nb.po
File diff suppressed because it is too large
Load Diff
1142
po/plume/nl.po
1142
po/plume/nl.po
File diff suppressed because it is too large
Load Diff
1089
po/plume/no.po
1089
po/plume/no.po
File diff suppressed because it is too large
Load Diff
1161
po/plume/pl.po
1161
po/plume/pl.po
File diff suppressed because it is too large
Load Diff
@ -33,9 +33,6 @@ msgstr ""
|
||||
msgid "Your feed"
|
||||
msgstr ""
|
||||
|
||||
msgid "My feed"
|
||||
msgstr ""
|
||||
|
||||
msgid "Local feed"
|
||||
msgstr ""
|
||||
|
||||
@ -225,19 +222,139 @@ msgstr ""
|
||||
msgid "You can't delete someone else's account."
|
||||
msgstr ""
|
||||
|
||||
msgid "Create your account"
|
||||
msgstr ""
|
||||
|
||||
msgid "Create an account"
|
||||
msgstr ""
|
||||
|
||||
msgid "Email"
|
||||
msgstr ""
|
||||
|
||||
msgid "Email confirmation"
|
||||
msgstr ""
|
||||
|
||||
msgid "An email will be sent to provided email. You can continue signing-up via the email."
|
||||
msgstr ""
|
||||
|
||||
msgid "Apologies, but registrations are closed on this particular instance. You can, however, find a different one."
|
||||
msgstr ""
|
||||
|
||||
msgid "Registration"
|
||||
msgstr ""
|
||||
|
||||
msgid "Check your inbox!"
|
||||
msgstr ""
|
||||
|
||||
msgid "We sent a mail to the address you gave us, with a link for registration."
|
||||
msgstr ""
|
||||
|
||||
msgid "Username"
|
||||
msgstr ""
|
||||
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
|
||||
msgid "Password confirmation"
|
||||
msgstr ""
|
||||
|
||||
msgid "Media upload"
|
||||
msgstr ""
|
||||
|
||||
msgid "Description"
|
||||
msgstr ""
|
||||
|
||||
msgid "Useful for visually impaired people, as well as licensing information"
|
||||
msgstr ""
|
||||
|
||||
msgid "Content warning"
|
||||
msgstr ""
|
||||
|
||||
msgid "Leave it empty, if none is needed"
|
||||
msgstr ""
|
||||
|
||||
msgid "File"
|
||||
msgstr ""
|
||||
|
||||
msgid "Send"
|
||||
msgstr ""
|
||||
|
||||
msgid "Your media"
|
||||
msgstr ""
|
||||
|
||||
msgid "Upload"
|
||||
msgstr ""
|
||||
|
||||
msgid "You don't have any media yet."
|
||||
msgstr ""
|
||||
|
||||
msgid "Content warning: {0}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
msgid "Details"
|
||||
msgstr ""
|
||||
|
||||
msgid "Media details"
|
||||
msgstr ""
|
||||
|
||||
msgid "Go back to the gallery"
|
||||
msgstr ""
|
||||
|
||||
msgid "Markdown syntax"
|
||||
msgstr ""
|
||||
|
||||
msgid "Copy it into your articles, to insert this media:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Use as an avatar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Plume"
|
||||
msgstr ""
|
||||
|
||||
msgid "Menu"
|
||||
msgstr ""
|
||||
|
||||
msgid "Search"
|
||||
msgstr ""
|
||||
|
||||
msgid "Dashboard"
|
||||
msgstr ""
|
||||
|
||||
msgid "Notifications"
|
||||
msgstr ""
|
||||
|
||||
msgid "{0}'s subscriptions"
|
||||
msgid "Log Out"
|
||||
msgstr ""
|
||||
|
||||
msgid "Articles"
|
||||
msgid "My account"
|
||||
msgstr ""
|
||||
|
||||
msgid "Subscribers"
|
||||
msgid "Log In"
|
||||
msgstr ""
|
||||
|
||||
msgid "Subscriptions"
|
||||
msgid "Register"
|
||||
msgstr ""
|
||||
|
||||
msgid "About this instance"
|
||||
msgstr ""
|
||||
|
||||
msgid "Privacy policy"
|
||||
msgstr ""
|
||||
|
||||
msgid "Administration"
|
||||
msgstr ""
|
||||
|
||||
msgid "Documentation"
|
||||
msgstr ""
|
||||
|
||||
msgid "Source code"
|
||||
msgstr ""
|
||||
|
||||
msgid "Matrix room"
|
||||
msgstr ""
|
||||
|
||||
msgid "Admin"
|
||||
@ -258,30 +375,30 @@ msgstr ""
|
||||
msgid "Subscribe"
|
||||
msgstr ""
|
||||
|
||||
msgid "Create your account"
|
||||
msgid "Follow {}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Create an account"
|
||||
msgid "Log in to follow"
|
||||
msgstr ""
|
||||
|
||||
msgid "Username"
|
||||
msgstr ""
|
||||
|
||||
msgid "Email"
|
||||
msgstr ""
|
||||
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
|
||||
msgid "Password confirmation"
|
||||
msgstr ""
|
||||
|
||||
msgid "Apologies, but registrations are closed on this particular instance. You can, however, find a different one."
|
||||
msgid "Enter your full username handle to follow"
|
||||
msgstr ""
|
||||
|
||||
msgid "{0}'s subscribers"
|
||||
msgstr ""
|
||||
|
||||
msgid "Articles"
|
||||
msgstr ""
|
||||
|
||||
msgid "Subscribers"
|
||||
msgstr ""
|
||||
|
||||
msgid "Subscriptions"
|
||||
msgstr ""
|
||||
|
||||
msgid "{0}'s subscriptions"
|
||||
msgstr ""
|
||||
|
||||
msgid "Your Dashboard"
|
||||
msgstr ""
|
||||
|
||||
@ -297,21 +414,9 @@ msgstr ""
|
||||
msgid "Your Drafts"
|
||||
msgstr ""
|
||||
|
||||
msgid "Your media"
|
||||
msgstr ""
|
||||
|
||||
msgid "Go to your gallery"
|
||||
msgstr ""
|
||||
|
||||
msgid "Follow {}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Log in to follow"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enter your full username handle to follow"
|
||||
msgstr ""
|
||||
|
||||
msgid "Edit your account"
|
||||
msgstr ""
|
||||
|
||||
@ -366,81 +471,10 @@ msgstr ""
|
||||
msgid "Recently boosted"
|
||||
msgstr ""
|
||||
|
||||
msgid "Nothing to see here yet."
|
||||
msgid "Articles tagged \"{0}\""
|
||||
msgstr ""
|
||||
|
||||
msgid "Edit"
|
||||
msgstr ""
|
||||
|
||||
msgid "By {0}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Draft"
|
||||
msgstr ""
|
||||
|
||||
msgid "One like"
|
||||
msgid_plural "{0} likes"
|
||||
msgstr[0] ""
|
||||
|
||||
msgid "One boost"
|
||||
msgid_plural "{0} boosts"
|
||||
msgstr[0] ""
|
||||
|
||||
msgid "What is Plume?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Plume is a decentralized blogging engine."
|
||||
msgstr ""
|
||||
|
||||
msgid "Authors can manage multiple blogs, each as its own website."
|
||||
msgstr ""
|
||||
|
||||
msgid "Articles are also visible on other Plume instances, and you can interact with them directly from other platforms like Mastodon."
|
||||
msgstr ""
|
||||
|
||||
msgid "About {0}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Home to <em>{0}</em> people"
|
||||
msgstr ""
|
||||
|
||||
msgid "Who wrote <em>{0}</em> articles"
|
||||
msgstr ""
|
||||
|
||||
msgid "Read the detailed rules"
|
||||
msgstr ""
|
||||
|
||||
msgid "Respond"
|
||||
msgstr ""
|
||||
|
||||
msgid "Are you sure?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete this comment"
|
||||
msgstr ""
|
||||
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
msgid "No description"
|
||||
msgstr ""
|
||||
|
||||
msgid "You are not authorized."
|
||||
msgstr ""
|
||||
|
||||
msgid "Invalid CSRF token"
|
||||
msgstr ""
|
||||
|
||||
msgid "Something is wrong with your CSRF token. Make sure cookies are enabled in you browser, and try reloading this page. If you continue to see this error message, please report it."
|
||||
msgstr ""
|
||||
|
||||
msgid "Page not found"
|
||||
msgstr ""
|
||||
|
||||
msgid "We couldn't find this page."
|
||||
msgstr ""
|
||||
|
||||
msgid "The link that led you here may be broken."
|
||||
msgid "There are currently no articles with such a tag"
|
||||
msgstr ""
|
||||
|
||||
msgid "The content you sent can't be processed."
|
||||
@ -458,172 +492,72 @@ msgstr ""
|
||||
msgid "Sorry about that. If you think this is a bug, please report it."
|
||||
msgstr ""
|
||||
|
||||
msgid "Articles tagged \"{0}\""
|
||||
msgid "Invalid CSRF token"
|
||||
msgstr ""
|
||||
|
||||
msgid "There are currently no articles with such a tag"
|
||||
msgid "Something is wrong with your CSRF token. Make sure cookies are enabled in you browser, and try reloading this page. If you continue to see this error message, please report it."
|
||||
msgstr ""
|
||||
|
||||
msgid "New Blog"
|
||||
msgid "You are not authorized."
|
||||
msgstr ""
|
||||
|
||||
msgid "Create a blog"
|
||||
msgid "Page not found"
|
||||
msgstr ""
|
||||
|
||||
msgid "Title"
|
||||
msgid "We couldn't find this page."
|
||||
msgstr ""
|
||||
|
||||
msgid "Create blog"
|
||||
msgstr ""
|
||||
|
||||
msgid "Edit \"{}\""
|
||||
msgstr ""
|
||||
|
||||
msgid "Description"
|
||||
msgstr ""
|
||||
|
||||
msgid "Markdown syntax is supported"
|
||||
msgstr ""
|
||||
|
||||
msgid "You can upload images to your gallery, to use them as blog icons, or banners."
|
||||
msgstr ""
|
||||
|
||||
msgid "Upload images"
|
||||
msgstr ""
|
||||
|
||||
msgid "Blog icon"
|
||||
msgstr ""
|
||||
|
||||
msgid "Blog banner"
|
||||
msgstr ""
|
||||
|
||||
msgid "Custom theme"
|
||||
msgstr ""
|
||||
|
||||
msgid "Update blog"
|
||||
msgstr ""
|
||||
|
||||
msgid "Be very careful, any action taken here can't be reversed."
|
||||
msgstr ""
|
||||
|
||||
msgid "Are you sure that you want to permanently delete this blog?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Permanently delete this blog"
|
||||
msgstr ""
|
||||
|
||||
msgid "{}'s icon"
|
||||
msgstr ""
|
||||
|
||||
msgid "There's one author on this blog: "
|
||||
msgid_plural "There are {0} authors on this blog: "
|
||||
msgstr[0] ""
|
||||
|
||||
msgid "No posts to see here yet."
|
||||
msgstr ""
|
||||
|
||||
msgid "Media upload"
|
||||
msgstr ""
|
||||
|
||||
msgid "Useful for visually impaired people, as well as licensing information"
|
||||
msgstr ""
|
||||
|
||||
msgid "Content warning"
|
||||
msgstr ""
|
||||
|
||||
msgid "Leave it empty, if none is needed"
|
||||
msgstr ""
|
||||
|
||||
msgid "File"
|
||||
msgstr ""
|
||||
|
||||
msgid "Send"
|
||||
msgstr ""
|
||||
|
||||
msgid "Upload"
|
||||
msgstr ""
|
||||
|
||||
msgid "You don't have any media yet."
|
||||
msgstr ""
|
||||
|
||||
msgid "Content warning: {0}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
msgid "Details"
|
||||
msgstr ""
|
||||
|
||||
msgid "Media details"
|
||||
msgstr ""
|
||||
|
||||
msgid "Go back to the gallery"
|
||||
msgstr ""
|
||||
|
||||
msgid "Markdown syntax"
|
||||
msgstr ""
|
||||
|
||||
msgid "Copy it into your articles, to insert this media:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Use as an avatar"
|
||||
msgstr ""
|
||||
|
||||
msgid "I'm from this instance"
|
||||
msgstr ""
|
||||
|
||||
msgid "Username, or email"
|
||||
msgstr ""
|
||||
|
||||
msgid "Log in"
|
||||
msgstr ""
|
||||
|
||||
msgid "I'm from another instance"
|
||||
msgstr ""
|
||||
|
||||
msgid "Continue to your instance"
|
||||
msgstr ""
|
||||
|
||||
msgid "Email confirmation"
|
||||
msgstr ""
|
||||
|
||||
msgid "An email will be sent to provided email. You can continue signing-up via the email."
|
||||
msgstr ""
|
||||
|
||||
msgid "Registration"
|
||||
msgstr ""
|
||||
|
||||
msgid "Check your inbox!"
|
||||
msgstr ""
|
||||
|
||||
msgid "We sent a mail to the address you gave us, with a link for registration."
|
||||
msgstr ""
|
||||
|
||||
msgid "Administration of {0}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Instances"
|
||||
msgstr ""
|
||||
|
||||
msgid "Configuration"
|
||||
msgid "The link that led you here may be broken."
|
||||
msgstr ""
|
||||
|
||||
msgid "Users"
|
||||
msgstr ""
|
||||
|
||||
msgid "Configuration"
|
||||
msgstr ""
|
||||
|
||||
msgid "Instances"
|
||||
msgstr ""
|
||||
|
||||
msgid "Email blocklist"
|
||||
msgstr ""
|
||||
|
||||
msgid "Grant admin rights"
|
||||
msgstr ""
|
||||
|
||||
msgid "Revoke admin rights"
|
||||
msgstr ""
|
||||
|
||||
msgid "Grant moderator rights"
|
||||
msgstr ""
|
||||
|
||||
msgid "Revoke moderator rights"
|
||||
msgstr ""
|
||||
|
||||
msgid "Ban"
|
||||
msgstr ""
|
||||
|
||||
msgid "Run on selected users"
|
||||
msgstr ""
|
||||
|
||||
msgid "Moderator"
|
||||
msgstr ""
|
||||
|
||||
msgid "Moderation"
|
||||
msgstr ""
|
||||
|
||||
msgid "Home"
|
||||
msgstr ""
|
||||
|
||||
msgid "Administration of {0}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unblock"
|
||||
msgstr ""
|
||||
|
||||
msgid "Block"
|
||||
msgstr ""
|
||||
|
||||
msgid "Administration"
|
||||
msgstr ""
|
||||
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
@ -633,6 +567,9 @@ msgstr ""
|
||||
msgid "Short description"
|
||||
msgstr ""
|
||||
|
||||
msgid "Markdown syntax is supported"
|
||||
msgstr ""
|
||||
|
||||
msgid "Long description"
|
||||
msgstr ""
|
||||
|
||||
@ -642,22 +579,13 @@ msgstr ""
|
||||
msgid "Save these settings"
|
||||
msgstr ""
|
||||
|
||||
msgid "Welcome to {}"
|
||||
msgid "If you are browsing this site as a visitor, no data about you is collected."
|
||||
msgstr ""
|
||||
|
||||
msgid "Runs Plume {0}"
|
||||
msgid "As a registered user, you have to provide your username (which does not have to be your real name), your functional email address and a password, in order to be able to log in, write articles and comment. The content you submit is stored until you delete it."
|
||||
msgstr ""
|
||||
|
||||
msgid "And are connected to <em>{0}</em> other instances"
|
||||
msgstr ""
|
||||
|
||||
msgid "Administred by"
|
||||
msgstr ""
|
||||
|
||||
msgid "Moderation"
|
||||
msgstr ""
|
||||
|
||||
msgid "Home"
|
||||
msgid "When you log in, we store two cookies, one to keep your session open, the second to prevent other people to act on your behalf. We don't store any other cookies."
|
||||
msgstr ""
|
||||
|
||||
msgid "Blocklisted Emails"
|
||||
@ -705,100 +633,37 @@ msgstr ""
|
||||
msgid "The user will be silently prevented from making an account"
|
||||
msgstr ""
|
||||
|
||||
msgid "Search users"
|
||||
msgid "Welcome to {}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Grant admin rights"
|
||||
msgid "Nothing to see here yet."
|
||||
msgstr ""
|
||||
|
||||
msgid "Revoke admin rights"
|
||||
msgid "About {0}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Grant moderator rights"
|
||||
msgid "Runs Plume {0}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Revoke moderator rights"
|
||||
msgid "Home to <em>{0}</em> people"
|
||||
msgstr ""
|
||||
|
||||
msgid "Ban"
|
||||
msgid "Who wrote <em>{0}</em> articles"
|
||||
msgstr ""
|
||||
|
||||
msgid "Run on selected users"
|
||||
msgid "And are connected to <em>{0}</em> other instances"
|
||||
msgstr ""
|
||||
|
||||
msgid "Moderator"
|
||||
msgid "Administred by"
|
||||
msgstr ""
|
||||
|
||||
msgid "Privacy policy"
|
||||
msgid "Interact with {}"
|
||||
msgstr ""
|
||||
|
||||
msgid "If you are browsing this site as a visitor, no data about you is collected."
|
||||
msgid "Log in to interact"
|
||||
msgstr ""
|
||||
|
||||
msgid "As a registered user, you have to provide your username (which does not have to be your real name), your functional email address and a password, in order to be able to log in, write articles and comment. The content you submit is stored until you delete it."
|
||||
msgstr ""
|
||||
|
||||
msgid "When you log in, we store two cookies, one to keep your session open, the second to prevent other people to act on your behalf. We don't store any other cookies."
|
||||
msgstr ""
|
||||
|
||||
msgid "This token has expired"
|
||||
msgstr ""
|
||||
|
||||
msgid "Please start the process again by clicking <a href=\"/password-reset\">here</a>."
|
||||
msgstr ""
|
||||
|
||||
msgid "Reset your password"
|
||||
msgstr ""
|
||||
|
||||
msgid "New password"
|
||||
msgstr ""
|
||||
|
||||
msgid "Confirmation"
|
||||
msgstr ""
|
||||
|
||||
msgid "Update password"
|
||||
msgstr ""
|
||||
|
||||
msgid "Send password reset link"
|
||||
msgstr ""
|
||||
|
||||
msgid "We sent a mail to the address you gave us, with a link to reset your password."
|
||||
msgstr ""
|
||||
|
||||
msgid "Plume"
|
||||
msgstr ""
|
||||
|
||||
msgid "Menu"
|
||||
msgstr ""
|
||||
|
||||
msgid "Search"
|
||||
msgstr ""
|
||||
|
||||
msgid "Dashboard"
|
||||
msgstr ""
|
||||
|
||||
msgid "Log Out"
|
||||
msgstr ""
|
||||
|
||||
msgid "My account"
|
||||
msgstr ""
|
||||
|
||||
msgid "Log In"
|
||||
msgstr ""
|
||||
|
||||
msgid "Register"
|
||||
msgstr ""
|
||||
|
||||
msgid "About this instance"
|
||||
msgstr ""
|
||||
|
||||
msgid "Documentation"
|
||||
msgstr ""
|
||||
|
||||
msgid "Source code"
|
||||
msgstr ""
|
||||
|
||||
msgid "Matrix room"
|
||||
msgid "Enter your full username to interact"
|
||||
msgstr ""
|
||||
|
||||
msgid "Publish"
|
||||
@ -807,6 +672,9 @@ msgstr ""
|
||||
msgid "Classic editor (any changes will be lost)"
|
||||
msgstr ""
|
||||
|
||||
msgid "Title"
|
||||
msgstr ""
|
||||
|
||||
msgid "Subtitle"
|
||||
msgstr ""
|
||||
|
||||
@ -840,15 +708,6 @@ msgstr ""
|
||||
msgid "Publish your post"
|
||||
msgstr ""
|
||||
|
||||
msgid "Interact with {}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Log in to interact"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enter your full username to interact"
|
||||
msgstr ""
|
||||
|
||||
msgid "Written by {0}"
|
||||
msgstr ""
|
||||
|
||||
@ -858,12 +717,20 @@ msgstr ""
|
||||
msgid "This article is under the {0} license."
|
||||
msgstr ""
|
||||
|
||||
msgid "One like"
|
||||
msgid_plural "{0} likes"
|
||||
msgstr[0] ""
|
||||
|
||||
msgid "I don't like this anymore"
|
||||
msgstr ""
|
||||
|
||||
msgid "Add yours"
|
||||
msgstr ""
|
||||
|
||||
msgid "One boost"
|
||||
msgid_plural "{0} boosts"
|
||||
msgstr[0] ""
|
||||
|
||||
msgid "I don't want to boost this anymore"
|
||||
msgstr ""
|
||||
|
||||
@ -885,12 +752,151 @@ msgstr ""
|
||||
msgid "No comments yet. Be the first to react!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Are you sure?"
|
||||
msgstr ""
|
||||
|
||||
msgid "This article is still a draft. Only you and other authors can see it."
|
||||
msgstr ""
|
||||
|
||||
msgid "Only you and other authors can edit this article."
|
||||
msgstr ""
|
||||
|
||||
msgid "Edit"
|
||||
msgstr ""
|
||||
|
||||
msgid "I'm from this instance"
|
||||
msgstr ""
|
||||
|
||||
msgid "Username, or email"
|
||||
msgstr ""
|
||||
|
||||
msgid "Log in"
|
||||
msgstr ""
|
||||
|
||||
msgid "I'm from another instance"
|
||||
msgstr ""
|
||||
|
||||
msgid "Continue to your instance"
|
||||
msgstr ""
|
||||
|
||||
msgid "Reset your password"
|
||||
msgstr ""
|
||||
|
||||
msgid "New password"
|
||||
msgstr ""
|
||||
|
||||
msgid "Confirmation"
|
||||
msgstr ""
|
||||
|
||||
msgid "Update password"
|
||||
msgstr ""
|
||||
|
||||
msgid "We sent a mail to the address you gave us, with a link to reset your password."
|
||||
msgstr ""
|
||||
|
||||
msgid "Send password reset link"
|
||||
msgstr ""
|
||||
|
||||
msgid "This token has expired"
|
||||
msgstr ""
|
||||
|
||||
msgid "Please start the process again by clicking <a href=\"/password-reset\">here</a>."
|
||||
msgstr ""
|
||||
|
||||
msgid "New Blog"
|
||||
msgstr ""
|
||||
|
||||
msgid "Create a blog"
|
||||
msgstr ""
|
||||
|
||||
msgid "Create blog"
|
||||
msgstr ""
|
||||
|
||||
msgid "Edit \"{}\""
|
||||
msgstr ""
|
||||
|
||||
msgid "You can upload images to your gallery, to use them as blog icons, or banners."
|
||||
msgstr ""
|
||||
|
||||
msgid "Upload images"
|
||||
msgstr ""
|
||||
|
||||
msgid "Blog icon"
|
||||
msgstr ""
|
||||
|
||||
msgid "Blog banner"
|
||||
msgstr ""
|
||||
|
||||
msgid "Custom theme"
|
||||
msgstr ""
|
||||
|
||||
msgid "Update blog"
|
||||
msgstr ""
|
||||
|
||||
msgid "Be very careful, any action taken here can't be reversed."
|
||||
msgstr ""
|
||||
|
||||
msgid "Are you sure that you want to permanently delete this blog?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Permanently delete this blog"
|
||||
msgstr ""
|
||||
|
||||
msgid "{}'s icon"
|
||||
msgstr ""
|
||||
|
||||
msgid "There's one author on this blog: "
|
||||
msgid_plural "There are {0} authors on this blog: "
|
||||
msgstr[0] ""
|
||||
|
||||
msgid "No posts to see here yet."
|
||||
msgstr ""
|
||||
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
msgid "No description"
|
||||
msgstr ""
|
||||
|
||||
msgid "Respond"
|
||||
msgstr ""
|
||||
|
||||
msgid "Delete this comment"
|
||||
msgstr ""
|
||||
|
||||
msgid "What is Plume?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Plume is a decentralized blogging engine."
|
||||
msgstr ""
|
||||
|
||||
msgid "Authors can manage multiple blogs, each as its own website."
|
||||
msgstr ""
|
||||
|
||||
msgid "Articles are also visible on other Plume instances, and you can interact with them directly from other platforms like Mastodon."
|
||||
msgstr ""
|
||||
|
||||
msgid "Read the detailed rules"
|
||||
msgstr ""
|
||||
|
||||
msgid "By {0}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Draft"
|
||||
msgstr ""
|
||||
|
||||
msgid "Search result(s) for \"{0}\""
|
||||
msgstr ""
|
||||
|
||||
msgid "Search result(s)"
|
||||
msgstr ""
|
||||
|
||||
msgid "No results for your query"
|
||||
msgstr ""
|
||||
|
||||
msgid "No more results for your query"
|
||||
msgstr ""
|
||||
|
||||
msgid "Advanced search"
|
||||
msgstr ""
|
||||
|
||||
@ -947,15 +953,3 @@ msgstr ""
|
||||
|
||||
msgid "Article license"
|
||||
msgstr ""
|
||||
|
||||
msgid "Search result(s) for \"{0}\""
|
||||
msgstr ""
|
||||
|
||||
msgid "Search result(s)"
|
||||
msgstr ""
|
||||
|
||||
msgid "No results for your query"
|
||||
msgstr ""
|
||||
|
||||
msgid "No more results for your query"
|
||||
msgstr ""
|
||||
|
1026
po/plume/pt.po
1026
po/plume/pt.po
File diff suppressed because it is too large
Load Diff
1291
po/plume/ro.po
1291
po/plume/ro.po
File diff suppressed because it is too large
Load Diff
1167
po/plume/ru.po
1167
po/plume/ru.po
File diff suppressed because it is too large
Load Diff
1017
po/plume/sat.po
1017
po/plume/sat.po
File diff suppressed because it is too large
Load Diff
1001
po/plume/si.po
1001
po/plume/si.po
File diff suppressed because it is too large
Load Diff
1060
po/plume/sk.po
1060
po/plume/sk.po
File diff suppressed because it is too large
Load Diff
1235
po/plume/sl.po
1235
po/plume/sl.po
File diff suppressed because it is too large
Load Diff
1129
po/plume/sr.po
1129
po/plume/sr.po
File diff suppressed because it is too large
Load Diff
1128
po/plume/sv.po
1128
po/plume/sv.po
File diff suppressed because it is too large
Load Diff
1074
po/plume/tr.po
1074
po/plume/tr.po
File diff suppressed because it is too large
Load Diff
1101
po/plume/uk.po
1101
po/plume/uk.po
File diff suppressed because it is too large
Load Diff
1048
po/plume/vi.po
1048
po/plume/vi.po
File diff suppressed because it is too large
Load Diff
1049
po/plume/zh.po
1049
po/plume/zh.po
File diff suppressed because it is too large
Load Diff
@ -1 +1 @@
|
||||
nightly-2023-11-10
|
||||
nightly-2022-07-19
|
||||
|
@ -101,8 +101,7 @@ Then try to restart Plume.
|
||||
"#
|
||||
)
|
||||
}
|
||||
//let workpool = ScheduledThreadPool::with_name("worker {}", num_cpus::get());
|
||||
let workpool = ScheduledThreadPool::new(num_cpus::get());
|
||||
let workpool = ScheduledThreadPool::with_name("worker {}", num_cpus::get());
|
||||
// we want a fast exit here, so
|
||||
let searcher = Arc::new(UnmanagedSearcher::open_or_recreate(
|
||||
&CONFIG.search_index,
|
||||
|
@ -101,7 +101,7 @@ pub fn create(
|
||||
Ok(_) => ValidationErrors::new(),
|
||||
Err(e) => e,
|
||||
};
|
||||
if Blog::find_by_fqn(&conn, &slug).is_ok() {
|
||||
if Blog::find_by_fqn(&conn, slug).is_ok() {
|
||||
errors.add(
|
||||
"title",
|
||||
ValidationError {
|
||||
@ -122,7 +122,7 @@ pub fn create(
|
||||
let blog = Blog::insert(
|
||||
&conn,
|
||||
NewBlog::new_local(
|
||||
slug.clone().into(),
|
||||
slug.into(),
|
||||
form.title.to_string(),
|
||||
String::from(""),
|
||||
Instance::get_local()
|
||||
|
@ -51,7 +51,7 @@ pub fn index(conn: DbConn, rockets: PlumeRocket) -> Result<Ructe, ErrorPage> {
|
||||
}
|
||||
|
||||
#[get("/admin")]
|
||||
pub fn admin(_admin: InclusiveAdmin, conn: DbConn, rockets: PlumeRocket) -> Result<Ructe, ErrorPage> {
|
||||
pub fn admin(_admin: Admin, conn: DbConn, rockets: PlumeRocket) -> Result<Ructe, ErrorPage> {
|
||||
let local_inst = Instance::get_local()?;
|
||||
Ok(render!(instance::admin(
|
||||
&(&conn, &rockets).to_context(),
|
||||
|
@ -2,7 +2,7 @@ use crate::routes::{errors::ErrorPage, Page};
|
||||
use crate::template_utils::{IntoContext, Ructe};
|
||||
use guid_create::GUID;
|
||||
use multipart::server::{
|
||||
save::{SaveResult, SavedField, SavedData},
|
||||
save::{SaveResult, SavedData},
|
||||
Multipart,
|
||||
};
|
||||
use plume_models::{db_conn::DbConn, medias::*, users::User, Error, PlumeRocket, CONFIG};
|
||||
@ -55,16 +55,41 @@ pub fn upload(
|
||||
if let SaveResult::Full(entries) = Multipart::with_body(data.open(), boundary).save().temp() {
|
||||
let fields = entries.fields;
|
||||
|
||||
let file = fields
|
||||
let filename = fields
|
||||
.get("file")
|
||||
.and_then(|v| v.iter().next())
|
||||
.ok_or(status::BadRequest(Some("No file uploaded")))?;
|
||||
.ok_or(status::BadRequest(Some("No file uploaded")))?
|
||||
.headers
|
||||
.filename
|
||||
.clone();
|
||||
// Remove extension if it contains something else than just letters and numbers
|
||||
let ext = filename
|
||||
.and_then(|f| {
|
||||
f.rsplit('.')
|
||||
.next()
|
||||
.and_then(|ext| {
|
||||
if ext.chars().any(|c| !c.is_alphanumeric()) {
|
||||
None
|
||||
} else {
|
||||
Some(ext.to_lowercase())
|
||||
}
|
||||
})
|
||||
.map(|ext| format!(".{}", ext))
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let dest = format!("{}/{}{}", CONFIG.media_directory, GUID::rand(), ext);
|
||||
|
||||
let file_path = match save_uploaded_file(file) {
|
||||
Ok(Some(file_path)) => file_path,
|
||||
Ok(None) => return Ok(Redirect::to(uri!(new))),
|
||||
Err(_) => return Err(status::BadRequest(Some("Couldn't save uploaded media: {}"))),
|
||||
};
|
||||
match fields["file"][0].data {
|
||||
SavedData::Bytes(ref bytes) => fs::write(&dest, bytes)
|
||||
.map_err(|_| status::BadRequest(Some("Couldn't save upload")))?,
|
||||
SavedData::File(ref path, _) => {
|
||||
fs::copy(path, &dest)
|
||||
.map_err(|_| status::BadRequest(Some("Couldn't copy upload")))?;
|
||||
}
|
||||
_ => {
|
||||
return Ok(Redirect::to(uri!(new)));
|
||||
}
|
||||
}
|
||||
|
||||
let has_cw = !read(&fields["cw"][0].data)
|
||||
.map(|cw| cw.is_empty())
|
||||
@ -72,7 +97,7 @@ pub fn upload(
|
||||
let media = Media::insert(
|
||||
&conn,
|
||||
NewMedia {
|
||||
file_path,
|
||||
file_path: dest,
|
||||
alt_text: read(&fields["alt"][0].data)?,
|
||||
is_remote: false,
|
||||
remote_url: None,
|
||||
@ -92,74 +117,6 @@ pub fn upload(
|
||||
}
|
||||
}
|
||||
|
||||
fn save_uploaded_file(file: &SavedField) -> Result<Option<String>, plume_models::Error> {
|
||||
// Remove extension if it contains something else than just letters and numbers
|
||||
let ext = file
|
||||
.headers
|
||||
.filename
|
||||
.as_ref()
|
||||
.and_then(|f| {
|
||||
f.rsplit('.')
|
||||
.next()
|
||||
.and_then(|ext| {
|
||||
if ext.chars().any(|c| !c.is_alphanumeric()) {
|
||||
None
|
||||
} else {
|
||||
Some(ext.to_lowercase())
|
||||
}
|
||||
})
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
if CONFIG.s3.is_some() {
|
||||
#[cfg(not(feature="s3"))]
|
||||
unreachable!();
|
||||
|
||||
#[cfg(feature="s3")]
|
||||
{
|
||||
use std::borrow::Cow;
|
||||
|
||||
let dest = format!("static/media/{}.{}", GUID::rand(), ext);
|
||||
|
||||
let bytes = match file.data {
|
||||
SavedData::Bytes(ref bytes) => Cow::from(bytes),
|
||||
SavedData::File(ref path, _) => Cow::from(fs::read(path)?),
|
||||
_ => {
|
||||
return Ok(None);
|
||||
}
|
||||
};
|
||||
|
||||
let bucket = CONFIG.s3.as_ref().unwrap().get_bucket();
|
||||
let content_type = match &file.headers.content_type {
|
||||
Some(ct) => ct.to_string(),
|
||||
None => ContentType::from_extension(&ext)
|
||||
.unwrap_or(ContentType::Binary)
|
||||
.to_string(),
|
||||
};
|
||||
|
||||
bucket.put_object_with_content_type_blocking(&dest, &bytes, &content_type)?;
|
||||
|
||||
Ok(Some(dest))
|
||||
}
|
||||
} else {
|
||||
let dest = format!("{}/{}.{}", CONFIG.media_directory, GUID::rand(), ext);
|
||||
|
||||
match file.data {
|
||||
SavedData::Bytes(ref bytes) => {
|
||||
fs::write(&dest, bytes)?;
|
||||
}
|
||||
SavedData::File(ref path, _) => {
|
||||
fs::copy(path, &dest)?;
|
||||
}
|
||||
_ => {
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Some(dest))
|
||||
}
|
||||
}
|
||||
|
||||
fn read(data: &SavedData) -> Result<String, status::BadRequest<&'static str>> {
|
||||
if let SavedData::Text(s) = data {
|
||||
Ok(s.clone())
|
||||
|
@ -21,9 +21,6 @@ use std::{
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
#[cfg(feature = "s3")]
|
||||
use rocket::http::ContentType;
|
||||
|
||||
/// Special return type used for routes that "cannot fail", and instead
|
||||
/// `Redirect`, or `Flash<Redirect>`, when we cannot deliver a `Ructe` Response
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
@ -143,7 +140,7 @@ pub fn build_atom_feed(
|
||||
FeedBuilder::default()
|
||||
.title(title)
|
||||
.id(uri)
|
||||
.updated(DateTime::<Utc>::from_naive_utc_and_offset(*updated, Utc))
|
||||
.updated(DateTime::<Utc>::from_utc(*updated, Utc))
|
||||
.entries(
|
||||
entries
|
||||
.into_iter()
|
||||
@ -182,9 +179,9 @@ fn post_to_atom(post: Post, conn: &Connection) -> Entry {
|
||||
// Using RFC 4287 format, see https://tools.ietf.org/html/rfc4287#section-3.3 for dates
|
||||
// eg: 2003-12-13T18:30:02Z (Z is here because there is no timezone support with the NaiveDateTime crate)
|
||||
.published(Some(
|
||||
DateTime::<Utc>::from_naive_utc_and_offset(post.creation_date, Utc).into(),
|
||||
DateTime::<Utc>::from_utc(post.creation_date, Utc).into(),
|
||||
))
|
||||
.updated(DateTime::<Utc>::from_naive_utc_and_offset(post.creation_date, Utc))
|
||||
.updated(DateTime::<Utc>::from_utc(post.creation_date, Utc))
|
||||
.id(post.ap_url.clone())
|
||||
.links(vec![LinkBuilder::default().href(post.ap_url).build()])
|
||||
.build()
|
||||
@ -207,17 +204,10 @@ pub mod timelines;
|
||||
pub mod user;
|
||||
pub mod well_known;
|
||||
|
||||
#[derive(Responder)]
|
||||
enum FileKind {
|
||||
Local(NamedFile),
|
||||
#[cfg(feature = "s3")]
|
||||
S3(Vec<u8>, ContentType),
|
||||
}
|
||||
|
||||
#[derive(Responder)]
|
||||
#[response()]
|
||||
pub struct CachedFile {
|
||||
inner: FileKind,
|
||||
inner: NamedFile,
|
||||
cache_control: CacheControl,
|
||||
}
|
||||
|
||||
@ -263,41 +253,19 @@ pub fn plume_static_files(file: PathBuf, build_id: &RawStr) -> Option<CachedFile
|
||||
}
|
||||
#[get("/static/media/<file..>")]
|
||||
pub fn plume_media_files(file: PathBuf) -> Option<CachedFile> {
|
||||
if CONFIG.s3.is_some() {
|
||||
#[cfg(not(feature="s3"))]
|
||||
unreachable!();
|
||||
|
||||
#[cfg(feature="s3")]
|
||||
{
|
||||
let data = CONFIG.s3.as_ref().unwrap().get_bucket()
|
||||
.get_object_blocking(format!("static/media/{}", file.to_string_lossy())).ok()?;
|
||||
|
||||
let ct = data.headers().get("content-type")
|
||||
.and_then(|x| ContentType::parse_flexible(&x))
|
||||
.or_else(|| file.extension()
|
||||
.and_then(|ext| ContentType::from_extension(&ext.to_string_lossy())))
|
||||
.unwrap_or(ContentType::Binary);
|
||||
|
||||
Some(CachedFile {
|
||||
inner: FileKind::S3(data.to_vec(), ct),
|
||||
cache_control: CacheControl(vec![CacheDirective::MaxAge(60 * 60 * 24 * 30)]),
|
||||
})
|
||||
}
|
||||
} else {
|
||||
NamedFile::open(Path::new(&CONFIG.media_directory).join(file))
|
||||
.ok()
|
||||
.map(|f| CachedFile {
|
||||
inner: FileKind::Local(f),
|
||||
cache_control: CacheControl(vec![CacheDirective::MaxAge(60 * 60 * 24 * 30)]),
|
||||
})
|
||||
}
|
||||
NamedFile::open(Path::new(&CONFIG.media_directory).join(file))
|
||||
.ok()
|
||||
.map(|f| CachedFile {
|
||||
inner: f,
|
||||
cache_control: CacheControl(vec![CacheDirective::MaxAge(60 * 60 * 24 * 30)]),
|
||||
})
|
||||
}
|
||||
#[get("/static/<file..>", rank = 3)]
|
||||
pub fn static_files(file: PathBuf) -> Option<CachedFile> {
|
||||
NamedFile::open(Path::new("static/").join(file))
|
||||
.ok()
|
||||
.map(|f| CachedFile {
|
||||
inner: FileKind::Local(f),
|
||||
inner: f,
|
||||
cache_control: CacheControl(vec![CacheDirective::MaxAge(60 * 60 * 24 * 30)]),
|
||||
})
|
||||
}
|
||||
|
@ -87,8 +87,6 @@
|
||||
<a href="@uri!(instance::privacy)">@i18n!(ctx.1, "Privacy policy")</a>
|
||||
@if ctx.2.clone().map(|u| u.is_admin()).unwrap_or(false) {
|
||||
<a href="@uri!(instance::admin)">@i18n!(ctx.1, "Administration")</a>
|
||||
} else if ctx.2.clone().map(|u| u.is_moderator()).unwrap_or(false) {
|
||||
<a href="@uri!(instance::admin_mod)">@i18n!(ctx.1, "Moderation")</a>
|
||||
}
|
||||
</div>
|
||||
<div>
|
||||
|
@ -1,6 +1,6 @@
|
||||
@use plume_models::instance::Instance;
|
||||
@use validator::ValidationErrors;
|
||||
@use crate::templates::{base, instance::admin_header};
|
||||
@use crate::templates::base;
|
||||
@use crate::template_utils::*;
|
||||
@use crate::routes::instance::InstanceSettingsForm;
|
||||
@use crate::routes::*;
|
||||
@ -8,7 +8,15 @@
|
||||
@(ctx: BaseContext, instance: Instance, form: InstanceSettingsForm, errors: ValidationErrors)
|
||||
|
||||
@:base(ctx, i18n!(ctx.1, "Administration of {0}"; instance.name.clone()), {}, {}, {
|
||||
@:admin_header(ctx, "Administration", 1)
|
||||
<h1>@i18n!(ctx.1, "Administration")</h1>
|
||||
|
||||
@tabs(&[
|
||||
(&uri!(instance::admin).to_string(), i18n!(ctx.1, "Configuration"), true),
|
||||
(&uri!(instance::admin_instances: page = _).to_string(), i18n!(ctx.1, "Instances"), false),
|
||||
(&uri!(instance::admin_users: page = _).to_string(), i18n!(ctx.1, "Users"), false),
|
||||
(&uri!(instance::admin_email_blocklist: page=_).to_string(), i18n!(ctx.1, "Email blocklist"), false)
|
||||
])
|
||||
|
||||
<form method="post" action="@uri!(instance::update_settings)">
|
||||
@(Input::new("name", i18n!(ctx.1, "Name"))
|
||||
.default(&form.name)
|
||||
|
@ -1,22 +0,0 @@
|
||||
@use crate::template_utils::*;
|
||||
@use crate::routes::*;
|
||||
|
||||
@(ctx: BaseContext, title: &str, selected_tab: u8)
|
||||
|
||||
<h1>@i18n!(ctx.1, title)</h1>
|
||||
|
||||
@if ctx.2.clone().map(|u| u.is_admin()).unwrap_or(false) {
|
||||
@tabs(&[
|
||||
(&uri!(instance::admin).to_string(), i18n!(ctx.1, "Configuration"), selected_tab == 1),
|
||||
(&uri!(instance::admin_instances: page = _).to_string(), i18n!(ctx.1, "Instances"), selected_tab == 2),
|
||||
(&uri!(instance::admin_users: page = _).to_string(), i18n!(ctx.1, "Users"), selected_tab == 3),
|
||||
(&uri!(instance::admin_email_blocklist: page=_).to_string(), i18n!(ctx.1, "Email blocklist"), selected_tab == 4)
|
||||
])
|
||||
} else {
|
||||
@tabs(&[
|
||||
(&uri!(instance::admin_instances: page = _).to_string(), i18n!(ctx.1, "Instances"), selected_tab == 2),
|
||||
(&uri!(instance::admin_users: page = _).to_string(), i18n!(ctx.1, "Users"), selected_tab == 3),
|
||||
(&uri!(instance::admin_email_blocklist: page=_).to_string(), i18n!(ctx.1, "Email blocklist"), selected_tab == 4)
|
||||
])
|
||||
}
|
||||
|
@ -1,8 +1,15 @@
|
||||
@use crate::templates::{base, instance::admin_header};
|
||||
@use crate::templates::base;
|
||||
@use crate::template_utils::*;
|
||||
@use crate::routes::*;
|
||||
|
||||
@(ctx: BaseContext)
|
||||
|
||||
@:base(ctx, i18n!(ctx.1, "Moderation"), {}, {}, {
|
||||
@:admin_header(ctx, "Moderation", 0)
|
||||
<h1>@i18n!(ctx.1, "Moderation")</h1>
|
||||
|
||||
@tabs(&[
|
||||
(&uri!(instance::admin).to_string(), i18n!(ctx.1, "Home"), true),
|
||||
(&uri!(instance::admin_instances: page = _).to_string(), i18n!(ctx.1, "Instances"), false),
|
||||
(&uri!(instance::admin_users: page = _).to_string(), i18n!(ctx.1, "Users"), false),
|
||||
])
|
||||
})
|
||||
|
@ -1,11 +1,17 @@
|
||||
@use plume_models::blocklisted_emails::BlocklistedEmail;
|
||||
@use crate::templates::{base, instance::admin_header};
|
||||
@use crate::templates::base;
|
||||
@use crate::template_utils::*;
|
||||
@use crate::routes::*;
|
||||
|
||||
@(ctx:BaseContext, emails: Vec<BlocklistedEmail>, page:i32, n_pages:i32)
|
||||
@:base(ctx, i18n!(ctx.1, "Blocklisted Emails"), {}, {}, {
|
||||
@:admin_header(ctx, "Blocklisted Emails", 4)
|
||||
@:base(ctx, i18n!(ctx.1, "Blocklisted Emails"), {}, {}, {
|
||||
<h1>@i18n!(ctx.1,"Blocklisted Emails")</h1>
|
||||
@tabs(&[
|
||||
(&uri!(instance::admin).to_string(), i18n!(ctx.1, "Configuration"), false),
|
||||
(&uri!(instance::admin_instances: page = _).to_string(), i18n!(ctx.1, "Instances"), false),
|
||||
(&uri!(instance::admin_users: page = _).to_string(), i18n!(ctx.1, "Users"), false),
|
||||
(&uri!(instance::admin_email_blocklist:page=_).to_string(), i18n!(ctx.1, "Email blocklist"), true),
|
||||
])
|
||||
<form method="post" action="@uri!(instance::add_email_blocklist)">
|
||||
@(Input::new("email_address", i18n!(ctx.1, "Email address"))
|
||||
.details(i18n!(ctx.1, "The email address you wish to block. In order to block domains, you can use globbing syntax, for example '*@example.com' blocks all addresses from example.com"))
|
||||
|
@ -1,12 +1,19 @@
|
||||
@use plume_models::instance::Instance;
|
||||
@use crate::templates::{base, instance::admin_header};
|
||||
@use crate::templates::base;
|
||||
@use crate::template_utils::*;
|
||||
@use crate::routes::*;
|
||||
|
||||
@(ctx: BaseContext, instance: Instance, instances: Vec<Instance>, page: i32, n_pages: i32)
|
||||
|
||||
@:base(ctx, i18n!(ctx.1, "Administration of {0}"; instance.name), {}, {}, {
|
||||
@:admin_header(ctx, "Instances", 2))
|
||||
<h1>@i18n!(ctx.1, "Instances")</h1>
|
||||
|
||||
@tabs(&[
|
||||
(&uri!(instance::admin).to_string(), i18n!(ctx.1, "Configuration"), false),
|
||||
(&uri!(instance::admin_instances: page = _).to_string(), i18n!(ctx.1, "Instances"), true),
|
||||
(&uri!(instance::admin_users: page = _).to_string(), i18n!(ctx.1, "Users"), false),
|
||||
(&uri!(instance::admin_email_blocklist:page=_).to_string(), i18n!(ctx.1, "Email blocklist"), false),
|
||||
])
|
||||
|
||||
<div class="list">
|
||||
@for instance in instances {
|
||||
|
@ -1,12 +1,19 @@
|
||||
@use plume_models::users::User;
|
||||
@use crate::templates::{base, instance::admin_header};
|
||||
@use crate::templates::base;
|
||||
@use crate::template_utils::*;
|
||||
@use crate::routes::*;
|
||||
|
||||
@(ctx: BaseContext, users: Vec<User>, user: Option<&str>, page: i32, n_pages: i32)
|
||||
|
||||
@:base(ctx, i18n!(ctx.1, "Users"), {}, {}, {
|
||||
@:admin_header(ctx, "Users", 3))
|
||||
<h1>@i18n!(ctx.1, "Users")</h1>
|
||||
|
||||
@tabs(&[
|
||||
(&uri!(instance::admin).to_string(), i18n!(ctx.1, "Configuration"), false),
|
||||
(&uri!(instance::admin_instances: page = _).to_string(), i18n!(ctx.1, "Instances"), false),
|
||||
(&uri!(instance::admin_users: page = _).to_string(), i18n!(ctx.1, "Users"), true),
|
||||
(&uri!(instance::admin_email_blocklist: page=_).to_string(), i18n!(ctx.1, "Email blocklist"), false)
|
||||
])
|
||||
|
||||
<form method="get" action="@uri!(instance::admin_search_users: page = _, user = user.unwrap_or_default())">
|
||||
<header>
|
||||
|
@ -124,7 +124,7 @@
|
||||
</section>
|
||||
}
|
||||
<section class="banner">
|
||||
<div class="flex wrap p-author h-card user" dir="auto">
|
||||
<div class="flex p-author h-card user" dir="auto">
|
||||
@avatar(ctx.0, &author, Size::Medium, true, ctx.1)
|
||||
<div class="grow">
|
||||
<h2 class="p-name">
|
||||
|
Loading…
Reference in New Issue
Block a user