Merge branch 'develop' into refactor/types
This commit is contained in:
commit
082948bfe0
129 changed files with 1759 additions and 1221 deletions
|
@ -178,19 +178,13 @@ logLevel: [
|
||||||
# Media Proxy
|
# Media Proxy
|
||||||
#mediaProxy: https://example.com/proxy
|
#mediaProxy: https://example.com/proxy
|
||||||
|
|
||||||
# Proxy remote files (default: false)
|
# Proxy remote files (default: true)
|
||||||
#proxyRemoteFiles: true
|
#proxyRemoteFiles: true
|
||||||
|
|
||||||
#allowedPrivateNetworks: [
|
#allowedPrivateNetworks: [
|
||||||
# '127.0.0.1/32'
|
# '127.0.0.1/32'
|
||||||
#]
|
#]
|
||||||
|
|
||||||
# TWA
|
|
||||||
#twa:
|
|
||||||
# nameSpace: android_app
|
|
||||||
# packageName: tld.domain.twa
|
|
||||||
# sha256CertFingerprints: ['AB:CD:EF']
|
|
||||||
|
|
||||||
# Upload or download file size limits (bytes)
|
# Upload or download file size limits (bytes)
|
||||||
#maxFileSize: 262144000
|
#maxFileSize: 262144000
|
||||||
|
|
||||||
|
|
|
@ -3,30 +3,38 @@
|
||||||
🔒 Found a security vulnerability? [Please disclose it responsibly.](https://firefish.dev/firefish/firefish/-/blob/develop/SECURITY.md)
|
🔒 Found a security vulnerability? [Please disclose it responsibly.](https://firefish.dev/firefish/firefish/-/blob/develop/SECURITY.md)
|
||||||
🤝 By submitting this issue, you agree to follow our [Contribution Guidelines.](https://firefish.dev/firefish/firefish/-/blob/develop/CONTRIBUTING.md) -->
|
🤝 By submitting this issue, you agree to follow our [Contribution Guidelines.](https://firefish.dev/firefish/firefish/-/blob/develop/CONTRIBUTING.md) -->
|
||||||
|
|
||||||
**What happened?** _(Please give us a brief description of what happened.)_
|
## What happened? <!-- Please give us a brief description of what happened. -->
|
||||||
|
|
||||||
**What did you expect to happen?** _(Please give us a brief description of what you expected to happen.)_
|
## What did you expect to happen? <!-- Please give us a brief description of what you expected to happen. -->
|
||||||
|
|
||||||
**Version** _(What version of firefish is your instance running? You can find this by clicking your instance's logo at the bottom left and then clicking instance information.)_
|
## Version <!-- What version of firefish is your instance running? You can find this by clicking your instance's logo at the bottom left and then clicking instance information. -->
|
||||||
|
|
||||||
**Instance** _(What instance of firefish are you using?)_
|
## What type of issue is this? <!-- If this happens on your device and has to do with the user interface, it's client-side. If this happens on either with the API or the backend, or you got a server-side error in the client, it's server-side. -->
|
||||||
|
|
||||||
**What type of issue is this?** _(If this happens on your device and has to do with the user interface, it's client-side. If this happens on either with the API or the backend, or you got a server-side error in the client, it's server-side.)_
|
- [] server-side
|
||||||
|
- [] client-side
|
||||||
|
- [] not sure
|
||||||
|
|
||||||
**What browser are you using? (Client-side issues only)**
|
<details>
|
||||||
|
|
||||||
**What operating system are you using? (Client-side issues only)**
|
### Instance <!-- What instance of firefish are you using? -->
|
||||||
|
|
||||||
**How do you deploy Firefish on your server? (Server-side issues only)**
|
### What browser are you using? (client-side issues only)
|
||||||
|
|
||||||
**What operating system are you using? (Server-side issues only)**
|
### What operating system are you using? (client-side issues only)
|
||||||
|
|
||||||
**Relevant log output** _(Please copy and paste any relevant log output. You can find your log by inspecting the page, and going to the "console" tab. This will be automatically formatted into code, so no need for backticks.)_
|
### How do you deploy Firefish on your server? (server-side issues only)
|
||||||
|
|
||||||
**Contribution Guidelines**
|
### What operating system are you using? (Server-side issues only)
|
||||||
|
|
||||||
|
### Relevant log output <!-- Please copy and paste any relevant log output. You can find your log by inspecting the page, and going to the "console" tab. -->
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## Contribution Guidelines
|
||||||
By submitting this issue, you agree to follow our [Contribution Guidelines](https://firefish.dev/firefish/firefish/-/blob/develop/CONTRIBUTING.md)
|
By submitting this issue, you agree to follow our [Contribution Guidelines](https://firefish.dev/firefish/firefish/-/blob/develop/CONTRIBUTING.md)
|
||||||
- [ ] I agree to follow this project's Contribution Guidelines
|
- [ ] I agree to follow this project's Contribution Guidelines
|
||||||
- [ ] I have searched the issue tracker for similar issues, and this is not a duplicate.
|
- [ ] I have searched the issue tracker for similar issues, and this is not a duplicate.
|
||||||
|
|
||||||
**Are you willing to fix this bug?** (optional)
|
## Are you willing to fix this bug? (optional)
|
||||||
- [ ] Yes. I will fix this bug and open a merge request if the change is agreed upon.
|
- [ ] Yes. I will fix this bug and open a merge request if the change is agreed upon.
|
||||||
|
|
|
@ -3,18 +3,18 @@
|
||||||
🔒 Found a security vulnerability? [Please disclose it responsibly.](https://firefish.dev/firefish/firefish/-/blob/develop/SECURITY.md)
|
🔒 Found a security vulnerability? [Please disclose it responsibly.](https://firefish.dev/firefish/firefish/-/blob/develop/SECURITY.md)
|
||||||
🤝 By submitting this feature request, you agree to follow our [Contribution Guidelines.](https://firefish.dev/firefish/firefish/-/blob/develop/CONTRIBUTING.md) -->
|
🤝 By submitting this feature request, you agree to follow our [Contribution Guidelines.](https://firefish.dev/firefish/firefish/-/blob/develop/CONTRIBUTING.md) -->
|
||||||
|
|
||||||
**What feature would you like implemented?** _(Please give us a brief description of what you'd like.)_
|
## What feature would you like implemented? <!-- Please give us a brief description of what you'd like. -->
|
||||||
|
|
||||||
**Why should we add this feature?** _(Please give us a brief description of why your feature is important.)_
|
## Why should we add this feature? <!-- Please give us a brief description of why your feature is important. -->
|
||||||
|
|
||||||
**Version** _(What version of firefish is your instance running? You can find this by clicking your instance's logo at the bottom left and then clicking instance information.)_
|
## Version <!-- What version of firefish is your instance running? You can find this by clicking your instance's logo at the bottom left and then clicking instance information. -->
|
||||||
|
|
||||||
**Instance** _(What instance of firefish are you using?)_
|
## Instance <!-- What instance of firefish are you using? -->
|
||||||
|
|
||||||
**Contribution Guidelines**
|
## Contribution Guidelines
|
||||||
By submitting this issue, you agree to follow our [Contribution Guidelines](https://firefish.dev/firefish/firefish/-/blob/develop/CONTRIBUTING.md)
|
By submitting this issue, you agree to follow our [Contribution Guidelines](https://firefish.dev/firefish/firefish/-/blob/develop/CONTRIBUTING.md)
|
||||||
- [ ] I agree to follow this project's Contribution Guidelines
|
- [ ] I agree to follow this project's Contribution Guidelines
|
||||||
- [ ] I have searched the issue tracker for similar requests, and this is not a duplicate.
|
- [ ] I have searched the issue tracker for similar requests, and this is not a duplicate.
|
||||||
|
|
||||||
**Are you willing to implement this feature?** (optional)
|
## Are you willing to implement this feature? (optional)
|
||||||
- [ ] Yes. I will implement this feature and open a merge request if the change is agreed upon.
|
- [ ] Yes. I will implement this feature and open a merge request if the change is agreed upon.
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<!-- Thanks for taking the time to make Firefish better! It's not required, but please consider using [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) when making your commits. If you use VSCode, please use the [Conventional Commits extension](https://marketplace.visualstudio.com/items?itemName=vivaxy.vscode-conventional-commits). -->
|
<!-- Thanks for taking the time to make Firefish better! It's not required, but please consider using [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) when making your commits. If you use VSCode, please use the [Conventional Commits extension](https://marketplace.visualstudio.com/items?itemName=vivaxy.vscode-conventional-commits). -->
|
||||||
|
|
||||||
**What does this PR do?** _(Please give us a brief description of what this PR does.)_
|
## What does this PR do? <!-- Please give us a brief description of what this PR does. -->
|
||||||
|
|
||||||
**Contribution Guidelines**
|
## Contribution Guidelines
|
||||||
By submitting this merge request, you agree to follow our [Contribution Guidelines](https://firefish.dev/firefish/firefish/-/blob/develop/CONTRIBUTING.md)
|
By submitting this merge request, you agree to follow our [Contribution Guidelines](https://firefish.dev/firefish/firefish/-/blob/develop/CONTRIBUTING.md)
|
||||||
- [ ] This change is reviewed in an issue / This is a minor bug fix
|
- [ ] This change is reviewed in an issue / This is a minor bug fix
|
||||||
- [ ] I agree to follow this project's Contribution Guidelines
|
- [ ] I agree to follow this project's Contribution Guidelines
|
||||||
|
|
3
.vscode/extensions.json
vendored
3
.vscode/extensions.json
vendored
|
@ -12,6 +12,7 @@
|
||||||
"esbenp.prettier-vscode",
|
"esbenp.prettier-vscode",
|
||||||
"redhat.vscode-yaml",
|
"redhat.vscode-yaml",
|
||||||
"yoavbls.pretty-ts-errors",
|
"yoavbls.pretty-ts-errors",
|
||||||
"biomejs.biome"
|
"biomejs.biome",
|
||||||
|
"rust-lang.rust-analyzer"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
207
Cargo.lock
generated
207
Cargo.lock
generated
|
@ -59,9 +59,9 @@ checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "allocator-api2"
|
name = "allocator-api2"
|
||||||
version = "0.2.16"
|
version = "0.2.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
|
checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "android-tzdata"
|
name = "android-tzdata"
|
||||||
|
@ -132,6 +132,18 @@ version = "1.0.82"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519"
|
checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "argon2"
|
||||||
|
version = "0.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072"
|
||||||
|
dependencies = [
|
||||||
|
"base64ct",
|
||||||
|
"blake2",
|
||||||
|
"cpufeatures",
|
||||||
|
"password-hash",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayvec"
|
name = "arrayvec"
|
||||||
version = "0.7.4"
|
version = "0.7.4"
|
||||||
|
@ -190,11 +202,14 @@ checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
|
||||||
name = "backend-rs"
|
name = "backend-rs"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"argon2",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"basen",
|
"basen",
|
||||||
|
"bcrypt",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"chrono",
|
"chrono",
|
||||||
"cuid2",
|
"cuid2",
|
||||||
|
"emojis",
|
||||||
"idna",
|
"idna",
|
||||||
"jsonschema",
|
"jsonschema",
|
||||||
"macro_rs",
|
"macro_rs",
|
||||||
|
@ -238,6 +253,12 @@ version = "0.21.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
|
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.22.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base64ct"
|
name = "base64ct"
|
||||||
version = "1.6.0"
|
version = "1.6.0"
|
||||||
|
@ -250,6 +271,19 @@ version = "0.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1dbe4bb73fd931c4d1aaf53b35d1286c8a948ad00ec92c8e3c856f15fd027f43"
|
checksum = "1dbe4bb73fd931c4d1aaf53b35d1286c8a948ad00ec92c8e3c856f15fd027f43"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bcrypt"
|
||||||
|
version = "0.15.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e65938ed058ef47d92cf8b346cc76ef48984572ade631927e9937b5ffc7662c7"
|
||||||
|
dependencies = [
|
||||||
|
"base64 0.22.0",
|
||||||
|
"blowfish",
|
||||||
|
"getrandom",
|
||||||
|
"subtle",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bigdecimal"
|
name = "bigdecimal"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
|
@ -303,6 +337,15 @@ dependencies = [
|
||||||
"wyz",
|
"wyz",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "blake2"
|
||||||
|
version = "0.10.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe"
|
||||||
|
dependencies = [
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block-buffer"
|
name = "block-buffer"
|
||||||
version = "0.10.4"
|
version = "0.10.4"
|
||||||
|
@ -312,6 +355,16 @@ dependencies = [
|
||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "blowfish"
|
||||||
|
version = "0.9.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"cipher",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "borsh"
|
name = "borsh"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
|
@ -384,9 +437,9 @@ checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.92"
|
version = "1.0.94"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41"
|
checksum = "17f6e324229dc011159fcc089755d1e2e216a90d43a7dea6853ca740b84f35e7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
|
@ -412,7 +465,17 @@ dependencies = [
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"serde",
|
"serde",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"windows-targets 0.52.4",
|
"windows-targets 0.52.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cipher"
|
||||||
|
version = "0.4.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
|
||||||
|
dependencies = [
|
||||||
|
"crypto-common",
|
||||||
|
"inout",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -633,13 +696,22 @@ checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.10.0"
|
version = "1.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a"
|
checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "emojis"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4ee61eb945bff65ee7d19d157d39c67c33290ff0742907413fd5eefd29edc979"
|
||||||
|
dependencies = [
|
||||||
|
"phf",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encoding_rs"
|
name = "encoding_rs"
|
||||||
version = "0.8.34"
|
version = "0.8.34"
|
||||||
|
@ -1075,6 +1147,15 @@ dependencies = [
|
||||||
"syn 2.0.58",
|
"syn 2.0.58",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "inout"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ipnet"
|
name = "ipnet"
|
||||||
version = "2.9.0"
|
version = "2.9.0"
|
||||||
|
@ -1122,7 +1203,7 @@ checksum = "2a071f4f7efc9a9118dfb627a0a94ef247986e1ab8606a4c806ae2b3aa3b6978"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash 0.8.11",
|
"ahash 0.8.11",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64",
|
"base64 0.21.7",
|
||||||
"bytecount",
|
"bytecount",
|
||||||
"clap",
|
"clap",
|
||||||
"fancy-regex",
|
"fancy-regex",
|
||||||
|
@ -1175,7 +1256,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"
|
checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"windows-targets 0.52.4",
|
"windows-targets 0.52.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1296,9 +1377,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "napi-build"
|
name = "napi-build"
|
||||||
version = "2.1.2"
|
version = "2.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2f9130fccc5f763cf2069b34a089a18f0d0883c66aceb81f2fad541a3d823c43"
|
checksum = "e1c0f5d67ee408a4685b61f5ab7e58605c8ae3f2b4189f0127d804ff13d5560a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "napi-derive"
|
name = "napi-derive"
|
||||||
|
@ -1350,9 +1431,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num"
|
name = "num"
|
||||||
version = "0.4.1"
|
version = "0.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af"
|
checksum = "3135b08af27d103b0a51f2ae0f8632117b7b185ccf931445affa8df530576a41"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"num-complex",
|
"num-complex",
|
||||||
|
@ -1559,6 +1640,17 @@ dependencies = [
|
||||||
"syn 2.0.58",
|
"syn 2.0.58",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "password-hash"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166"
|
||||||
|
dependencies = [
|
||||||
|
"base64ct",
|
||||||
|
"rand_core",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "paste"
|
name = "paste"
|
||||||
version = "1.0.14"
|
version = "1.0.14"
|
||||||
|
@ -1580,6 +1672,24 @@ version = "2.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "phf"
|
||||||
|
version = "0.11.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
|
||||||
|
dependencies = [
|
||||||
|
"phf_shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "phf_shared"
|
||||||
|
version = "0.11.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b"
|
||||||
|
dependencies = [
|
||||||
|
"siphasher",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project-lite"
|
name = "pin-project-lite"
|
||||||
version = "0.2.14"
|
version = "0.2.14"
|
||||||
|
@ -1801,7 +1911,7 @@ version = "0.11.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62"
|
checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64 0.21.7",
|
||||||
"bytes",
|
"bytes",
|
||||||
"encoding_rs",
|
"encoding_rs",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
|
@ -1947,7 +2057,7 @@ version = "1.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c"
|
checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64 0.21.7",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2231,6 +2341,12 @@ version = "0.1.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a"
|
checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "siphasher"
|
||||||
|
version = "0.3.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "slab"
|
name = "slab"
|
||||||
version = "0.4.9"
|
version = "0.4.9"
|
||||||
|
@ -2398,7 +2514,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418"
|
checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atoi",
|
"atoi",
|
||||||
"base64",
|
"base64 0.21.7",
|
||||||
"bigdecimal",
|
"bigdecimal",
|
||||||
"bitflags 2.5.0",
|
"bitflags 2.5.0",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
|
@ -2445,7 +2561,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e"
|
checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atoi",
|
"atoi",
|
||||||
"base64",
|
"base64 0.21.7",
|
||||||
"bigdecimal",
|
"bigdecimal",
|
||||||
"bitflags 2.5.0",
|
"bitflags 2.5.0",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
|
@ -3041,7 +3157,7 @@ version = "0.52.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
|
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-targets 0.52.4",
|
"windows-targets 0.52.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3059,7 +3175,7 @@ version = "0.52.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-targets 0.52.4",
|
"windows-targets 0.52.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3079,17 +3195,18 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-targets"
|
name = "windows-targets"
|
||||||
version = "0.52.4"
|
version = "0.52.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
|
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows_aarch64_gnullvm 0.52.4",
|
"windows_aarch64_gnullvm 0.52.5",
|
||||||
"windows_aarch64_msvc 0.52.4",
|
"windows_aarch64_msvc 0.52.5",
|
||||||
"windows_i686_gnu 0.52.4",
|
"windows_i686_gnu 0.52.5",
|
||||||
"windows_i686_msvc 0.52.4",
|
"windows_i686_gnullvm",
|
||||||
"windows_x86_64_gnu 0.52.4",
|
"windows_i686_msvc 0.52.5",
|
||||||
"windows_x86_64_gnullvm 0.52.4",
|
"windows_x86_64_gnu 0.52.5",
|
||||||
"windows_x86_64_msvc 0.52.4",
|
"windows_x86_64_gnullvm 0.52.5",
|
||||||
|
"windows_x86_64_msvc 0.52.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3100,9 +3217,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_gnullvm"
|
name = "windows_aarch64_gnullvm"
|
||||||
version = "0.52.4"
|
version = "0.52.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
|
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_msvc"
|
name = "windows_aarch64_msvc"
|
||||||
|
@ -3112,9 +3229,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_msvc"
|
name = "windows_aarch64_msvc"
|
||||||
version = "0.52.4"
|
version = "0.52.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
|
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnu"
|
name = "windows_i686_gnu"
|
||||||
|
@ -3124,9 +3241,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnu"
|
name = "windows_i686_gnu"
|
||||||
version = "0.52.4"
|
version = "0.52.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
|
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnullvm"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_msvc"
|
name = "windows_i686_msvc"
|
||||||
|
@ -3136,9 +3259,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_msvc"
|
name = "windows_i686_msvc"
|
||||||
version = "0.52.4"
|
version = "0.52.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
|
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnu"
|
name = "windows_x86_64_gnu"
|
||||||
|
@ -3148,9 +3271,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnu"
|
name = "windows_x86_64_gnu"
|
||||||
version = "0.52.4"
|
version = "0.52.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
|
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnullvm"
|
name = "windows_x86_64_gnullvm"
|
||||||
|
@ -3160,9 +3283,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnullvm"
|
name = "windows_x86_64_gnullvm"
|
||||||
version = "0.52.4"
|
version = "0.52.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
|
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_msvc"
|
name = "windows_x86_64_msvc"
|
||||||
|
@ -3172,9 +3295,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_msvc"
|
name = "windows_x86_64_msvc"
|
||||||
version = "0.52.4"
|
version = "0.52.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
|
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winnow"
|
name = "winnow"
|
||||||
|
|
|
@ -7,14 +7,17 @@ macro_rs = { path = "packages/macro-rs" }
|
||||||
|
|
||||||
napi = { version = "2.16.2", default-features = false }
|
napi = { version = "2.16.2", default-features = false }
|
||||||
napi-derive = "2.16.2"
|
napi-derive = "2.16.2"
|
||||||
napi-build = "2.1.2"
|
napi-build = "2.1.3"
|
||||||
|
|
||||||
|
argon2 = "0.5.3"
|
||||||
async-trait = "0.1.80"
|
async-trait = "0.1.80"
|
||||||
basen = "0.1.0"
|
basen = "0.1.0"
|
||||||
|
bcrypt = "0.15.1"
|
||||||
cfg-if = "1.0.0"
|
cfg-if = "1.0.0"
|
||||||
chrono = "0.4.37"
|
chrono = "0.4.37"
|
||||||
convert_case = "0.6.0"
|
convert_case = "0.6.0"
|
||||||
cuid2 = "0.1.2"
|
cuid2 = "0.1.2"
|
||||||
|
emojis = "0.6.1"
|
||||||
idna = "0.5.0"
|
idna = "0.5.0"
|
||||||
jsonschema = "0.17.1"
|
jsonschema = "0.17.1"
|
||||||
once_cell = "1.19.0"
|
once_cell = "1.19.0"
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
Breaking changes are indicated by the :warning: icon.
|
Breaking changes are indicated by the :warning: icon.
|
||||||
|
|
||||||
## Unreleased
|
## v20240413
|
||||||
|
|
||||||
- :warning: Removed `patrons` endpoint.
|
- :warning: Removed `patrons` endpoint.
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,12 @@ Critical security updates are indicated by the :warning: icon.
|
||||||
- Server administrators should check [notice-for-admins.md](./notice-for-admins.md) as well.
|
- Server administrators should check [notice-for-admins.md](./notice-for-admins.md) as well.
|
||||||
- Third-party client/bot developers may want to check [api-change.md](./api-change.md) as well.
|
- Third-party client/bot developers may want to check [api-change.md](./api-change.md) as well.
|
||||||
|
|
||||||
## Unreleased
|
## [v20240413](https://firefish.dev/firefish/firefish/-/merge_requests/10741/commits)
|
||||||
|
|
||||||
- Add "Media" tab to user page
|
- Add "Media" tab to user page
|
||||||
|
- Improve federation and rendering of mathematical expressions
|
||||||
|
- Remove donor information from the web client
|
||||||
|
- See also: https://info.firefish.dev/notes/9s1n283sb10rh869
|
||||||
- Fix bugs
|
- Fix bugs
|
||||||
|
|
||||||
## [v20240405](https://firefish.dev/firefish/firefish/-/merge_requests/10733/commits)
|
## [v20240405](https://firefish.dev/firefish/firefish/-/merge_requests/10733/commits)
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
You can skip intermediate versions when upgrading from an old version, but please read the notices and follow the instructions for each intermediate version before [upgrading](./upgrade.md).
|
You can skip intermediate versions when upgrading from an old version, but please read the notices and follow the instructions for each intermediate version before [upgrading](./upgrade.md).
|
||||||
|
|
||||||
## Unreleased
|
## v20240413
|
||||||
|
|
||||||
### For all users
|
### For all users
|
||||||
|
|
||||||
|
|
|
@ -2318,3 +2318,4 @@ markLocalFilesNsfwByDefaultDescription: Indépendamment de ce réglage, les util
|
||||||
peuvent supprimer le drapeau « sensible » (NSFW) eux-mêmes. Les fichiers existants
|
peuvent supprimer le drapeau « sensible » (NSFW) eux-mêmes. Les fichiers existants
|
||||||
ne sont pas affectés.
|
ne sont pas affectés.
|
||||||
noteEditHistory: Historique des publications
|
noteEditHistory: Historique des publications
|
||||||
|
media: Multimédia
|
||||||
|
|
10
package.json
10
package.json
|
@ -1,11 +1,11 @@
|
||||||
{
|
{
|
||||||
"name": "firefish",
|
"name": "firefish",
|
||||||
"version": "20240405",
|
"version": "20240413",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://firefish.dev/firefish/firefish.git"
|
"url": "https://firefish.dev/firefish/firefish.git"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@8.15.6",
|
"packageManager": "pnpm@8.15.7",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"rebuild": "pnpm run clean && pnpm run build",
|
"rebuild": "pnpm run clean && pnpm run build",
|
||||||
|
@ -36,11 +36,11 @@
|
||||||
"clean-all": "pnpm run clean && pnpm run clean-cargo && pnpm run clean-npm"
|
"clean-all": "pnpm run clean && pnpm run clean-cargo && pnpm run clean-npm"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"js-yaml": "4.1.0",
|
|
||||||
"gulp": "4.0.2",
|
"gulp": "4.0.2",
|
||||||
"gulp-cssnano": "2.1.3",
|
"gulp-cssnano": "2.1.3",
|
||||||
"gulp-replace": "1.1.4",
|
"gulp-replace": "1.1.4",
|
||||||
"gulp-terser": "2.1.0"
|
"gulp-terser": "2.1.0",
|
||||||
|
"js-yaml": "4.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "1.6.4",
|
"@biomejs/biome": "1.6.4",
|
||||||
|
@ -50,7 +50,7 @@
|
||||||
"@biomejs/cli-linux-x64": "^1.6.4",
|
"@biomejs/cli-linux-x64": "^1.6.4",
|
||||||
"@types/node": "20.12.7",
|
"@types/node": "20.12.7",
|
||||||
"execa": "8.0.1",
|
"execa": "8.0.1",
|
||||||
"pnpm": "8.15.6",
|
"pnpm": "8.15.7",
|
||||||
"typescript": "5.4.5"
|
"typescript": "5.4.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ This directory contains all of the packages Firefish uses.
|
||||||
|
|
||||||
- `backend`: Main backend code written in TypeScript for NodeJS
|
- `backend`: Main backend code written in TypeScript for NodeJS
|
||||||
- `backend-rs`: Backend code written in Rust, bound to NodeJS by [NAPI-RS](https://napi.rs/)
|
- `backend-rs`: Backend code written in Rust, bound to NodeJS by [NAPI-RS](https://napi.rs/)
|
||||||
|
- `macro-rs`: Procedural macros for backend-rs
|
||||||
- `client`: Web interface written in Vue3 and TypeScript
|
- `client`: Web interface written in Vue3 and TypeScript
|
||||||
- `sw`: Web [Service Worker](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) written in TypeScript
|
- `sw`: Web [Service Worker](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) written in TypeScript
|
||||||
- `firefish-js`: TypeScript SDK for both backend and client
|
- `firefish-js`: TypeScript SDK for both backend and client
|
||||||
|
|
|
@ -17,11 +17,14 @@ macro_rs = { workspace = true }
|
||||||
napi = { workspace = true, optional = true, default-features = false, features = ["napi9", "tokio_rt", "chrono_date", "serde-json"] }
|
napi = { workspace = true, optional = true, default-features = false, features = ["napi9", "tokio_rt", "chrono_date", "serde-json"] }
|
||||||
napi-derive = { workspace = true, optional = true }
|
napi-derive = { workspace = true, optional = true }
|
||||||
|
|
||||||
|
argon2 = { workspace = true, features = ["std"] }
|
||||||
async-trait = { workspace = true }
|
async-trait = { workspace = true }
|
||||||
basen = { workspace = true }
|
basen = { workspace = true }
|
||||||
|
bcrypt = { workspace = true }
|
||||||
cfg-if = { workspace = true }
|
cfg-if = { workspace = true }
|
||||||
chrono = { workspace = true }
|
chrono = { workspace = true }
|
||||||
cuid2 = { workspace = true }
|
cuid2 = { workspace = true }
|
||||||
|
emojis = { workspace = true }
|
||||||
idna = { workspace = true }
|
idna = { workspace = true }
|
||||||
jsonschema = { workspace = true }
|
jsonschema = { workspace = true }
|
||||||
once_cell = { workspace = true }
|
once_cell = { workspace = true }
|
||||||
|
|
39
packages/backend-rs/index.d.ts
vendored
39
packages/backend-rs/index.d.ts
vendored
|
@ -3,6 +3,16 @@
|
||||||
|
|
||||||
/* auto-generated by NAPI-RS */
|
/* auto-generated by NAPI-RS */
|
||||||
|
|
||||||
|
export interface EnvConfig {
|
||||||
|
onlyQueue: boolean
|
||||||
|
onlyServer: boolean
|
||||||
|
noDaemons: boolean
|
||||||
|
disableClustering: boolean
|
||||||
|
verbose: boolean
|
||||||
|
withLogTime: boolean
|
||||||
|
slow: boolean
|
||||||
|
}
|
||||||
|
export function readEnvironmentConfig(): EnvConfig
|
||||||
export interface ServerConfig {
|
export interface ServerConfig {
|
||||||
url: string
|
url: string
|
||||||
port: number
|
port: number
|
||||||
|
@ -132,9 +142,38 @@ export function isSelfHost(host?: string | undefined | null): boolean
|
||||||
export function isSameOrigin(uri: string): boolean
|
export function isSameOrigin(uri: string): boolean
|
||||||
export function extractHost(uri: string): string
|
export function extractHost(uri: string): string
|
||||||
export function toPuny(host: string): string
|
export function toPuny(host: string): string
|
||||||
|
export function isUnicodeEmoji(s: string): boolean
|
||||||
|
export function sqlLikeEscape(src: string): string
|
||||||
|
export function safeForSql(src: string): boolean
|
||||||
|
/** Convert milliseconds to a human readable string */
|
||||||
|
export function formatMilliseconds(milliseconds: number): string
|
||||||
export function toMastodonId(firefishId: string): string | null
|
export function toMastodonId(firefishId: string): string | null
|
||||||
export function fromMastodonId(mastodonId: string): string | null
|
export function fromMastodonId(mastodonId: string): string | null
|
||||||
|
export function fetchMeta(useCache: boolean): Promise<Meta>
|
||||||
|
export interface PugArgs {
|
||||||
|
img: string | null
|
||||||
|
title: string
|
||||||
|
instanceName: string
|
||||||
|
desc: string | null
|
||||||
|
icon: string | null
|
||||||
|
splashIcon: string | null
|
||||||
|
themeColor: string | null
|
||||||
|
randomMotd: string
|
||||||
|
privateMode: boolean | null
|
||||||
|
}
|
||||||
|
export function metaToPugArgs(meta: Meta): PugArgs
|
||||||
export function nyaify(text: string, lang?: string | undefined | null): string
|
export function nyaify(text: string, lang?: string | undefined | null): string
|
||||||
|
export function hashPassword(password: string): string
|
||||||
|
export function verifyPassword(password: string, hash: string): boolean
|
||||||
|
export function isOldPasswordAlgorithm(hash: string): boolean
|
||||||
|
export interface DecodedReaction {
|
||||||
|
reaction: string
|
||||||
|
name: string | null
|
||||||
|
host: string | null
|
||||||
|
}
|
||||||
|
export function decodeReaction(reaction: string): DecodedReaction
|
||||||
|
export function countReactions(reactions: Record<string, number>): Record<string, number>
|
||||||
|
export function toDbReaction(reaction?: string | undefined | null, host?: string | undefined | null): Promise<string>
|
||||||
export interface AbuseUserReport {
|
export interface AbuseUserReport {
|
||||||
id: string
|
id: string
|
||||||
createdAt: Date
|
createdAt: Date
|
||||||
|
|
|
@ -310,8 +310,9 @@ if (!nativeBinding) {
|
||||||
throw new Error(`Failed to load native binding`)
|
throw new Error(`Failed to load native binding`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const { readServerConfig, stringToAcct, acctToString, checkWordMute, getFullApAccount, isSelfHost, isSameOrigin, extractHost, toPuny, toMastodonId, fromMastodonId, nyaify, AntennaSrcEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, initIdGenerator, getTimestamp, genId, secureRndstr } = nativeBinding
|
const { readEnvironmentConfig, readServerConfig, stringToAcct, acctToString, checkWordMute, getFullApAccount, isSelfHost, isSameOrigin, extractHost, toPuny, isUnicodeEmoji, sqlLikeEscape, safeForSql, formatMilliseconds, toMastodonId, fromMastodonId, fetchMeta, metaToPugArgs, nyaify, hashPassword, verifyPassword, isOldPasswordAlgorithm, decodeReaction, countReactions, toDbReaction, AntennaSrcEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, initIdGenerator, getTimestamp, genId, secureRndstr } = nativeBinding
|
||||||
|
|
||||||
|
module.exports.readEnvironmentConfig = readEnvironmentConfig
|
||||||
module.exports.readServerConfig = readServerConfig
|
module.exports.readServerConfig = readServerConfig
|
||||||
module.exports.stringToAcct = stringToAcct
|
module.exports.stringToAcct = stringToAcct
|
||||||
module.exports.acctToString = acctToString
|
module.exports.acctToString = acctToString
|
||||||
|
@ -321,9 +322,21 @@ module.exports.isSelfHost = isSelfHost
|
||||||
module.exports.isSameOrigin = isSameOrigin
|
module.exports.isSameOrigin = isSameOrigin
|
||||||
module.exports.extractHost = extractHost
|
module.exports.extractHost = extractHost
|
||||||
module.exports.toPuny = toPuny
|
module.exports.toPuny = toPuny
|
||||||
|
module.exports.isUnicodeEmoji = isUnicodeEmoji
|
||||||
|
module.exports.sqlLikeEscape = sqlLikeEscape
|
||||||
|
module.exports.safeForSql = safeForSql
|
||||||
|
module.exports.formatMilliseconds = formatMilliseconds
|
||||||
module.exports.toMastodonId = toMastodonId
|
module.exports.toMastodonId = toMastodonId
|
||||||
module.exports.fromMastodonId = fromMastodonId
|
module.exports.fromMastodonId = fromMastodonId
|
||||||
|
module.exports.fetchMeta = fetchMeta
|
||||||
|
module.exports.metaToPugArgs = metaToPugArgs
|
||||||
module.exports.nyaify = nyaify
|
module.exports.nyaify = nyaify
|
||||||
|
module.exports.hashPassword = hashPassword
|
||||||
|
module.exports.verifyPassword = verifyPassword
|
||||||
|
module.exports.isOldPasswordAlgorithm = isOldPasswordAlgorithm
|
||||||
|
module.exports.decodeReaction = decodeReaction
|
||||||
|
module.exports.countReactions = countReactions
|
||||||
|
module.exports.toDbReaction = toDbReaction
|
||||||
module.exports.AntennaSrcEnum = AntennaSrcEnum
|
module.exports.AntennaSrcEnum = AntennaSrcEnum
|
||||||
module.exports.MutedNoteReasonEnum = MutedNoteReasonEnum
|
module.exports.MutedNoteReasonEnum = MutedNoteReasonEnum
|
||||||
module.exports.NoteVisibilityEnum = NoteVisibilityEnum
|
module.exports.NoteVisibilityEnum = NoteVisibilityEnum
|
||||||
|
|
27
packages/backend-rs/src/config/environment.rs
Normal file
27
packages/backend-rs/src/config/environment.rs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
// FIXME: Are these options used?
|
||||||
|
#[crate::export(object)]
|
||||||
|
pub struct EnvConfig {
|
||||||
|
pub only_queue: bool,
|
||||||
|
pub only_server: bool,
|
||||||
|
pub no_daemons: bool,
|
||||||
|
pub disable_clustering: bool,
|
||||||
|
pub verbose: bool,
|
||||||
|
pub with_log_time: bool,
|
||||||
|
pub slow: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[crate::export]
|
||||||
|
pub fn read_environment_config() -> EnvConfig {
|
||||||
|
let node_env = std::env::var("NODE_ENV").unwrap_or_default().to_lowercase();
|
||||||
|
let is_testing = node_env == "test";
|
||||||
|
|
||||||
|
EnvConfig {
|
||||||
|
only_queue: std::env::var("MK_ONLY_QUEUE").is_ok(),
|
||||||
|
only_server: std::env::var("MK_ONLY_SERVER").is_ok(),
|
||||||
|
no_daemons: is_testing || std::env::var("MK_NO_DAEMONS").is_ok(),
|
||||||
|
disable_clustering: is_testing || std::env::var("MK_DISABLE_CLUSTERING").is_ok(),
|
||||||
|
verbose: std::env::var("MK_VERBOSE").is_ok(),
|
||||||
|
with_log_time: std::env::var("MK_WITH_LOG_TIME").is_ok(),
|
||||||
|
slow: std::env::var("MK_SLOW").is_ok(),
|
||||||
|
}
|
||||||
|
}
|
|
@ -1 +1,2 @@
|
||||||
|
pub mod environment;
|
||||||
pub mod server;
|
pub mod server;
|
||||||
|
|
31
packages/backend-rs/src/misc/emoji.rs
Normal file
31
packages/backend-rs/src/misc/emoji.rs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#[inline]
|
||||||
|
#[crate::export]
|
||||||
|
pub fn is_unicode_emoji(s: &str) -> bool {
|
||||||
|
emojis::get(s).is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod unit_test {
|
||||||
|
use super::is_unicode_emoji;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_unicode_emoji_check() {
|
||||||
|
assert!(is_unicode_emoji("⭐"));
|
||||||
|
assert!(is_unicode_emoji("👍"));
|
||||||
|
assert!(is_unicode_emoji("❤"));
|
||||||
|
assert!(is_unicode_emoji("♥️"));
|
||||||
|
assert!(is_unicode_emoji("❤️"));
|
||||||
|
assert!(is_unicode_emoji("💙"));
|
||||||
|
assert!(is_unicode_emoji("🩷"));
|
||||||
|
assert!(is_unicode_emoji("🖖🏿"));
|
||||||
|
assert!(is_unicode_emoji("🏃➡️"));
|
||||||
|
assert!(is_unicode_emoji("👩❤️👨"));
|
||||||
|
assert!(is_unicode_emoji("👩👦👦"));
|
||||||
|
assert!(is_unicode_emoji("🏳️🌈"));
|
||||||
|
|
||||||
|
assert!(!is_unicode_emoji("⭐⭐"));
|
||||||
|
assert!(!is_unicode_emoji("x"));
|
||||||
|
assert!(!is_unicode_emoji("\t"));
|
||||||
|
assert!(!is_unicode_emoji(":meow_aww:"));
|
||||||
|
}
|
||||||
|
}
|
36
packages/backend-rs/src/misc/escape_sql.rs
Normal file
36
packages/backend-rs/src/misc/escape_sql.rs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#[crate::export]
|
||||||
|
pub fn sql_like_escape(src: &str) -> String {
|
||||||
|
src.replace('%', r"\%").replace('_', r"\_")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[crate::export]
|
||||||
|
pub fn safe_for_sql(src: &str) -> bool {
|
||||||
|
!src.contains([
|
||||||
|
'\0', '\x08', '\x09', '\x1a', '\n', '\r', '"', '\'', '\\', '%',
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod unit_test {
|
||||||
|
use super::{safe_for_sql, sql_like_escape};
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sql_like_escape_test() {
|
||||||
|
assert_eq!(sql_like_escape(""), "");
|
||||||
|
assert_eq!(sql_like_escape("abc"), "abc");
|
||||||
|
assert_eq!(sql_like_escape("a%bc"), r"a\%bc");
|
||||||
|
assert_eq!(sql_like_escape("a呼%吸bc"), r"a呼\%吸bc");
|
||||||
|
assert_eq!(sql_like_escape("a呼%吸b%_c"), r"a呼\%吸b\%\_c");
|
||||||
|
assert_eq!(sql_like_escape("_اللغة العربية"), r"\_اللغة العربية");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn safe_for_sql_test() {
|
||||||
|
assert!(safe_for_sql("123"));
|
||||||
|
assert!(safe_for_sql("人間"));
|
||||||
|
assert!(!safe_for_sql("人間\x09"));
|
||||||
|
assert!(!safe_for_sql("abc\ndef"));
|
||||||
|
assert!(!safe_for_sql("%something%"));
|
||||||
|
}
|
||||||
|
}
|
46
packages/backend-rs/src/misc/format_milliseconds.rs
Normal file
46
packages/backend-rs/src/misc/format_milliseconds.rs
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/// Convert milliseconds to a human readable string
|
||||||
|
#[crate::export]
|
||||||
|
pub fn format_milliseconds(milliseconds: u32) -> String {
|
||||||
|
let mut seconds = milliseconds / 1000;
|
||||||
|
let mut minutes = seconds / 60;
|
||||||
|
let mut hours = minutes / 60;
|
||||||
|
let days = hours / 24;
|
||||||
|
|
||||||
|
seconds %= 60;
|
||||||
|
minutes %= 60;
|
||||||
|
hours %= 24;
|
||||||
|
|
||||||
|
let mut buf: Vec<String> = vec![];
|
||||||
|
|
||||||
|
if days > 0 {
|
||||||
|
buf.push(format!("{} day(s)", days));
|
||||||
|
}
|
||||||
|
if hours > 0 {
|
||||||
|
buf.push(format!("{} hour(s)", hours));
|
||||||
|
}
|
||||||
|
if minutes > 0 {
|
||||||
|
buf.push(format!("{} minute(s)", minutes));
|
||||||
|
}
|
||||||
|
if seconds > 0 {
|
||||||
|
buf.push(format!("{} second(s)", seconds));
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.join(", ")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod unit_test {
|
||||||
|
use super::format_milliseconds;
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn format_milliseconds_test() {
|
||||||
|
assert_eq!(format_milliseconds(1000), "1 second(s)");
|
||||||
|
assert_eq!(format_milliseconds(1387938), "23 minute(s), 7 second(s)");
|
||||||
|
assert_eq!(format_milliseconds(34200457), "9 hour(s), 30 minute(s)");
|
||||||
|
assert_eq!(
|
||||||
|
format_milliseconds(998244353),
|
||||||
|
"11 day(s), 13 hour(s), 17 minute(s), 24 second(s)"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
83
packages/backend-rs/src/misc/meta.rs
Normal file
83
packages/backend-rs/src/misc/meta.rs
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
use crate::database::db_conn;
|
||||||
|
use crate::model::entity::meta;
|
||||||
|
use rand::prelude::*;
|
||||||
|
use sea_orm::{prelude::*, ActiveValue};
|
||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
type Meta = meta::Model;
|
||||||
|
|
||||||
|
static CACHE: Mutex<Option<Meta>> = Mutex::new(None);
|
||||||
|
fn update_cache(meta: &Meta) {
|
||||||
|
let _ = CACHE.lock().map(|mut cache| *cache = Some(meta.clone()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[crate::export]
|
||||||
|
pub async fn fetch_meta(use_cache: bool) -> Result<Meta, DbErr> {
|
||||||
|
// try using cache
|
||||||
|
if use_cache {
|
||||||
|
if let Some(cache) = CACHE.lock().ok().and_then(|cache| cache.clone()) {
|
||||||
|
return Ok(cache);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// try fetching from db
|
||||||
|
let db = db_conn().await?;
|
||||||
|
let meta = meta::Entity::find().one(db).await?;
|
||||||
|
if let Some(meta) = meta {
|
||||||
|
update_cache(&meta);
|
||||||
|
return Ok(meta);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a new meta object and insert into db
|
||||||
|
let meta = meta::Entity::insert(meta::ActiveModel {
|
||||||
|
id: ActiveValue::Set("x".to_owned()),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.exec_with_returning(db)
|
||||||
|
.await?;
|
||||||
|
update_cache(&meta);
|
||||||
|
Ok(meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[crate::export(object)]
|
||||||
|
pub struct PugArgs {
|
||||||
|
pub img: Option<String>,
|
||||||
|
pub title: String,
|
||||||
|
pub instance_name: String,
|
||||||
|
pub desc: Option<String>,
|
||||||
|
pub icon: Option<String>,
|
||||||
|
pub splash_icon: Option<String>,
|
||||||
|
pub theme_color: Option<String>,
|
||||||
|
pub random_motd: String,
|
||||||
|
pub private_mode: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[crate::export]
|
||||||
|
pub fn meta_to_pug_args(meta: Meta) -> PugArgs {
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
|
let splash_icon = meta
|
||||||
|
.custom_splash_icons
|
||||||
|
.choose(&mut rng)
|
||||||
|
.map(|s| s.to_owned())
|
||||||
|
.or_else(|| meta.icon_url.to_owned());
|
||||||
|
|
||||||
|
let random_motd = meta
|
||||||
|
.custom_motd
|
||||||
|
.choose(&mut rng)
|
||||||
|
.map(|s| s.to_owned())
|
||||||
|
.unwrap_or_else(|| "Loading...".to_owned());
|
||||||
|
|
||||||
|
let name = meta.name.unwrap_or_else(|| "Firefish".to_owned());
|
||||||
|
PugArgs {
|
||||||
|
img: meta.banner_url,
|
||||||
|
title: name.clone(),
|
||||||
|
instance_name: name.clone(),
|
||||||
|
desc: meta.description,
|
||||||
|
icon: meta.icon_url,
|
||||||
|
splash_icon,
|
||||||
|
theme_color: meta.theme_color,
|
||||||
|
random_motd,
|
||||||
|
private_mode: meta.private_mode,
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,11 @@
|
||||||
pub mod acct;
|
pub mod acct;
|
||||||
pub mod check_word_mute;
|
pub mod check_word_mute;
|
||||||
pub mod convert_host;
|
pub mod convert_host;
|
||||||
|
pub mod emoji;
|
||||||
|
pub mod escape_sql;
|
||||||
|
pub mod format_milliseconds;
|
||||||
pub mod mastodon_id;
|
pub mod mastodon_id;
|
||||||
|
pub mod meta;
|
||||||
pub mod nyaify;
|
pub mod nyaify;
|
||||||
|
pub mod password;
|
||||||
|
pub mod reaction;
|
||||||
|
|
69
packages/backend-rs/src/misc/password.rs
Normal file
69
packages/backend-rs/src/misc/password.rs
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
use argon2::{
|
||||||
|
password_hash,
|
||||||
|
password_hash::{rand_core::OsRng, PasswordHash, PasswordHasher, PasswordVerifier, SaltString},
|
||||||
|
Argon2,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[crate::export]
|
||||||
|
pub fn hash_password(password: &str) -> Result<String, password_hash::errors::Error> {
|
||||||
|
let salt = SaltString::generate(&mut OsRng);
|
||||||
|
Ok(Argon2::default()
|
||||||
|
.hash_password(password.as_bytes(), &salt)?
|
||||||
|
.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(thiserror::Error, Debug)]
|
||||||
|
pub enum VerifyError {
|
||||||
|
#[error("An error occured while bcrypt verification: {0}")]
|
||||||
|
BcryptError(#[from] bcrypt::BcryptError),
|
||||||
|
#[error("Invalid argon2 password hash: {0}")]
|
||||||
|
InvalidArgon2Hash(#[from] password_hash::Error),
|
||||||
|
#[error("An error occured while argon2 verification: {0}")]
|
||||||
|
Argon2Error(#[from] argon2::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[crate::export]
|
||||||
|
pub fn verify_password(password: &str, hash: &str) -> Result<bool, VerifyError> {
|
||||||
|
if is_old_password_algorithm(hash) {
|
||||||
|
Ok(bcrypt::verify(password, hash)?)
|
||||||
|
} else {
|
||||||
|
let parsed_hash = PasswordHash::new(hash)?;
|
||||||
|
Ok(Argon2::default()
|
||||||
|
.verify_password(password.as_bytes(), &parsed_hash)
|
||||||
|
.is_ok())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[crate::export]
|
||||||
|
pub fn is_old_password_algorithm(hash: &str) -> bool {
|
||||||
|
// bcrypt hashes start with $2[ab]$
|
||||||
|
hash.starts_with("$2")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod unit_test {
|
||||||
|
use super::{hash_password, is_old_password_algorithm, verify_password};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn verify_password_test() {
|
||||||
|
let password = "omWc*%sD^fn7o2cXmc9e2QasBdrbRuhNB*gx!J5";
|
||||||
|
|
||||||
|
let hash = hash_password(password).unwrap();
|
||||||
|
assert!(verify_password(password, hash.as_str()).unwrap());
|
||||||
|
|
||||||
|
let argon2_hash = "$argon2id$v=19$m=19456,t=2,p=1$jty3puDFd4ENv/lgHn3ROQ$kRHDdEoVv2rruvnF731E74NxnYlvj5FMgePdGIIq3Jk";
|
||||||
|
let argon2_invalid_hash = "$argon2id$v=19$m=19456,t=2,p=1$jty3puDFd4ENv/lgHn3ROQ$kRHDdEoVv2rruvnF731E74NxnYlvj4FMgePdGIIq3Jk";
|
||||||
|
let bcrypt_hash = "$2a$12$WzUc.20jgbHmQjUMqTr8vOhKqYbS1BUvubapv/GLjCK1IN.h4e4la";
|
||||||
|
let bcrypt_invalid_hash = "$2a$12$WzUc.20jgbHmQjUMqTr7vOhKqYbS1BUvubapv/GLjCK1IN.h4e4la";
|
||||||
|
|
||||||
|
assert!(!is_old_password_algorithm(argon2_hash));
|
||||||
|
assert!(is_old_password_algorithm(bcrypt_hash));
|
||||||
|
|
||||||
|
assert!(verify_password(password, argon2_hash).unwrap());
|
||||||
|
assert!(verify_password(password, bcrypt_hash).unwrap());
|
||||||
|
|
||||||
|
assert!(!verify_password(password, argon2_invalid_hash).unwrap());
|
||||||
|
assert!(!verify_password(password, bcrypt_invalid_hash).unwrap());
|
||||||
|
}
|
||||||
|
}
|
191
packages/backend-rs/src/misc/reaction.rs
Normal file
191
packages/backend-rs/src/misc/reaction.rs
Normal file
|
@ -0,0 +1,191 @@
|
||||||
|
use crate::database::db_conn;
|
||||||
|
use crate::misc::{convert_host::to_puny, emoji::is_unicode_emoji, meta::fetch_meta};
|
||||||
|
use crate::model::entity::emoji;
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
use regex::Regex;
|
||||||
|
use sea_orm::prelude::*;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[derive(PartialEq, Debug)]
|
||||||
|
#[crate::export(object)]
|
||||||
|
pub struct DecodedReaction {
|
||||||
|
pub reaction: String,
|
||||||
|
pub name: Option<String>,
|
||||||
|
pub host: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[crate::export]
|
||||||
|
pub fn decode_reaction(reaction: &str) -> DecodedReaction {
|
||||||
|
// Misskey allows you to include "+" and "-" in emoji shortcodes
|
||||||
|
// MFM spec: https://github.com/misskey-dev/mfm.js/blob/6aaf68089023c6adebe44123eebbc4dcd75955e0/docs/syntax.md?plain=1#L583
|
||||||
|
// Misskey's implementation: https://github.com/misskey-dev/misskey/blob/bba3097765317cbf95d09627961b5b5dce16a972/packages/backend/src/core/ReactionService.ts#L68
|
||||||
|
static RE: Lazy<Regex> =
|
||||||
|
Lazy::new(|| Regex::new(r"^:([0-9A-Za-z_+-]+)(?:@([0-9A-Za-z_.-]+))?:$").unwrap());
|
||||||
|
|
||||||
|
if let Some(captures) = RE.captures(reaction) {
|
||||||
|
let name = &captures[1];
|
||||||
|
let host = captures.get(2).map(|s| s.as_str());
|
||||||
|
|
||||||
|
DecodedReaction {
|
||||||
|
reaction: format!(":{}@{}:", name, host.unwrap_or(".")),
|
||||||
|
name: Some(name.to_owned()),
|
||||||
|
host: host.map(|s| s.to_owned()),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DecodedReaction {
|
||||||
|
reaction: reaction.to_owned(),
|
||||||
|
name: None,
|
||||||
|
host: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[crate::export]
|
||||||
|
pub fn count_reactions(reactions: &HashMap<String, u32>) -> HashMap<String, u32> {
|
||||||
|
let mut res = HashMap::<String, u32>::new();
|
||||||
|
|
||||||
|
for (reaction, count) in reactions.iter() {
|
||||||
|
if count > &0 {
|
||||||
|
let decoded = decode_reaction(reaction).reaction;
|
||||||
|
let total = res.entry(decoded).or_insert(0);
|
||||||
|
*total += count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(thiserror::Error, Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
#[error("Idna error: {0}")]
|
||||||
|
IdnaError(#[from] idna::Errors),
|
||||||
|
#[error("Database error: {0}")]
|
||||||
|
DbError(#[from] DbErr),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[crate::export]
|
||||||
|
pub async fn to_db_reaction(reaction: Option<&str>, host: Option<&str>) -> Result<String, Error> {
|
||||||
|
if let Some(reaction) = reaction {
|
||||||
|
// FIXME: Is it okay to do this only here?
|
||||||
|
// This was introduced in https://firefish.dev/firefish/firefish/-/commit/af730e75b6fc1a57ca680ce83459d7e433b130cf
|
||||||
|
if reaction.contains('❤') || reaction.contains("♥️") {
|
||||||
|
return Ok("❤️".to_owned());
|
||||||
|
}
|
||||||
|
|
||||||
|
if is_unicode_emoji(reaction) {
|
||||||
|
return Ok(reaction.to_owned());
|
||||||
|
}
|
||||||
|
|
||||||
|
static RE: Lazy<Regex> =
|
||||||
|
Lazy::new(|| Regex::new(r"^:([0-9A-Za-z_+-]+)(?:@\.)?:$").unwrap());
|
||||||
|
|
||||||
|
if let Some(captures) = RE.captures(reaction) {
|
||||||
|
let name = &captures[1];
|
||||||
|
let db = db_conn().await?;
|
||||||
|
|
||||||
|
if let Some(host) = host {
|
||||||
|
// remote emoji
|
||||||
|
let ascii_host = to_puny(host)?;
|
||||||
|
|
||||||
|
// TODO: Does SeaORM have the `exists` method?
|
||||||
|
if emoji::Entity::find()
|
||||||
|
.filter(emoji::Column::Name.eq(name))
|
||||||
|
.filter(emoji::Column::Host.eq(&ascii_host))
|
||||||
|
.one(db)
|
||||||
|
.await?
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
|
return Ok(format!(":{name}@{ascii_host}:"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// local emoji
|
||||||
|
// TODO: Does SeaORM have the `exists` method?
|
||||||
|
if emoji::Entity::find()
|
||||||
|
.filter(emoji::Column::Name.eq(name))
|
||||||
|
.filter(emoji::Column::Host.is_null())
|
||||||
|
.one(db)
|
||||||
|
.await?
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
|
return Ok(format!(":{name}:"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(fetch_meta(true).await?.default_reaction)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod unit_test {
|
||||||
|
use super::{decode_reaction, DecodedReaction};
|
||||||
|
use pretty_assertions::{assert_eq, assert_ne};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_decode_reaction() {
|
||||||
|
let unicode_emoji_1 = DecodedReaction {
|
||||||
|
reaction: "⭐".to_string(),
|
||||||
|
name: None,
|
||||||
|
host: None,
|
||||||
|
};
|
||||||
|
let unicode_emoji_2 = DecodedReaction {
|
||||||
|
reaction: "🩷".to_string(),
|
||||||
|
name: None,
|
||||||
|
host: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(decode_reaction("⭐"), unicode_emoji_1);
|
||||||
|
assert_eq!(decode_reaction("🩷"), unicode_emoji_2);
|
||||||
|
|
||||||
|
assert_ne!(decode_reaction("⭐"), unicode_emoji_2);
|
||||||
|
assert_ne!(decode_reaction("🩷"), unicode_emoji_1);
|
||||||
|
|
||||||
|
let unicode_emoji_3 = DecodedReaction {
|
||||||
|
reaction: "🖖🏿".to_string(),
|
||||||
|
name: None,
|
||||||
|
host: None,
|
||||||
|
};
|
||||||
|
assert_eq!(decode_reaction("🖖🏿"), unicode_emoji_3);
|
||||||
|
|
||||||
|
let local_emoji = DecodedReaction {
|
||||||
|
reaction: ":meow_melt_tears@.:".to_string(),
|
||||||
|
name: Some("meow_melt_tears".to_string()),
|
||||||
|
host: None,
|
||||||
|
};
|
||||||
|
assert_eq!(decode_reaction(":meow_melt_tears:"), local_emoji);
|
||||||
|
|
||||||
|
let remote_emoji_1 = DecodedReaction {
|
||||||
|
reaction: ":meow_uwu@some-domain.example.org:".to_string(),
|
||||||
|
name: Some("meow_uwu".to_string()),
|
||||||
|
host: Some("some-domain.example.org".to_string()),
|
||||||
|
};
|
||||||
|
assert_eq!(
|
||||||
|
decode_reaction(":meow_uwu@some-domain.example.org:"),
|
||||||
|
remote_emoji_1
|
||||||
|
);
|
||||||
|
|
||||||
|
let remote_emoji_2 = DecodedReaction {
|
||||||
|
reaction: ":C++23@xn--eckwd4c7c.example.org:".to_string(),
|
||||||
|
name: Some("C++23".to_string()),
|
||||||
|
host: Some("xn--eckwd4c7c.example.org".to_string()),
|
||||||
|
};
|
||||||
|
assert_eq!(
|
||||||
|
decode_reaction(":C++23@xn--eckwd4c7c.example.org:"),
|
||||||
|
remote_emoji_2
|
||||||
|
);
|
||||||
|
|
||||||
|
let invalid_reaction_1 = DecodedReaction {
|
||||||
|
reaction: ":foo".to_string(),
|
||||||
|
name: None,
|
||||||
|
host: None,
|
||||||
|
};
|
||||||
|
assert_eq!(decode_reaction(":foo"), invalid_reaction_1);
|
||||||
|
|
||||||
|
let invalid_reaction_2 = DecodedReaction {
|
||||||
|
reaction: ":foo&@example.com:".to_string(),
|
||||||
|
name: None,
|
||||||
|
host: None,
|
||||||
|
};
|
||||||
|
assert_eq!(decode_reaction(":foo&@example.com:"), invalid_reaction_2);
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,9 +22,9 @@
|
||||||
"@swc/core-android-arm64": "1.3.11"
|
"@swc/core-android-arm64": "1.3.11"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@bull-board/api": "5.15.3",
|
"@bull-board/api": "5.15.5",
|
||||||
"@bull-board/koa": "5.15.3",
|
"@bull-board/koa": "5.15.5",
|
||||||
"@bull-board/ui": "5.15.3",
|
"@bull-board/ui": "5.15.5",
|
||||||
"@discordapp/twemoji": "^15.0.3",
|
"@discordapp/twemoji": "^15.0.3",
|
||||||
"@koa/cors": "5.0.0",
|
"@koa/cors": "5.0.0",
|
||||||
"@koa/multer": "3.0.2",
|
"@koa/multer": "3.0.2",
|
||||||
|
@ -33,15 +33,12 @@
|
||||||
"@peertube/http-signature": "1.7.0",
|
"@peertube/http-signature": "1.7.0",
|
||||||
"@redocly/openapi-core": "1.11.0",
|
"@redocly/openapi-core": "1.11.0",
|
||||||
"@sinonjs/fake-timers": "11.2.2",
|
"@sinonjs/fake-timers": "11.2.2",
|
||||||
"@twemoji/parser": "^15.1.1",
|
|
||||||
"adm-zip": "0.5.10",
|
"adm-zip": "0.5.10",
|
||||||
"ajv": "8.12.0",
|
"ajv": "8.12.0",
|
||||||
"archiver": "7.0.1",
|
"archiver": "7.0.1",
|
||||||
"argon2": "^0.40.1",
|
"aws-sdk": "2.1599.0",
|
||||||
"aws-sdk": "2.1597.0",
|
|
||||||
"axios": "^1.6.8",
|
"axios": "^1.6.8",
|
||||||
"backend-rs": "workspace:*",
|
"backend-rs": "workspace:*",
|
||||||
"bcryptjs": "2.4.3",
|
|
||||||
"blurhash": "2.0.5",
|
"blurhash": "2.0.5",
|
||||||
"bull": "4.12.2",
|
"bull": "4.12.2",
|
||||||
"cacheable-lookup": "TheEssem/cacheable-lookup",
|
"cacheable-lookup": "TheEssem/cacheable-lookup",
|
||||||
|
@ -54,7 +51,7 @@
|
||||||
"date-fns": "3.6.0",
|
"date-fns": "3.6.0",
|
||||||
"decompress": "^4.2.1",
|
"decompress": "^4.2.1",
|
||||||
"deep-email-validator": "0.1.21",
|
"deep-email-validator": "0.1.21",
|
||||||
"deepl-node": "1.12.0",
|
"deepl-node": "1.13.0",
|
||||||
"escape-regexp": "0.0.1",
|
"escape-regexp": "0.0.1",
|
||||||
"feed": "4.2.2",
|
"feed": "4.2.2",
|
||||||
"file-type": "19.0.0",
|
"file-type": "19.0.0",
|
||||||
|
@ -100,7 +97,7 @@
|
||||||
"punycode": "2.3.1",
|
"punycode": "2.3.1",
|
||||||
"pureimage": "0.4.13",
|
"pureimage": "0.4.13",
|
||||||
"qrcode": "1.5.3",
|
"qrcode": "1.5.3",
|
||||||
"qs": "6.12.0",
|
"qs": "6.12.1",
|
||||||
"random-seed": "0.3.0",
|
"random-seed": "0.3.0",
|
||||||
"ratelimiter": "3.4.1",
|
"ratelimiter": "3.4.1",
|
||||||
"redis-semaphore": "5.5.1",
|
"redis-semaphore": "5.5.1",
|
||||||
|
@ -130,7 +127,6 @@
|
||||||
"@swc/cli": "0.3.12",
|
"@swc/cli": "0.3.12",
|
||||||
"@swc/core": "1.4.13",
|
"@swc/core": "1.4.13",
|
||||||
"@types/adm-zip": "^0.5.5",
|
"@types/adm-zip": "^0.5.5",
|
||||||
"@types/bcryptjs": "2.4.6",
|
|
||||||
"@types/color-convert": "^2.0.3",
|
"@types/color-convert": "^2.0.3",
|
||||||
"@types/content-disposition": "^0.5.8",
|
"@types/content-disposition": "^0.5.8",
|
||||||
"@types/escape-regexp": "0.0.3",
|
"@types/escape-regexp": "0.0.3",
|
||||||
|
|
|
@ -3,7 +3,7 @@ import chalk from "chalk";
|
||||||
import Xev from "xev";
|
import Xev from "xev";
|
||||||
|
|
||||||
import Logger from "@/services/logger.js";
|
import Logger from "@/services/logger.js";
|
||||||
import { envOption } from "../env.js";
|
import { envOption } from "@/config/index.js";
|
||||||
import { inspect } from "node:util";
|
import { inspect } from "node:util";
|
||||||
|
|
||||||
// for typeorm
|
// for typeorm
|
||||||
|
@ -76,9 +76,7 @@ cluster.on("exit", (worker) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Display detail of unhandled promise rejection
|
// Display detail of unhandled promise rejection
|
||||||
if (!envOption.quiet) {
|
process.on("unhandledRejection", console.dir);
|
||||||
process.on("unhandledRejection", console.dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Display detail of uncaught exception
|
// Display detail of uncaught exception
|
||||||
process.on("uncaughtException", (err) => {
|
process.on("uncaughtException", (err) => {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import semver from "semver";
|
||||||
import Logger from "@/services/logger.js";
|
import Logger from "@/services/logger.js";
|
||||||
import loadConfig from "@/config/load.js";
|
import loadConfig from "@/config/load.js";
|
||||||
import type { Config } from "@/config/types.js";
|
import type { Config } from "@/config/types.js";
|
||||||
import { envOption } from "@/env.js";
|
import { envOption } from "@/config/index.js";
|
||||||
import { showMachineInfo } from "@/misc/show-machine-info.js";
|
import { showMachineInfo } from "@/misc/show-machine-info.js";
|
||||||
import { db, initDb } from "@/db/postgre.js";
|
import { db, initDb } from "@/db/postgre.js";
|
||||||
import { inspect } from "node:util";
|
import { inspect } from "node:util";
|
||||||
|
@ -28,58 +28,56 @@ const bootLogger = logger.createSubLogger("boot", "magenta", false);
|
||||||
const themeColor = chalk.hex("#31748f");
|
const themeColor = chalk.hex("#31748f");
|
||||||
|
|
||||||
function greet() {
|
function greet() {
|
||||||
if (!envOption.quiet) {
|
//#region Firefish logo
|
||||||
//#region Firefish logo
|
console.log(
|
||||||
console.log(
|
themeColor(
|
||||||
themeColor(
|
"██████╗ ██╗██████╗ ███████╗███████╗██╗███████╗██╗ ██╗ ○ ▄ ▄ ",
|
||||||
"██████╗ ██╗██████╗ ███████╗███████╗██╗███████╗██╗ ██╗ ○ ▄ ▄ ",
|
),
|
||||||
),
|
);
|
||||||
);
|
console.log(
|
||||||
console.log(
|
themeColor(
|
||||||
themeColor(
|
"██╔════╝██║██╔══██╗██╔════╝██╔════╝██║██╔════╝██║ ██║ ⚬ █▄▄ █▄▄ ",
|
||||||
"██╔════╝██║██╔══██╗██╔════╝██╔════╝██║██╔════╝██║ ██║ ⚬ █▄▄ █▄▄ ",
|
),
|
||||||
),
|
);
|
||||||
);
|
console.log(
|
||||||
console.log(
|
themeColor(
|
||||||
themeColor(
|
"█████╗ ██║██████╔╝█████╗ █████╗ ██║███████╗███████║ ▄▄▄▄▄▄ ▄ ",
|
||||||
"█████╗ ██║██████╔╝█████╗ █████╗ ██║███████╗███████║ ▄▄▄▄▄▄ ▄ ",
|
),
|
||||||
),
|
);
|
||||||
);
|
console.log(
|
||||||
console.log(
|
themeColor(
|
||||||
themeColor(
|
"██╔══╝ ██║██╔══██╗██╔══╝ ██╔══╝ ██║╚════██║██╔══██║ █ █ █▄▄ ",
|
||||||
"██╔══╝ ██║██╔══██╗██╔══╝ ██╔══╝ ██║╚════██║██╔══██║ █ █ █▄▄ ",
|
),
|
||||||
),
|
);
|
||||||
);
|
console.log(
|
||||||
console.log(
|
themeColor(
|
||||||
themeColor(
|
"██║ ██║██║ ██║███████╗██║ ██║███████║██║ ██║ █ ● ● █ ",
|
||||||
"██║ ██║██║ ██║███████╗██║ ██║███████║██║ ██║ █ ● ● █ ",
|
),
|
||||||
),
|
);
|
||||||
);
|
console.log(
|
||||||
console.log(
|
themeColor(
|
||||||
themeColor(
|
"╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ▀▄▄▄▄▄▄▀ ",
|
||||||
"╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ▀▄▄▄▄▄▄▀ ",
|
),
|
||||||
),
|
);
|
||||||
);
|
//#endregion
|
||||||
//#endregion
|
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
" Firefish is an open-source decentralized microblogging platform.",
|
" Firefish is an open-source decentralized microblogging platform.",
|
||||||
);
|
);
|
||||||
console.log(
|
console.log(
|
||||||
chalk.rgb(
|
chalk.rgb(
|
||||||
255,
|
255,
|
||||||
136,
|
136,
|
||||||
0,
|
0,
|
||||||
)(
|
)(
|
||||||
" If you like Firefish, please consider contributing to the repo. https://firefish.dev/firefish/firefish",
|
" If you like Firefish, please consider contributing to the repo. https://firefish.dev/firefish/firefish",
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log("");
|
console.log("");
|
||||||
console.log(
|
console.log(
|
||||||
chalkTemplate`--- ${os.hostname()} {gray (PID: ${process.pid.toString()})} ---`,
|
chalkTemplate`--- ${os.hostname()} {gray (PID: ${process.pid.toString()})} ---`,
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
bootLogger.info("Welcome to Firefish!");
|
bootLogger.info("Welcome to Firefish!");
|
||||||
bootLogger.info(`Firefish v${meta.version}`, null, true);
|
bootLogger.info(`Firefish v${meta.version}`, null, true);
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
import load from "./load.js";
|
import load from "./load.js";
|
||||||
|
import { readEnvironmentConfig } from "backend-rs";
|
||||||
|
|
||||||
export default load();
|
export default load();
|
||||||
|
export const envOption = readEnvironmentConfig();
|
||||||
|
|
|
@ -55,6 +55,7 @@ export default function load() {
|
||||||
mixin.userAgent = `Firefish/${meta.version} (${config.url})`;
|
mixin.userAgent = `Firefish/${meta.version} (${config.url})`;
|
||||||
mixin.clientEntry = clientManifest["src/init.ts"];
|
mixin.clientEntry = clientManifest["src/init.ts"];
|
||||||
|
|
||||||
|
if (config.proxyRemoteFiles == null) config.proxyRemoteFiles = true;
|
||||||
if (!config.redis.prefix) config.redis.prefix = mixin.hostname;
|
if (!config.redis.prefix) config.redis.prefix = mixin.hostname;
|
||||||
if (config.cacheServer && !config.cacheServer.prefix)
|
if (config.cacheServer && !config.cacheServer.prefix)
|
||||||
config.cacheServer.prefix = mixin.hostname;
|
config.cacheServer.prefix = mixin.hostname;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import si from "systeminformation";
|
import si from "systeminformation";
|
||||||
import Xev from "xev";
|
import Xev from "xev";
|
||||||
import * as osUtils from "os-utils";
|
import * as osUtils from "os-utils";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "backend-rs";
|
||||||
|
|
||||||
const ev = new Xev();
|
const ev = new Xev();
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ export default function () {
|
||||||
ev.emit(`serverStatsLog:${x.id}`, log.slice(0, x.length || 50));
|
ev.emit(`serverStatsLog:${x.id}`, log.slice(0, x.length || 50));
|
||||||
});
|
});
|
||||||
|
|
||||||
fetchMeta().then((meta) => {
|
fetchMeta(true).then((meta) => {
|
||||||
if (!meta.enableServerMachineStats) return;
|
if (!meta.enableServerMachineStats) return;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
const envOption = {
|
|
||||||
onlyQueue: false,
|
|
||||||
onlyServer: false,
|
|
||||||
noDaemons: false,
|
|
||||||
disableClustering: false,
|
|
||||||
verbose: false,
|
|
||||||
withLogTime: false,
|
|
||||||
quiet: false,
|
|
||||||
slow: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const key of Object.keys(envOption) as (keyof typeof envOption)[]) {
|
|
||||||
if (
|
|
||||||
process.env[
|
|
||||||
`MK_${key.replace(/[A-Z]/g, (letter) => `_${letter}`).toUpperCase()}`
|
|
||||||
]
|
|
||||||
)
|
|
||||||
envOption[key] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (process.env.NODE_ENV === "test") envOption.disableClustering = true;
|
|
||||||
if (process.env.NODE_ENV === "test") envOption.quiet = true;
|
|
||||||
if (process.env.NODE_ENV === "test") envOption.noDaemons = true;
|
|
||||||
|
|
||||||
export { envOption };
|
|
|
@ -1,17 +0,0 @@
|
||||||
export function convertMilliseconds(ms: number) {
|
|
||||||
let seconds = Math.round(ms / 1000);
|
|
||||||
let minutes = Math.round(seconds / 60);
|
|
||||||
let hours = Math.round(minutes / 60);
|
|
||||||
const days = Math.round(hours / 24);
|
|
||||||
seconds %= 60;
|
|
||||||
minutes %= 60;
|
|
||||||
hours %= 24;
|
|
||||||
|
|
||||||
const result = [];
|
|
||||||
if (days > 0) result.push(`${days} day(s)`);
|
|
||||||
if (hours > 0) result.push(`${hours} hour(s)`);
|
|
||||||
if (minutes > 0) result.push(`${minutes} minute(s)`);
|
|
||||||
if (seconds > 0) result.push(`${seconds} second(s)`);
|
|
||||||
|
|
||||||
return result.join(", ");
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
import twemoji from "@twemoji/parser/dist/lib/regex.js";
|
|
||||||
const twemojiRegex = twemoji.default;
|
|
||||||
|
|
||||||
export const emojiRegex = new RegExp(`(${twemojiRegex.source})`);
|
|
||||||
export const emojiRegexAtStartToEnd = new RegExp(`^(${twemojiRegex.source})$`);
|
|
|
@ -1,72 +0,0 @@
|
||||||
import { db } from "@/db/postgre.js";
|
|
||||||
import { Meta } from "@/models/entities/meta.js";
|
|
||||||
|
|
||||||
let cache: Meta;
|
|
||||||
|
|
||||||
export function metaToPugArgs(meta: Meta): object {
|
|
||||||
let motd = ["Loading..."];
|
|
||||||
if (meta.customMotd.length > 0) {
|
|
||||||
motd = meta.customMotd;
|
|
||||||
}
|
|
||||||
let splashIconUrl = meta.iconUrl;
|
|
||||||
if (meta.customSplashIcons.length > 0) {
|
|
||||||
splashIconUrl =
|
|
||||||
meta.customSplashIcons[
|
|
||||||
Math.floor(Math.random() * meta.customSplashIcons.length)
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
img: meta.bannerUrl,
|
|
||||||
title: meta.name || "Firefish",
|
|
||||||
instanceName: meta.name || "Firefish",
|
|
||||||
desc: meta.description,
|
|
||||||
icon: meta.iconUrl,
|
|
||||||
splashIcon: splashIconUrl,
|
|
||||||
themeColor: meta.themeColor,
|
|
||||||
randomMOTD: motd[Math.floor(Math.random() * motd.length)],
|
|
||||||
privateMode: meta.privateMode,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function fetchMeta(noCache = false): Promise<Meta> {
|
|
||||||
if (!noCache && cache) return cache;
|
|
||||||
|
|
||||||
return await db.transaction(async (transactionalEntityManager) => {
|
|
||||||
// New IDs are prioritized because multiple records may have been created due to past bugs.
|
|
||||||
const metas = await transactionalEntityManager.find(Meta, {
|
|
||||||
order: {
|
|
||||||
id: "DESC",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const meta = metas[0];
|
|
||||||
|
|
||||||
if (meta) {
|
|
||||||
cache = meta;
|
|
||||||
return meta;
|
|
||||||
} else {
|
|
||||||
// If fetchMeta is called at the same time when meta is empty, this part may be called at the same time, so use fail-safe upsert.
|
|
||||||
const saved = await transactionalEntityManager
|
|
||||||
.upsert(
|
|
||||||
Meta,
|
|
||||||
{
|
|
||||||
id: "x",
|
|
||||||
},
|
|
||||||
["id"],
|
|
||||||
)
|
|
||||||
.then((x) =>
|
|
||||||
transactionalEntityManager.findOneByOrFail(Meta, x.identifiers[0]),
|
|
||||||
);
|
|
||||||
|
|
||||||
cache = saved;
|
|
||||||
return saved;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setInterval(() => {
|
|
||||||
fetchMeta(true).then((meta) => {
|
|
||||||
cache = meta;
|
|
||||||
});
|
|
||||||
}, 1000 * 10);
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { fetchMeta } from "./fetch-meta.js";
|
import { fetchMeta } from "backend-rs";
|
||||||
import type { ILocalUser } from "@/models/entities/user.js";
|
import type { ILocalUser } from "@/models/entities/user.js";
|
||||||
import { Users } from "@/models/index.js";
|
import { Users } from "@/models/index.js";
|
||||||
|
|
||||||
export async function fetchProxyAccount(): Promise<ILocalUser | null> {
|
export async function fetchProxyAccount(): Promise<ILocalUser | null> {
|
||||||
const meta = await fetchMeta();
|
const meta = await fetchMeta(true);
|
||||||
if (meta.proxyAccountId == null) return null;
|
if (meta.proxyAccountId == null) return null;
|
||||||
return (await Users.findOneByOrFail({
|
return (await Users.findOneByOrFail({
|
||||||
id: meta.proxyAccountId,
|
id: meta.proxyAccountId,
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
import bcrypt from "bcryptjs";
|
|
||||||
import * as argon2 from "argon2";
|
|
||||||
|
|
||||||
export async function hashPassword(password: string): Promise<string> {
|
|
||||||
return argon2.hash(password);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function comparePassword(
|
|
||||||
password: string,
|
|
||||||
hash: string,
|
|
||||||
): Promise<boolean> {
|
|
||||||
if (isOldAlgorithm(hash)) return bcrypt.compare(password, hash);
|
|
||||||
|
|
||||||
return argon2.verify(hash, password);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isOldAlgorithm(hash: string): boolean {
|
|
||||||
// bcrypt hashes start with $2[ab]$
|
|
||||||
return hash.startsWith("$2");
|
|
||||||
}
|
|
|
@ -3,8 +3,7 @@ import { Emojis } from "@/models/index.js";
|
||||||
import type { Emoji } from "@/models/entities/emoji.js";
|
import type { Emoji } from "@/models/entities/emoji.js";
|
||||||
import type { Note } from "@/models/entities/note.js";
|
import type { Note } from "@/models/entities/note.js";
|
||||||
import { Cache } from "./cache.js";
|
import { Cache } from "./cache.js";
|
||||||
import { isSelfHost, toPuny } from "backend-rs";
|
import { decodeReaction, isSelfHost, toPuny } from "backend-rs";
|
||||||
import { decodeReaction } from "./reaction-lib.js";
|
|
||||||
import config from "@/config/index.js";
|
import config from "@/config/index.js";
|
||||||
import { query } from "@/prelude/url.js";
|
import { query } from "@/prelude/url.js";
|
||||||
import { redisClient } from "@/db/redis.js";
|
import { redisClient } from "@/db/redis.js";
|
||||||
|
|
|
@ -12,7 +12,7 @@ export function parse(acct: any): Post {
|
||||||
cw: acct.cw,
|
cw: acct.cw,
|
||||||
localOnly: acct.localOnly,
|
localOnly: acct.localOnly,
|
||||||
createdAt: new Date(acct.createdAt),
|
createdAt: new Date(acct.createdAt),
|
||||||
visibility: "hidden" + (acct.visibility || ""),
|
visibility: `hidden${acct.visibility || ""}`,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,87 +0,0 @@
|
||||||
import { emojiRegex } from "./emoji-regex.js";
|
|
||||||
import { fetchMeta } from "./fetch-meta.js";
|
|
||||||
import { Emojis } from "@/models/index.js";
|
|
||||||
import { toPuny } from "backend-rs";
|
|
||||||
import { IsNull } from "typeorm";
|
|
||||||
|
|
||||||
export function convertReactions(reactions: Record<string, number>) {
|
|
||||||
const result = new Map();
|
|
||||||
|
|
||||||
for (const reaction in reactions) {
|
|
||||||
if (reactions[reaction] <= 0) continue;
|
|
||||||
|
|
||||||
const decoded = decodeReaction(reaction).reaction;
|
|
||||||
result.set(decoded, (result.get(decoded) || 0) + reactions[reaction]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Object.fromEntries(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function toDbReaction(
|
|
||||||
reaction?: string | null,
|
|
||||||
reacterHost?: string | null,
|
|
||||||
): Promise<string> {
|
|
||||||
if (!reaction) return (await fetchMeta()).defaultReaction;
|
|
||||||
|
|
||||||
reacterHost = reacterHost == null ? null : toPuny(reacterHost);
|
|
||||||
|
|
||||||
if (reaction.includes("❤") || reaction.includes("♥️")) return "❤️";
|
|
||||||
|
|
||||||
// Allow unicode reactions
|
|
||||||
const match = emojiRegex.exec(reaction);
|
|
||||||
if (match) {
|
|
||||||
const unicode = match[0];
|
|
||||||
return unicode;
|
|
||||||
}
|
|
||||||
|
|
||||||
const custom = reaction.match(/^:([\w+-]+)(?:@\.)?:$/);
|
|
||||||
if (custom) {
|
|
||||||
const name = custom[1];
|
|
||||||
const emoji = await Emojis.findOneBy({
|
|
||||||
host: reacterHost || IsNull(),
|
|
||||||
name,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (emoji) return reacterHost ? `:${name}@${reacterHost}:` : `:${name}:`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (await fetchMeta()).defaultReaction;
|
|
||||||
}
|
|
||||||
|
|
||||||
type DecodedReaction = {
|
|
||||||
/**
|
|
||||||
* リアクション名 (Unicode Emoji or ':name@hostname' or ':name@.')
|
|
||||||
*/
|
|
||||||
reaction: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* name (カスタム絵文字の場合name, Emojiクエリに使う)
|
|
||||||
*/
|
|
||||||
name?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* host (カスタム絵文字の場合host, Emojiクエリに使う)
|
|
||||||
*/
|
|
||||||
host?: string | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function decodeReaction(str: string): DecodedReaction {
|
|
||||||
const custom = str.match(/^:([\w+-]+)(?:@([\w.-]+))?:$/);
|
|
||||||
|
|
||||||
if (custom) {
|
|
||||||
const name = custom[1];
|
|
||||||
const host = custom[2] || null;
|
|
||||||
|
|
||||||
return {
|
|
||||||
reaction: `:${name}@${host || "."}:`, // ローカル分は@以降を省略するのではなく.にする
|
|
||||||
name,
|
|
||||||
host,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
reaction: str,
|
|
||||||
name: undefined,
|
|
||||||
host: undefined,
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
export function safeForSql(text: string): boolean {
|
|
||||||
return !/[\0\x08\x09\x1a\n\r"'\\\%]/g.test(text);
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "backend-rs";
|
||||||
import type { Instance } from "@/models/entities/instance.js";
|
import type { Instance } from "@/models/entities/instance.js";
|
||||||
import type { Meta } from "@/models/entities/meta.js";
|
import type { Meta } from "@/models/entities/meta.js";
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ export async function shouldBlockInstance(
|
||||||
host: Instance["host"],
|
host: Instance["host"],
|
||||||
meta?: Meta,
|
meta?: Meta,
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
const { blockedHosts } = meta ?? (await fetchMeta());
|
const { blockedHosts } = meta ?? (await fetchMeta(true));
|
||||||
return blockedHosts.some(
|
return blockedHosts.some(
|
||||||
(blockedHost) => host === blockedHost || host.endsWith(`.${blockedHost}`),
|
(blockedHost) => host === blockedHost || host.endsWith(`.${blockedHost}`),
|
||||||
);
|
);
|
||||||
|
@ -30,7 +30,7 @@ export async function shouldSilenceInstance(
|
||||||
host: Instance["host"],
|
host: Instance["host"],
|
||||||
meta?: Meta,
|
meta?: Meta,
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
const { silencedHosts } = meta ?? (await fetchMeta());
|
const { silencedHosts } = meta ?? (await fetchMeta(true));
|
||||||
return silencedHosts.some(
|
return silencedHosts.some(
|
||||||
(silencedHost) =>
|
(silencedHost) =>
|
||||||
host === silencedHost || host.endsWith(`.${silencedHost}`),
|
host === silencedHost || host.endsWith(`.${silencedHost}`),
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Brackets } from "typeorm";
|
import { Brackets } from "typeorm";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "backend-rs";
|
||||||
import { Instances } from "@/models/index.js";
|
import { Instances } from "@/models/index.js";
|
||||||
import type { Instance } from "@/models/entities/instance.js";
|
import type { Instance } from "@/models/entities/instance.js";
|
||||||
import { DAY } from "@/const.js";
|
import { DAY } from "@/const.js";
|
||||||
|
@ -19,7 +19,7 @@ export async function skippedInstances(
|
||||||
hosts: Instance["host"][],
|
hosts: Instance["host"][],
|
||||||
): Promise<Instance["host"][]> {
|
): Promise<Instance["host"][]> {
|
||||||
// first check for blocked instances since that info may already be in memory
|
// first check for blocked instances since that info may already be in memory
|
||||||
const meta = await fetchMeta();
|
const meta = await fetchMeta(true);
|
||||||
const shouldSkip = await Promise.all(
|
const shouldSkip = await Promise.all(
|
||||||
hosts.map((host) => shouldBlockInstance(host, meta)),
|
hosts.map((host) => shouldBlockInstance(host, meta)),
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
export function sqlLikeEscape(s: string) {
|
|
||||||
return s.replace(/([%_])/g, "\\$1");
|
|
||||||
}
|
|
|
@ -1,7 +1,7 @@
|
||||||
import fetch from "node-fetch";
|
import fetch from "node-fetch";
|
||||||
import { Converter } from "opencc-js";
|
import { Converter } from "opencc-js";
|
||||||
import { getAgentByUrl } from "@/misc/fetch.js";
|
import { getAgentByUrl } from "@/misc/fetch.js";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "backend-rs";
|
||||||
import type { PostLanguage } from "@/misc/langmap";
|
import type { PostLanguage } from "@/misc/langmap";
|
||||||
import * as deepl from "deepl-node";
|
import * as deepl from "deepl-node";
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ export async function translate(
|
||||||
from: PostLanguage | null,
|
from: PostLanguage | null,
|
||||||
to: PostLanguage,
|
to: PostLanguage,
|
||||||
) {
|
) {
|
||||||
const instance = await fetchMeta();
|
const instance = await fetchMeta(true);
|
||||||
|
|
||||||
if (instance.deeplAuthKey == null && instance.libreTranslateApiUrl == null) {
|
if (instance.deeplAuthKey == null && instance.libreTranslateApiUrl == null) {
|
||||||
throw Error("No translator is set up on this server.");
|
throw Error("No translator is set up on this server.");
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { db } from "@/db/postgre.js";
|
||||||
import { NoteReaction } from "@/models/entities/note-reaction.js";
|
import { NoteReaction } from "@/models/entities/note-reaction.js";
|
||||||
import { Notes, Users } from "../index.js";
|
import { Notes, Users } from "../index.js";
|
||||||
import type { Packed } from "@/misc/schema.js";
|
import type { Packed } from "@/misc/schema.js";
|
||||||
import { decodeReaction } from "@/misc/reaction-lib.js";
|
import { decodeReaction } from "backend-rs";
|
||||||
import type { User } from "@/models/entities/user.js";
|
import type { User } from "@/models/entities/user.js";
|
||||||
|
|
||||||
export const NoteReactionRepository = db.getRepository(NoteReaction).extend({
|
export const NoteReactionRepository = db.getRepository(NoteReaction).extend({
|
||||||
|
|
|
@ -12,9 +12,8 @@ import {
|
||||||
Channels,
|
Channels,
|
||||||
} from "../index.js";
|
} from "../index.js";
|
||||||
import type { Packed } from "@/misc/schema.js";
|
import type { Packed } from "@/misc/schema.js";
|
||||||
import { nyaify } from "backend-rs";
|
import { countReactions, decodeReaction, nyaify } from "backend-rs";
|
||||||
import { awaitAll } from "@/prelude/await-all.js";
|
import { awaitAll } from "@/prelude/await-all.js";
|
||||||
import { convertReactions, decodeReaction } from "@/misc/reaction-lib.js";
|
|
||||||
import type { NoteReaction } from "@/models/entities/note-reaction.js";
|
import type { NoteReaction } from "@/models/entities/note-reaction.js";
|
||||||
import {
|
import {
|
||||||
aggregateNoteEmojis,
|
aggregateNoteEmojis,
|
||||||
|
@ -214,7 +213,7 @@ export const NoteRepository = db.getRepository(Note).extend({
|
||||||
note.visibility === "specified" ? note.visibleUserIds : undefined,
|
note.visibility === "specified" ? note.visibleUserIds : undefined,
|
||||||
renoteCount: note.renoteCount,
|
renoteCount: note.renoteCount,
|
||||||
repliesCount: note.repliesCount,
|
repliesCount: note.repliesCount,
|
||||||
reactions: convertReactions(note.reactions),
|
reactions: countReactions(note.reactions),
|
||||||
reactionEmojis: reactionEmoji,
|
reactionEmojis: reactionEmoji,
|
||||||
emojis: noteEmoji,
|
emojis: noteEmoji,
|
||||||
tags: note.tags.length > 0 ? note.tags : undefined,
|
tags: note.tags.length > 0 ? note.tags : undefined,
|
||||||
|
|
|
@ -5,7 +5,7 @@ import config from "@/config/index.js";
|
||||||
import type { DriveFile } from "@/models/entities/drive-file.js";
|
import type { DriveFile } from "@/models/entities/drive-file.js";
|
||||||
import type { IActivity } from "@/remote/activitypub/type.js";
|
import type { IActivity } from "@/remote/activitypub/type.js";
|
||||||
import type { Webhook, webhookEventTypes } from "@/models/entities/webhook.js";
|
import type { Webhook, webhookEventTypes } from "@/models/entities/webhook.js";
|
||||||
import { envOption } from "../env.js";
|
import { envOption } from "@/config/index.js";
|
||||||
|
|
||||||
import processDeliver from "./processors/deliver.js";
|
import processDeliver from "./processors/deliver.js";
|
||||||
import processInbox from "./processors/inbox.js";
|
import processInbox from "./processors/inbox.js";
|
||||||
|
|
|
@ -5,7 +5,7 @@ import perform from "@/remote/activitypub/perform.js";
|
||||||
import Logger from "@/services/logger.js";
|
import Logger from "@/services/logger.js";
|
||||||
import { registerOrFetchInstanceDoc } from "@/services/register-or-fetch-instance-doc.js";
|
import { registerOrFetchInstanceDoc } from "@/services/register-or-fetch-instance-doc.js";
|
||||||
import { Instances } from "@/models/index.js";
|
import { Instances } from "@/models/index.js";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "backend-rs";
|
||||||
import { toPuny, extractHost } from "backend-rs";
|
import { toPuny, extractHost } from "backend-rs";
|
||||||
import { getApId } from "@/remote/activitypub/type.js";
|
import { getApId } from "@/remote/activitypub/type.js";
|
||||||
import { fetchInstanceMetadata } from "@/services/fetch-instance-metadata.js";
|
import { fetchInstanceMetadata } from "@/services/fetch-instance-metadata.js";
|
||||||
|
@ -41,7 +41,7 @@ export default async (job: Bull.Job<InboxJobData>): Promise<string> => {
|
||||||
const host = toPuny(new URL(signature.keyId).hostname);
|
const host = toPuny(new URL(signature.keyId).hostname);
|
||||||
|
|
||||||
// interrupt if blocked
|
// interrupt if blocked
|
||||||
const meta = await fetchMeta();
|
const meta = await fetchMeta(true);
|
||||||
if (await shouldBlockInstance(host, meta)) {
|
if (await shouldBlockInstance(host, meta)) {
|
||||||
return `Blocked request: ${host}`;
|
return `Blocked request: ${host}`;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { URL } from "url";
|
import { URL } from "url";
|
||||||
import httpSignature, { IParsedSignature } from "@peertube/http-signature";
|
import httpSignature, { IParsedSignature } from "@peertube/http-signature";
|
||||||
import config from "@/config/index.js";
|
import config from "@/config/index.js";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "backend-rs";
|
||||||
import { toPuny } from "backend-rs";
|
import { toPuny } from "backend-rs";
|
||||||
import DbResolver from "@/remote/activitypub/db-resolver.js";
|
import DbResolver from "@/remote/activitypub/db-resolver.js";
|
||||||
import { getApId } from "@/remote/activitypub/type.js";
|
import { getApId } from "@/remote/activitypub/type.js";
|
||||||
|
@ -12,7 +12,7 @@ import type { UserPublickey } from "@/models/entities/user-publickey.js";
|
||||||
import { verify } from "node:crypto";
|
import { verify } from "node:crypto";
|
||||||
|
|
||||||
export async function hasSignature(req: IncomingMessage): Promise<string> {
|
export async function hasSignature(req: IncomingMessage): Promise<string> {
|
||||||
const meta = await fetchMeta();
|
const meta = await fetchMeta(true);
|
||||||
const required = meta.secureMode || meta.privateMode;
|
const required = meta.secureMode || meta.privateMode;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -27,7 +27,7 @@ export async function hasSignature(req: IncomingMessage): Promise<string> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function checkFetch(req: IncomingMessage): Promise<number> {
|
export async function checkFetch(req: IncomingMessage): Promise<number> {
|
||||||
const meta = await fetchMeta();
|
const meta = await fetchMeta(true);
|
||||||
if (meta.secureMode || meta.privateMode) {
|
if (meta.secureMode || meta.privateMode) {
|
||||||
if (req.headers.host !== config.host) return 400;
|
if (req.headers.host !== config.host) return 400;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import type { CacheableRemoteUser } from "@/models/entities/user.js";
|
import type { CacheableRemoteUser } from "@/models/entities/user.js";
|
||||||
import deleteNode from "@/services/note/delete.js";
|
import deleteNote from "@/services/note/delete.js";
|
||||||
import { apLogger } from "../../logger.js";
|
import { apLogger } from "../../logger.js";
|
||||||
import DbResolver from "../../db-resolver.js";
|
import DbResolver from "../../db-resolver.js";
|
||||||
import { getApLock } from "@/misc/app-lock.js";
|
import { getApLock } from "@/misc/app-lock.js";
|
||||||
|
@ -36,7 +36,7 @@ export default async function (
|
||||||
return "The user trying to delete the post is not the post author";
|
return "The user trying to delete the post is not the post author";
|
||||||
}
|
}
|
||||||
|
|
||||||
await deleteNode(actor, note);
|
await deleteNote(actor, note);
|
||||||
return "ok: note deleted";
|
return "ok: note deleted";
|
||||||
} finally {
|
} finally {
|
||||||
await lock.release();
|
await lock.release();
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { uploadFromUrl } from "@/services/drive/upload-from-url.js";
|
import { uploadFromUrl } from "@/services/drive/upload-from-url.js";
|
||||||
import type { CacheableRemoteUser } from "@/models/entities/user.js";
|
import type { CacheableRemoteUser } from "@/models/entities/user.js";
|
||||||
import Resolver from "../resolver.js";
|
import Resolver from "../resolver.js";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "backend-rs";
|
||||||
import { apLogger } from "../logger.js";
|
import { apLogger } from "../logger.js";
|
||||||
import type { DriveFile } from "@/models/entities/drive-file.js";
|
import type { DriveFile } from "@/models/entities/drive-file.js";
|
||||||
import { DriveFiles } from "@/models/index.js";
|
import { DriveFiles } from "@/models/index.js";
|
||||||
|
@ -34,7 +34,7 @@ export async function createImage(
|
||||||
|
|
||||||
logger.info(`Creating the Image: ${image.url}`);
|
logger.info(`Creating the Image: ${image.url}`);
|
||||||
|
|
||||||
const instance = await fetchMeta();
|
const instance = await fetchMeta(true);
|
||||||
|
|
||||||
let file = await uploadFromUrl({
|
let file = await uploadFromUrl({
|
||||||
url: image.url,
|
url: image.url,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import config from "@/config/index.js";
|
import config from "@/config/index.js";
|
||||||
import type { ILocalUser } from "@/models/entities/user.js";
|
import type { ILocalUser } from "@/models/entities/user.js";
|
||||||
import { getInstanceActor } from "@/services/instance-actor.js";
|
import { getInstanceActor } from "@/services/instance-actor.js";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "backend-rs";
|
||||||
import { extractHost, isSelfHost } from "backend-rs";
|
import { extractHost, isSelfHost } from "backend-rs";
|
||||||
import { apGet } from "./request.js";
|
import { apGet } from "./request.js";
|
||||||
import type { IObject, ICollection, IOrderedCollection } from "./type.js";
|
import type { IObject, ICollection, IOrderedCollection } from "./type.js";
|
||||||
|
@ -100,7 +100,7 @@ export default class Resolver {
|
||||||
return await this.resolveLocal(value);
|
return await this.resolveLocal(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
const meta = await fetchMeta();
|
const meta = await fetchMeta(true);
|
||||||
if (await shouldBlockInstance(host, meta)) {
|
if (await shouldBlockInstance(host, meta)) {
|
||||||
throw new Error("Instance is blocked");
|
throw new Error("Instance is blocked");
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import renderKey from "@/remote/activitypub/renderer/key.js";
|
||||||
import { renderPerson } from "@/remote/activitypub/renderer/person.js";
|
import { renderPerson } from "@/remote/activitypub/renderer/person.js";
|
||||||
import renderEmoji from "@/remote/activitypub/renderer/emoji.js";
|
import renderEmoji from "@/remote/activitypub/renderer/emoji.js";
|
||||||
import { inbox as processInbox } from "@/queue/index.js";
|
import { inbox as processInbox } from "@/queue/index.js";
|
||||||
import { isSelfHost } from "backend-rs";
|
import { fetchMeta, isSelfHost } from "backend-rs";
|
||||||
import {
|
import {
|
||||||
Notes,
|
Notes,
|
||||||
Users,
|
Users,
|
||||||
|
@ -25,7 +25,6 @@ import {
|
||||||
getSignatureUser,
|
getSignatureUser,
|
||||||
} from "@/remote/activitypub/check-fetch.js";
|
} from "@/remote/activitypub/check-fetch.js";
|
||||||
import { getInstanceActor } from "@/services/instance-actor.js";
|
import { getInstanceActor } from "@/services/instance-actor.js";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
|
||||||
import renderFollow from "@/remote/activitypub/renderer/follow.js";
|
import renderFollow from "@/remote/activitypub/renderer/follow.js";
|
||||||
import Featured from "./activitypub/featured.js";
|
import Featured from "./activitypub/featured.js";
|
||||||
import Following from "./activitypub/following.js";
|
import Following from "./activitypub/following.js";
|
||||||
|
@ -238,7 +237,7 @@ router.get("/notes/:note", async (ctx, next) => {
|
||||||
|
|
||||||
ctx.body = renderActivity(await renderNote(note, false));
|
ctx.body = renderActivity(await renderNote(note, false));
|
||||||
|
|
||||||
const meta = await fetchMeta();
|
const meta = await fetchMeta(true);
|
||||||
if (meta.secureMode || meta.privateMode) {
|
if (meta.secureMode || meta.privateMode) {
|
||||||
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
||||||
} else {
|
} else {
|
||||||
|
@ -268,7 +267,7 @@ router.get("/notes/:note/activity", async (ctx) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.body = renderActivity(await packActivity(note));
|
ctx.body = renderActivity(await packActivity(note));
|
||||||
const meta = await fetchMeta();
|
const meta = await fetchMeta(true);
|
||||||
if (meta.secureMode || meta.privateMode) {
|
if (meta.secureMode || meta.privateMode) {
|
||||||
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
||||||
} else {
|
} else {
|
||||||
|
@ -323,7 +322,7 @@ router.get("/users/:user/publickey", async (ctx) => {
|
||||||
|
|
||||||
if (Users.isLocalUser(user)) {
|
if (Users.isLocalUser(user)) {
|
||||||
ctx.body = renderActivity(renderKey(user, keypair));
|
ctx.body = renderActivity(renderKey(user, keypair));
|
||||||
const meta = await fetchMeta();
|
const meta = await fetchMeta(true);
|
||||||
if (meta.secureMode || meta.privateMode) {
|
if (meta.secureMode || meta.privateMode) {
|
||||||
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
||||||
} else {
|
} else {
|
||||||
|
@ -343,7 +342,7 @@ async function userInfo(ctx: Router.RouterContext, user: User | null) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.body = renderActivity(await renderPerson(user as ILocalUser));
|
ctx.body = renderActivity(await renderPerson(user as ILocalUser));
|
||||||
const meta = await fetchMeta();
|
const meta = await fetchMeta(true);
|
||||||
if (meta.secureMode || meta.privateMode) {
|
if (meta.secureMode || meta.privateMode) {
|
||||||
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
||||||
} else {
|
} else {
|
||||||
|
@ -426,8 +425,8 @@ router.get("/emojis/:emoji", async (ctx) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.body = renderActivity(await renderEmoji(emoji));
|
ctx.body = renderActivity(renderEmoji(emoji));
|
||||||
const meta = await fetchMeta();
|
const meta = await fetchMeta(true);
|
||||||
if (meta.secureMode || meta.privateMode) {
|
if (meta.secureMode || meta.privateMode) {
|
||||||
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
||||||
} else {
|
} else {
|
||||||
|
@ -459,7 +458,7 @@ router.get("/likes/:like", async (ctx) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.body = renderActivity(await renderLike(reaction, note));
|
ctx.body = renderActivity(await renderLike(reaction, note));
|
||||||
const meta = await fetchMeta();
|
const meta = await fetchMeta(true);
|
||||||
if (meta.secureMode || meta.privateMode) {
|
if (meta.secureMode || meta.privateMode) {
|
||||||
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
||||||
} else {
|
} else {
|
||||||
|
@ -497,7 +496,7 @@ router.get(
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.body = renderActivity(renderFollow(follower, followee));
|
ctx.body = renderActivity(renderFollow(follower, followee));
|
||||||
const meta = await fetchMeta();
|
const meta = await fetchMeta(true);
|
||||||
if (meta.secureMode || meta.privateMode) {
|
if (meta.secureMode || meta.privateMode) {
|
||||||
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
||||||
} else {
|
} else {
|
||||||
|
@ -540,7 +539,7 @@ router.get("/follows/:followRequestId", async (ctx: Router.RouterContext) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const meta = await fetchMeta();
|
const meta = await fetchMeta(true);
|
||||||
if (meta.secureMode || meta.privateMode) {
|
if (meta.secureMode || meta.privateMode) {
|
||||||
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -5,7 +5,7 @@ import renderOrderedCollection from "@/remote/activitypub/renderer/ordered-colle
|
||||||
import renderNote from "@/remote/activitypub/renderer/note.js";
|
import renderNote from "@/remote/activitypub/renderer/note.js";
|
||||||
import { Users, Notes, UserNotePinings } from "@/models/index.js";
|
import { Users, Notes, UserNotePinings } from "@/models/index.js";
|
||||||
import { checkFetch } from "@/remote/activitypub/check-fetch.js";
|
import { checkFetch } from "@/remote/activitypub/check-fetch.js";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "backend-rs";
|
||||||
import { setResponseType } from "../activitypub.js";
|
import { setResponseType } from "../activitypub.js";
|
||||||
import type Router from "@koa/router";
|
import type Router from "@koa/router";
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ export default async (ctx: Router.RouterContext) => {
|
||||||
|
|
||||||
ctx.body = renderActivity(rendered);
|
ctx.body = renderActivity(rendered);
|
||||||
|
|
||||||
const meta = await fetchMeta();
|
const meta = await fetchMeta(true);
|
||||||
if (meta.secureMode || meta.privateMode) {
|
if (meta.secureMode || meta.privateMode) {
|
||||||
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -8,7 +8,7 @@ import renderFollowUser from "@/remote/activitypub/renderer/follow-user.js";
|
||||||
import { Users, Followings, UserProfiles } from "@/models/index.js";
|
import { Users, Followings, UserProfiles } from "@/models/index.js";
|
||||||
import type { Following } from "@/models/entities/following.js";
|
import type { Following } from "@/models/entities/following.js";
|
||||||
import { checkFetch } from "@/remote/activitypub/check-fetch.js";
|
import { checkFetch } from "@/remote/activitypub/check-fetch.js";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "backend-rs";
|
||||||
import { setResponseType } from "../activitypub.js";
|
import { setResponseType } from "../activitypub.js";
|
||||||
import type { FindOptionsWhere } from "typeorm";
|
import type { FindOptionsWhere } from "typeorm";
|
||||||
import type Router from "@koa/router";
|
import type Router from "@koa/router";
|
||||||
|
@ -110,7 +110,7 @@ export default async (ctx: Router.RouterContext) => {
|
||||||
ctx.body = renderActivity(rendered);
|
ctx.body = renderActivity(rendered);
|
||||||
setResponseType(ctx);
|
setResponseType(ctx);
|
||||||
}
|
}
|
||||||
const meta = await fetchMeta();
|
const meta = await fetchMeta(true);
|
||||||
if (meta.secureMode || meta.privateMode) {
|
if (meta.secureMode || meta.privateMode) {
|
||||||
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -8,7 +8,7 @@ import renderFollowUser from "@/remote/activitypub/renderer/follow-user.js";
|
||||||
import { Users, Followings, UserProfiles } from "@/models/index.js";
|
import { Users, Followings, UserProfiles } from "@/models/index.js";
|
||||||
import type { Following } from "@/models/entities/following.js";
|
import type { Following } from "@/models/entities/following.js";
|
||||||
import { checkFetch } from "@/remote/activitypub/check-fetch.js";
|
import { checkFetch } from "@/remote/activitypub/check-fetch.js";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "backend-rs";
|
||||||
import { setResponseType } from "../activitypub.js";
|
import { setResponseType } from "../activitypub.js";
|
||||||
import type { FindOptionsWhere } from "typeorm";
|
import type { FindOptionsWhere } from "typeorm";
|
||||||
import type Router from "@koa/router";
|
import type Router from "@koa/router";
|
||||||
|
@ -110,7 +110,7 @@ export default async (ctx: Router.RouterContext) => {
|
||||||
ctx.body = renderActivity(rendered);
|
ctx.body = renderActivity(rendered);
|
||||||
setResponseType(ctx);
|
setResponseType(ctx);
|
||||||
}
|
}
|
||||||
const meta = await fetchMeta();
|
const meta = await fetchMeta(true);
|
||||||
if (meta.secureMode || meta.privateMode) {
|
if (meta.secureMode || meta.privateMode) {
|
||||||
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -11,7 +11,7 @@ import * as url from "@/prelude/url.js";
|
||||||
import { Users, Notes } from "@/models/index.js";
|
import { Users, Notes } from "@/models/index.js";
|
||||||
import type { Note } from "@/models/entities/note.js";
|
import type { Note } from "@/models/entities/note.js";
|
||||||
import { checkFetch } from "@/remote/activitypub/check-fetch.js";
|
import { checkFetch } from "@/remote/activitypub/check-fetch.js";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "backend-rs";
|
||||||
import { makePaginationQuery } from "../api/common/make-pagination-query.js";
|
import { makePaginationQuery } from "../api/common/make-pagination-query.js";
|
||||||
import { setResponseType } from "../activitypub.js";
|
import { setResponseType } from "../activitypub.js";
|
||||||
import type Router from "@koa/router";
|
import type Router from "@koa/router";
|
||||||
|
@ -117,7 +117,7 @@ export default async (ctx: Router.RouterContext) => {
|
||||||
|
|
||||||
setResponseType(ctx);
|
setResponseType(ctx);
|
||||||
}
|
}
|
||||||
const meta = await fetchMeta();
|
const meta = await fetchMeta(true);
|
||||||
if (meta.secureMode || meta.privateMode) {
|
if (meta.secureMode || meta.privateMode) {
|
||||||
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -2,7 +2,7 @@ import type Koa from "koa";
|
||||||
|
|
||||||
import type { User } from "@/models/entities/user.js";
|
import type { User } from "@/models/entities/user.js";
|
||||||
import { UserIps } from "@/models/index.js";
|
import { UserIps } from "@/models/index.js";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "backend-rs";
|
||||||
import type { IEndpoint } from "./endpoints.js";
|
import type { IEndpoint } from "./endpoints.js";
|
||||||
import authenticate, { AuthenticationError } from "./authenticate.js";
|
import authenticate, { AuthenticationError } from "./authenticate.js";
|
||||||
import call from "./call.js";
|
import call from "./call.js";
|
||||||
|
@ -84,7 +84,7 @@ export default (endpoint: IEndpoint, ctx: Koa.Context) =>
|
||||||
|
|
||||||
// Log IP
|
// Log IP
|
||||||
if (user) {
|
if (user) {
|
||||||
fetchMeta().then((meta) => {
|
fetchMeta(true).then((meta) => {
|
||||||
if (!meta.enableIpLogging) return;
|
if (!meta.enableIpLogging) return;
|
||||||
const ip = ctx.ip;
|
const ip = ctx.ip;
|
||||||
const ips = userIpHistories.get(user.id);
|
const ips = userIpHistories.get(user.id);
|
||||||
|
|
|
@ -10,7 +10,7 @@ import endpoints from "./endpoints.js";
|
||||||
import compatibility from "./compatibility.js";
|
import compatibility from "./compatibility.js";
|
||||||
import { ApiError } from "./error.js";
|
import { ApiError } from "./error.js";
|
||||||
import { apiLogger } from "./logger.js";
|
import { apiLogger } from "./logger.js";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "backend-rs";
|
||||||
|
|
||||||
const accessDenied = {
|
const accessDenied = {
|
||||||
message: "Access denied.",
|
message: "Access denied.",
|
||||||
|
@ -117,7 +117,7 @@ export default async (
|
||||||
}
|
}
|
||||||
|
|
||||||
// private mode
|
// private mode
|
||||||
const meta = await fetchMeta();
|
const meta = await fetchMeta(true);
|
||||||
if (
|
if (
|
||||||
meta.privateMode &&
|
meta.privateMode &&
|
||||||
ep.meta.requireCredentialPrivateMode &&
|
ep.meta.requireCredentialPrivateMode &&
|
||||||
|
|
|
@ -4,12 +4,11 @@ import { User } from "@/models/entities/user.js";
|
||||||
import { Users, UsedUsernames } from "@/models/index.js";
|
import { Users, UsedUsernames } from "@/models/index.js";
|
||||||
import { UserProfile } from "@/models/entities/user-profile.js";
|
import { UserProfile } from "@/models/entities/user-profile.js";
|
||||||
import { IsNull } from "typeorm";
|
import { IsNull } from "typeorm";
|
||||||
import { genId, toPuny } from "backend-rs";
|
import { genId, hashPassword, toPuny } from "backend-rs";
|
||||||
import { UserKeypair } from "@/models/entities/user-keypair.js";
|
import { UserKeypair } from "@/models/entities/user-keypair.js";
|
||||||
import { UsedUsername } from "@/models/entities/used-username.js";
|
import { UsedUsername } from "@/models/entities/used-username.js";
|
||||||
import { db } from "@/db/postgre.js";
|
import { db } from "@/db/postgre.js";
|
||||||
import config from "@/config/index.js";
|
import config from "@/config/index.js";
|
||||||
import { hashPassword } from "@/misc/password.js";
|
|
||||||
|
|
||||||
export async function signup(opts: {
|
export async function signup(opts: {
|
||||||
username: User["username"];
|
username: User["username"];
|
||||||
|
@ -40,7 +39,7 @@ export async function signup(opts: {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate hash of password
|
// Generate hash of password
|
||||||
hash = await hashPassword(password);
|
hash = hashPassword(password);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate secret
|
// Generate secret
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
import { Emojis } from "@/models/index.js";
|
import { Emojis } from "@/models/index.js";
|
||||||
import { toPuny } from "backend-rs";
|
import { sqlLikeEscape, toPuny } from "backend-rs";
|
||||||
import { makePaginationQuery } from "@/server/api/common/make-pagination-query.js";
|
import { makePaginationQuery } from "@/server/api/common/make-pagination-query.js";
|
||||||
import { sqlLikeEscape } from "@/misc/sql-like-escape.js";
|
|
||||||
import { ApiError } from "@/server/api/error.js";
|
import { ApiError } from "@/server/api/error.js";
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
import { Emojis } from "@/models/index.js";
|
import { Emojis } from "@/models/index.js";
|
||||||
import { makePaginationQuery } from "../../../common/make-pagination-query.js";
|
import { makePaginationQuery } from "@/server/api/common/make-pagination-query.js";
|
||||||
import type { Emoji } from "@/models/entities/emoji.js";
|
import type { Emoji } from "@/models/entities/emoji.js";
|
||||||
//import { sqlLikeEscape } from "@/misc/sql-like-escape.js";
|
//import { sqlLikeEscape } from "backend-rs";
|
||||||
import { ApiError } from "@/server/api/error.js";
|
import { ApiError } from "@/server/api/error.js";
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import config from "@/config/index.js";
|
import config from "@/config/index.js";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "backend-rs";
|
||||||
import { MAX_NOTE_TEXT_LENGTH, MAX_CAPTION_TEXT_LENGTH } from "@/const.js";
|
import { MAX_NOTE_TEXT_LENGTH, MAX_CAPTION_TEXT_LENGTH } from "@/const.js";
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
|
|
||||||
|
@ -466,7 +466,7 @@ export const paramDef = {
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export default define(meta, paramDef, async () => {
|
export default define(meta, paramDef, async () => {
|
||||||
const instance = await fetchMeta(true);
|
const instance = await fetchMeta(false);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
maintainerName: instance.maintainerName,
|
maintainerName: instance.maintainerName,
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
// import bcrypt from "bcryptjs";
|
|
||||||
import rndstr from "rndstr";
|
import rndstr from "rndstr";
|
||||||
import { Users, UserProfiles } from "@/models/index.js";
|
import { Users, UserProfiles } from "@/models/index.js";
|
||||||
import { hashPassword } from "@/misc/password.js";
|
import { hashPassword } from "backend-rs";
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ["admin"],
|
tags: ["admin"],
|
||||||
|
@ -48,8 +47,7 @@ export default define(meta, paramDef, async (ps) => {
|
||||||
const passwd = rndstr("a-zA-Z0-9", 8);
|
const passwd = rndstr("a-zA-Z0-9", 8);
|
||||||
|
|
||||||
// Generate hash of password
|
// Generate hash of password
|
||||||
// const hash = bcrypt.hashSync(passwd);
|
const hash = hashPassword(passwd);
|
||||||
const hash = await hashPassword(passwd);
|
|
||||||
|
|
||||||
await UserProfiles.update(
|
await UserProfiles.update(
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Users } from "@/models/index.js";
|
import { Users } from "@/models/index.js";
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
import { sqlLikeEscape } from "@/misc/sql-like-escape.js";
|
import { sqlLikeEscape } from "backend-rs";
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ["admin"],
|
tags: ["admin"],
|
||||||
|
|
|
@ -2,7 +2,7 @@ import define from "@/server/api/define.js";
|
||||||
import { Brackets } from "typeorm";
|
import { Brackets } from "typeorm";
|
||||||
import { makePaginationQuery } from "@/server/api/common/make-pagination-query.js";
|
import { makePaginationQuery } from "@/server/api/common/make-pagination-query.js";
|
||||||
import { Channels } from "@/models/index.js";
|
import { Channels } from "@/models/index.js";
|
||||||
import { sqlLikeEscape } from "@/misc/sql-like-escape.js";
|
import { sqlLikeEscape } from "backend-rs";
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ["channels"],
|
tags: ["channels"],
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// import { IsNull } from 'typeorm';
|
// import { IsNull } from 'typeorm';
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "backend-rs";
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
|
@ -27,7 +27,7 @@ export const paramDef = {
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export default define(meta, paramDef, async () => {
|
export default define(meta, paramDef, async () => {
|
||||||
const meta = await fetchMeta();
|
const meta = await fetchMeta(true);
|
||||||
const motd = await Promise.all(meta.customMotd.map((x) => x));
|
const motd = await Promise.all(meta.customMotd.map((x) => x));
|
||||||
return motd;
|
return motd;
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// import { IsNull } from 'typeorm';
|
// import { IsNull } from 'typeorm';
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "backend-rs";
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
|
@ -27,7 +27,7 @@ export const paramDef = {
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export default define(meta, paramDef, async () => {
|
export default define(meta, paramDef, async () => {
|
||||||
const meta = await fetchMeta();
|
const meta = await fetchMeta(true);
|
||||||
const icons = await Promise.all(meta.customSplashIcons.map((x) => x));
|
const icons = await Promise.all(meta.customSplashIcons.map((x) => x));
|
||||||
return icons;
|
return icons;
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "backend-rs";
|
||||||
import { DriveFiles } from "@/models/index.js";
|
import { DriveFiles } from "@/models/index.js";
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ export const paramDef = {
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export default define(meta, paramDef, async (ps, user) => {
|
export default define(meta, paramDef, async (ps, user) => {
|
||||||
const instance = await fetchMeta(true);
|
const instance = await fetchMeta(false);
|
||||||
|
|
||||||
// Calculate drive usage
|
// Calculate drive usage
|
||||||
const usage = await DriveFiles.calcDriveUsageOf(user.id);
|
const usage = await DriveFiles.calcDriveUsageOf(user.id);
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { addFile } from "@/services/drive/add-file.js";
|
||||||
import { DriveFiles } from "@/models/index.js";
|
import { DriveFiles } from "@/models/index.js";
|
||||||
import { DB_MAX_IMAGE_COMMENT_LENGTH } from "@/misc/hard-limits.js";
|
import { DB_MAX_IMAGE_COMMENT_LENGTH } from "@/misc/hard-limits.js";
|
||||||
import { IdentifiableError } from "@/misc/identifiable-error.js";
|
import { IdentifiableError } from "@/misc/identifiable-error.js";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "backend-rs";
|
||||||
import { MINUTE } from "@/const.js";
|
import { MINUTE } from "@/const.js";
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
import { apiLogger } from "@/server/api/logger.js";
|
import { apiLogger } from "@/server/api/logger.js";
|
||||||
|
@ -96,7 +96,7 @@ export default define(
|
||||||
name = null;
|
name = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const instanceMeta = await fetchMeta();
|
const instanceMeta = await fetchMeta(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Create file
|
// Create file
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
import { Instances } from "@/models/index.js";
|
import { Instances } from "@/models/index.js";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta, sqlLikeEscape } from "backend-rs";
|
||||||
import { sqlLikeEscape } from "@/misc/sql-like-escape.js";
|
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ["federation"],
|
tags: ["federation"],
|
||||||
|
@ -101,7 +100,7 @@ export default define(meta, paramDef, async (ps, me) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof ps.blocked === "boolean") {
|
if (typeof ps.blocked === "boolean") {
|
||||||
const meta = await fetchMeta(true);
|
const meta = await fetchMeta(false);
|
||||||
if (ps.blocked) {
|
if (ps.blocked) {
|
||||||
if (meta.blockedHosts.length === 0) {
|
if (meta.blockedHosts.length === 0) {
|
||||||
return [];
|
return [];
|
||||||
|
@ -117,7 +116,7 @@ export default define(meta, paramDef, async (ps, me) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof ps.silenced === "boolean") {
|
if (typeof ps.silenced === "boolean") {
|
||||||
const meta = await fetchMeta(true);
|
const meta = await fetchMeta(false);
|
||||||
if (ps.silenced) {
|
if (ps.silenced) {
|
||||||
if (meta.silencedHosts.length === 0) {
|
if (meta.silencedHosts.length === 0) {
|
||||||
return [];
|
return [];
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
import { Hashtags } from "@/models/index.js";
|
import { Hashtags } from "@/models/index.js";
|
||||||
import { sqlLikeEscape } from "@/misc/sql-like-escape.js";
|
import { sqlLikeEscape } from "backend-rs";
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ["hashtags"],
|
tags: ["hashtags"],
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import { Brackets } from "typeorm";
|
import { Brackets } from "typeorm";
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta, safeForSql } from "backend-rs";
|
||||||
import { Notes } from "@/models/index.js";
|
import { Notes } from "@/models/index.js";
|
||||||
import type { Note } from "@/models/entities/note.js";
|
import type { Note } from "@/models/entities/note.js";
|
||||||
import { safeForSql } from "@/misc/safe-for-sql.js";
|
|
||||||
import { normalizeForSearch } from "@/misc/normalize-for-search.js";
|
import { normalizeForSearch } from "@/misc/normalize-for-search.js";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -67,7 +66,7 @@ export const paramDef = {
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export default define(meta, paramDef, async () => {
|
export default define(meta, paramDef, async () => {
|
||||||
const instance = await fetchMeta(true);
|
const instance = await fetchMeta(false);
|
||||||
const hiddenTags = instance.hiddenTags.map((t) => normalizeForSearch(t));
|
const hiddenTags = instance.hiddenTags.map((t) => normalizeForSearch(t));
|
||||||
|
|
||||||
const now = new Date(); // 5分単位で丸めた現在日時
|
const now = new Date(); // 5分単位で丸めた現在日時
|
||||||
|
|
|
@ -9,7 +9,7 @@ import {
|
||||||
import config from "@/config/index.js";
|
import config from "@/config/index.js";
|
||||||
import { procedures, hash } from "@/server/api/2fa.js";
|
import { procedures, hash } from "@/server/api/2fa.js";
|
||||||
import { publishMainStream } from "@/services/stream.js";
|
import { publishMainStream } from "@/services/stream.js";
|
||||||
import { comparePassword } from "@/misc/password.js";
|
import { verifyPassword } from "backend-rs";
|
||||||
|
|
||||||
const rpIdHashReal = hash(Buffer.from(config.hostname, "utf-8"));
|
const rpIdHashReal = hash(Buffer.from(config.hostname, "utf-8"));
|
||||||
|
|
||||||
|
@ -40,8 +40,8 @@ export const paramDef = {
|
||||||
export default define(meta, paramDef, async (ps, user) => {
|
export default define(meta, paramDef, async (ps, user) => {
|
||||||
const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
|
const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
|
||||||
|
|
||||||
// Compare password
|
// Compare passwords
|
||||||
const same = await comparePassword(ps.password, profile.password!);
|
const same = verifyPassword(ps.password, profile.password!);
|
||||||
|
|
||||||
if (!same) {
|
if (!same) {
|
||||||
throw new Error("incorrect password");
|
throw new Error("incorrect password");
|
||||||
|
|
|
@ -2,9 +2,8 @@ import define from "@/server/api/define.js";
|
||||||
import { UserProfiles, AttestationChallenges } from "@/models/index.js";
|
import { UserProfiles, AttestationChallenges } from "@/models/index.js";
|
||||||
import { promisify } from "node:util";
|
import { promisify } from "node:util";
|
||||||
import * as crypto from "node:crypto";
|
import * as crypto from "node:crypto";
|
||||||
import { genId } from "backend-rs";
|
import { genId, verifyPassword } from "backend-rs";
|
||||||
import { hash } from "@/server/api/2fa.js";
|
import { hash } from "@/server/api/2fa.js";
|
||||||
import { comparePassword } from "@/misc/password.js";
|
|
||||||
|
|
||||||
const randomBytes = promisify(crypto.randomBytes);
|
const randomBytes = promisify(crypto.randomBytes);
|
||||||
|
|
||||||
|
@ -25,8 +24,8 @@ export const paramDef = {
|
||||||
export default define(meta, paramDef, async (ps, user) => {
|
export default define(meta, paramDef, async (ps, user) => {
|
||||||
const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
|
const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
|
||||||
|
|
||||||
// Compare password
|
// Compare passwords
|
||||||
const same = await comparePassword(ps.password, profile.password!);
|
const same = verifyPassword(ps.password, profile.password!);
|
||||||
|
|
||||||
if (!same) {
|
if (!same) {
|
||||||
throw new Error("incorrect password");
|
throw new Error("incorrect password");
|
||||||
|
|
|
@ -3,7 +3,7 @@ import * as QRCode from "qrcode";
|
||||||
import config from "@/config/index.js";
|
import config from "@/config/index.js";
|
||||||
import { UserProfiles } from "@/models/index.js";
|
import { UserProfiles } from "@/models/index.js";
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
import { comparePassword } from "@/misc/password.js";
|
import { verifyPassword } from "backend-rs";
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
@ -22,8 +22,8 @@ export const paramDef = {
|
||||||
export default define(meta, paramDef, async (ps, user) => {
|
export default define(meta, paramDef, async (ps, user) => {
|
||||||
const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
|
const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
|
||||||
|
|
||||||
// Compare password
|
// Compare passwords
|
||||||
const same = await comparePassword(ps.password, profile.password!);
|
const same = verifyPassword(ps.password, profile.password!);
|
||||||
|
|
||||||
if (!same) {
|
if (!same) {
|
||||||
throw new Error("incorrect password");
|
throw new Error("incorrect password");
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { comparePassword } from "@/misc/password.js";
|
import { verifyPassword } from "backend-rs";
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
import { UserProfiles, UserSecurityKeys, Users } from "@/models/index.js";
|
import { UserProfiles, UserSecurityKeys, Users } from "@/models/index.js";
|
||||||
import { publishMainStream } from "@/services/stream.js";
|
import { publishMainStream } from "@/services/stream.js";
|
||||||
|
@ -21,8 +21,8 @@ export const paramDef = {
|
||||||
export default define(meta, paramDef, async (ps, user) => {
|
export default define(meta, paramDef, async (ps, user) => {
|
||||||
const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
|
const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
|
||||||
|
|
||||||
// Compare password
|
// Compare passwords
|
||||||
const same = await comparePassword(ps.password, profile.password!);
|
const same = verifyPassword(ps.password, profile.password!);
|
||||||
|
|
||||||
if (!same) {
|
if (!same) {
|
||||||
throw new Error("incorrect password");
|
throw new Error("incorrect password");
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { publishMainStream } from "@/services/stream.js";
|
import { publishMainStream } from "@/services/stream.js";
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
import { Users, UserProfiles } from "@/models/index.js";
|
import { Users, UserProfiles } from "@/models/index.js";
|
||||||
import { comparePassword } from "@/misc/password.js";
|
import { verifyPassword } from "backend-rs";
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
@ -20,8 +20,8 @@ export const paramDef = {
|
||||||
export default define(meta, paramDef, async (ps, user) => {
|
export default define(meta, paramDef, async (ps, user) => {
|
||||||
const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
|
const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
|
||||||
|
|
||||||
// Compare password
|
// Compare passwords
|
||||||
const same = await comparePassword(ps.password, profile.password!);
|
const same = verifyPassword(ps.password, profile.password!);
|
||||||
|
|
||||||
if (!same) {
|
if (!same) {
|
||||||
throw new Error("incorrect password");
|
throw new Error("incorrect password");
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
import { UserProfiles } from "@/models/index.js";
|
import { UserProfiles } from "@/models/index.js";
|
||||||
import { hashPassword, comparePassword } from "@/misc/password.js";
|
import { hashPassword, verifyPassword } from "backend-rs";
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
@ -20,8 +20,8 @@ export const paramDef = {
|
||||||
export default define(meta, paramDef, async (ps, user) => {
|
export default define(meta, paramDef, async (ps, user) => {
|
||||||
const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
|
const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
|
||||||
|
|
||||||
// Compare password
|
// Compare passwords
|
||||||
const same = await comparePassword(ps.currentPassword, profile.password!);
|
const same = verifyPassword(ps.currentPassword, profile.password!);
|
||||||
|
|
||||||
if (!same) {
|
if (!same) {
|
||||||
throw new Error("incorrect password");
|
throw new Error("incorrect password");
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { UserProfiles, Users } from "@/models/index.js";
|
import { UserProfiles, Users } from "@/models/index.js";
|
||||||
import { deleteAccount } from "@/services/delete-account.js";
|
import { deleteAccount } from "@/services/delete-account.js";
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
import { comparePassword } from "@/misc/password.js";
|
import { verifyPassword } from "backend-rs";
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
@ -24,8 +24,8 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compare password
|
// Compare passwords
|
||||||
const same = await comparePassword(ps.password, profile.password!);
|
const same = verifyPassword(ps.password, profile.password!);
|
||||||
|
|
||||||
if (!same) {
|
if (!same) {
|
||||||
throw new Error("incorrect password");
|
throw new Error("incorrect password");
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { createImportPostsJob } from "@/queue/index.js";
|
||||||
import { ApiError } from "@/server/api/error.js";
|
import { ApiError } from "@/server/api/error.js";
|
||||||
import { DriveFiles } from "@/models/index.js";
|
import { DriveFiles } from "@/models/index.js";
|
||||||
import { DAY } from "@/const.js";
|
import { DAY } from "@/const.js";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "backend-rs";
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
secure: true,
|
secure: true,
|
||||||
|
@ -45,7 +45,7 @@ export const paramDef = {
|
||||||
export default define(meta, paramDef, async (ps, user) => {
|
export default define(meta, paramDef, async (ps, user) => {
|
||||||
const file = await DriveFiles.findOneBy({ id: ps.fileId });
|
const file = await DriveFiles.findOneBy({ id: ps.fileId });
|
||||||
|
|
||||||
const instanceMeta = await fetchMeta();
|
const instanceMeta = await fetchMeta(true);
|
||||||
if (instanceMeta.experimentalFeatures?.postImports === false)
|
if (instanceMeta.experimentalFeatures?.postImports === false)
|
||||||
throw new ApiError(meta.errors.importsDisabled);
|
throw new ApiError(meta.errors.importsDisabled);
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import {
|
||||||
import generateUserToken from "@/server/api/common/generate-native-user-token.js";
|
import generateUserToken from "@/server/api/common/generate-native-user-token.js";
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
import { Users, UserProfiles } from "@/models/index.js";
|
import { Users, UserProfiles } from "@/models/index.js";
|
||||||
import { comparePassword } from "@/misc/password.js";
|
import { verifyPassword } from "backend-rs";
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
@ -28,8 +28,8 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
|
|
||||||
const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
|
const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
|
||||||
|
|
||||||
// Compare password
|
// Compare passwords
|
||||||
const same = await comparePassword(ps.password, profile.password!);
|
const same = verifyPassword(ps.password, profile.password!);
|
||||||
|
|
||||||
if (!same) {
|
if (!same) {
|
||||||
throw new Error("incorrect password");
|
throw new Error("incorrect password");
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { sendEmail } from "@/services/send-email.js";
|
||||||
import { ApiError } from "@/server/api/error.js";
|
import { ApiError } from "@/server/api/error.js";
|
||||||
import { validateEmailForAccount } from "@/services/validate-email-for-account.js";
|
import { validateEmailForAccount } from "@/services/validate-email-for-account.js";
|
||||||
import { HOUR } from "@/const.js";
|
import { HOUR } from "@/const.js";
|
||||||
import { comparePassword } from "@/misc/password.js";
|
import { verifyPassword } from "backend-rs";
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
@ -46,8 +46,8 @@ export const paramDef = {
|
||||||
export default define(meta, paramDef, async (ps, user) => {
|
export default define(meta, paramDef, async (ps, user) => {
|
||||||
const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
|
const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
|
||||||
|
|
||||||
// Compare password
|
// Compare passwords
|
||||||
const same = await comparePassword(ps.password, profile.password!);
|
const same = verifyPassword(ps.password, profile.password!);
|
||||||
|
|
||||||
if (!same) {
|
if (!same) {
|
||||||
throw new ApiError(meta.errors.incorrectPassword);
|
throw new ApiError(meta.errors.incorrectPassword);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import JSON5 from "json5";
|
import JSON5 from "json5";
|
||||||
import { IsNull, MoreThan } from "typeorm";
|
import { IsNull, MoreThan } from "typeorm";
|
||||||
import config from "@/config/index.js";
|
import config from "@/config/index.js";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "backend-rs";
|
||||||
import { Ads, Emojis, Users } from "@/models/index.js";
|
import { Ads, Emojis, Users } from "@/models/index.js";
|
||||||
import { MAX_NOTE_TEXT_LENGTH, MAX_CAPTION_TEXT_LENGTH } from "@/const.js";
|
import { MAX_NOTE_TEXT_LENGTH, MAX_CAPTION_TEXT_LENGTH } from "@/const.js";
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
|
@ -398,7 +398,7 @@ export const paramDef = {
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export default define(meta, paramDef, async (ps, me) => {
|
export default define(meta, paramDef, async (ps, me) => {
|
||||||
const instance = await fetchMeta(true);
|
const instance = await fetchMeta(false);
|
||||||
|
|
||||||
const emojis = await Emojis.find({
|
const emojis = await Emojis.find({
|
||||||
where: {
|
where: {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "backend-rs";
|
||||||
import { Notes } from "@/models/index.js";
|
import { Notes } from "@/models/index.js";
|
||||||
import { activeUsersChart } from "@/services/chart/index.js";
|
import { activeUsersChart } from "@/services/chart/index.js";
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
|
@ -64,7 +64,7 @@ export const paramDef = {
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export default define(meta, paramDef, async (ps, user) => {
|
export default define(meta, paramDef, async (ps, user) => {
|
||||||
const m = await fetchMeta();
|
const m = await fetchMeta(true);
|
||||||
if (m.disableGlobalTimeline) {
|
if (m.disableGlobalTimeline) {
|
||||||
if (user == null || !(user.isAdmin || user.isModerator)) {
|
if (user == null || !(user.isAdmin || user.isModerator)) {
|
||||||
throw new ApiError(meta.errors.gtlDisabled);
|
throw new ApiError(meta.errors.gtlDisabled);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Brackets } from "typeorm";
|
import { Brackets } from "typeorm";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "backend-rs";
|
||||||
import { Followings, Notes } from "@/models/index.js";
|
import { Followings, Notes } from "@/models/index.js";
|
||||||
import { activeUsersChart } from "@/services/chart/index.js";
|
import { activeUsersChart } from "@/services/chart/index.js";
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
|
@ -71,7 +71,7 @@ export const paramDef = {
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export default define(meta, paramDef, async (ps, user) => {
|
export default define(meta, paramDef, async (ps, user) => {
|
||||||
const m = await fetchMeta();
|
const m = await fetchMeta(true);
|
||||||
if (m.disableLocalTimeline && !user.isAdmin && !user.isModerator) {
|
if (m.disableLocalTimeline && !user.isAdmin && !user.isModerator) {
|
||||||
throw new ApiError(meta.errors.stlDisabled);
|
throw new ApiError(meta.errors.stlDisabled);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Brackets } from "typeorm";
|
import { Brackets } from "typeorm";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "backend-rs";
|
||||||
import { Notes } from "@/models/index.js";
|
import { Notes } from "@/models/index.js";
|
||||||
import { activeUsersChart } from "@/services/chart/index.js";
|
import { activeUsersChart } from "@/services/chart/index.js";
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
|
@ -74,7 +74,7 @@ export const paramDef = {
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export default define(meta, paramDef, async (ps, user) => {
|
export default define(meta, paramDef, async (ps, user) => {
|
||||||
const m = await fetchMeta();
|
const m = await fetchMeta(true);
|
||||||
if (m.disableLocalTimeline) {
|
if (m.disableLocalTimeline) {
|
||||||
if (user == null || !(user.isAdmin || user.isModerator)) {
|
if (user == null || !(user.isAdmin || user.isModerator)) {
|
||||||
throw new ApiError(meta.errors.ltlDisabled);
|
throw new ApiError(meta.errors.ltlDisabled);
|
||||||
|
|
|
@ -53,7 +53,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
throw new ApiError(meta.errors.accessDenied);
|
throw new ApiError(meta.errors.accessDenied);
|
||||||
}
|
}
|
||||||
|
|
||||||
await deleteNote(user, note, false, false);
|
await deleteNote(user, note, false);
|
||||||
await Notes.update(note.id, {
|
await Notes.update(note.id, {
|
||||||
visibility: "specified",
|
visibility: "specified",
|
||||||
visibleUserIds: [],
|
visibleUserIds: [],
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Brackets } from "typeorm";
|
import { Brackets } from "typeorm";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "backend-rs";
|
||||||
import { Notes } from "@/models/index.js";
|
import { Notes } from "@/models/index.js";
|
||||||
import { activeUsersChart } from "@/services/chart/index.js";
|
import { activeUsersChart } from "@/services/chart/index.js";
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
|
@ -74,7 +74,7 @@ export const paramDef = {
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export default define(meta, paramDef, async (ps, user) => {
|
export default define(meta, paramDef, async (ps, user) => {
|
||||||
const m = await fetchMeta();
|
const m = await fetchMeta(true);
|
||||||
if (m.disableRecommendedTimeline) {
|
if (m.disableRecommendedTimeline) {
|
||||||
if (user == null || !(user.isAdmin || user.isModerator)) {
|
if (user == null || !(user.isAdmin || user.isModerator)) {
|
||||||
throw new ApiError(meta.errors.rtlDisabled);
|
throw new ApiError(meta.errors.rtlDisabled);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Brackets } from "typeorm";
|
import { Brackets } from "typeorm";
|
||||||
import { Notes } from "@/models/index.js";
|
import { Notes } from "@/models/index.js";
|
||||||
import { safeForSql } from "@/misc/safe-for-sql.js";
|
import { safeForSql } from "backend-rs";
|
||||||
import { normalizeForSearch } from "@/misc/normalize-for-search.js";
|
import { normalizeForSearch } from "@/misc/normalize-for-search.js";
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
import { makePaginationQuery } from "@/server/api/common/make-pagination-query.js";
|
import { makePaginationQuery } from "@/server/api/common/make-pagination-query.js";
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { Notes } from "@/models/index.js";
|
import { Notes } from "@/models/index.js";
|
||||||
import { Note } from "@/models/entities/note.js";
|
import type { Note } from "@/models/entities/note.js";
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
import { makePaginationQuery } from "@/server/api/common/make-pagination-query.js";
|
import { makePaginationQuery } from "@/server/api/common/make-pagination-query.js";
|
||||||
import { generateVisibilityQuery } from "@/server/api/common/generate-visibility-query.js";
|
import { generateVisibilityQuery } from "@/server/api/common/generate-visibility-query.js";
|
||||||
import { generateMutedUserQuery } from "@/server/api/common/generate-muted-user-query.js";
|
import { generateMutedUserQuery } from "@/server/api/common/generate-muted-user-query.js";
|
||||||
import { generateBlockedUserQuery } from "@/server/api/common/generate-block-query.js";
|
import { generateBlockedUserQuery } from "@/server/api/common/generate-block-query.js";
|
||||||
import { sqlLikeEscape } from "@/misc/sql-like-escape.js";
|
import { sqlLikeEscape } from "backend-rs";
|
||||||
import type { SelectQueryBuilder } from "typeorm";
|
import type { SelectQueryBuilder } from "typeorm";
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { IsNull } from "typeorm";
|
import { IsNull } from "typeorm";
|
||||||
import { Users } from "@/models/index.js";
|
import { Users } from "@/models/index.js";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "backend-rs";
|
||||||
import { stringToAcct } from "backend-rs";
|
import { stringToAcct } from "backend-rs";
|
||||||
import type { User } from "@/models/entities/user.js";
|
import type { User } from "@/models/entities/user.js";
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
|
@ -31,7 +31,7 @@ export const paramDef = {
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export default define(meta, paramDef, async (ps, me) => {
|
export default define(meta, paramDef, async (ps, me) => {
|
||||||
const meta = await fetchMeta();
|
const meta = await fetchMeta(true);
|
||||||
|
|
||||||
const users = await Promise.all(
|
const users = await Promise.all(
|
||||||
meta.pinnedUsers
|
meta.pinnedUsers
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// import { IsNull } from 'typeorm';
|
// import { IsNull } from 'typeorm';
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "backend-rs";
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
|
@ -27,7 +27,7 @@ export const paramDef = {
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export default define(meta, paramDef, async () => {
|
export default define(meta, paramDef, async () => {
|
||||||
const meta = await fetchMeta();
|
const meta = await fetchMeta(true);
|
||||||
const instances = await Promise.all(meta.recommendedInstances.map((x) => x));
|
const instances = await Promise.all(meta.recommendedInstances.map((x) => x));
|
||||||
return instances;
|
return instances;
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { UserProfiles, PasswordResetRequests } from "@/models/index.js";
|
import { UserProfiles, PasswordResetRequests } from "@/models/index.js";
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
import { hashPassword } from "@/misc/password.js";
|
import { hashPassword } from "backend-rs";
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ["reset password"],
|
tags: ["reset password"],
|
||||||
|
@ -32,7 +32,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate hash of password
|
// Generate hash of password
|
||||||
const hash = await hashPassword(ps.password);
|
const hash = hashPassword(ps.password);
|
||||||
|
|
||||||
await UserProfiles.update(req.userId, {
|
await UserProfiles.update(req.userId, {
|
||||||
password: hash,
|
password: hash,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import * as os from "node:os";
|
import * as os from "node:os";
|
||||||
import si from "systeminformation";
|
import si from "systeminformation";
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "backend-rs";
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
requireCredential: false,
|
requireCredential: false,
|
||||||
|
@ -30,7 +30,7 @@ export default define(meta, paramDef, async () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const instanceMeta = await fetchMeta();
|
const instanceMeta = await fetchMeta(true);
|
||||||
if (!instanceMeta.enableServerMachineStats) {
|
if (!instanceMeta.enableServerMachineStats) {
|
||||||
return {
|
return {
|
||||||
machine: "Not specified",
|
machine: "Not specified",
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "backend-rs";
|
||||||
import { genId } from "backend-rs";
|
import { genId } from "backend-rs";
|
||||||
import { SwSubscriptions } from "@/models/index.js";
|
import { SwSubscriptions } from "@/models/index.js";
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
|
@ -64,7 +64,7 @@ export default define(meta, paramDef, async (ps, me) => {
|
||||||
publickey: ps.publickey,
|
publickey: ps.publickey,
|
||||||
});
|
});
|
||||||
|
|
||||||
const instance = await fetchMeta(true);
|
const instance = await fetchMeta(false);
|
||||||
|
|
||||||
// if already subscribed
|
// if already subscribed
|
||||||
if (subscription != null) {
|
if (subscription != null) {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { publishAdminStream } from "@/services/stream.js";
|
||||||
import { AbuseUserReports, UserProfiles, Users } from "@/models/index.js";
|
import { AbuseUserReports, UserProfiles, Users } from "@/models/index.js";
|
||||||
import { genId } from "backend-rs";
|
import { genId } from "backend-rs";
|
||||||
import { sendEmail } from "@/services/send-email.js";
|
import { sendEmail } from "@/services/send-email.js";
|
||||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
import { fetchMeta } from "backend-rs";
|
||||||
import { getUser } from "@/server/api/common/getters.js";
|
import { getUser } from "@/server/api/common/getters.js";
|
||||||
import { ApiError } from "@/server/api/error.js";
|
import { ApiError } from "@/server/api/error.js";
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
|
@ -86,7 +86,7 @@ export default define(meta, paramDef, async (ps, me) => {
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
const meta = await fetchMeta();
|
const meta = await fetchMeta(true);
|
||||||
for (const moderator of moderators) {
|
for (const moderator of moderators) {
|
||||||
publishAdminStream(moderator.id, "newAbuseUserReport", {
|
publishAdminStream(moderator.id, "newAbuseUserReport", {
|
||||||
id: report.id,
|
id: report.id,
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { Brackets } from "typeorm";
|
||||||
import { Followings, Users } from "@/models/index.js";
|
import { Followings, Users } from "@/models/index.js";
|
||||||
import type { User } from "@/models/entities/user.js";
|
import type { User } from "@/models/entities/user.js";
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
import { sqlLikeEscape } from "@/misc/sql-like-escape.js";
|
import { sqlLikeEscape } from "backend-rs";
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ["users"],
|
tags: ["users"],
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { Brackets } from "typeorm";
|
||||||
import { UserProfiles, Users } from "@/models/index.js";
|
import { UserProfiles, Users } from "@/models/index.js";
|
||||||
import type { User } from "@/models/entities/user.js";
|
import type { User } from "@/models/entities/user.js";
|
||||||
import define from "@/server/api/define.js";
|
import define from "@/server/api/define.js";
|
||||||
import { sqlLikeEscape } from "@/misc/sql-like-escape.js";
|
import { sqlLikeEscape } from "backend-rs";
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ["users"],
|
tags: ["users"],
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue