merge: branch 'master' into insert/feat/user-safety-api

This commit is contained in:
Paul Makles
2023-02-17 09:43:12 +00:00
52 changed files with 516 additions and 339 deletions

2
.github/FUNDING.yml vendored
View File

@@ -1,2 +0,0 @@
ko_fi: insertish
custom: https://insrt.uk/donate

View File

@@ -15,10 +15,10 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Install latest nightly - name: Install latest stable
uses: actions-rs/toolchain@v1 uses: actions-rs/toolchain@v1
with: with:
toolchain: nightly toolchain: stable
override: true override: true
components: rustfmt, clippy components: rustfmt, clippy
@@ -59,6 +59,7 @@ jobs:
with: with:
repository: revoltchat/api repository: revoltchat/api
path: api path: api
token: ${{ secrets.PAT }}
- name: Download OpenAPI specification - name: Download OpenAPI specification
if: github.event_name != 'pull_request' if: github.event_name != 'pull_request'
@@ -71,5 +72,3 @@ jobs:
cwd: "api" cwd: "api"
add: "*.json" add: "*.json"
message: "chore: generate OpenAPI specification" message: "chore: generate OpenAPI specification"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -15,22 +15,27 @@ jobs:
gh api graphql -f query=' gh api graphql -f query='
query { query {
organization(login: "revoltchat"){ organization(login: "revoltchat"){
projectNext(number: 3) { projectV2(number: 3) {
id id
fields(first:20) { fields(first:20) {
nodes { nodes {
id ... on ProjectV2SingleSelectField {
name id
settings name
options {
id
name
}
}
} }
} }
} }
} }
}' > project_data.json }' > project_data.json
echo 'PROJECT_ID='$(jq '.data.organization.projectNext.id' project_data.json) >> $GITHUB_ENV echo 'PROJECT_ID='$(jq '.data.organization.projectV2.id' project_data.json) >> $GITHUB_ENV
echo 'STATUS_FIELD_ID='$(jq '.data.organization.projectNext.fields.nodes[] | select(.name== "Status") | .id' project_data.json) >> $GITHUB_ENV echo 'STATUS_FIELD_ID='$(jq '.data.organization.projectV2.fields.nodes[] | select(.name== "Status") | .id' project_data.json) >> $GITHUB_ENV
echo 'TODO_OPTION_ID='$(jq '.data.organization.projectNext.fields.nodes[] | select(.name== "Status") |.settings | fromjson.options[] | select(.name=="Todo") |.id' project_data.json) >> $GITHUB_ENV echo 'TODO_OPTION_ID='$(jq '.data.organization.projectV2.fields.nodes[] | select(.name== "Status") | .options[] | select(.name=="Todo") |.id' project_data.json) >> $GITHUB_ENV
- name: Add issue to project - name: Add issue to project
env: env:
@@ -39,11 +44,11 @@ jobs:
run: | run: |
item_id="$( gh api graphql -f query=' item_id="$( gh api graphql -f query='
mutation($project:ID!, $issue:ID!) { mutation($project:ID!, $issue:ID!) {
addProjectNextItem(input: {projectId: $project, contentId: $issue}) { addProjectV2ItemById(input: {projectId: $project, contentId: $issue}) {
projectNextItem { item {
id id
} }
} }
}' -f project=$PROJECT_ID -f issue=$ISSUE_ID --jq '.data.addProjectNextItem.projectNextItem.id')" }' -f project=$PROJECT_ID -f issue=$ISSUE_ID --jq '.data.addProjectV2ItemById.item.id')"
echo 'ITEM_ID='$item_id >> $GITHUB_ENV echo 'ITEM_ID='$item_id >> $GITHUB_ENV

View File

@@ -15,22 +15,27 @@ jobs:
gh api graphql -f query=' gh api graphql -f query='
query { query {
organization(login: "revoltchat"){ organization(login: "revoltchat"){
projectNext(number: 3) { projectV2(number: 3) {
id id
fields(first:20) { fields(first:20) {
nodes { nodes {
id ... on ProjectV2SingleSelectField {
name id
settings name
options {
id
name
}
}
} }
} }
} }
} }
}' > project_data.json }' > project_data.json
echo 'PROJECT_ID='$(jq '.data.organization.projectNext.id' project_data.json) >> $GITHUB_ENV echo 'PROJECT_ID='$(jq '.data.organization.projectV2.id' project_data.json) >> $GITHUB_ENV
echo 'STATUS_FIELD_ID='$(jq '.data.organization.projectNext.fields.nodes[] | select(.name== "Status") | .id' project_data.json) >> $GITHUB_ENV echo 'STATUS_FIELD_ID='$(jq '.data.organization.projectV2.fields.nodes[] | select(.name== "Status") | .id' project_data.json) >> $GITHUB_ENV
echo 'INCOMING_OPTION_ID='$(jq '.data.organization.projectNext.fields.nodes[] | select(.name== "Status") |.settings | fromjson.options[] | select(.name=="Incoming PRs") |.id' project_data.json) >> $GITHUB_ENV echo 'INCOMING_OPTION_ID='$(jq '.data.organization.projectV2.fields.nodes[] | select(.name== "Status") | .options[] | select(.name=="Incoming PRs") |.id' project_data.json) >> $GITHUB_ENV
- name: Add PR to project - name: Add PR to project
env: env:
@@ -39,13 +44,13 @@ jobs:
run: | run: |
item_id="$( gh api graphql -f query=' item_id="$( gh api graphql -f query='
mutation($project:ID!, $pr:ID!) { mutation($project:ID!, $pr:ID!) {
addProjectNextItem(input: {projectId: $project, contentId: $pr}) { addProjectV2ItemById(input: {projectId: $project, contentId: $pr}) {
projectNextItem { item {
id id
} }
} }
}' -f project=$PROJECT_ID -f pr=$PR_ID --jq '.data.addProjectNextItem.projectNextItem.id')" }' -f project=$PROJECT_ID -f pr=$PR_ID --jq '.data.addProjectV2ItemById.item.id')"
echo 'ITEM_ID='$item_id >> $GITHUB_ENV echo 'ITEM_ID='$item_id >> $GITHUB_ENV
- name: Set fields - name: Set fields
@@ -59,14 +64,16 @@ jobs:
$status_field: ID! $status_field: ID!
$status_value: String! $status_value: String!
) { ) {
set_status: updateProjectNextItemField(input: { set_status: updateProjectV2ItemFieldValue(input: {
projectId: $project projectId: $project
itemId: $item itemId: $item
fieldId: $status_field fieldId: $status_field
value: $status_value value: {
singleSelectOptionId: $status_value
}
}) { }) {
projectNextItem { projectV2Item {
id id
} }
} }
}' -f project=$PROJECT_ID -f item=$ITEM_ID -f status_field=$STATUS_FIELD_ID -f status_value=${{ env.INCOMING_OPTION_ID }} --silent }' -f project=$PROJECT_ID -f item=$ITEM_ID -f status_field=$STATUS_FIELD_ID -f status_value=${{ env.INCOMING_OPTION_ID }} --silent

301
Cargo.lock generated
View File

@@ -106,7 +106,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5"
dependencies = [ dependencies = [
"quote 1.0.18", "quote 1.0.18",
"syn 1.0.96", "syn 1.0.107",
] ]
[[package]] [[package]]
@@ -172,11 +172,12 @@ dependencies = [
[[package]] [[package]]
name = "async-lock" name = "async-lock"
version = "2.5.0" version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e97a171d191782fba31bb902b14ad94e24a68145032b7eedf871ab0bc0d077b6" checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685"
dependencies = [ dependencies = [
"event-listener", "event-listener",
"futures-lite",
] ]
[[package]] [[package]]
@@ -204,7 +205,7 @@ checksum = "2cda8f4bcc10624c4e85bc66b3f452cca98cfa5ca002dc83a16aad2367641bea"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.18", "quote 1.0.18",
"syn 1.0.96", "syn 1.0.107",
] ]
[[package]] [[package]]
@@ -269,7 +270,7 @@ checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.18", "quote 1.0.18",
"syn 1.0.96", "syn 1.0.107",
] ]
[[package]] [[package]]
@@ -286,7 +287,7 @@ checksum = "96cf8829f67d2eab0b2dfa42c5d0ef737e0724e4a82b01b3e292456202b19716"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.18", "quote 1.0.18",
"syn 1.0.96", "syn 1.0.107",
] ]
[[package]] [[package]]
@@ -329,6 +330,40 @@ dependencies = [
"winapi 0.3.9", "winapi 0.3.9",
] ]
[[package]]
name = "authifier"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a84411393a4326726ead660991ce8047f1865fa89900fb6c18e1e6c513cf1f9b"
dependencies = [
"async-std",
"async-trait",
"base32",
"bson",
"chrono",
"futures",
"handlebars",
"iso8601-timestamp",
"lazy_static",
"lettre",
"log",
"mongodb",
"nanoid",
"rand 0.8.5",
"regex",
"reqwest",
"revolt_okapi",
"revolt_rocket_okapi",
"rocket",
"rust-argon2",
"schemars",
"serde",
"serde_json",
"totp-lite",
"ulid 0.5.0",
"validator 0.15.0",
]
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "0.1.8" version = "0.1.8"
@@ -681,7 +716,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c" checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c"
dependencies = [ dependencies = [
"quote 1.0.18", "quote 1.0.18",
"syn 1.0.96", "syn 1.0.107",
] ]
[[package]] [[package]]
@@ -714,7 +749,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.18", "quote 1.0.18",
"strsim", "strsim",
"syn 1.0.96", "syn 1.0.107",
] ]
[[package]] [[package]]
@@ -725,7 +760,7 @@ checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835"
dependencies = [ dependencies = [
"darling_core", "darling_core",
"quote 1.0.18", "quote 1.0.18",
"syn 1.0.96", "syn 1.0.107",
] ]
[[package]] [[package]]
@@ -774,7 +809,7 @@ checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.18", "quote 1.0.18",
"syn 1.0.96", "syn 1.0.107",
] ]
[[package]] [[package]]
@@ -807,7 +842,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"proc-macro2-diagnostics", "proc-macro2-diagnostics",
"quote 1.0.18", "quote 1.0.18",
"syn 1.0.96", "syn 1.0.107",
] ]
[[package]] [[package]]
@@ -881,7 +916,7 @@ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2",
"quote 1.0.18", "quote 1.0.18",
"syn 1.0.96", "syn 1.0.107",
] ]
[[package]] [[package]]
@@ -901,7 +936,7 @@ checksum = "828de45d0ca18782232dfb8f3ea9cc428e8ced380eb26a520baaacfc70de39ce"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.18", "quote 1.0.18",
"syn 1.0.96", "syn 1.0.107",
] ]
[[package]] [[package]]
@@ -1085,7 +1120,7 @@ checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.18", "quote 1.0.18",
"syn 1.0.96", "syn 1.0.107",
] ]
[[package]] [[package]]
@@ -1176,7 +1211,7 @@ dependencies = [
"proc-macro-error", "proc-macro-error",
"proc-macro2", "proc-macro2",
"quote 1.0.18", "quote 1.0.18",
"syn 1.0.96", "syn 1.0.107",
] ]
[[package]] [[package]]
@@ -2057,7 +2092,7 @@ dependencies = [
"proc-macro-crate", "proc-macro-crate",
"proc-macro2", "proc-macro2",
"quote 1.0.18", "quote 1.0.18",
"syn 1.0.96", "syn 1.0.107",
] ]
[[package]] [[package]]
@@ -2069,17 +2104,6 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "okapi"
version = "0.7.0-rc.1"
source = "git+https://github.com/insertish/okapi?rev=a1048d0c8cd771e424ec97d33d825c32e06aa120#a1048d0c8cd771e424ec97d33d825c32e06aa120"
dependencies = [
"log",
"schemars",
"serde",
"serde_json",
]
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.13.0" version = "1.13.0"
@@ -2121,7 +2145,7 @@ checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.18", "quote 1.0.18",
"syn 1.0.96", "syn 1.0.107",
] ]
[[package]] [[package]]
@@ -2226,7 +2250,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"proc-macro2-diagnostics", "proc-macro2-diagnostics",
"quote 1.0.18", "quote 1.0.18",
"syn 1.0.96", "syn 1.0.107",
] ]
[[package]] [[package]]
@@ -2264,7 +2288,7 @@ dependencies = [
"pest_meta", "pest_meta",
"proc-macro2", "proc-macro2",
"quote 1.0.18", "quote 1.0.18",
"syn 1.0.96", "syn 1.0.107",
] ]
[[package]] [[package]]
@@ -2295,7 +2319,7 @@ checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.18", "quote 1.0.18",
"syn 1.0.96", "syn 1.0.107",
] ]
[[package]] [[package]]
@@ -2382,7 +2406,7 @@ dependencies = [
"proc-macro-error-attr", "proc-macro-error-attr",
"proc-macro2", "proc-macro2",
"quote 1.0.18", "quote 1.0.18",
"syn 1.0.96", "syn 1.0.107",
"version_check", "version_check",
] ]
@@ -2399,9 +2423,9 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.39" version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@@ -2414,7 +2438,7 @@ checksum = "4bf29726d67464d49fa6224a1d07936a8c08bb3fba727c7493f6cf1616fdaada"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.18", "quote 1.0.18",
"syn 1.0.96", "syn 1.0.107",
"version_check", "version_check",
"yansi", "yansi",
] ]
@@ -2589,39 +2613,6 @@ dependencies = [
"rand_core 0.3.1", "rand_core 0.3.1",
] ]
[[package]]
name = "rauth"
version = "1.0.0"
source = "git+https://github.com/insertish/rauth?rev=cbdec69c684a4854fbedba9ed1f0e7ee466bf3f7#cbdec69c684a4854fbedba9ed1f0e7ee466bf3f7"
dependencies = [
"async-std",
"async-trait",
"base32",
"bson",
"chrono",
"futures",
"handlebars",
"iso8601-timestamp",
"lazy_static",
"lettre",
"log",
"mongodb",
"nanoid",
"okapi",
"rand 0.8.5",
"regex",
"reqwest",
"rocket",
"rocket_okapi",
"rust-argon2",
"schemars",
"serde",
"serde_json",
"totp-lite",
"ulid 0.5.0",
"validator 0.15.0",
]
[[package]] [[package]]
name = "rdrand" name = "rdrand"
version = "0.4.0" version = "0.4.0"
@@ -2715,7 +2706,7 @@ checksum = "a043824e29c94169374ac5183ac0ed43f5724dc4556b19568007486bd840fa1f"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.18", "quote 1.0.18",
"syn 1.0.96", "syn 1.0.107",
] ]
[[package]] [[package]]
@@ -2801,7 +2792,7 @@ dependencies = [
[[package]] [[package]]
name = "revolt-bonfire" name = "revolt-bonfire"
version = "0.5.5" version = "0.5.7"
dependencies = [ dependencies = [
"async-std", "async-std",
"async-tungstenite", "async-tungstenite",
@@ -2817,7 +2808,7 @@ dependencies = [
[[package]] [[package]]
name = "revolt-delta" name = "revolt-delta"
version = "0.5.5" version = "0.5.7"
dependencies = [ dependencies = [
"async-channel", "async-channel",
"async-std", "async-std",
@@ -2842,10 +2833,10 @@ dependencies = [
"regex", "regex",
"reqwest", "reqwest",
"revolt-quark", "revolt-quark",
"revolt_rocket_okapi",
"rocket", "rocket",
"rocket_authifier",
"rocket_empty", "rocket_empty",
"rocket_okapi",
"rocket_rauth",
"schemars", "schemars",
"serde", "serde",
"serde_json", "serde_json",
@@ -2857,11 +2848,13 @@ dependencies = [
[[package]] [[package]]
name = "revolt-quark" name = "revolt-quark"
version = "0.1.0" version = "0.5.7"
dependencies = [ dependencies = [
"async-lock",
"async-recursion", "async-recursion",
"async-std", "async-std",
"async-trait", "async-trait",
"authifier",
"base64 0.13.0", "base64 0.13.0",
"bincode", "bincode",
"bitfield", "bitfield",
@@ -2880,19 +2873,18 @@ dependencies = [
"mongodb", "mongodb",
"nanoid", "nanoid",
"num_enum", "num_enum",
"okapi",
"once_cell", "once_cell",
"optional_struct", "optional_struct",
"pretty_env_logger", "pretty_env_logger",
"rauth",
"redis-kiss", "redis-kiss",
"regex", "regex",
"reqwest", "reqwest",
"revolt_okapi",
"revolt_rocket_okapi",
"rocket", "rocket",
"rocket_cors", "rocket_cors",
"rocket_empty", "rocket_empty",
"rocket_http", "rocket_http",
"rocket_okapi",
"schemars", "schemars",
"sentry", "sentry",
"serde", "serde",
@@ -2902,6 +2894,47 @@ dependencies = [
"web-push", "web-push",
] ]
[[package]]
name = "revolt_okapi"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23bfdf7ae769c3042fe727f6e5c17363b02a64b4b33ad60c3e5f73b26df7835b"
dependencies = [
"log",
"schemars",
"serde",
"serde_json",
]
[[package]]
name = "revolt_rocket_okapi"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "275e1e9bd3343f75225cafa64f4bfb939c8b21c5f861141180fc0e24769ff6cf"
dependencies = [
"either",
"log",
"revolt_okapi",
"revolt_rocket_okapi_codegen",
"rocket",
"schemars",
"serde",
"serde_json",
]
[[package]]
name = "revolt_rocket_okapi_codegen"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc6620569d8ac8f0a1690fcca13f488503807a60e96ebf729749b59aca1dbef9"
dependencies = [
"darling",
"proc-macro2",
"quote 1.0.18",
"rocket_http",
"syn 1.0.107",
]
[[package]] [[package]]
name = "ring" name = "ring"
version = "0.16.20" version = "0.16.20"
@@ -2978,6 +3011,22 @@ dependencies = [
"yansi", "yansi",
] ]
[[package]]
name = "rocket_authifier"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4554a81937341d8c3cd3e43431ac2d23624444dc3a88e7ffd3ff66593779293"
dependencies = [
"authifier",
"iso8601-timestamp",
"revolt_okapi",
"revolt_rocket_okapi",
"rocket",
"rocket_empty",
"schemars",
"serde",
]
[[package]] [[package]]
name = "rocket_codegen" name = "rocket_codegen"
version = "0.5.0-rc.2" version = "0.5.0-rc.2"
@@ -2990,15 +3039,16 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.18", "quote 1.0.18",
"rocket_http", "rocket_http",
"syn 1.0.96", "syn 1.0.107",
"unicode-xid 0.2.3", "unicode-xid 0.2.3",
] ]
[[package]] [[package]]
name = "rocket_cors" name = "rocket_cors"
version = "0.5.2" version = "0.6.0-alpha1"
source = "git+https://github.com/lawliet89/rocket_cors?rev=5843861a88958c16bfaa0b40f0d8910772bcd2f6#5843861a88958c16bfaa0b40f0d8910772bcd2f6" source = "git+https://github.com/lawliet89/rocket_cors?rev=c17e8145baa4790319fdb6a473e465b960f55e7c#c17e8145baa4790319fdb6a473e465b960f55e7c"
dependencies = [ dependencies = [
"http",
"log", "log",
"regex", "regex",
"rocket", "rocket",
@@ -3011,12 +3061,13 @@ dependencies = [
[[package]] [[package]]
name = "rocket_empty" name = "rocket_empty"
version = "0.1.0" version = "0.1.1"
source = "git+https://github.com/insertish/rocket_empty?branch=master#9d8234fc3bb215ea241b787301e8cff68ae53652" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c0922e47f981204fee38578a8efcf47a5c1a4ac0eb7f59e6bdfa3e61c8e3d69"
dependencies = [ dependencies = [
"okapi", "revolt_okapi",
"revolt_rocket_okapi",
"rocket", "rocket",
"rocket_okapi",
] ]
[[package]] [[package]]
@@ -3046,48 +3097,6 @@ dependencies = [
"uncased", "uncased",
] ]
[[package]]
name = "rocket_okapi"
version = "0.8.0-rc.1"
source = "git+https://github.com/insertish/okapi?rev=a1048d0c8cd771e424ec97d33d825c32e06aa120#a1048d0c8cd771e424ec97d33d825c32e06aa120"
dependencies = [
"either",
"log",
"okapi",
"rocket",
"rocket_okapi_codegen",
"schemars",
"serde",
"serde_json",
]
[[package]]
name = "rocket_okapi_codegen"
version = "0.8.0-rc.1"
source = "git+https://github.com/insertish/okapi?rev=a1048d0c8cd771e424ec97d33d825c32e06aa120#a1048d0c8cd771e424ec97d33d825c32e06aa120"
dependencies = [
"darling",
"proc-macro2",
"quote 1.0.18",
"rocket_http",
"syn 1.0.96",
]
[[package]]
name = "rocket_rauth"
version = "1.0.0"
source = "git+https://github.com/insertish/rauth?rev=cbdec69c684a4854fbedba9ed1f0e7ee466bf3f7#cbdec69c684a4854fbedba9ed1f0e7ee466bf3f7"
dependencies = [
"iso8601-timestamp",
"okapi",
"rauth",
"rocket",
"rocket_empty",
"rocket_okapi",
"schemars",
"serde",
]
[[package]] [[package]]
name = "rust-argon2" name = "rust-argon2"
version = "1.0.0" version = "1.0.0"
@@ -3205,7 +3214,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.18", "quote 1.0.18",
"serde_derive_internals", "serde_derive_internals",
"syn 1.0.96", "syn 1.0.107",
] ]
[[package]] [[package]]
@@ -3356,9 +3365,9 @@ dependencies = [
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.137" version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
@@ -3374,13 +3383,13 @@ dependencies = [
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.137" version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.18", "quote 1.0.18",
"syn 1.0.96", "syn 1.0.107",
] ]
[[package]] [[package]]
@@ -3391,14 +3400,14 @@ checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.18", "quote 1.0.18",
"syn 1.0.96", "syn 1.0.107",
] ]
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.81" version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
dependencies = [ dependencies = [
"indexmap", "indexmap",
"itoa 1.0.2", "itoa 1.0.2",
@@ -3437,7 +3446,7 @@ dependencies = [
"darling", "darling",
"proc-macro2", "proc-macro2",
"quote 1.0.18", "quote 1.0.18",
"syn 1.0.96", "syn 1.0.107",
] ]
[[package]] [[package]]
@@ -3615,9 +3624,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.96" version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0748dd251e24453cb8717f0354206b91557e4ec8703673a4b30208f2abaf1ebf" checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.18", "quote 1.0.18",
@@ -3693,7 +3702,7 @@ checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.18", "quote 1.0.18",
"syn 1.0.96", "syn 1.0.107",
] ]
[[package]] [[package]]
@@ -3802,7 +3811,7 @@ checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.18", "quote 1.0.18",
"syn 1.0.96", "syn 1.0.107",
] ]
[[package]] [[package]]
@@ -3938,7 +3947,7 @@ checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.18", "quote 1.0.18",
"syn 1.0.96", "syn 1.0.107",
] ]
[[package]] [[package]]
@@ -4068,7 +4077,7 @@ checksum = "89851716b67b937e393b3daa8423e67ddfc4bbbf1654bcf05488e95e0828db0c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.18", "quote 1.0.18",
"syn 1.0.96", "syn 1.0.107",
] ]
[[package]] [[package]]
@@ -4279,7 +4288,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.18", "quote 1.0.18",
"regex", "regex",
"syn 1.0.96", "syn 1.0.107",
"validator_types", "validator_types",
] ]
@@ -4290,7 +4299,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ded9d97e1d42327632f5f3bae6403c04886e2de3036261ef42deebd931a6a291" checksum = "ded9d97e1d42327632f5f3bae6403c04886e2de3036261ef42deebd931a6a291"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"syn 1.0.96", "syn 1.0.107",
] ]
[[package]] [[package]]
@@ -4388,7 +4397,7 @@ dependencies = [
"log", "log",
"proc-macro2", "proc-macro2",
"quote 1.0.18", "quote 1.0.18",
"syn 1.0.96", "syn 1.0.107",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@@ -4422,7 +4431,7 @@ checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.18", "quote 1.0.18",
"syn 1.0.96", "syn 1.0.107",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]

View File

@@ -1,7 +0,0 @@
#!/bin/bash
# Build base image
docker build -t revolt.chat/base:latest -f Dockerfile .
# Build crates
docker build -t revolt.chat/delta:latest -f crates/delta/Dockerfile .
docker build -t revolt.chat/bonfire:latest -f crates/bonfire/Dockerfile .

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "revolt-bonfire" name = "revolt-bonfire"
version = "0.5.5" version = "0.5.7"
license = "AGPL-3.0-or-later" license = "AGPL-3.0-or-later"
edition = "2021" edition = "2021"

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "revolt-delta" name = "revolt-delta"
version = "0.5.5" version = "0.5.7"
license = "AGPL-3.0-or-later" license = "AGPL-3.0-or-later"
authors = ["Paul Makles <paulmakles@gmail.com>"] authors = ["Paul Makles <paulmakles@gmail.com>"]
edition = "2018" edition = "2018"
@@ -51,13 +51,12 @@ mobc-redis = { version = "0.7.0", default-features = false, features = ["async-s
# web # web
rocket = { version = "0.5.0-rc.2", default-features = false, features = ["json"] } rocket = { version = "0.5.0-rc.2", default-features = false, features = ["json"] }
rocket_empty = { git = "https://github.com/insertish/rocket_empty", branch = "master" } rocket_empty = { version = "0.1.1", features = ["schema"] }
rocket_rauth = { git = "https://github.com/insertish/rauth", rev = "cbdec69c684a4854fbedba9ed1f0e7ee466bf3f7" } rocket_authifier = { version = "1.0.7" }
# spec generation # spec generation
schemars = "0.8.8" schemars = "0.8.8"
# rocket_okapi = "0.8.0-rc.1" revolt_rocket_okapi = { version = "0.9.1", features = [ "swagger" ] }
rocket_okapi = { git = "https://github.com/insertish/okapi", rev = "a1048d0c8cd771e424ec97d33d825c32e06aa120", features = [ "swagger" ] }
# quark # quark
revolt-quark = { path = "../quark" } revolt-quark = { path = "../quark" }

View File

@@ -12,5 +12,5 @@ fn main() {
} }
} }
vergen(Config::default()).unwrap(); vergen(Config::default()).ok();
} }

View File

@@ -1,7 +1,7 @@
#[macro_use] #[macro_use]
extern crate rocket; extern crate rocket;
#[macro_use] #[macro_use]
extern crate rocket_okapi; extern crate revolt_rocket_okapi;
#[macro_use] #[macro_use]
extern crate serde_json; extern crate serde_json;
#[macro_use] #[macro_use]
@@ -10,7 +10,9 @@ extern crate lazy_static;
pub mod routes; pub mod routes;
pub mod util; pub mod util;
use revolt_quark::rauth::RAuth; use async_std::channel::unbounded;
use revolt_quark::authifier::{Authifier, AuthifierEvent};
use revolt_quark::events::client::EventV1;
use revolt_quark::DatabaseInfo; use revolt_quark::DatabaseInfo;
#[launch] #[launch]
@@ -25,13 +27,33 @@ async fn rocket() -> _ {
let db = DatabaseInfo::Auto.connect().await.unwrap(); let db = DatabaseInfo::Auto.connect().await.unwrap();
db.migrate_database().await.unwrap(); db.migrate_database().await.unwrap();
// Setup rAuth // Setup Authifier event channel
let rauth = RAuth { let (sender, receiver) = unbounded();
// Setup Authifier
let authifier = Authifier {
database: db.clone().into(), database: db.clone().into(),
config: revolt_quark::util::rauth::config(), config: revolt_quark::util::authifier::config(),
event_channel: Some(sender),
}; };
// Launch background task workers. // Launch a listener for Authifier events
async_std::task::spawn(async move {
while let Ok(event) = receiver.recv().await {
match &event {
AuthifierEvent::CreateSession { .. } | AuthifierEvent::CreateAccount { .. } => {
EventV1::Auth(event).global().await
}
AuthifierEvent::DeleteSession { user_id, .. }
| AuthifierEvent::DeleteAllSessions { user_id, .. } => {
let id = user_id.to_string();
EventV1::Auth(event).private(id).await
}
}
}
});
// Launch background task workers
async_std::task::spawn(revolt_quark::tasks::start_workers(db.clone())); async_std::task::spawn(revolt_quark::tasks::start_workers(db.clone()));
// Configure CORS // Configure CORS
@@ -43,7 +65,7 @@ async fn rocket() -> _ {
.mount("/", revolt_quark::web::cors::catch_all_options_routes()) .mount("/", revolt_quark::web::cors::catch_all_options_routes())
.mount("/", revolt_quark::web::ratelimiter::routes()) .mount("/", revolt_quark::web::ratelimiter::routes())
.mount("/swagger/", revolt_quark::web::swagger::routes()) .mount("/swagger/", revolt_quark::web::swagger::routes())
.manage(rauth) .manage(authifier)
.manage(db) .manage(db)
.manage(cors.clone()) .manage(cors.clone())
.attach(revolt_quark::web::ratelimiter::RatelimitFairing) .attach(revolt_quark::web::ratelimiter::RatelimitFairing)

View File

@@ -1,5 +1,5 @@
use revolt_rocket_okapi::revolt_okapi::openapi3::OpenApi;
use rocket::Route; use rocket::Route;
use rocket_okapi::okapi::openapi3::OpenApi;
mod create; mod create;
mod delete; mod delete;

View File

@@ -65,16 +65,20 @@ pub async fn message_send(
data.validate() data.validate()
.map_err(|error| Error::FailedValidation { error })?; .map_err(|error| Error::FailedValidation { error })?;
// Validate Message is within reasonable length limits
Message::validate_sum(&data.content, &data.embeds)?; Message::validate_sum(&data.content, &data.embeds)?;
// Ensure the request is unique
idempotency.consume_nonce(data.nonce).await?; idempotency.consume_nonce(data.nonce).await?;
// Ensure we have permissions to send a message
let channel = target.as_channel(db).await?; let channel = target.as_channel(db).await?;
let mut permissions = perms(&user).channel(&channel); let mut permissions = perms(&user).channel(&channel);
permissions permissions
.throw_permission_and_view_channel(db, Permission::SendMessage) .throw_permission_and_view_channel(db, Permission::SendMessage)
.await?; .await?;
// Check the message is not empty
if (data.content.as_ref().map_or(true, |v| v.is_empty())) if (data.content.as_ref().map_or(true, |v| v.is_empty()))
&& (data.attachments.as_ref().map_or(true, |v| v.is_empty())) && (data.attachments.as_ref().map_or(true, |v| v.is_empty()))
&& (data.embeds.as_ref().map_or(true, |v| v.is_empty())) && (data.embeds.as_ref().map_or(true, |v| v.is_empty()))
@@ -82,6 +86,22 @@ pub async fn message_send(
return Err(Error::EmptyMessage); return Err(Error::EmptyMessage);
} }
// Ensure restrict_reactions is not specified without reactions list
if let Some(interactions) = &data.interactions {
if interactions.restrict_reactions {
let disallowed = if let Some(list) = &interactions.reactions {
list.is_empty()
} else {
true
};
if disallowed {
return Err(Error::InvalidProperty);
}
}
}
// Start constructing the message
let message_id = Ulid::new().to_string(); let message_id = Ulid::new().to_string();
let mut message = Message { let mut message = Message {
id: message_id.clone(), id: message_id.clone(),

View File

@@ -1,5 +1,5 @@
use revolt_rocket_okapi::revolt_okapi::openapi3::OpenApi;
use rocket::Route; use rocket::Route;
use rocket_okapi::okapi::openapi3::OpenApi;
mod channel_ack; mod channel_ack;
mod channel_delete; mod channel_delete;

View File

@@ -1,5 +1,5 @@
use revolt_rocket_okapi::revolt_okapi::openapi3::OpenApi;
use rocket::Route; use rocket::Route;
use rocket_okapi::okapi::openapi3::OpenApi;
mod emoji_create; mod emoji_create;
mod emoji_delete; mod emoji_delete;

View File

@@ -23,6 +23,9 @@ pub enum InviteResponse {
/// Attachment for server banner /// Attachment for server banner
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
server_banner: Option<File>, server_banner: Option<File>,
/// Enum of server flags
#[serde(skip_serializing_if = "Option::is_none")]
server_flags: Option<i32>,
/// Id of server channel /// Id of server channel
channel_id: String, channel_id: String,
/// Name of server channel /// Name of server channel
@@ -94,6 +97,7 @@ pub async fn req(db: &Db, target: Ref) -> Result<Json<InviteResponse>> {
server_name: server.name, server_name: server.name,
server_icon: server.icon, server_icon: server.icon,
server_banner: server.banner, server_banner: server.banner,
server_flags: server.flags,
channel_id: id, channel_id: id,
channel_name: name, channel_name: name,
channel_description: description, channel_description: description,

View File

@@ -1,5 +1,5 @@
use revolt_rocket_okapi::revolt_okapi::openapi3::OpenApi;
use rocket::Route; use rocket::Route;
use rocket_okapi::okapi::openapi3::OpenApi;
mod invite_delete; mod invite_delete;
mod invite_fetch; mod invite_fetch;

View File

@@ -1,7 +1,7 @@
use revolt_rocket_okapi::{revolt_okapi::openapi3::OpenApi, settings::OpenApiSettings};
pub use rocket::http::Status; pub use rocket::http::Status;
pub use rocket::response::Redirect; pub use rocket::response::Redirect;
use rocket::{Build, Rocket}; use rocket::{Build, Rocket};
use rocket_okapi::{okapi::openapi3::OpenApi, settings::OpenApiSettings};
mod bots; mod bots;
mod channels; mod channels;
@@ -29,9 +29,9 @@ pub fn mount(mut rocket: Rocket<Build>) -> Rocket<Build> {
"/invites" => invites::routes(), "/invites" => invites::routes(),
"/custom" => customisation::routes(), "/custom" => customisation::routes(),
"/safety" => safety::routes(), "/safety" => safety::routes(),
"/auth/account" => rocket_rauth::routes::account::routes(), "/auth/account" => rocket_authifier::routes::account::routes(),
"/auth/session" => rocket_rauth::routes::session::routes(), "/auth/session" => rocket_authifier::routes::session::routes(),
"/auth/mfa" => rocket_rauth::routes::mfa::routes(), "/auth/mfa" => rocket_authifier::routes::mfa::routes(),
"/onboard" => onboard::routes(), "/onboard" => onboard::routes(),
"/push" => push::routes(), "/push" => push::routes(),
"/sync" => sync::routes(), "/sync" => sync::routes(),
@@ -41,7 +41,7 @@ pub fn mount(mut rocket: Rocket<Build>) -> Rocket<Build> {
} }
fn custom_openapi_spec() -> OpenApi { fn custom_openapi_spec() -> OpenApi {
use rocket_okapi::okapi::openapi3::*; use revolt_rocket_okapi::revolt_okapi::openapi3::*;
let mut extensions = schemars::Map::new(); let mut extensions = schemars::Map::new();
extensions.insert( extensions.insert(

View File

@@ -1,5 +1,7 @@
use crate::util::regex::RE_USERNAME; use crate::util::regex::RE_USERNAME;
use revolt_quark::{models::User, rauth::models::Session, Database, EmptyResponse, Error, Result}; use revolt_quark::{
authifier::models::Session, models::User, Database, EmptyResponse, Error, Result,
};
use rocket::{serde::json::Json, State}; use rocket::{serde::json::Json, State};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};

View File

@@ -1,4 +1,4 @@
use revolt_quark::{models::User, rauth::models::Session}; use revolt_quark::{authifier::models::Session, models::User};
use rocket::serde::json::Json; use rocket::serde::json::Json;
use serde::Serialize; use serde::Serialize;

View File

@@ -1,5 +1,5 @@
use revolt_rocket_okapi::revolt_okapi::openapi3::OpenApi;
use rocket::Route; use rocket::Route;
use rocket_okapi::okapi::openapi3::OpenApi;
mod complete; mod complete;
mod hello; mod hello;

View File

@@ -1,5 +1,5 @@
use revolt_rocket_okapi::revolt_okapi::openapi3::OpenApi;
use rocket::Route; use rocket::Route;
use rocket_okapi::okapi::openapi3::OpenApi;
mod subscribe; mod subscribe;
mod unsubscribe; mod unsubscribe;

View File

@@ -1,7 +1,7 @@
use revolt_quark::{ use revolt_quark::{
rauth::{ authifier::{
models::{Session, WebPushSubscription}, models::{Session, WebPushSubscription},
RAuth, Authifier,
}, },
EmptyResponse, Error, Result, EmptyResponse, Error, Result,
}; };
@@ -16,13 +16,13 @@ use rocket::{serde::json::Json, State};
#[openapi(tag = "Web Push")] #[openapi(tag = "Web Push")]
#[post("/subscribe", data = "<data>")] #[post("/subscribe", data = "<data>")]
pub async fn req( pub async fn req(
rauth: &State<RAuth>, authifier: &State<Authifier>,
mut session: Session, mut session: Session,
data: Json<WebPushSubscription>, data: Json<WebPushSubscription>,
) -> Result<EmptyResponse> { ) -> Result<EmptyResponse> {
session.subscription = Some(data.into_inner()); session.subscription = Some(data.into_inner());
session session
.save(rauth) .save(authifier)
.await .await
.map(|_| EmptyResponse) .map(|_| EmptyResponse)
.map_err(|_| Error::DatabaseError { .map_err(|_| Error::DatabaseError {

View File

@@ -1,5 +1,5 @@
use revolt_quark::{ use revolt_quark::{
rauth::{models::Session, RAuth}, authifier::{models::Session, Authifier},
EmptyResponse, Error, Result, EmptyResponse, Error, Result,
}; };
@@ -10,10 +10,10 @@ use rocket::State;
/// Remove the Web Push subscription associated with the current session. /// Remove the Web Push subscription associated with the current session.
#[openapi(tag = "Web Push")] #[openapi(tag = "Web Push")]
#[post("/unsubscribe")] #[post("/unsubscribe")]
pub async fn req(rauth: &State<RAuth>, mut session: Session) -> Result<EmptyResponse> { pub async fn req(authifier: &State<Authifier>, mut session: Session) -> Result<EmptyResponse> {
session.subscription = None; session.subscription = None;
session session
.save(rauth) .save(authifier)
.await .await
.map(|_| EmptyResponse) .map(|_| EmptyResponse)
.map_err(|_| Error::DatabaseError { .map_err(|_| Error::DatabaseError {

View File

@@ -119,11 +119,21 @@ pub async fn root() -> Result<Json<RevoltConfig>> {
app: APP_URL.to_string(), app: APP_URL.to_string(),
vapid: VAPID_PUBLIC_KEY.to_string(), vapid: VAPID_PUBLIC_KEY.to_string(),
build: BuildInformation { build: BuildInformation {
commit_sha: env!("VERGEN_GIT_SHA").to_string(), commit_sha: option_env!("VERGEN_GIT_SHA")
commit_timestamp: env!("VERGEN_GIT_COMMIT_TIMESTAMP").to_string(), .unwrap_or_else(|| "<failed to generate>")
semver: env!("VERGEN_GIT_SEMVER").to_string(), .to_string(),
origin_url: env!("GIT_ORIGIN_URL", "<missing>").to_string(), commit_timestamp: option_env!("VERGEN_GIT_COMMIT_TIMESTAMP")
timestamp: env!("VERGEN_BUILD_TIMESTAMP").to_string(), .unwrap_or_else(|| "<failed to generate>")
.to_string(),
semver: option_env!("VERGEN_GIT_SEMVER")
.unwrap_or_else(|| "<failed to generate>")
.to_string(),
origin_url: option_env!("GIT_ORIGIN_URL")
.unwrap_or_else(|| "<failed to generate>")
.to_string(),
timestamp: option_env!("VERGEN_BUILD_TIMESTAMP")
.unwrap_or_else(|| "<failed to generate>")
.to_string(),
}, },
})) }))
} }

View File

@@ -1,5 +1,5 @@
use revolt_rocket_okapi::revolt_okapi::openapi3::OpenApi;
use rocket::Route; use rocket::Route;
use rocket_okapi::okapi::openapi3::OpenApi;
mod ban_create; mod ban_create;
mod ban_list; mod ban_list;

View File

@@ -1,5 +1,5 @@
use revolt_rocket_okapi::revolt_okapi::openapi3::OpenApi;
use rocket::Route; use rocket::Route;
use rocket_okapi::okapi::openapi3::OpenApi;
mod get_settings; mod get_settings;
mod get_unreads; mod get_unreads;

View File

@@ -1,5 +1,5 @@
use crate::util::regex::RE_USERNAME; use crate::util::regex::RE_USERNAME;
use revolt_quark::{models::User, rauth::models::Account, Database, Error, Result}; use revolt_quark::{authifier::models::Account, models::User, Database, Error, Result};
use rocket::{serde::json::Json, State}; use rocket::{serde::json::Json, State};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use validator::Validate; use validator::Validate;

View File

@@ -0,0 +1,26 @@
use revolt_quark::{Database, Ref, Result};
use rocket::{serde::json::Json, State};
use serde::Serialize;
/// # Flag Response
#[derive(Serialize, JsonSchema)]
pub struct FlagResponse {
/// Flags
flags: i32,
}
/// # Fetch User Flags
///
/// Retrieve a user's flags.
#[openapi(tag = "User Information")]
#[get("/<target>/flags")]
pub async fn fetch_user_flags(db: &State<Database>, target: Ref) -> Result<Json<FlagResponse>> {
let flags = if let Ok(target) = target.as_user(db).await {
target.flags.unwrap_or_default()
} else {
0
};
Ok(Json(FlagResponse { flags }))
}

View File

@@ -1,7 +1,7 @@
use revolt_rocket_okapi::revolt_okapi::openapi3::{self, MediaType, RefOr};
use rocket::http::ContentType; use rocket::http::ContentType;
use rocket::response::{self, Responder}; use rocket::response::{self, Responder};
use rocket::{Request, Response}; use rocket::{Request, Response};
use rocket_okapi::okapi::openapi3::{self, MediaType, RefOr};
use schemars::schema::{InstanceType, SchemaObject, SingleOrVec}; use schemars::schema::{InstanceType, SchemaObject, SingleOrVec};
pub struct CachedFile((ContentType, Vec<u8>)); pub struct CachedFile((ContentType, Vec<u8>));
@@ -16,10 +16,10 @@ impl<'r> Responder<'r, 'static> for CachedFile {
} }
} }
impl rocket_okapi::response::OpenApiResponderInner for CachedFile { impl revolt_rocket_okapi::response::OpenApiResponderInner for CachedFile {
fn responses( fn responses(
_gen: &mut rocket_okapi::gen::OpenApiGenerator, _gen: &mut revolt_rocket_okapi::gen::OpenApiGenerator,
) -> std::result::Result<openapi3::Responses, rocket_okapi::OpenApiError> { ) -> std::result::Result<openapi3::Responses, revolt_rocket_okapi::OpenApiError> {
let mut responses = schemars::Map::new(); let mut responses = schemars::Map::new();
let mut content = schemars::Map::new(); let mut content = schemars::Map::new();

View File

@@ -1,5 +1,5 @@
use revolt_rocket_okapi::revolt_okapi::openapi3::OpenApi;
use rocket::Route; use rocket::Route;
use rocket_okapi::okapi::openapi3::OpenApi;
mod add_friend; mod add_friend;
mod block_user; mod block_user;
@@ -9,6 +9,7 @@ mod fetch_dms;
mod fetch_profile; mod fetch_profile;
mod fetch_self; mod fetch_self;
mod fetch_user; mod fetch_user;
mod fetch_user_flags;
mod find_mutual; mod find_mutual;
mod get_default_avatar; mod get_default_avatar;
mod open_dm; mod open_dm;
@@ -21,6 +22,7 @@ pub fn routes() -> (Vec<Route>, OpenApi) {
// User Information // User Information
fetch_self::req, fetch_self::req,
fetch_user::req, fetch_user::req,
fetch_user_flags::fetch_user_flags,
edit_user::req, edit_user::req,
change_username::req, change_username::req,
get_default_avatar::req, get_default_avatar::req,

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "revolt-quark" name = "revolt-quark"
version = "0.1.0" version = "0.5.7"
license = "AGPL-3.0-or-later" license = "AGPL-3.0-or-later"
edition = "2021" edition = "2021"
@@ -16,9 +16,9 @@ rocket_impl = [
"lru", "lru",
"dashmap", "dashmap",
"rauth/database-mongodb", "authifier/database-mongodb",
"rauth/rocket_impl", "authifier/rocket_impl",
"rauth/okapi_impl" "authifier/okapi_impl"
] ]
test = [ "async-std", "mongo", "mongodb/async-std-runtime", "rocket_impl" ] test = [ "async-std", "mongo", "mongodb/async-std-runtime", "rocket_impl" ]
@@ -38,10 +38,8 @@ bson = { version = "2.1.0", features = ["chrono-0_4"] }
# Spec Generation # Spec Generation
schemars = "0.8.8" schemars = "0.8.8"
okapi = { git = "https://github.com/insertish/okapi", rev = "a1048d0c8cd771e424ec97d33d825c32e06aa120" } revolt_okapi = "0.9.1"
rocket_okapi = { git = "https://github.com/insertish/okapi", rev = "a1048d0c8cd771e424ec97d33d825c32e06aa120" } revolt_rocket_okapi = { version = "0.9.1", features = [ "swagger" ] }
# okapi = "0.7.0-rc.1"
# rocket_okapi = "0.8.0-rc.1"
# Databases # Databases
redis-kiss = { version = "0.1.3" } redis-kiss = { version = "0.1.3" }
@@ -71,6 +69,7 @@ reqwest = "0.11.10"
bitfield = "0.13.2" bitfield = "0.13.2"
once_cell = "1.13.0" once_cell = "1.13.0"
lazy_static = "1.4.0" lazy_static = "1.4.0"
async-lock = "2.6.0"
lru = { version = "0.7.6", optional = true } lru = { version = "0.7.6", optional = true }
dashmap = { version = "5.2.0", optional = true } dashmap = { version = "5.2.0", optional = true }
@@ -82,11 +81,11 @@ web-push = "0.7.2"
# Implementations # Implementations
rocket_http = { optional = true, version = "0.5.0-rc.2" } rocket_http = { optional = true, version = "0.5.0-rc.2" }
rocket = { optional = true, version = "0.5.0-rc.2", default-features = false, features = ["json"] } rocket = { optional = true, version = "0.5.0-rc.2", default-features = false, features = ["json"] }
rocket_empty = { optional = true, git = "https://github.com/insertish/rocket_empty", branch = "master" } rocket_empty = { version = "0.1.1", optional = true, features = [ "schema" ] }
rocket_cors = { optional = true, git = "https://github.com/lawliet89/rocket_cors", rev = "5843861a88958c16bfaa0b40f0d8910772bcd2f6" } rocket_cors = { optional = true, git = "https://github.com/lawliet89/rocket_cors", rev = "c17e8145baa4790319fdb6a473e465b960f55e7c" }
# rAuth # Authifier
rauth = { git = "https://github.com/insertish/rauth", rev = "cbdec69c684a4854fbedba9ed1f0e7ee466bf3f7", features = [ "async-std-runtime" ] } authifier = { version = "1.0.7", features = [ "async-std-runtime" ] }
# Sentry # Sentry
sentry = "0.25.0" sentry = "0.25.0"

View File

@@ -61,13 +61,13 @@ impl Deref for Database {
} }
} }
impl From<Database> for rauth::Database { impl From<Database> for authifier::Database {
fn from(val: Database) -> Self { fn from(val: Database) -> Self {
match val { match val {
Database::Dummy(_) => rauth::Database::default(), Database::Dummy(_) => authifier::Database::default(),
Database::MongoDb(MongoDb(client)) => { Database::MongoDb(MongoDb(client)) => authifier::Database::MongoDb(
rauth::Database::MongoDb(rauth::database::MongoDb(client.database("revolt"))) authifier::database::MongoDb(client.database("revolt")),
} ),
} }
} }
} }

View File

@@ -1,3 +1,4 @@
use authifier::AuthifierEvent;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::models::channel::{FieldsChannel, PartialChannel}; use crate::models::channel::{FieldsChannel, PartialChannel};
@@ -195,9 +196,23 @@ pub enum EventV1 {
/// Settings updated remotely /// Settings updated remotely
UserSettingsUpdate { id: String, update: UserSettings }, UserSettingsUpdate { id: String, update: UserSettings },
/// User has been platform banned or deleted their account
///
/// Clients should remove the following associated data:
/// - Messages
/// - DM Channels
/// - Relationships
/// - Server Memberships
///
/// User flags are specified to explain why a wipe is occurring though not all reasons will necessarily ever appear.
UserPlatformWipe { user_id: String, flags: i32 },
/// New emoji /// New emoji
EmojiCreate(Emoji), EmojiCreate(Emoji),
/// Delete emoji /// Delete emoji
EmojiDelete { id: String }, EmojiDelete { id: String },
/// Auth events
Auth(AuthifierEvent),
} }

View File

@@ -23,11 +23,7 @@ impl Cache {
pub async fn can_view_channel(&self, db: &Database, channel: &Channel) -> bool { pub async fn can_view_channel(&self, db: &Database, channel: &Channel) -> bool {
match &channel { match &channel {
Channel::TextChannel { server, .. } | Channel::VoiceChannel { server, .. } => { Channel::TextChannel { server, .. } | Channel::VoiceChannel { server, .. } => {
let member = self let member = self.members.values().find(|x| &x.id.server == server);
.members
.iter()
.map(|(_, x)| x)
.find(|x| &x.id.server == server);
let server = self.servers.get(server); let server = self.servers.get(server);
let mut perms = perms(self.users.get(&self.user_id).unwrap()).channel(channel); let mut perms = perms(self.users.get(&self.user_id).unwrap()).channel(channel);
@@ -563,4 +559,9 @@ impl EventV1 {
pub async fn private(self, id: String) { pub async fn private(self, id: String) {
self.p(format!("{}!", id)).await; self.p(format!("{}!", id)).await;
} }
/// Publish internal global event
pub async fn global(self) {
self.p("global".to_string()).await;
}
} }

View File

@@ -215,7 +215,7 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 {
} }
if revision <= 8 { if revision <= 8 {
info!("Running migration [revision 8 / 2021-09-10]: Update to rAuth version 1."); info!("Running migration [revision 8 / 2021-09-10]: Update to Authifier version 1.");
db.db() db.db()
.run_command( .run_command(
@@ -603,20 +603,20 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 {
} }
if revision <= 15 { if revision <= 15 {
info!("Running migration [revision 15 / 04-06-2022]: Migrate rAuth to latest version."); info!("Running migration [revision 15 / 04-06-2022]: Migrate Authifier to latest version.");
let db = rauth::Database::MongoDb(rauth::database::MongoDb(db.db())); let db = authifier::Database::MongoDb(authifier::database::MongoDb(db.db()));
db.run_migration(rauth::Migration::M2022_06_03EnsureUpToSpec) db.run_migration(authifier::Migration::M2022_06_03EnsureUpToSpec)
.await .await
.unwrap(); .unwrap();
} }
if revision <= 16 { if revision <= 16 {
info!("Running migration [revision 16 / 07-07-2022]: Add `emojis` collection and rAuth migration."); info!("Running migration [revision 16 / 07-07-2022]: Add `emojis` collection and Authifier migration.");
let rauth_db = rauth::Database::MongoDb(rauth::database::MongoDb(db.db())); let authifier_db = authifier::Database::MongoDb(authifier::database::MongoDb(db.db()));
rauth_db authifier_db
.run_migration(rauth::Migration::M2022_06_09AddIndexForDeletion) .run_migration(authifier::Migration::M2022_06_09AddIndexForDeletion)
.await .await
.unwrap(); .unwrap();

View File

@@ -1,7 +1,7 @@
use okapi::openapi3::{SecurityScheme, SecuritySchemeData}; use authifier::models::Session;
use rauth::models::Session; use revolt_okapi::openapi3::{SecurityScheme, SecuritySchemeData};
use rocket_okapi::gen::OpenApiGenerator; use revolt_rocket_okapi::gen::OpenApiGenerator;
use rocket_okapi::request::{OpenApiFromRequest, RequestHeaderInput}; use revolt_rocket_okapi::request::{OpenApiFromRequest, RequestHeaderInput};
use rocket::http::Status; use rocket::http::Status;
use rocket::request::{self, FromRequest, Outcome, Request}; use rocket::request::{self, FromRequest, Outcome, Request};
@@ -12,7 +12,7 @@ use crate::Database;
#[rocket::async_trait] #[rocket::async_trait]
impl<'r> FromRequest<'r> for User { impl<'r> FromRequest<'r> for User {
type Error = rauth::Error; type Error = authifier::Error;
async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, Self::Error> { async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
let user: &Option<User> = request let user: &Option<User> = request
@@ -43,7 +43,7 @@ impl<'r> FromRequest<'r> for User {
if let Some(user) = user { if let Some(user) = user {
Outcome::Success(user.clone()) Outcome::Success(user.clone())
} else { } else {
Outcome::Failure((Status::Unauthorized, rauth::Error::InvalidSession)) Outcome::Failure((Status::Unauthorized, authifier::Error::InvalidSession))
} }
} }
} }
@@ -53,7 +53,7 @@ impl<'r> OpenApiFromRequest<'r> for User {
_gen: &mut OpenApiGenerator, _gen: &mut OpenApiGenerator,
_name: String, _name: String,
_required: bool, _required: bool,
) -> rocket_okapi::Result<RequestHeaderInput> { ) -> revolt_rocket_okapi::Result<RequestHeaderInput> {
let mut requirements = schemars::Map::new(); let mut requirements = schemars::Map::new();
requirements.insert("Session Token".to_owned(), vec![]); requirements.insert("Session Token".to_owned(), vec![]);

View File

@@ -17,8 +17,8 @@ extern crate bitfield;
#[macro_use] #[macro_use]
extern crate bson; extern crate bson;
pub use authifier;
pub use iso8601_timestamp::Timestamp; pub use iso8601_timestamp::Timestamp;
pub use rauth;
pub use redis_kiss; pub use redis_kiss;
pub mod events; pub mod events;

View File

@@ -81,7 +81,7 @@ pub struct Masquerade {
pub name: Option<String>, pub name: Option<String>,
/// Replace the avatar shown on this message (URL to image file) /// Replace the avatar shown on this message (URL to image file)
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
#[validate(length(min = 1, max = 128))] #[validate(length(min = 1, max = 256))]
pub avatar: Option<String>, pub avatar: Option<String>,
/// Replace the display role colour shown on this message /// Replace the display role colour shown on this message
/// ///
@@ -98,6 +98,8 @@ pub struct Interactions {
#[serde(skip_serializing_if = "Option::is_none", default)] #[serde(skip_serializing_if = "Option::is_none", default)]
pub reactions: Option<IndexSet<String>>, pub reactions: Option<IndexSet<String>>,
/// Whether reactions should be restricted to the given list /// Whether reactions should be restricted to the given list
///
/// Can only be set to true if reactions list is of at least length 1
#[serde(skip_serializing_if = "if_false", default)] #[serde(skip_serializing_if = "if_false", default)]
pub restrict_reactions: bool, pub restrict_reactions: bool,
} }

View File

@@ -105,6 +105,8 @@ pub enum Flags {
Deleted = 2, Deleted = 2,
/// User was banned off the platform /// User was banned off the platform
Banned = 4, Banned = 4,
/// User was marked as spam and removed from platform
Spam = 8,
} }
/// Bot information for if the user is a bot /// Bot information for if the user is a bot

View File

@@ -97,7 +97,7 @@ impl From<i64> for PermissionValue {
impl From<u64> for PermissionValue { impl From<u64> for PermissionValue {
fn from(v: u64) -> Self { fn from(v: u64) -> Self {
Self(v as u64) Self(v)
} }
} }

View File

@@ -24,7 +24,7 @@ pub enum Permission {
/// Manage server customisation (includes emoji) /// Manage server customisation (includes emoji)
ManageCustomisation = 1 << 4, ManageCustomisation = 1 << 4,
// % 1 bits reserved // % 1 bit reserved
// * Member permissions // * Member permissions
/// Kick other members below their ranking /// Kick other members below their ranking
@@ -109,10 +109,11 @@ lazy_static! {
+ Permission::Connect + Permission::Connect
+ Permission::Speak; + Permission::Speak;
pub static ref DEFAULT_PERMISSION_SAVED_MESSAGES: u64 = Permission::GrantAllSafe as u64; pub static ref DEFAULT_PERMISSION_SAVED_MESSAGES: u64 = Permission::GrantAllSafe as u64;
pub static ref DEFAULT_PERMISSION_DIRECT_MESSAGE: u64 = pub static ref DEFAULT_PERMISSION_DIRECT_MESSAGE: u64 = *DEFAULT_PERMISSION
*DEFAULT_PERMISSION + Permission::ManageChannel; + Permission::ManageChannel
+ Permission::React;
pub static ref DEFAULT_PERMISSION_SERVER: u64 = pub static ref DEFAULT_PERMISSION_SERVER: u64 =
*DEFAULT_PERMISSION + Permission::ChangeNickname + Permission::ChangeAvatar; *DEFAULT_PERMISSION + Permission::React + Permission::ChangeNickname + Permission::ChangeAvatar;
} }
bitfield! { bitfield! {

View File

@@ -35,7 +35,7 @@ pub async fn presence_create_session(user_id: &str, flags: u8) -> (bool, u8) {
__set_key_presence_entry(&mut conn, user_id, entry).await; __set_key_presence_entry(&mut conn, user_id, entry).await;
// Add to region set in case of failure. // Add to region set in case of failure.
__add_to_set_sessions(&mut conn, &*REGION_KEY, user_id, session_id).await; __add_to_set_sessions(&mut conn, &REGION_KEY, user_id, session_id).await;
(was_empty, session_id) (was_empty, session_id)
} }
@@ -74,7 +74,7 @@ async fn presence_delete_session_internal(
// Remove from region set. // Remove from region set.
if !skip_region { if !skip_region {
__remove_from_set_sessions(&mut conn, &*REGION_KEY, user_id, session_id).await; __remove_from_set_sessions(&mut conn, &REGION_KEY, user_id, session_id).await;
} }
} }

View File

@@ -1,11 +1,14 @@
use crate::util::variables::delta::{JANUARY_URL, MAX_EMBED_COUNT}; use crate::util::variables::delta::{JANUARY_URL, MAX_EMBED_COUNT, JANUARY_CONCURRENT_CONNECTIONS};
use crate::{ use crate::{
models::{message::AppendMessage, Message}, models::{message::AppendMessage, Message},
types::january::Embed, types::january::Embed,
Database, Database,
}; };
use async_lock::Semaphore;
use async_std::task::spawn;
use deadqueue::limited::Queue; use deadqueue::limited::Queue;
use std::sync::Arc;
/// Task information /// Task information
#[derive(Debug)] #[derive(Debug)]
@@ -36,21 +39,30 @@ pub async fn queue(channel: String, id: String, content: String) {
/// Start a new worker /// Start a new worker
pub async fn worker(db: Database) { pub async fn worker(db: Database) {
let semaphore = Arc::new(Semaphore::new(*JANUARY_CONCURRENT_CONNECTIONS));
loop { loop {
let task = Q.pop().await; let task = Q.pop().await;
if let Ok(embeds) = Embed::generate(task.content, &*JANUARY_URL, *MAX_EMBED_COUNT).await { let db = db.clone();
if let Err(err) = Message::append( let semaphore = semaphore.clone();
&db,
task.id, spawn(async move {
task.channel, let embeds = Embed::generate(task.content, &JANUARY_URL, *MAX_EMBED_COUNT, semaphore).await;
AppendMessage {
embeds: Some(embeds), if let Ok(embeds) = embeds {
}, if let Err(err) = Message::append(
) &db,
.await task.id,
{ task.channel,
error!("Encountered an error appending to message: {:?}", err); AppendMessage {
embeds: Some(embeds),
},
)
.await
{
error!("Encountered an error appending to message: {:?}", err);
}
} }
} });
} }
} }

View File

@@ -1,8 +1,8 @@
use crate::bson::doc; use crate::bson::doc;
use crate::util::variables::delta::VAPID_PRIVATE_KEY; use crate::util::variables::delta::VAPID_PRIVATE_KEY;
use authifier::Database;
use deadqueue::limited::Queue; use deadqueue::limited::Queue;
use rauth::Database;
use web_push::{ use web_push::{
ContentEncoding, SubscriptionInfo, SubscriptionKeys, VapidSignatureBuilder, WebPushClient, ContentEncoding, SubscriptionInfo, SubscriptionKeys, VapidSignatureBuilder, WebPushClient,
WebPushMessageBuilder, WebPushMessageBuilder,

View File

@@ -1,7 +1,10 @@
use async_lock::Semaphore;
use async_std::task::spawn;
use futures::future::join_all;
use linkify::{LinkFinder, LinkKind}; use linkify::{LinkFinder, LinkKind};
use regex::Regex; use regex::Regex;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::HashSet; use std::{collections::HashSet, sync::Arc};
use crate::{models::attachment::File, Error, Result}; use crate::{models::attachment::File, Error, Result};
@@ -95,6 +98,8 @@ pub enum Special {
content_type: BandcampType, content_type: BandcampType,
id: String, id: String,
}, },
/// Streamable Video
Streamable { id: String },
} }
/// Website metadata /// Website metadata
@@ -172,7 +177,12 @@ pub enum Embed {
impl Embed { impl Embed {
/// Generate embeds from given content /// Generate embeds from given content
pub async fn generate(content: String, host: &str, max_embeds: usize) -> Result<Vec<Embed>> { pub async fn generate(
content: String,
host: &str,
max_embeds: usize,
semaphore: Arc<Semaphore>,
) -> Result<Vec<Embed>> {
lazy_static! { lazy_static! {
static ref RE_CODE: Regex = Regex::new("```(?:.|\n)+?```|`(?:.|\n)+?`").unwrap(); static ref RE_CODE: Regex = Regex::new("```(?:.|\n)+?```|`(?:.|\n)+?`").unwrap();
static ref RE_IGNORED: Regex = Regex::new("(<http.+>)").unwrap(); static ref RE_IGNORED: Regex = Regex::new("(<http.+>)").unwrap();
@@ -223,26 +233,37 @@ impl Embed {
} }
// ! FIXME: batch request to january? // ! FIXME: batch request to january?
let mut embeds: Vec<Embed> = Vec::new();
let client = reqwest::Client::new(); let client = reqwest::Client::new();
let mut tasks = Vec::new();
let url = format!("{host}/embed");
for link in links { for link in links {
let result = client let client = client.clone();
.get(&format!("{}/embed", host)) let url = url.clone();
.query(&[("url", link)]) let semaphore = semaphore.clone();
.send()
.await;
if result.is_err() { tasks.push(spawn(async move {
continue; let guard = semaphore.acquire().await;
}
let response = result.unwrap(); let response = client.get(url).query(&[("url", link)]).send().await.ok()?;
if response.status().is_success() {
let res: Embed = response.json().await.map_err(|_| Error::InvalidOperation)?; drop(guard);
embeds.push(res);
} if response.status().is_success() {
response.json::<Embed>().await.ok()
} else {
None
}
}));
} }
let embeds = join_all(tasks)
.await
.into_iter()
.flatten()
.collect::<Vec<Embed>>();
// Prevent database update when no embeds are found. // Prevent database update when no embeds are found.
if !embeds.is_empty() { if !embeds.is_empty() {
Ok(embeds) Ok(embeds)

View File

@@ -1,9 +1,11 @@
use authifier::config::{ResolveIp, Shield};
use super::variables::delta::{ use super::variables::delta::{
APP_URL, HCAPTCHA_KEY, INVITE_ONLY, SMTP_FROM, SMTP_HOST, SMTP_PASSWORD, SMTP_USERNAME, APP_URL, AUTHIFIER_SHIELD_KEY, HCAPTCHA_KEY, INVITE_ONLY, SMTP_FROM, SMTP_HOST, SMTP_PASSWORD,
USE_EMAIL, USE_HCAPTCHA, SMTP_USERNAME, USE_EMAIL, USE_HCAPTCHA,
}; };
use crate::rauth::config::{ use crate::authifier::config::{
Captcha, Config, EmailVerificationConfig, SMTPSettings, Template, Templates, Captcha, Config, EmailVerificationConfig, SMTPSettings, Template, Templates,
}; };
@@ -59,5 +61,19 @@ pub fn config() -> Config {
}; };
} }
if let Some(api_key) = &*AUTHIFIER_SHIELD_KEY {
config.shield = Shield::Enabled {
api_key: api_key.to_string(),
strict: false,
};
}
if std::env::var("TRUST_CLOUDFLARE")
.map(|x| x == "1")
.unwrap_or_default()
{
config.resolve_ip = ResolveIp::Cloudflare;
}
config config
} }

View File

@@ -1,7 +1,7 @@
pub mod authifier;
pub mod log; pub mod log;
pub mod manipulation; pub mod manipulation;
pub mod pfp; pub mod pfp;
pub mod rauth;
pub mod r#ref; pub mod r#ref;
pub mod regex; pub mod regex;
pub mod result; pub mod result;

View File

@@ -1,4 +1,5 @@
use okapi::openapi3::{self, SchemaObject}; use revolt_okapi::openapi3::SchemaObject;
use revolt_rocket_okapi::revolt_okapi::openapi3;
use rocket::{ use rocket::{
http::{ContentType, Status}, http::{ContentType, Status},
response::{self, Responder}, response::{self, Responder},
@@ -19,10 +20,10 @@ pub enum Error {
/// This error was not labeled :( /// This error was not labeled :(
LabelMe, LabelMe,
// ? Onboarding related errors. // ? Onboarding related errors
AlreadyOnboarded, AlreadyOnboarded,
// ? User related errors. // ? User related errors
UsernameTaken, UsernameTaken,
InvalidUsername, InvalidUsername,
UnknownUser, UnknownUser,
@@ -32,7 +33,7 @@ pub enum Error {
BlockedByOther, BlockedByOther,
NotFriends, NotFriends,
// ? Channel related errors. // ? Channel related errors
UnknownChannel, UnknownChannel,
UnknownAttachment, UnknownAttachment,
UnknownMessage, UnknownMessage,
@@ -49,7 +50,7 @@ pub enum Error {
AlreadyInGroup, AlreadyInGroup,
NotInGroup, NotInGroup,
// ? Server related errors. // ? Server related errors
UnknownServer, UnknownServer,
InvalidRole, InvalidRole,
Banned, Banned,
@@ -58,12 +59,12 @@ pub enum Error {
}, },
TooManyEmoji, TooManyEmoji,
// ? Bot related errors. // ? Bot related errors
ReachedMaximumBots, ReachedMaximumBots,
IsBot, IsBot,
BotIsPrivate, BotIsPrivate,
// ? Permission errors. // ? Permission errors
MissingPermission { MissingPermission {
permission: Permission, permission: Permission,
}, },
@@ -74,7 +75,7 @@ pub enum Error {
CannotGiveMissingPermissions, CannotGiveMissingPermissions,
NotOwner, NotOwner,
// ? General errors. // ? General errors
DatabaseError { DatabaseError {
operation: &'static str, operation: &'static str,
with: &'static str, with: &'static str,
@@ -82,6 +83,7 @@ pub enum Error {
InternalError, InternalError,
InvalidOperation, InvalidOperation,
InvalidCredentials, InvalidCredentials,
InvalidProperty,
InvalidSession, InvalidSession,
DuplicateNonce, DuplicateNonce,
VosoUnavailable, VosoUnavailable,
@@ -174,6 +176,7 @@ impl<'r> Responder<'r, 'static> for Error {
Error::InternalError => Status::InternalServerError, Error::InternalError => Status::InternalServerError,
Error::InvalidOperation => Status::BadRequest, Error::InvalidOperation => Status::BadRequest,
Error::InvalidCredentials => Status::Unauthorized, Error::InvalidCredentials => Status::Unauthorized,
Error::InvalidProperty => Status::BadRequest,
Error::InvalidSession => Status::Unauthorized, Error::InvalidSession => Status::Unauthorized,
Error::DuplicateNonce => Status::Conflict, Error::DuplicateNonce => Status::Conflict,
Error::VosoUnavailable => Status::BadRequest, Error::VosoUnavailable => Status::BadRequest,
@@ -194,11 +197,11 @@ impl<'r> Responder<'r, 'static> for Error {
} }
} }
impl rocket_okapi::response::OpenApiResponderInner for Error { impl revolt_rocket_okapi::response::OpenApiResponderInner for Error {
fn responses( fn responses(
gen: &mut rocket_okapi::gen::OpenApiGenerator, gen: &mut revolt_rocket_okapi::gen::OpenApiGenerator,
) -> std::result::Result<openapi3::Responses, rocket_okapi::OpenApiError> { ) -> std::result::Result<openapi3::Responses, revolt_rocket_okapi::OpenApiError> {
let mut content = okapi::Map::new(); let mut content = revolt_okapi::Map::new();
let settings = schemars::gen::SchemaSettings::default().with(|s| { let settings = schemars::gen::SchemaSettings::default().with(|s| {
s.option_nullable = true; s.option_nullable = true;

View File

@@ -13,6 +13,8 @@ lazy_static! {
env::var("AUTUMN_PUBLIC_URL").unwrap_or_else(|_| "https://example.com".to_string()); env::var("AUTUMN_PUBLIC_URL").unwrap_or_else(|_| "https://example.com".to_string());
pub static ref JANUARY_URL: String = pub static ref JANUARY_URL: String =
env::var("JANUARY_PUBLIC_URL").unwrap_or_else(|_| "https://example.com".to_string()); env::var("JANUARY_PUBLIC_URL").unwrap_or_else(|_| "https://example.com".to_string());
pub static ref JANUARY_CONCURRENT_CONNECTIONS: usize =
env::var("JANUARY_CONCURRENT_CONNECTIONS").map_or(50, |v| v.parse().unwrap());
pub static ref VOSO_URL: String = pub static ref VOSO_URL: String =
env::var("VOSO_PUBLIC_URL").unwrap_or_else(|_| "https://example.com".to_string()); env::var("VOSO_PUBLIC_URL").unwrap_or_else(|_| "https://example.com".to_string());
pub static ref VOSO_WS_HOST: String = pub static ref VOSO_WS_HOST: String =
@@ -28,6 +30,8 @@ lazy_static! {
env::var("REVOLT_VAPID_PRIVATE_KEY").expect("Missing REVOLT_VAPID_PRIVATE_KEY environment variable."); env::var("REVOLT_VAPID_PRIVATE_KEY").expect("Missing REVOLT_VAPID_PRIVATE_KEY environment variable.");
pub static ref VAPID_PUBLIC_KEY: String = pub static ref VAPID_PUBLIC_KEY: String =
env::var("REVOLT_VAPID_PUBLIC_KEY").expect("Missing REVOLT_VAPID_PUBLIC_KEY environment variable."); env::var("REVOLT_VAPID_PUBLIC_KEY").expect("Missing REVOLT_VAPID_PUBLIC_KEY environment variable.");
pub static ref AUTHIFIER_SHIELD_KEY: Option<String> =
env::var("REVOLT_AUTHIFIER_SHIELD_KEY").ok();
// Application Flags // Application Flags
pub static ref INVITE_ONLY: bool = env::var("REVOLT_INVITE_ONLY").map_or(false, |v| v == "1"); pub static ref INVITE_ONLY: bool = env::var("REVOLT_INVITE_ONLY").map_or(false, |v| v == "1");

View File

@@ -1,11 +1,11 @@
use crate::{Error, Result}; use crate::{Error, Result};
use async_std::sync::Mutex; use async_std::sync::Mutex;
use revolt_rocket_okapi::gen::OpenApiGenerator;
use revolt_rocket_okapi::request::{OpenApiFromRequest, RequestHeaderInput};
use revolt_rocket_okapi::revolt_okapi::openapi3::{Parameter, ParameterValue};
use rocket::http::Status; use rocket::http::Status;
use rocket::request::{FromRequest, Outcome}; use rocket::request::{FromRequest, Outcome};
use rocket_okapi::gen::OpenApiGenerator;
use rocket_okapi::okapi::openapi3::{Parameter, ParameterValue};
use rocket_okapi::request::{OpenApiFromRequest, RequestHeaderInput};
use schemars::schema::{InstanceType, SchemaObject, SingleOrVec}; use schemars::schema::{InstanceType, SchemaObject, SingleOrVec};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use validator::Validate; use validator::Validate;
@@ -47,7 +47,7 @@ impl<'r> OpenApiFromRequest<'r> for IdempotencyKey {
_gen: &mut OpenApiGenerator, _gen: &mut OpenApiGenerator,
_name: String, _name: String,
_required: bool, _required: bool,
) -> rocket_okapi::Result<RequestHeaderInput> { ) -> revolt_rocket_okapi::Result<RequestHeaderInput> {
Ok(RequestHeaderInput::Parameter(Parameter { Ok(RequestHeaderInput::Parameter(Parameter {
name: "Idempotency-Key".to_string(), name: "Idempotency-Key".to_string(),
description: Some("Unique key to prevent duplicate requests".to_string()), description: Some("Unique key to prevent duplicate requests".to_string()),

View File

@@ -8,7 +8,7 @@ use std::hash::Hasher;
use std::ops::Add; use std::ops::Add;
use std::time::{Duration, SystemTime, UNIX_EPOCH}; use std::time::{Duration, SystemTime, UNIX_EPOCH};
use crate::rauth::models::Session; use crate::authifier::models::Session;
use rocket::fairing::{Fairing, Info, Kind}; use rocket::fairing::{Fairing, Info, Kind};
use rocket::http::uri::Origin; use rocket::http::uri::Origin;
use rocket::http::{Method, Status}; use rocket::http::{Method, Status};
@@ -16,8 +16,8 @@ use rocket::request::{FromRequest, Outcome};
use rocket::serde::json::Json; use rocket::serde::json::Json;
use rocket::{Data, Request, Response}; use rocket::{Data, Request, Response};
use rocket_okapi::gen::OpenApiGenerator; use revolt_rocket_okapi::gen::OpenApiGenerator;
use rocket_okapi::request::{OpenApiFromRequest, RequestHeaderInput}; use revolt_rocket_okapi::request::{OpenApiFromRequest, RequestHeaderInput};
use serde::Serialize; use serde::Serialize;
@@ -51,7 +51,7 @@ impl Entry {
} }
/// Deduct one unit from the bucket and save /// Deduct one unit from the bucket and save
pub fn deduct(mut self, key: u64) { pub fn deduct(mut self) {
let current_time = now().as_millis(); let current_time = now().as_millis();
if current_time > self.reset { if current_time > self.reset {
self.used = 1; self.used = 1;
@@ -59,7 +59,10 @@ impl Entry {
} else { } else {
self.used += 1; self.used += 1;
} }
}
/// Save information
pub fn save(self, key: u64) {
MAP.insert(key, self); MAP.insert(key, self);
} }
@@ -193,10 +196,12 @@ impl Ratelimiter {
let entry = Entry::from(key); let entry = Entry::from(key);
let remaining = entry.get_remaining(limit); let remaining = entry.get_remaining(limit);
let reset = entry.left_until_reset();
if remaining > 0 { if remaining > 0 {
entry.deduct(key); entry.deduct();
let reset = entry.left_until_reset();
entry.save(key);
Ok(Ratelimiter { Ok(Ratelimiter {
key, key,
limit, limit,
@@ -204,7 +209,7 @@ impl Ratelimiter {
reset, reset,
}) })
} else { } else {
Err(reset) Err(entry.left_until_reset())
} }
} }
} }
@@ -240,7 +245,7 @@ impl<'r> OpenApiFromRequest<'r> for Ratelimiter {
_gen: &mut OpenApiGenerator, _gen: &mut OpenApiGenerator,
_name: String, _name: String,
_required: bool, _required: bool,
) -> rocket_okapi::Result<RequestHeaderInput> { ) -> revolt_rocket_okapi::Result<RequestHeaderInput> {
Ok(RequestHeaderInput::None) Ok(RequestHeaderInput::None)
} }
} }

View File

@@ -1,7 +1,7 @@
use rocket::Route; use rocket::Route;
pub fn routes() -> Vec<Route> { pub fn routes() -> Vec<Route> {
rocket_okapi::swagger_ui::make_swagger_ui(&rocket_okapi::swagger_ui::SwaggerUIConfig { revolt_rocket_okapi::swagger_ui::make_swagger_ui(&revolt_rocket_okapi::swagger_ui::SwaggerUIConfig {
url: "../openapi.json".to_owned(), url: "../openapi.json".to_owned(),
..Default::default() ..Default::default()
}) })