forked from jmug/stoatchat
Merge branch 'master' into webhooks
This commit is contained in:
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@@ -1,2 +0,0 @@
|
|||||||
ko_fi: insertish
|
|
||||||
custom: https://insrt.uk/donate
|
|
||||||
9
.github/workflows/rust.yaml
vendored
9
.github/workflows/rust.yaml
vendored
@@ -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'
|
||||||
@@ -70,6 +71,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
cwd: "api"
|
cwd: "api"
|
||||||
add: "*.json"
|
add: "*.json"
|
||||||
|
author_name: Revolt CI
|
||||||
|
author_email: revolt-ci@users.noreply.github.com
|
||||||
message: "chore: generate OpenAPI specification"
|
message: "chore: generate OpenAPI specification"
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|||||||
108
Cargo.lock
generated
108
Cargo.lock
generated
@@ -330,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"
|
||||||
@@ -2579,39 +2613,6 @@ dependencies = [
|
|||||||
"rand_core 0.3.1",
|
"rand_core 0.3.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rauth"
|
|
||||||
version = "1.0.4"
|
|
||||||
source = "git+https://github.com/insertish/rauth?tag=1.0.4#2d3bc59623672e3ff57c49a90c4d3cd20780dbba"
|
|
||||||
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 = "rdrand"
|
name = "rdrand"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
@@ -2791,7 +2792,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "revolt-bonfire"
|
name = "revolt-bonfire"
|
||||||
version = "0.5.6"
|
version = "0.5.9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-std",
|
"async-std",
|
||||||
"async-tungstenite",
|
"async-tungstenite",
|
||||||
@@ -2807,7 +2808,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "revolt-delta"
|
name = "revolt-delta"
|
||||||
version = "0.5.6"
|
version = "0.5.9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-channel",
|
"async-channel",
|
||||||
"async-std",
|
"async-std",
|
||||||
@@ -2834,8 +2835,8 @@ dependencies = [
|
|||||||
"revolt-quark",
|
"revolt-quark",
|
||||||
"revolt_rocket_okapi",
|
"revolt_rocket_okapi",
|
||||||
"rocket",
|
"rocket",
|
||||||
|
"rocket_authifier",
|
||||||
"rocket_empty",
|
"rocket_empty",
|
||||||
"rocket_rauth",
|
|
||||||
"schemars",
|
"schemars",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@@ -2847,12 +2848,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "revolt-quark"
|
name = "revolt-quark"
|
||||||
version = "0.5.6"
|
version = "0.5.9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-lock",
|
"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",
|
||||||
@@ -2874,7 +2876,6 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
"optional_struct",
|
"optional_struct",
|
||||||
"pretty_env_logger",
|
"pretty_env_logger",
|
||||||
"rauth",
|
|
||||||
"redis-kiss",
|
"redis-kiss",
|
||||||
"regex",
|
"regex",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
@@ -3010,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"
|
||||||
@@ -3080,21 +3097,6 @@ dependencies = [
|
|||||||
"uncased",
|
"uncased",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rocket_rauth"
|
|
||||||
version = "1.0.4"
|
|
||||||
source = "git+https://github.com/insertish/rauth?tag=1.0.4#2d3bc59623672e3ff57c49a90c4d3cd20780dbba"
|
|
||||||
dependencies = [
|
|
||||||
"iso8601-timestamp",
|
|
||||||
"rauth",
|
|
||||||
"revolt_okapi",
|
|
||||||
"revolt_rocket_okapi",
|
|
||||||
"rocket",
|
|
||||||
"rocket_empty",
|
|
||||||
"schemars",
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rust-argon2"
|
name = "rust-argon2"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
|||||||
7
build.sh
7
build.sh
@@ -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 .
|
|
||||||
2
crates/bonfire/.github/FUNDING.yml
vendored
2
crates/bonfire/.github/FUNDING.yml
vendored
@@ -1,2 +0,0 @@
|
|||||||
ko_fi: insertish
|
|
||||||
custom: https://insrt.uk/donate
|
|
||||||
98
crates/bonfire/.github/workflows/docker.yml
vendored
98
crates/bonfire/.github/workflows/docker.yml
vendored
@@ -1,98 +0,0 @@
|
|||||||
name: Docker
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- "master"
|
|
||||||
tags:
|
|
||||||
- "*"
|
|
||||||
paths-ignore:
|
|
||||||
- ".github/**"
|
|
||||||
- "!.github/workflows/docker.yml"
|
|
||||||
- ".vscode/**"
|
|
||||||
- ".gitignore"
|
|
||||||
- ".gitlab-ci.yml"
|
|
||||||
- "LICENSE"
|
|
||||||
- "README"
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- "master"
|
|
||||||
paths:
|
|
||||||
- "Dockerfile"
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
architecture: [linux/amd64]
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
submodules: "recursive"
|
|
||||||
- name: Set up QEMU
|
|
||||||
uses: docker/setup-qemu-action@v1
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v1
|
|
||||||
- name: Cache Docker layers
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: /tmp/.buildx-cache/${{ matrix.architecture }}
|
|
||||||
key: ${{ runner.os }}-buildx-${{ matrix.architecture }}-${{ github.sha }}
|
|
||||||
- name: Build
|
|
||||||
uses: docker/build-push-action@v2
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
platforms: ${{ matrix.architecture }}
|
|
||||||
cache-from: type=local,src=/tmp/.buildx-cache/${{ matrix.architecture }}
|
|
||||||
cache-to: type=local,dest=/tmp/.buildx-cache-new/${{ matrix.architecture }},mode=max
|
|
||||||
- name: Move cache
|
|
||||||
run: |
|
|
||||||
rm -rf /tmp/.buildx-cache/${{ matrix.architecture }}
|
|
||||||
mv /tmp/.buildx-cache-new/${{ matrix.architecture }} /tmp/.buildx-cache/${{ matrix.architecture }}
|
|
||||||
|
|
||||||
publish_amd64:
|
|
||||||
needs: [test]
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.event_name != 'pull_request'
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
submodules: "recursive"
|
|
||||||
- name: Set up QEMU
|
|
||||||
uses: docker/setup-qemu-action@v1
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v1
|
|
||||||
- name: Cache amd64 Docker layers
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: /tmp/.buildx-cache/linux/amd64
|
|
||||||
key: ${{ runner.os }}-buildx-linux/amd64-${{ github.sha }}
|
|
||||||
- name: Docker meta
|
|
||||||
id: meta
|
|
||||||
uses: docker/metadata-action@v3
|
|
||||||
with:
|
|
||||||
images: ghcr.io/revoltchat/bonfire
|
|
||||||
- name: Login to Github Container Registry
|
|
||||||
uses: docker/login-action@v1
|
|
||||||
with:
|
|
||||||
registry: ghcr.io
|
|
||||||
username: ${{ github.actor }}
|
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
- name: Build and publish
|
|
||||||
uses: docker/build-push-action@v2
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
push: true
|
|
||||||
platforms: linux/amd64
|
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
|
||||||
cache-from: type=local,src=/tmp/.buildx-cache/linux/amd64
|
|
||||||
cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
|
|
||||||
- name: Move cache
|
|
||||||
run: |
|
|
||||||
rm -rf /tmp/.buildx-cache
|
|
||||||
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
|
|
||||||
33
crates/bonfire/.github/workflows/rust.yaml
vendored
33
crates/bonfire/.github/workflows/rust.yaml
vendored
@@ -1,33 +0,0 @@
|
|||||||
name: Rust build and test
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ master ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ master ]
|
|
||||||
|
|
||||||
env:
|
|
||||||
CARGO_TERM_COLOR: always
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
check:
|
|
||||||
name: Rust project
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Install latest nightly
|
|
||||||
uses: actions-rs/toolchain@v1
|
|
||||||
with:
|
|
||||||
toolchain: nightly
|
|
||||||
override: true
|
|
||||||
components: rustfmt, clippy
|
|
||||||
|
|
||||||
- name: Run cargo build
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: build
|
|
||||||
|
|
||||||
- name: Run cargo test
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: test
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
name: Add Issue to Board
|
|
||||||
|
|
||||||
on:
|
|
||||||
issues:
|
|
||||||
types: [opened]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
track_issue:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Get project data
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.PAT }}
|
|
||||||
run: |
|
|
||||||
gh api graphql -f query='
|
|
||||||
query {
|
|
||||||
organization(login: "revoltchat"){
|
|
||||||
projectNext(number: 3) {
|
|
||||||
id
|
|
||||||
fields(first:20) {
|
|
||||||
nodes {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
settings
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}' > project_data.json
|
|
||||||
|
|
||||||
echo 'PROJECT_ID='$(jq '.data.organization.projectNext.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 'TODO_OPTION_ID='$(jq '.data.organization.projectNext.fields.nodes[] | select(.name== "Status") |.settings | fromjson.options[] | select(.name=="Todo") |.id' project_data.json) >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Add issue to project
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.PAT }}
|
|
||||||
ISSUE_ID: ${{ github.event.issue.node_id }}
|
|
||||||
run: |
|
|
||||||
item_id="$( gh api graphql -f query='
|
|
||||||
mutation($project:ID!, $issue:ID!) {
|
|
||||||
addProjectNextItem(input: {projectId: $project, contentId: $issue}) {
|
|
||||||
projectNextItem {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}' -f project=$PROJECT_ID -f issue=$ISSUE_ID --jq '.data.addProjectNextItem.projectNextItem.id')"
|
|
||||||
|
|
||||||
echo 'ITEM_ID='$item_id >> $GITHUB_ENV
|
|
||||||
72
crates/bonfire/.github/workflows/triage_pr.yml
vendored
72
crates/bonfire/.github/workflows/triage_pr.yml
vendored
@@ -1,72 +0,0 @@
|
|||||||
name: Add PR to Board
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request_target:
|
|
||||||
types: [opened, synchronize, ready_for_review, review_requested]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
track_pr:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Get project data
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.PAT }}
|
|
||||||
run: |
|
|
||||||
gh api graphql -f query='
|
|
||||||
query {
|
|
||||||
organization(login: "revoltchat"){
|
|
||||||
projectNext(number: 3) {
|
|
||||||
id
|
|
||||||
fields(first:20) {
|
|
||||||
nodes {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
settings
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}' > project_data.json
|
|
||||||
|
|
||||||
echo 'PROJECT_ID='$(jq '.data.organization.projectNext.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 '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
|
|
||||||
|
|
||||||
- name: Add PR to project
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.PAT }}
|
|
||||||
PR_ID: ${{ github.event.pull_request.node_id }}
|
|
||||||
run: |
|
|
||||||
item_id="$( gh api graphql -f query='
|
|
||||||
mutation($project:ID!, $pr:ID!) {
|
|
||||||
addProjectNextItem(input: {projectId: $project, contentId: $pr}) {
|
|
||||||
projectNextItem {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}' -f project=$PROJECT_ID -f pr=$PR_ID --jq '.data.addProjectNextItem.projectNextItem.id')"
|
|
||||||
|
|
||||||
echo 'ITEM_ID='$item_id >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Set fields
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.PAT }}
|
|
||||||
run: |
|
|
||||||
gh api graphql -f query='
|
|
||||||
mutation (
|
|
||||||
$project: ID!
|
|
||||||
$item: ID!
|
|
||||||
$status_field: ID!
|
|
||||||
$status_value: String!
|
|
||||||
) {
|
|
||||||
set_status: updateProjectNextItemField(input: {
|
|
||||||
projectId: $project
|
|
||||||
itemId: $item
|
|
||||||
fieldId: $status_field
|
|
||||||
value: $status_value
|
|
||||||
}) {
|
|
||||||
projectNextItem {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}' -f project=$PROJECT_ID -f item=$ITEM_ID -f status_field=$STATUS_FIELD_ID -f status_value=${{ env.INCOMING_OPTION_ID }} --silent
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "revolt-bonfire"
|
name = "revolt-bonfire"
|
||||||
version = "0.5.6"
|
version = "0.5.9"
|
||||||
license = "AGPL-3.0-or-later"
|
license = "AGPL-3.0-or-later"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "revolt-delta"
|
name = "revolt-delta"
|
||||||
version = "0.5.6"
|
version = "0.5.9"
|
||||||
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"
|
||||||
@@ -52,7 +52,7 @@ 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 = { version = "0.1.1", features = ["schema"] }
|
rocket_empty = { version = "0.1.1", features = ["schema"] }
|
||||||
rocket_rauth = { git = "https://github.com/insertish/rauth", tag = "1.0.4" }
|
rocket_authifier = { version = "1.0.7" }
|
||||||
|
|
||||||
# spec generation
|
# spec generation
|
||||||
schemars = "0.8.8"
|
schemars = "0.8.8"
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ pub mod routes;
|
|||||||
pub mod util;
|
pub mod util;
|
||||||
|
|
||||||
use async_std::channel::unbounded;
|
use async_std::channel::unbounded;
|
||||||
|
use revolt_quark::authifier::{Authifier, AuthifierEvent};
|
||||||
use revolt_quark::events::client::EventV1;
|
use revolt_quark::events::client::EventV1;
|
||||||
use revolt_quark::rauth::{RAuth, RAuthEvent};
|
|
||||||
use revolt_quark::DatabaseInfo;
|
use revolt_quark::DatabaseInfo;
|
||||||
use rocket::data::ToByteUnit;
|
use rocket::data::ToByteUnit;
|
||||||
|
|
||||||
@@ -28,25 +28,25 @@ 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 event channel
|
// Setup Authifier event channel
|
||||||
let (sender, receiver) = unbounded();
|
let (sender, receiver) = unbounded();
|
||||||
|
|
||||||
// Setup rAuth
|
// Setup Authifier
|
||||||
let rauth = RAuth {
|
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),
|
event_channel: Some(sender),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Launch a listener for rAuth events
|
// Launch a listener for Authifier events
|
||||||
async_std::task::spawn(async move {
|
async_std::task::spawn(async move {
|
||||||
while let Ok(event) = receiver.recv().await {
|
while let Ok(event) = receiver.recv().await {
|
||||||
match &event {
|
match &event {
|
||||||
RAuthEvent::CreateSession { .. } | RAuthEvent::CreateAccount { .. } => {
|
AuthifierEvent::CreateSession { .. } | AuthifierEvent::CreateAccount { .. } => {
|
||||||
EventV1::Auth(event).global().await
|
EventV1::Auth(event).global().await
|
||||||
}
|
}
|
||||||
RAuthEvent::DeleteSession { user_id, .. }
|
AuthifierEvent::DeleteSession { user_id, .. }
|
||||||
| RAuthEvent::DeleteAllSessions { user_id, .. } => {
|
| AuthifierEvent::DeleteAllSessions { user_id, .. } => {
|
||||||
let id = user_id.to_string();
|
let id = user_id.to_string();
|
||||||
EventV1::Auth(event).private(id).await
|
EventV1::Auth(event).private(id).await
|
||||||
}
|
}
|
||||||
@@ -66,7 +66,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)
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ mod invites;
|
|||||||
mod onboard;
|
mod onboard;
|
||||||
mod push;
|
mod push;
|
||||||
mod root;
|
mod root;
|
||||||
|
mod safety;
|
||||||
mod servers;
|
mod servers;
|
||||||
mod sync;
|
mod sync;
|
||||||
mod users;
|
mod users;
|
||||||
@@ -28,9 +29,10 @@ pub fn mount(mut rocket: Rocket<Build>) -> Rocket<Build> {
|
|||||||
"/servers" => servers::routes(),
|
"/servers" => servers::routes(),
|
||||||
"/invites" => invites::routes(),
|
"/invites" => invites::routes(),
|
||||||
"/custom" => customisation::routes(),
|
"/custom" => customisation::routes(),
|
||||||
"/auth/account" => rocket_rauth::routes::account::routes(),
|
"/safety" => safety::routes(),
|
||||||
"/auth/session" => rocket_rauth::routes::session::routes(),
|
"/auth/account" => rocket_authifier::routes::account::routes(),
|
||||||
"/auth/mfa" => rocket_rauth::routes::mfa::routes(),
|
"/auth/session" => rocket_authifier::routes::session::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(),
|
||||||
@@ -108,6 +110,12 @@ fn custom_openapi_spec() -> OpenApi {
|
|||||||
"Emojis"
|
"Emojis"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Platform Moderation",
|
||||||
|
"tags": [
|
||||||
|
"User Safety"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Authentication",
|
"name": "Authentication",
|
||||||
"tags": [
|
"tags": [
|
||||||
|
|||||||
@@ -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};
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -119,12 +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", "<failed to generate>").to_string(),
|
commit_sha: option_env!("VERGEN_GIT_SHA")
|
||||||
commit_timestamp: env!("VERGEN_GIT_COMMIT_TIMESTAMP", "<failed to generate>")
|
.unwrap_or_else(|| "<failed to generate>")
|
||||||
|
.to_string(),
|
||||||
|
commit_timestamp: option_env!("VERGEN_GIT_COMMIT_TIMESTAMP")
|
||||||
|
.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(),
|
.to_string(),
|
||||||
semver: env!("VERGEN_GIT_SEMVER", "<failed to generate>").to_string(),
|
|
||||||
origin_url: env!("GIT_ORIGIN_URL", "<failed to generate>").to_string(),
|
|
||||||
timestamp: env!("VERGEN_BUILD_TIMESTAMP", "<failed to generate>").to_string(),
|
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|||||||
11
crates/delta/src/routes/safety/mod.rs
Normal file
11
crates/delta/src/routes/safety/mod.rs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
use revolt_rocket_okapi::revolt_okapi::openapi3::OpenApi;
|
||||||
|
use rocket::Route;
|
||||||
|
|
||||||
|
mod report_content;
|
||||||
|
|
||||||
|
pub fn routes() -> (Vec<Route>, OpenApi) {
|
||||||
|
openapi_get_routes_spec![
|
||||||
|
// Reports
|
||||||
|
report_content::report_content
|
||||||
|
]
|
||||||
|
}
|
||||||
159
crates/delta/src/routes/safety/report_content.rs
Normal file
159
crates/delta/src/routes/safety/report_content.rs
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
use revolt_quark::events::client::EventV1;
|
||||||
|
use revolt_quark::models::report::ReportedContent;
|
||||||
|
use revolt_quark::models::snapshot::{Snapshot, SnapshotContent};
|
||||||
|
use revolt_quark::models::{Report, User};
|
||||||
|
use revolt_quark::{Db, Error, Result};
|
||||||
|
use serde::Deserialize;
|
||||||
|
use ulid::Ulid;
|
||||||
|
use validator::Validate;
|
||||||
|
|
||||||
|
use rocket::serde::json::Json;
|
||||||
|
|
||||||
|
/// # Report Data
|
||||||
|
#[derive(Validate, Deserialize, JsonSchema)]
|
||||||
|
pub struct DataReportContent {
|
||||||
|
/// Content being reported
|
||||||
|
content: ReportedContent,
|
||||||
|
/// Additional report description
|
||||||
|
#[validate(length(min = 0, max = 1000))]
|
||||||
|
#[serde(default)]
|
||||||
|
additional_context: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// # Report Content
|
||||||
|
///
|
||||||
|
/// Report a piece of content to the moderation team.
|
||||||
|
#[openapi(tag = "User Safety")]
|
||||||
|
#[post("/report", data = "<data>")]
|
||||||
|
pub async fn report_content(db: &Db, user: User, data: Json<DataReportContent>) -> Result<()> {
|
||||||
|
let data = data.into_inner();
|
||||||
|
data.validate()
|
||||||
|
.map_err(|error| Error::FailedValidation { error })?;
|
||||||
|
|
||||||
|
// Bots cannot create reports
|
||||||
|
if user.bot.is_some() {
|
||||||
|
return Err(Error::IsBot);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the content and create a snapshot of it
|
||||||
|
// Also retrieve any references to Files
|
||||||
|
let (content, files): (SnapshotContent, Vec<String>) = match &data.content {
|
||||||
|
ReportedContent::Message { id, .. } => {
|
||||||
|
let message = db.fetch_message(id).await?;
|
||||||
|
|
||||||
|
// Users cannot report themselves
|
||||||
|
if message.author == user.id {
|
||||||
|
return Err(Error::CannotReportYourself);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect message attachments
|
||||||
|
let files = message
|
||||||
|
.attachments
|
||||||
|
.as_ref()
|
||||||
|
.map(|attachments| attachments.iter().map(|x| x.id.to_string()).collect())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
// Collect prior context
|
||||||
|
let prior_context = db
|
||||||
|
.fetch_messages(
|
||||||
|
&message.channel,
|
||||||
|
Some(15),
|
||||||
|
Some(message.id.to_string()),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
// Collect leading context
|
||||||
|
let leading_context = db
|
||||||
|
.fetch_messages(
|
||||||
|
&message.channel,
|
||||||
|
Some(15),
|
||||||
|
None,
|
||||||
|
Some(message.id.to_string()),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
(
|
||||||
|
SnapshotContent::Message {
|
||||||
|
message,
|
||||||
|
prior_context,
|
||||||
|
leading_context,
|
||||||
|
},
|
||||||
|
files,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
ReportedContent::Server { id, .. } => {
|
||||||
|
let server = db.fetch_server(id).await?;
|
||||||
|
|
||||||
|
// Users cannot report their own server
|
||||||
|
if server.owner == user.id {
|
||||||
|
return Err(Error::CannotReportYourself);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect server's icon and banner
|
||||||
|
let files = [&server.icon, &server.banner]
|
||||||
|
.iter()
|
||||||
|
.filter_map(|x| x.as_ref().map(|x| x.id.to_string()))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
(SnapshotContent::Server(server), files)
|
||||||
|
}
|
||||||
|
ReportedContent::User { id, .. } => {
|
||||||
|
let reported_user = db.fetch_user(id).await?;
|
||||||
|
|
||||||
|
// Users cannot report themselves
|
||||||
|
if reported_user.id == user.id {
|
||||||
|
return Err(Error::CannotReportYourself);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect user's avatar and profile background
|
||||||
|
let files = [
|
||||||
|
reported_user.avatar.as_ref(),
|
||||||
|
reported_user
|
||||||
|
.profile
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|profile| profile.background.as_ref()),
|
||||||
|
]
|
||||||
|
.iter()
|
||||||
|
.filter_map(|x| x.as_ref().map(|x| x.id.to_string()))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
(SnapshotContent::User(reported_user), files)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Mark all the attachments as reported
|
||||||
|
for file in files {
|
||||||
|
db.mark_attachment_as_reported(&file).await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate an id for the report
|
||||||
|
let id = Ulid::new().to_string();
|
||||||
|
|
||||||
|
// Save a snapshot of the content
|
||||||
|
let snapshot = Snapshot {
|
||||||
|
id: Ulid::new().to_string(),
|
||||||
|
report_id: id.to_string(),
|
||||||
|
content,
|
||||||
|
};
|
||||||
|
|
||||||
|
db.insert_snapshot(&snapshot).await?;
|
||||||
|
|
||||||
|
// Save the report
|
||||||
|
let report = Report {
|
||||||
|
id,
|
||||||
|
author_id: user.id,
|
||||||
|
content: data.content,
|
||||||
|
additional_context: data.additional_context,
|
||||||
|
};
|
||||||
|
|
||||||
|
db.insert_report(&report).await?;
|
||||||
|
|
||||||
|
EventV1::ReportCreate(report).global().await;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
|||||||
2
crates/quark/.github/FUNDING.yml
vendored
2
crates/quark/.github/FUNDING.yml
vendored
@@ -1,2 +0,0 @@
|
|||||||
ko_fi: insertish
|
|
||||||
custom: https://insrt.uk/donate
|
|
||||||
33
crates/quark/.github/workflows/rust.yaml
vendored
33
crates/quark/.github/workflows/rust.yaml
vendored
@@ -1,33 +0,0 @@
|
|||||||
name: Rust build and test
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ master ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ master ]
|
|
||||||
|
|
||||||
env:
|
|
||||||
CARGO_TERM_COLOR: always
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
check:
|
|
||||||
name: Rust project
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Install latest nightly
|
|
||||||
uses: actions-rs/toolchain@v1
|
|
||||||
with:
|
|
||||||
toolchain: nightly
|
|
||||||
override: true
|
|
||||||
components: rustfmt, clippy
|
|
||||||
|
|
||||||
- name: Run cargo build
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: build
|
|
||||||
|
|
||||||
- name: Run cargo test
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: test
|
|
||||||
49
crates/quark/.github/workflows/triage_issue.yml
vendored
49
crates/quark/.github/workflows/triage_issue.yml
vendored
@@ -1,49 +0,0 @@
|
|||||||
name: Add Issue to Board
|
|
||||||
|
|
||||||
on:
|
|
||||||
issues:
|
|
||||||
types: [opened]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
track_issue:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Get project data
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.PAT }}
|
|
||||||
run: |
|
|
||||||
gh api graphql -f query='
|
|
||||||
query {
|
|
||||||
organization(login: "revoltchat"){
|
|
||||||
projectNext(number: 3) {
|
|
||||||
id
|
|
||||||
fields(first:20) {
|
|
||||||
nodes {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
settings
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}' > project_data.json
|
|
||||||
|
|
||||||
echo 'PROJECT_ID='$(jq '.data.organization.projectNext.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 'TODO_OPTION_ID='$(jq '.data.organization.projectNext.fields.nodes[] | select(.name== "Status") |.settings | fromjson.options[] | select(.name=="Todo") |.id' project_data.json) >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Add issue to project
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.PAT }}
|
|
||||||
ISSUE_ID: ${{ github.event.issue.node_id }}
|
|
||||||
run: |
|
|
||||||
item_id="$( gh api graphql -f query='
|
|
||||||
mutation($project:ID!, $issue:ID!) {
|
|
||||||
addProjectNextItem(input: {projectId: $project, contentId: $issue}) {
|
|
||||||
projectNextItem {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}' -f project=$PROJECT_ID -f issue=$ISSUE_ID --jq '.data.addProjectNextItem.projectNextItem.id')"
|
|
||||||
|
|
||||||
echo 'ITEM_ID='$item_id >> $GITHUB_ENV
|
|
||||||
72
crates/quark/.github/workflows/triage_pr.yml
vendored
72
crates/quark/.github/workflows/triage_pr.yml
vendored
@@ -1,72 +0,0 @@
|
|||||||
name: Add PR to Board
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request_target:
|
|
||||||
types: [opened, synchronize, ready_for_review, review_requested]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
track_pr:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Get project data
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.PAT }}
|
|
||||||
run: |
|
|
||||||
gh api graphql -f query='
|
|
||||||
query {
|
|
||||||
organization(login: "revoltchat"){
|
|
||||||
projectNext(number: 3) {
|
|
||||||
id
|
|
||||||
fields(first:20) {
|
|
||||||
nodes {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
settings
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}' > project_data.json
|
|
||||||
|
|
||||||
echo 'PROJECT_ID='$(jq '.data.organization.projectNext.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 '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
|
|
||||||
|
|
||||||
- name: Add PR to project
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.PAT }}
|
|
||||||
PR_ID: ${{ github.event.pull_request.node_id }}
|
|
||||||
run: |
|
|
||||||
item_id="$( gh api graphql -f query='
|
|
||||||
mutation($project:ID!, $pr:ID!) {
|
|
||||||
addProjectNextItem(input: {projectId: $project, contentId: $pr}) {
|
|
||||||
projectNextItem {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}' -f project=$PROJECT_ID -f pr=$PR_ID --jq '.data.addProjectNextItem.projectNextItem.id')"
|
|
||||||
|
|
||||||
echo 'ITEM_ID='$item_id >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Set fields
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.PAT }}
|
|
||||||
run: |
|
|
||||||
gh api graphql -f query='
|
|
||||||
mutation (
|
|
||||||
$project: ID!
|
|
||||||
$item: ID!
|
|
||||||
$status_field: ID!
|
|
||||||
$status_value: String!
|
|
||||||
) {
|
|
||||||
set_status: updateProjectNextItemField(input: {
|
|
||||||
projectId: $project
|
|
||||||
itemId: $item
|
|
||||||
fieldId: $status_field
|
|
||||||
value: $status_value
|
|
||||||
}) {
|
|
||||||
projectNextItem {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}' -f project=$PROJECT_ID -f item=$ITEM_ID -f status_field=$STATUS_FIELD_ID -f status_value=${{ env.INCOMING_OPTION_ID }} --silent
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "revolt-quark"
|
name = "revolt-quark"
|
||||||
version = "0.5.6"
|
version = "0.5.9"
|
||||||
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" ]
|
||||||
@@ -84,8 +84,8 @@ rocket = { optional = true, version = "0.5.0-rc.2", default-features = false, fe
|
|||||||
rocket_empty = { version = "0.1.1", optional = true, features = [ "schema" ] }
|
rocket_empty = { version = "0.1.1", optional = true, features = [ "schema" ] }
|
||||||
rocket_cors = { optional = true, git = "https://github.com/lawliet89/rocket_cors", rev = "c17e8145baa4790319fdb6a473e465b960f55e7c" }
|
rocket_cors = { optional = true, git = "https://github.com/lawliet89/rocket_cors", rev = "c17e8145baa4790319fdb6a473e465b960f55e7c" }
|
||||||
|
|
||||||
# rAuth
|
# Authifier
|
||||||
rauth = { git = "https://github.com/insertish/rauth", tag = "1.0.4", features = [ "async-std-runtime" ] }
|
authifier = { version = "1.0.7", features = [ "async-std-runtime" ] }
|
||||||
|
|
||||||
# Sentry
|
# Sentry
|
||||||
sentry = "0.25.0"
|
sentry = "0.25.0"
|
||||||
|
|||||||
@@ -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")),
|
||||||
}
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use rauth::RAuthEvent;
|
use authifier::AuthifierEvent;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::models::channel::{FieldsChannel, PartialChannel};
|
use crate::models::channel::{FieldsChannel, PartialChannel};
|
||||||
@@ -7,7 +7,7 @@ use crate::models::message::{AppendMessage, PartialMessage};
|
|||||||
use crate::models::server::{FieldsRole, FieldsServer, PartialRole, PartialServer};
|
use crate::models::server::{FieldsRole, FieldsServer, PartialRole, PartialServer};
|
||||||
use crate::models::server_member::{FieldsMember, MemberCompositeKey, PartialMember};
|
use crate::models::server_member::{FieldsMember, MemberCompositeKey, PartialMember};
|
||||||
use crate::models::user::{FieldsUser, PartialUser, RelationshipStatus};
|
use crate::models::user::{FieldsUser, PartialUser, RelationshipStatus};
|
||||||
use crate::models::{Channel, Emoji, Member, Message, Server, User, UserSettings, Webhook};
|
use crate::models::{Channel, Emoji, Member, Message, Server, User, UserSettings, Webhook, Report};
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
/// WebSocket Client Errors
|
/// WebSocket Client Errors
|
||||||
@@ -229,6 +229,9 @@ pub enum EventV1 {
|
|||||||
id: String
|
id: String
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/// New report
|
||||||
|
ReportCreate(Report),
|
||||||
|
|
||||||
/// Auth events
|
/// Auth events
|
||||||
Auth(RAuthEvent),
|
Auth(AuthifierEvent),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,11 @@ pub mod users {
|
|||||||
pub mod user_settings;
|
pub mod user_settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub mod safety {
|
||||||
|
pub mod report;
|
||||||
|
pub mod snapshot;
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct DummyDb;
|
pub struct DummyDb;
|
||||||
|
|
||||||
|
|||||||
12
crates/quark/src/impl/dummy/safety/report.rs
Normal file
12
crates/quark/src/impl/dummy/safety/report.rs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
use crate::models::Report;
|
||||||
|
use crate::{AbstractReport, Result};
|
||||||
|
|
||||||
|
use super::super::DummyDb;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl AbstractReport for DummyDb {
|
||||||
|
async fn insert_report(&self, report: &Report) -> Result<()> {
|
||||||
|
info!("Insert {:?}", report);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
12
crates/quark/src/impl/dummy/safety/snapshot.rs
Normal file
12
crates/quark/src/impl/dummy/safety/snapshot.rs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
use crate::models::Snapshot;
|
||||||
|
use crate::{AbstractSnapshot, Result};
|
||||||
|
|
||||||
|
use super::super::DummyDb;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl AbstractSnapshot for DummyDb {
|
||||||
|
async fn insert_snapshot(&self, snapshot: &Snapshot) -> Result<()> {
|
||||||
|
info!("Insert {:?}", snapshot);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,11 @@ pub mod users {
|
|||||||
pub mod user_settings;
|
pub mod user_settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub mod safety {
|
||||||
|
pub mod report;
|
||||||
|
pub mod snapshot;
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct MongoDb(pub mongodb::Client);
|
pub struct MongoDb(pub mongodb::Client);
|
||||||
|
|
||||||
|
|||||||
13
crates/quark/src/impl/mongo/safety/report.rs
Normal file
13
crates/quark/src/impl/mongo/safety/report.rs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
use crate::models::Report;
|
||||||
|
use crate::{AbstractReport, Result};
|
||||||
|
|
||||||
|
use super::super::MongoDb;
|
||||||
|
|
||||||
|
static COL: &str = "safety_reports";
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl AbstractReport for MongoDb {
|
||||||
|
async fn insert_report(&self, report: &Report) -> Result<()> {
|
||||||
|
self.insert_one(COL, report).await.map(|_| ())
|
||||||
|
}
|
||||||
|
}
|
||||||
13
crates/quark/src/impl/mongo/safety/snapshot.rs
Normal file
13
crates/quark/src/impl/mongo/safety/snapshot.rs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
use crate::models::Snapshot;
|
||||||
|
use crate::{AbstractSnapshot, Result};
|
||||||
|
|
||||||
|
use super::super::MongoDb;
|
||||||
|
|
||||||
|
static COL: &str = "safety_snapshots";
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl AbstractSnapshot for MongoDb {
|
||||||
|
async fn insert_snapshot(&self, snapshot: &Snapshot) -> Result<()> {
|
||||||
|
self.insert_one(COL, snapshot).await.map(|_| ())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
use rauth::models::Session;
|
use authifier::models::Session;
|
||||||
use revolt_okapi::openapi3::{SecurityScheme, SecuritySchemeData};
|
use revolt_okapi::openapi3::{SecurityScheme, SecuritySchemeData};
|
||||||
use revolt_rocket_okapi::gen::OpenApiGenerator;
|
use revolt_rocket_okapi::gen::OpenApiGenerator;
|
||||||
use revolt_rocket_okapi::request::{OpenApiFromRequest, RequestHeaderInput};
|
use revolt_rocket_okapi::request::{OpenApiFromRequest, RequestHeaderInput};
|
||||||
@@ -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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -28,9 +28,15 @@ mod users {
|
|||||||
pub mod user_settings;
|
pub mod user_settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod safety {
|
||||||
|
pub mod report;
|
||||||
|
pub mod snapshot;
|
||||||
|
}
|
||||||
|
|
||||||
pub use admin::*;
|
pub use admin::*;
|
||||||
pub use channels::*;
|
pub use channels::*;
|
||||||
pub use media::*;
|
pub use media::*;
|
||||||
|
pub use safety::*;
|
||||||
pub use servers::*;
|
pub use servers::*;
|
||||||
pub use users::*;
|
pub use users::*;
|
||||||
|
|
||||||
@@ -42,10 +48,12 @@ pub use channel_unread::ChannelUnread;
|
|||||||
pub use emoji::Emoji;
|
pub use emoji::Emoji;
|
||||||
pub use message::Message;
|
pub use message::Message;
|
||||||
pub use migrations::MigrationInfo;
|
pub use migrations::MigrationInfo;
|
||||||
|
pub use report::Report;
|
||||||
pub use server::Server;
|
pub use server::Server;
|
||||||
pub use server_ban::ServerBan;
|
pub use server_ban::ServerBan;
|
||||||
pub use server_member::Member;
|
pub use server_member::Member;
|
||||||
pub use simple::SimpleModel;
|
pub use simple::SimpleModel;
|
||||||
|
pub use snapshot::Snapshot;
|
||||||
pub use user::User;
|
pub use user::User;
|
||||||
pub use user_settings::UserSettings;
|
pub use user_settings::UserSettings;
|
||||||
pub use webhook::Webhook;
|
pub use webhook::Webhook;
|
||||||
|
|||||||
85
crates/quark/src/models/safety/report.rs
Normal file
85
crates/quark/src/models/safety/report.rs
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
/// Reason for reporting content (message or server)
|
||||||
|
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone)]
|
||||||
|
pub enum ContentReportReason {
|
||||||
|
/// No reason has been specified
|
||||||
|
NoneSpecified,
|
||||||
|
|
||||||
|
/// Blatantly illegal content
|
||||||
|
Illegal,
|
||||||
|
|
||||||
|
/// Content that promotes harm to others / self
|
||||||
|
PromotesHarm,
|
||||||
|
|
||||||
|
/// Spam or platform abuse
|
||||||
|
SpamAbuse,
|
||||||
|
|
||||||
|
/// Distribution of malware
|
||||||
|
Malware,
|
||||||
|
|
||||||
|
/// Harassment or abuse targeted at another user
|
||||||
|
Harassment,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reason for reporting a user
|
||||||
|
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone)]
|
||||||
|
pub enum UserReportReason {
|
||||||
|
/// No reason has been specified
|
||||||
|
NoneSpecified,
|
||||||
|
|
||||||
|
/// User is sending spam or otherwise abusing the platform
|
||||||
|
SpamAbuse,
|
||||||
|
|
||||||
|
/// User's profile contains inappropriate content for a general audience
|
||||||
|
InappropriateProfile,
|
||||||
|
|
||||||
|
/// User is impersonating another user
|
||||||
|
Impersonation,
|
||||||
|
|
||||||
|
/// User is evading a ban
|
||||||
|
BanEvasion,
|
||||||
|
|
||||||
|
/// User is not of minimum age to use the platform
|
||||||
|
Underage,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone)]
|
||||||
|
#[serde(tag = "type")]
|
||||||
|
pub enum ReportedContent {
|
||||||
|
/// Report a message
|
||||||
|
Message {
|
||||||
|
/// ID of the message
|
||||||
|
id: String,
|
||||||
|
/// Reason for reporting message
|
||||||
|
report_reason: ContentReportReason,
|
||||||
|
},
|
||||||
|
/// Report a server
|
||||||
|
Server {
|
||||||
|
/// ID of the server
|
||||||
|
id: String,
|
||||||
|
/// Reason for reporting server
|
||||||
|
report_reason: ContentReportReason,
|
||||||
|
},
|
||||||
|
/// Report a user
|
||||||
|
User {
|
||||||
|
/// ID of the user
|
||||||
|
id: String,
|
||||||
|
/// Reason for reporting a user
|
||||||
|
report_reason: UserReportReason,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/// User-generated platform moderation report.
|
||||||
|
#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone)]
|
||||||
|
pub struct Report {
|
||||||
|
/// Unique Id
|
||||||
|
#[serde(rename = "_id")]
|
||||||
|
pub id: String,
|
||||||
|
/// Id of the user creating this report
|
||||||
|
pub author_id: String,
|
||||||
|
/// Reported content
|
||||||
|
pub content: ReportedContent,
|
||||||
|
/// Additional report context
|
||||||
|
pub additional_context: String,
|
||||||
|
}
|
||||||
37
crates/quark/src/models/safety/snapshot.rs
Normal file
37
crates/quark/src/models/safety/snapshot.rs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::models::{Message, Server, User};
|
||||||
|
|
||||||
|
/// Enum to map into different models
|
||||||
|
/// that can be saved in a snapshot
|
||||||
|
#[derive(Serialize, Deserialize, JsonSchema, Debug)]
|
||||||
|
#[serde(tag = "_type")]
|
||||||
|
pub enum SnapshotContent {
|
||||||
|
Message {
|
||||||
|
/// Context before the message
|
||||||
|
#[serde(rename = "_prior_context")]
|
||||||
|
prior_context: Vec<Message>,
|
||||||
|
|
||||||
|
/// Context after the message
|
||||||
|
#[serde(rename = "_leading_context")]
|
||||||
|
leading_context: Vec<Message>,
|
||||||
|
|
||||||
|
/// Message
|
||||||
|
#[serde(flatten)]
|
||||||
|
message: Message,
|
||||||
|
},
|
||||||
|
Server(Server),
|
||||||
|
User(User),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Snapshot of some content
|
||||||
|
#[derive(Serialize, Deserialize, JsonSchema, Debug)]
|
||||||
|
pub struct Snapshot {
|
||||||
|
/// Unique Id
|
||||||
|
#[serde(rename = "_id")]
|
||||||
|
pub id: String,
|
||||||
|
/// Report parent Id
|
||||||
|
pub report_id: String,
|
||||||
|
/// Snapshot of content
|
||||||
|
pub content: SnapshotContent,
|
||||||
|
}
|
||||||
@@ -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,
|
||||||
|
|||||||
@@ -27,6 +27,11 @@ mod users {
|
|||||||
pub mod user_settings;
|
pub mod user_settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod safety {
|
||||||
|
pub mod report;
|
||||||
|
pub mod snapshot;
|
||||||
|
}
|
||||||
|
|
||||||
pub use admin::migrations::AbstractMigrations;
|
pub use admin::migrations::AbstractMigrations;
|
||||||
|
|
||||||
pub use media::attachment::AbstractAttachment;
|
pub use media::attachment::AbstractAttachment;
|
||||||
@@ -46,6 +51,9 @@ pub use users::bot::AbstractBot;
|
|||||||
pub use users::user::AbstractUser;
|
pub use users::user::AbstractUser;
|
||||||
pub use users::user_settings::AbstractUserSettings;
|
pub use users::user_settings::AbstractUserSettings;
|
||||||
|
|
||||||
|
pub use safety::report::AbstractReport;
|
||||||
|
pub use safety::snapshot::AbstractSnapshot;
|
||||||
|
|
||||||
pub trait AbstractDatabase:
|
pub trait AbstractDatabase:
|
||||||
Sync
|
Sync
|
||||||
+ Send
|
+ Send
|
||||||
@@ -63,5 +71,7 @@ pub trait AbstractDatabase:
|
|||||||
+ AbstractUser
|
+ AbstractUser
|
||||||
+ AbstractUserSettings
|
+ AbstractUserSettings
|
||||||
+ AbstractWebhook
|
+ AbstractWebhook
|
||||||
|
+ AbstractReport
|
||||||
|
+ AbstractSnapshot
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
8
crates/quark/src/traits/safety/report.rs
Normal file
8
crates/quark/src/traits/safety/report.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
use crate::models::Report;
|
||||||
|
use crate::Result;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
pub trait AbstractReport: Sync + Send {
|
||||||
|
/// Insert a new report into the database
|
||||||
|
async fn insert_report(&self, report: &Report) -> Result<()>;
|
||||||
|
}
|
||||||
8
crates/quark/src/traits/safety/snapshot.rs
Normal file
8
crates/quark/src/traits/safety/snapshot.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
use crate::models::Snapshot;
|
||||||
|
use crate::Result;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
pub trait AbstractSnapshot: Sync + Send {
|
||||||
|
/// Insert a new snapshot into the database
|
||||||
|
async fn insert_snapshot(&self, snapshot: &Snapshot) -> Result<()>;
|
||||||
|
}
|
||||||
@@ -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
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -64,6 +64,9 @@ pub enum Error {
|
|||||||
IsBot,
|
IsBot,
|
||||||
BotIsPrivate,
|
BotIsPrivate,
|
||||||
|
|
||||||
|
// ? User safety related errors
|
||||||
|
CannotReportYourself,
|
||||||
|
|
||||||
// ? Permission errors
|
// ? Permission errors
|
||||||
MissingPermission {
|
MissingPermission {
|
||||||
permission: Permission,
|
permission: Permission,
|
||||||
@@ -166,6 +169,8 @@ impl<'r> Responder<'r, 'static> for Error {
|
|||||||
Error::IsBot => Status::BadRequest,
|
Error::IsBot => Status::BadRequest,
|
||||||
Error::BotIsPrivate => Status::Forbidden,
|
Error::BotIsPrivate => Status::Forbidden,
|
||||||
|
|
||||||
|
Error::CannotReportYourself => Status::BadRequest,
|
||||||
|
|
||||||
Error::MissingPermission { .. } => Status::Forbidden,
|
Error::MissingPermission { .. } => Status::Forbidden,
|
||||||
Error::MissingUserPermission { .. } => Status::Forbidden,
|
Error::MissingUserPermission { .. } => Status::Forbidden,
|
||||||
Error::NotElevated => Status::Forbidden,
|
Error::NotElevated => Status::Forbidden,
|
||||||
|
|||||||
@@ -30,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");
|
||||||
|
|||||||
@@ -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};
|
||||||
@@ -129,6 +129,8 @@ fn resolve_bucket<'r>(request: &'r rocket::Request<'_>) -> (&'r str, Option<&'r
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
("swagger", _) => ("swagger", None),
|
("swagger", _) => ("swagger", None),
|
||||||
|
("safety", Some("report")) => ("safety_report", Some("report")),
|
||||||
|
("safety", _) => ("safety", None),
|
||||||
_ => ("any", None),
|
_ => ("any", None),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -148,6 +150,8 @@ fn resolve_bucket_limit(bucket: &str) -> u8 {
|
|||||||
"auth_delete" => 255,
|
"auth_delete" => 255,
|
||||||
"default_avatar" => 255,
|
"default_avatar" => 255,
|
||||||
"swagger" => 100,
|
"swagger" => 100,
|
||||||
|
"safety" => 15,
|
||||||
|
"safety_report" => 3,
|
||||||
_ => 20,
|
_ => 20,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user