Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c020ef97ab | ||
|
|
e346464720 | ||
|
|
3ab5fda21d | ||
|
|
9e17a5e73a | ||
|
|
c7f09ab9d0 |
+69
-121
@@ -2,13 +2,24 @@ name: Docker Test & Publish
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
# branches:
|
||||||
|
# - "main"
|
||||||
tags:
|
tags:
|
||||||
- "*"
|
- "*"
|
||||||
|
paths-ignore:
|
||||||
|
- ".github/**"
|
||||||
|
- "!.github/workflows/docker.yml"
|
||||||
|
- ".vscode/**"
|
||||||
|
- "doc/**"
|
||||||
|
- ".gitignore"
|
||||||
|
- "LICENSE"
|
||||||
|
- "README"
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- "main"
|
- "main"
|
||||||
paths:
|
paths:
|
||||||
- "Dockerfile"
|
- "Dockerfile"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
@@ -16,9 +27,8 @@ permissions:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
base:
|
base:
|
||||||
name: Test base image build
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: github.event_name == 'pull_request'
|
name: Build base image
|
||||||
steps:
|
steps:
|
||||||
# Configure build environment
|
# Configure build environment
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -26,21 +36,33 @@ jobs:
|
|||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v2
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
# Build the image
|
# Authenticate with GHCR
|
||||||
|
- name: Login to Github Container Registry
|
||||||
|
if: ${{ github.event_name != 'pull_request' }}
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Build base image
|
- name: Build base image
|
||||||
uses: docker/build-push-action@v4
|
uses: docker/build-push-action@v4
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
push: false
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
tags: ghcr.io/${{ github.repository_owner }}/base:latest
|
tags: ghcr.io/${{ github.repository_owner }}/base:latest
|
||||||
cache-from: type=gha,scope=buildx-base-multi-arch
|
cache-from: type=gha,scope=buildx-base-multi-arch
|
||||||
cache-to: type=gha,scope=buildx-base-multi-arch,mode=max
|
cache-to: type=gha,scope=buildx-base-multi-arch,mode=max
|
||||||
|
|
||||||
publish:
|
publish:
|
||||||
runs-on: self-hosted
|
needs: [base]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
if: github.event_name != 'pull_request'
|
if: github.event_name != 'pull_request'
|
||||||
name: Publish Docker images
|
strategy:
|
||||||
|
matrix:
|
||||||
|
project: [delta, bonfire, autumn, january, pushd]
|
||||||
|
name: Build ${{ matrix.project }} image
|
||||||
steps:
|
steps:
|
||||||
# Configure build environment
|
# Configure build environment
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -55,7 +77,6 @@ jobs:
|
|||||||
registry: docker.io
|
registry: docker.io
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Login to Github Container Registry
|
- name: Login to Github Container Registry
|
||||||
uses: docker/login-action@v2
|
uses: docker/login-action@v2
|
||||||
with:
|
with:
|
||||||
@@ -63,131 +84,58 @@ jobs:
|
|||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
# Build the image
|
# Resolve the correct project
|
||||||
- name: Build base image
|
- uses: kanga333/variable-mapper@master
|
||||||
uses: docker/build-push-action@v4
|
id: export
|
||||||
with:
|
with:
|
||||||
context: .
|
key: "${{ matrix.project }}"
|
||||||
push: true
|
map: |
|
||||||
platforms: linux/amd64,linux/arm64
|
{
|
||||||
tags: ghcr.io/${{ github.repository_owner }}/base:latest
|
"delta": {
|
||||||
|
"path": "crates/delta",
|
||||||
|
"tag": "${{ github.repository_owner }}/server"
|
||||||
|
},
|
||||||
|
"bonfire": {
|
||||||
|
"path": "crates/bonfire",
|
||||||
|
"tag": "${{ github.repository_owner }}/bonfire"
|
||||||
|
},
|
||||||
|
"autumn": {
|
||||||
|
"path": "crates/services/autumn",
|
||||||
|
"tag": "${{ github.repository_owner }}/autumn"
|
||||||
|
},
|
||||||
|
"january": {
|
||||||
|
"path": "crates/services/january",
|
||||||
|
"tag": "${{ github.repository_owner }}/january"
|
||||||
|
},
|
||||||
|
"pushd": {
|
||||||
|
"path": "crates/daemons/pushd",
|
||||||
|
"tag": "${{ github.repository_owner }}/pushd"
|
||||||
|
},
|
||||||
|
"crond": {
|
||||||
|
"path": "crates/daemons/crond",
|
||||||
|
"tag": "${{ github.repository_owner }}/crond"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export_to: output
|
||||||
|
|
||||||
# revoltchat/server
|
# Configure metadata
|
||||||
- name: Docker meta
|
- name: Docker meta
|
||||||
id: meta-delta
|
id: meta
|
||||||
uses: docker/metadata-action@v4
|
uses: docker/metadata-action@v4
|
||||||
with:
|
with:
|
||||||
images: |
|
images: |
|
||||||
docker.io/revoltchat/server
|
docker.io/${{ steps.export.outputs.tag }}
|
||||||
ghcr.io/revoltchat/server
|
ghcr.io/${{ steps.export.outputs.tag }}
|
||||||
|
|
||||||
|
# Build crate image
|
||||||
- name: Publish
|
- name: Publish
|
||||||
uses: docker/build-push-action@v4
|
uses: docker/build-push-action@v4
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
push: true
|
push: true
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
file: crates/delta/Dockerfile
|
file: ${{ steps.export.outputs.path }}/Dockerfile
|
||||||
tags: ${{ steps.meta-delta.outputs.tags }}
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
build-args: |
|
build-args: |
|
||||||
BASE_IMAGE=ghcr.io/${{ github.repository_owner }}/base:latest
|
BASE_IMAGE=ghcr.io/${{ github.repository_owner }}/base:latest
|
||||||
labels: ${{ steps.meta-delta.outputs.labels }}
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
|
||||||
# revoltchat/bonfire
|
|
||||||
- name: Docker meta
|
|
||||||
id: meta-bonfire
|
|
||||||
uses: docker/metadata-action@v4
|
|
||||||
with:
|
|
||||||
images: |
|
|
||||||
docker.io/revoltchat/bonfire
|
|
||||||
ghcr.io/revoltchat/bonfire
|
|
||||||
- name: Publish
|
|
||||||
uses: docker/build-push-action@v4
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
push: true
|
|
||||||
platforms: linux/amd64,linux/arm64
|
|
||||||
file: crates/bonfire/Dockerfile
|
|
||||||
tags: ${{ steps.meta-bonfire.outputs.tags }}
|
|
||||||
build-args: |
|
|
||||||
BASE_IMAGE=ghcr.io/${{ github.repository_owner }}/base:latest
|
|
||||||
labels: ${{ steps.meta-bonfire.outputs.labels }}
|
|
||||||
|
|
||||||
# revoltchat/autumn
|
|
||||||
- name: Docker meta
|
|
||||||
id: meta-autumn
|
|
||||||
uses: docker/metadata-action@v4
|
|
||||||
with:
|
|
||||||
images: |
|
|
||||||
docker.io/revoltchat/autumn
|
|
||||||
ghcr.io/revoltchat/autumn
|
|
||||||
- name: Publish
|
|
||||||
uses: docker/build-push-action@v4
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
push: true
|
|
||||||
platforms: linux/amd64,linux/arm64
|
|
||||||
file: crates/services/autumn/Dockerfile
|
|
||||||
tags: ${{ steps.meta-autumn.outputs.tags }}
|
|
||||||
build-args: |
|
|
||||||
BASE_IMAGE=ghcr.io/${{ github.repository_owner }}/base:latest
|
|
||||||
labels: ${{ steps.meta-autumn.outputs.labels }}
|
|
||||||
|
|
||||||
# revoltchat/january
|
|
||||||
- name: Docker meta
|
|
||||||
id: meta-january
|
|
||||||
uses: docker/metadata-action@v4
|
|
||||||
with:
|
|
||||||
images: |
|
|
||||||
docker.io/revoltchat/january
|
|
||||||
ghcr.io/revoltchat/january
|
|
||||||
- name: Publish
|
|
||||||
uses: docker/build-push-action@v4
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
push: true
|
|
||||||
platforms: linux/amd64,linux/arm64
|
|
||||||
file: crates/services/january/Dockerfile
|
|
||||||
tags: ${{ steps.meta-january.outputs.tags }}
|
|
||||||
build-args: |
|
|
||||||
BASE_IMAGE=ghcr.io/${{ github.repository_owner }}/base:latest
|
|
||||||
labels: ${{ steps.meta-january.outputs.labels }}
|
|
||||||
|
|
||||||
# revoltchat/crond
|
|
||||||
- name: Docker meta
|
|
||||||
id: meta-crond
|
|
||||||
uses: docker/metadata-action@v4
|
|
||||||
with:
|
|
||||||
images: |
|
|
||||||
docker.io/revoltchat/crond
|
|
||||||
ghcr.io/revoltchat/crond
|
|
||||||
- name: Publish
|
|
||||||
uses: docker/build-push-action@v4
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
push: true
|
|
||||||
platforms: linux/amd64,linux/arm64
|
|
||||||
file: crates/daemons/crond/Dockerfile
|
|
||||||
tags: ${{ steps.meta-crond.outputs.tags }}
|
|
||||||
build-args: |
|
|
||||||
BASE_IMAGE=ghcr.io/${{ github.repository_owner }}/base:latest
|
|
||||||
labels: ${{ steps.meta-crond.outputs.labels }}
|
|
||||||
|
|
||||||
# revoltchat/pushd
|
|
||||||
- name: Docker meta
|
|
||||||
id: meta-pushd
|
|
||||||
uses: docker/metadata-action@v4
|
|
||||||
with:
|
|
||||||
images: |
|
|
||||||
docker.io/revoltchat/pushd
|
|
||||||
ghcr.io/revoltchat/pushd
|
|
||||||
- name: Publish
|
|
||||||
uses: docker/build-push-action@v4
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
push: true
|
|
||||||
platforms: linux/amd64,linux/arm64
|
|
||||||
file: crates/daemons/pushd/Dockerfile
|
|
||||||
tags: ${{ steps.meta-pushd.outputs.tags }}
|
|
||||||
build-args: |
|
|
||||||
BASE_IMAGE=ghcr.io/${{ github.repository_owner }}/base:latest
|
|
||||||
labels: ${{ steps.meta-pushd.outputs.labels }}
|
|
||||||
|
|||||||
Generated
+134
-25
@@ -443,9 +443,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "authifier"
|
name = "authifier"
|
||||||
version = "1.0.13"
|
version = "1.0.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ca26cb6b5ab776a1de5a8122fe6cc77fadd84fed30704c496f2aca451637877b"
|
checksum = "edfe88c4a9fcf24b18a216b27c9766966af2a40603d24c7782237afd6ca0d5cd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-std",
|
"async-std",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@@ -454,7 +454,7 @@ dependencies = [
|
|||||||
"chrono",
|
"chrono",
|
||||||
"futures",
|
"futures",
|
||||||
"handlebars",
|
"handlebars",
|
||||||
"iso8601-timestamp",
|
"iso8601-timestamp 0.1.11",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"lettre",
|
"lettre",
|
||||||
"log",
|
"log",
|
||||||
@@ -470,7 +470,6 @@ dependencies = [
|
|||||||
"schemars",
|
"schemars",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sha1",
|
|
||||||
"totp-lite",
|
"totp-lite",
|
||||||
"ulid 0.5.0",
|
"ulid 0.5.0",
|
||||||
"validator 0.15.0",
|
"validator 0.15.0",
|
||||||
@@ -3648,6 +3647,17 @@ dependencies = [
|
|||||||
"waker-fn",
|
"waker-fn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iso8601-timestamp"
|
||||||
|
version = "0.1.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b088f3296223f11d6bd70998132653b30b6f39e6ab4be055c0bda486fa8d11c7"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array 0.14.7",
|
||||||
|
"serde",
|
||||||
|
"time",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iso8601-timestamp"
|
name = "iso8601-timestamp"
|
||||||
version = "0.2.17"
|
version = "0.2.17"
|
||||||
@@ -3986,6 +3996,16 @@ dependencies = [
|
|||||||
"pkg-config",
|
"pkg-config",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libloading"
|
||||||
|
version = "0.8.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"windows-targets 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libm"
|
name = "libm"
|
||||||
version = "0.2.11"
|
version = "0.2.11"
|
||||||
@@ -4479,6 +4499,43 @@ dependencies = [
|
|||||||
"tempfile",
|
"tempfile",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "neon"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7d75440242411c87dc39847b0e33e961ec1f10326a9d8ecf9c1ea64a3b3c13dc"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
"libloading",
|
||||||
|
"neon-macros",
|
||||||
|
"once_cell",
|
||||||
|
"semver",
|
||||||
|
"send_wrapper",
|
||||||
|
"smallvec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "neon-macros"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c6813fde79b646e47e7ad75f480aa80ef76a5d9599e2717407961531169ee38b"
|
||||||
|
dependencies = [
|
||||||
|
"quote 1.0.38",
|
||||||
|
"syn 2.0.94",
|
||||||
|
"syn-mid",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "neon-serde4"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8778b4afaa506e067da24566623873c38797987be593232a4f9ad82c84bb3eb3"
|
||||||
|
dependencies = [
|
||||||
|
"neon",
|
||||||
|
"num",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "new_debug_unreachable"
|
name = "new_debug_unreachable"
|
||||||
version = "1.0.6"
|
version = "1.0.6"
|
||||||
@@ -4520,6 +4577,19 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23"
|
||||||
|
dependencies = [
|
||||||
|
"num-complex",
|
||||||
|
"num-integer",
|
||||||
|
"num-iter",
|
||||||
|
"num-rational",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-bigint"
|
name = "num-bigint"
|
||||||
version = "0.4.6"
|
version = "0.4.6"
|
||||||
@@ -4547,6 +4617,15 @@ dependencies = [
|
|||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-complex"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-conv"
|
name = "num-conv"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -5904,7 +5983,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "revolt-autumn"
|
name = "revolt-autumn"
|
||||||
version = "0.8.5"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"axum",
|
"axum",
|
||||||
"axum-macros",
|
"axum-macros",
|
||||||
@@ -5941,7 +6020,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "revolt-bonfire"
|
name = "revolt-bonfire"
|
||||||
version = "0.8.5"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-channel 2.3.1",
|
"async-channel 2.3.1",
|
||||||
"async-std",
|
"async-std",
|
||||||
@@ -5971,7 +6050,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "revolt-config"
|
name = "revolt-config"
|
||||||
version = "0.8.5"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-std",
|
"async-std",
|
||||||
"cached",
|
"cached",
|
||||||
@@ -5987,7 +6066,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "revolt-crond"
|
name = "revolt-crond"
|
||||||
version = "0.8.5"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"revolt-config",
|
"revolt-config",
|
||||||
@@ -5999,7 +6078,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "revolt-database"
|
name = "revolt-database"
|
||||||
version = "0.8.5"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"amqprs",
|
"amqprs",
|
||||||
"async-lock 2.8.0",
|
"async-lock 2.8.0",
|
||||||
@@ -6016,7 +6095,7 @@ dependencies = [
|
|||||||
"futures",
|
"futures",
|
||||||
"indexmap 1.9.3",
|
"indexmap 1.9.3",
|
||||||
"isahc",
|
"isahc",
|
||||||
"iso8601-timestamp",
|
"iso8601-timestamp 0.2.17",
|
||||||
"linkify 0.8.1",
|
"linkify 0.8.1",
|
||||||
"log",
|
"log",
|
||||||
"lru 0.11.1",
|
"lru 0.11.1",
|
||||||
@@ -6049,7 +6128,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "revolt-delta"
|
name = "revolt-delta"
|
||||||
version = "0.8.5"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"amqprs",
|
"amqprs",
|
||||||
"async-channel 1.9.0",
|
"async-channel 1.9.0",
|
||||||
@@ -6061,7 +6140,7 @@ dependencies = [
|
|||||||
"env_logger",
|
"env_logger",
|
||||||
"futures",
|
"futures",
|
||||||
"impl_ops",
|
"impl_ops",
|
||||||
"iso8601-timestamp",
|
"iso8601-timestamp 0.2.17",
|
||||||
"lettre",
|
"lettre",
|
||||||
"linkify 0.6.0",
|
"linkify 0.6.0",
|
||||||
"log",
|
"log",
|
||||||
@@ -6096,7 +6175,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "revolt-files"
|
name = "revolt-files"
|
||||||
version = "0.8.5"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes-gcm",
|
"aes-gcm",
|
||||||
"aws-config",
|
"aws-config",
|
||||||
@@ -6119,7 +6198,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "revolt-january"
|
name = "revolt-january"
|
||||||
version = "0.8.5"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-recursion",
|
"async-recursion",
|
||||||
"axum",
|
"axum",
|
||||||
@@ -6147,10 +6226,10 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "revolt-models"
|
name = "revolt-models"
|
||||||
version = "0.8.5"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap 1.9.3",
|
"indexmap 1.9.3",
|
||||||
"iso8601-timestamp",
|
"iso8601-timestamp 0.2.17",
|
||||||
"num_enum 0.6.1",
|
"num_enum 0.6.1",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"regex",
|
"regex",
|
||||||
@@ -6164,16 +6243,29 @@ dependencies = [
|
|||||||
"validator 0.16.1",
|
"validator 0.16.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "revolt-nodejs-bindings"
|
||||||
|
version = "0.8.4"
|
||||||
|
dependencies = [
|
||||||
|
"async-std",
|
||||||
|
"neon",
|
||||||
|
"neon-serde4",
|
||||||
|
"revolt-config",
|
||||||
|
"revolt-database",
|
||||||
|
"revolt-result",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "revolt-parser"
|
name = "revolt-parser"
|
||||||
version = "0.1.1"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"logos",
|
"logos",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "revolt-permissions"
|
name = "revolt-permissions"
|
||||||
version = "0.8.5"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-std",
|
"async-std",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@@ -6188,7 +6280,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "revolt-presence"
|
name = "revolt-presence"
|
||||||
version = "0.8.5"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-std",
|
"async-std",
|
||||||
"log",
|
"log",
|
||||||
@@ -6199,7 +6291,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "revolt-pushd"
|
name = "revolt-pushd"
|
||||||
version = "0.8.5"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"amqprs",
|
"amqprs",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@@ -6207,7 +6299,7 @@ dependencies = [
|
|||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
"fcm_v1",
|
"fcm_v1",
|
||||||
"isahc",
|
"isahc",
|
||||||
"iso8601-timestamp",
|
"iso8601-timestamp 0.2.17",
|
||||||
"log",
|
"log",
|
||||||
"pretty_env_logger",
|
"pretty_env_logger",
|
||||||
"revolt-config",
|
"revolt-config",
|
||||||
@@ -6225,7 +6317,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "revolt-result"
|
name = "revolt-result"
|
||||||
version = "0.8.5"
|
version = "0.8.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"axum",
|
"axum",
|
||||||
"revolt_okapi",
|
"revolt_okapi",
|
||||||
@@ -6425,12 +6517,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rocket_authifier"
|
name = "rocket_authifier"
|
||||||
version = "1.0.13"
|
version = "1.0.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0490f4a6f0a359a9ffff9acbdf4eddf49890ec94941b8ddd88163c16f6159f5a"
|
checksum = "c2aa1bfaee106d088b78de7c3cc2a8ab2c9e05a0286b6b912f0b18ea656b329e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"authifier",
|
"authifier",
|
||||||
"iso8601-timestamp",
|
"iso8601-timestamp 0.1.11",
|
||||||
"revolt_okapi",
|
"revolt_okapi",
|
||||||
"revolt_rocket_okapi",
|
"revolt_rocket_okapi",
|
||||||
"rocket",
|
"rocket",
|
||||||
@@ -6909,6 +7001,12 @@ version = "1.0.24"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba"
|
checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "send_wrapper"
|
||||||
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sentry"
|
name = "sentry"
|
||||||
version = "0.31.8"
|
version = "0.31.8"
|
||||||
@@ -7499,6 +7597,17 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn-mid"
|
||||||
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b5dc35bb08dd1ca3dfb09dce91fd2d13294d6711c88897d9a9d60acf39bce049"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote 1.0.38",
|
||||||
|
"syn 2.0.94",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sync_wrapper"
|
name = "sync_wrapper"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
|
|||||||
+4
-3
@@ -6,6 +6,7 @@ members = [
|
|||||||
"crates/bonfire",
|
"crates/bonfire",
|
||||||
"crates/core/*",
|
"crates/core/*",
|
||||||
"crates/services/*",
|
"crates/services/*",
|
||||||
|
"crates/bindings/*",
|
||||||
"crates/daemons/*",
|
"crates/daemons/*",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -15,6 +16,6 @@ redis23 = { package = "redis", version = "0.23.3", git = "https://github.com/rev
|
|||||||
# I'm 99% sure this is overloading the GitHub worker
|
# I'm 99% sure this is overloading the GitHub worker
|
||||||
# hence builds have been failing since, let's just
|
# hence builds have been failing since, let's just
|
||||||
# disable it for now. In the future, we could use this
|
# disable it for now. In the future, we could use this
|
||||||
# if we were rolling our own CI (that is now).
|
# if we were rolling our own CI.
|
||||||
[profile.release]
|
# [profile.release]
|
||||||
lto = true
|
# lto = true
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
# Build Stage
|
# Build Stage
|
||||||
FROM --platform="${BUILDPLATFORM}" rust:1.86.0-slim-bookworm
|
FROM --platform="${BUILDPLATFORM}" rust:1.77.2-slim-bookworm
|
||||||
USER 0:0
|
USER 0:0
|
||||||
WORKDIR /home/rust/src
|
WORKDIR /home/rust/src
|
||||||
|
|
||||||
@@ -17,13 +17,13 @@ RUN sh /tmp/build-image-layer.sh tools
|
|||||||
|
|
||||||
# Build all dependencies
|
# Build all dependencies
|
||||||
COPY Cargo.toml Cargo.lock ./
|
COPY Cargo.toml Cargo.lock ./
|
||||||
|
COPY crates/bindings/node/Cargo.toml ./crates/bindings/node/
|
||||||
COPY crates/bonfire/Cargo.toml ./crates/bonfire/
|
COPY crates/bonfire/Cargo.toml ./crates/bonfire/
|
||||||
COPY crates/delta/Cargo.toml ./crates/delta/
|
COPY crates/delta/Cargo.toml ./crates/delta/
|
||||||
COPY crates/core/config/Cargo.toml ./crates/core/config/
|
COPY crates/core/config/Cargo.toml ./crates/core/config/
|
||||||
COPY crates/core/database/Cargo.toml ./crates/core/database/
|
COPY crates/core/database/Cargo.toml ./crates/core/database/
|
||||||
COPY crates/core/files/Cargo.toml ./crates/core/files/
|
COPY crates/core/files/Cargo.toml ./crates/core/files/
|
||||||
COPY crates/core/models/Cargo.toml ./crates/core/models/
|
COPY crates/core/models/Cargo.toml ./crates/core/models/
|
||||||
COPY crates/core/parser/Cargo.toml ./crates/core/parser/
|
|
||||||
COPY crates/core/permissions/Cargo.toml ./crates/core/permissions/
|
COPY crates/core/permissions/Cargo.toml ./crates/core/permissions/
|
||||||
COPY crates/core/presence/Cargo.toml ./crates/core/presence/
|
COPY crates/core/presence/Cargo.toml ./crates/core/presence/
|
||||||
COPY crates/core/result/Cargo.toml ./crates/core/result/
|
COPY crates/core/result/Cargo.toml ./crates/core/result/
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Build Stage
|
# Build Stage
|
||||||
FROM rust:1.86.0-slim-bookworm
|
FROM rust:1.77.2-slim-bookworm
|
||||||
USER 0:0
|
USER 0:0
|
||||||
WORKDIR /home/rust/src
|
WORKDIR /home/rust/src
|
||||||
|
|
||||||
@@ -13,13 +13,13 @@ COPY scripts/build-image-layer.sh /tmp/
|
|||||||
|
|
||||||
# Build all dependencies
|
# Build all dependencies
|
||||||
COPY Cargo.toml Cargo.lock ./
|
COPY Cargo.toml Cargo.lock ./
|
||||||
|
COPY crates/bindings/node/Cargo.toml ./crates/bindings/node/
|
||||||
COPY crates/bonfire/Cargo.toml ./crates/bonfire/
|
COPY crates/bonfire/Cargo.toml ./crates/bonfire/
|
||||||
COPY crates/delta/Cargo.toml ./crates/delta/
|
COPY crates/delta/Cargo.toml ./crates/delta/
|
||||||
COPY crates/core/config/Cargo.toml ./crates/core/config/
|
COPY crates/core/config/Cargo.toml ./crates/core/config/
|
||||||
COPY crates/core/database/Cargo.toml ./crates/core/database/
|
COPY crates/core/database/Cargo.toml ./crates/core/database/
|
||||||
COPY crates/core/files/Cargo.toml ./crates/core/files/
|
COPY crates/core/files/Cargo.toml ./crates/core/files/
|
||||||
COPY crates/core/models/Cargo.toml ./crates/core/models/
|
COPY crates/core/models/Cargo.toml ./crates/core/models/
|
||||||
COPY crates/core/parser/Cargo.toml ./crates/core/parser/
|
|
||||||
COPY crates/core/permissions/Cargo.toml ./crates/core/permissions/
|
COPY crates/core/permissions/Cargo.toml ./crates/core/permissions/
|
||||||
COPY crates/core/presence/Cargo.toml ./crates/core/presence/
|
COPY crates/core/presence/Cargo.toml ./crates/core/presence/
|
||||||
COPY crates/core/result/Cargo.toml ./crates/core/result/
|
COPY crates/core/result/Cargo.toml ./crates/core/result/
|
||||||
|
|||||||
@@ -12,31 +12,32 @@
|
|||||||
The services and libraries that power the Revolt service.<br/>
|
The services and libraries that power the Revolt service.<br/>
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
| Crate | Path | Description | |
|
| Crate | Path | Description | |
|
||||||
| ------------------ | -------------------------------------------------- | ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ------------------ | -------------------------------------------------- | ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `core/config` | [crates/core/config](crates/core/config) | Core: Configuration |     |
|
| `core/config` | [crates/core/config](crates/core/config) | Core: Configuration |     |
|
||||||
| `core/database` | [crates/core/database](crates/core/database) | Core: Database Implementation |     |
|
| `core/database` | [crates/core/database](crates/core/database) | Core: Database Implementation |     |
|
||||||
| `core/files` | [crates/core/files](crates/core/files) | Core: S3 and encryption subroutines |     |
|
| `core/files` | [crates/core/files](crates/core/files) | Core: S3 and encryption subroutines |     |
|
||||||
| `core/models` | [crates/core/models](crates/core/models) | Core: API Models |     |
|
| `core/models` | [crates/core/models](crates/core/models) | Core: API Models |     |
|
||||||
| `core/permissions` | [crates/core/permissions](crates/core/permissions) | Core: Permission Logic |     |
|
| `core/permissions` | [crates/core/permissions](crates/core/permissions) | Core: Permission Logic |     |
|
||||||
| `core/presence` | [crates/core/presence](crates/core/presence) | Core: User Presence |     |
|
| `core/presence` | [crates/core/presence](crates/core/presence) | Core: User Presence |     |
|
||||||
| `core/result` | [crates/core/result](crates/core/result) | Core: Result and Error types |     |
|
| `core/result` | [crates/core/result](crates/core/result) | Core: Result and Error types |     |
|
||||||
| `delta` | [crates/delta](crates/delta) | REST API server |  |
|
| `delta` | [crates/delta](crates/delta) | REST API server |  |
|
||||||
| `bonfire` | [crates/bonfire](crates/bonfire) | WebSocket events server |  |
|
| `bonfire` | [crates/bonfire](crates/bonfire) | WebSocket events server |  |
|
||||||
| `services/january` | [crates/services/january](crates/services/january) | Proxy server |  |
|
| `services/january` | [crates/services/january](crates/services/january) | Proxy server |  |
|
||||||
| `services/autumn` | [crates/services/autumn](crates/services/autumn) | File server |  |
|
| `services/autumn` | [crates/services/autumn](crates/services/autumn) | File server |  |
|
||||||
| `daemons/crond` | [crates/daemons/crond](crates/daemons/crond) | Timed data clean up daemon server |  |
|
| `bindings/node` | [crates/bindings/node](crates/bindings/node) | Node.js bindings for the Revolt software |  |
|
||||||
| `daemons/pushd` | [crates/daemons/pushd](crates/daemons/pushd) | Push notification daemon server |  |
|
| `daemons/crond` | [crates/daemons/crond](crates/daemons/crond) | Timed data clean up daemon server |  |
|
||||||
|
| `daemons/pushd` | [crates/daemons/pushd](crates/daemons/pushd) | Push notification daemon server |  |
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
## Minimum Supported Rust Version
|
## Minimum Supported Rust Version
|
||||||
|
|
||||||
Rust 1.86.0 or higher.
|
Rust 1.76 or higher.
|
||||||
|
|
||||||
> [!CAUTION]
|
> [!CAUTION]
|
||||||
> The events server has a significant performance regression between Rust 1.77.2 and 1.78.0 onwards, see [issue #341](https://github.com/revoltchat/backend/issues/341). This is currently solved by build time options but we are looking for a proper fix.
|
> The events server has a significant performance regression between Rust 1.77.2 and 1.78.0 onwards, see [issue #341](https://github.com/revoltchat/backend/issues/341).
|
||||||
|
|
||||||
## Development Guide
|
## Development Guide
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ from_address = "development@revolt.chat"
|
|||||||
reply_to = "support@revolt.chat"
|
reply_to = "support@revolt.chat"
|
||||||
port = 14025
|
port = 14025
|
||||||
use_tls = false
|
use_tls = false
|
||||||
use_starttls = false
|
|
||||||
|
|
||||||
[files.s3]
|
[files.s3]
|
||||||
# S3 protocol endpoint
|
# S3 protocol endpoint
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
target
|
||||||
|
index.node
|
||||||
|
**/node_modules
|
||||||
|
**/.DS_Store
|
||||||
|
npm-debug.log*
|
||||||
|
cargo.log
|
||||||
|
cross.log
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
[package]
|
||||||
|
name = "revolt-nodejs-bindings"
|
||||||
|
version = "0.8.4"
|
||||||
|
description = "Node.js bindings for the Revolt software"
|
||||||
|
authors = ["Paul Makles <me@insrt.uk>"]
|
||||||
|
license = "MIT"
|
||||||
|
edition = "2021"
|
||||||
|
exclude = ["index.node"]
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
neon = "1.0.0"
|
||||||
|
neon-serde4 = "1.0.0"
|
||||||
|
|
||||||
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
|
||||||
|
async-std = "1.12.0"
|
||||||
|
|
||||||
|
revolt-config = { version = "0.8.4", path = "../../core/config" }
|
||||||
|
revolt-result = { version = "0.8.4", path = "../../core/result" }
|
||||||
|
revolt-database = { version = "0.8.4", path = "../../core/database" }
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
# revolt.node
|
||||||
|
|
||||||
|
**revolt.node:** Node.js bindings for the Revolt software
|
||||||
|
|
||||||
|
This project was bootstrapped by [create-neon](https://www.npmjs.com/package/create-neon).
|
||||||
|
|
||||||
|
## Building revolt.node
|
||||||
|
|
||||||
|
Building revolt.node requires a [supported version of Node and Rust](https://github.com/neon-bindings/neon#platform-support).
|
||||||
|
|
||||||
|
To run the build, run:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
This command uses the [@neon-rs/cli](https://www.npmjs.com/package/@neon-rs/cli) utility to assemble the binary Node addon from the output of `cargo`.
|
||||||
|
|
||||||
|
## Exploring revolt.node
|
||||||
|
|
||||||
|
After building revolt.node, you can explore its exports at the Node console:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ npm i
|
||||||
|
$ npm run build
|
||||||
|
$ node
|
||||||
|
> require('.').hello()
|
||||||
|
'hello node'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Available Scripts
|
||||||
|
|
||||||
|
In the project directory, you can run:
|
||||||
|
|
||||||
|
#### `npm install`
|
||||||
|
|
||||||
|
Installs the project, including running `npm run build`.
|
||||||
|
|
||||||
|
#### `npm run build`
|
||||||
|
|
||||||
|
Builds the Node addon (`index.node`) from source, generating a release build with `cargo --release`.
|
||||||
|
|
||||||
|
Additional [`cargo build`](https://doc.rust-lang.org/cargo/commands/cargo-build.html) arguments may be passed to `npm run build` and similar commands. For example, to enable a [cargo feature](https://doc.rust-lang.org/cargo/reference/features.html):
|
||||||
|
|
||||||
|
```
|
||||||
|
npm run build -- --feature=beetle
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `npm run debug`
|
||||||
|
|
||||||
|
Similar to `npm run build` but generates a debug build with `cargo`.
|
||||||
|
|
||||||
|
#### `npm run cross`
|
||||||
|
|
||||||
|
Similar to `npm run build` but uses [cross-rs](https://github.com/cross-rs/cross) to cross-compile for another platform. Use the [`CARGO_BUILD_TARGET`](https://doc.rust-lang.org/cargo/reference/config.html#buildtarget) environment variable to select the build target.
|
||||||
|
|
||||||
|
#### `npm test`
|
||||||
|
|
||||||
|
Runs the unit tests by calling `cargo test`. You can learn more about [adding tests to your Rust code](https://doc.rust-lang.org/book/ch11-01-writing-tests.html) from the [Rust book](https://doc.rust-lang.org/book/).
|
||||||
|
|
||||||
|
## Project Layout
|
||||||
|
|
||||||
|
The directory structure of this project is:
|
||||||
|
|
||||||
|
```
|
||||||
|
revolt.node/
|
||||||
|
├── Cargo.toml
|
||||||
|
├── README.md
|
||||||
|
├── src/
|
||||||
|
| └── lib.rs
|
||||||
|
├── index.node
|
||||||
|
├── package.json
|
||||||
|
└── target/
|
||||||
|
```
|
||||||
|
|
||||||
|
| Entry | Purpose |
|
||||||
|
|----------------|------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| `Cargo.toml` | The Cargo [manifest file](https://doc.rust-lang.org/cargo/reference/manifest.html), which informs the `cargo` command. |
|
||||||
|
| `README.md` | This file. |
|
||||||
|
| `src/` | The directory tree containing the Rust source code for the project. |
|
||||||
|
| `lib.rs` | Entry point for the Rust source code. |
|
||||||
|
| `index.node` | The main module, a [Node addon](https://nodejs.org/api/addons.html) generated by the build and pointed to by `"main"` in `package.json`. |
|
||||||
|
| `package.json` | The npm [manifest file](https://docs.npmjs.com/cli/v7/configuring-npm/package-json), which informs the `npm` command. |
|
||||||
|
| `target/` | Binary artifacts generated by the Rust build. |
|
||||||
|
|
||||||
|
## Learn More
|
||||||
|
|
||||||
|
Learn more about:
|
||||||
|
|
||||||
|
- [Neon](https://neon-bindings.com).
|
||||||
|
- [Rust](https://www.rust-lang.org).
|
||||||
|
- [Node](https://nodejs.org).
|
||||||
Vendored
+84
@@ -0,0 +1,84 @@
|
|||||||
|
import { Channel, User } from "revolt-api";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opaque type for Revolt database
|
||||||
|
*/
|
||||||
|
export declare interface Database {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opaque type for Revolt database
|
||||||
|
*/
|
||||||
|
export declare interface OpaqueUser {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error type from Revolt backend
|
||||||
|
*/
|
||||||
|
export declare interface Err {
|
||||||
|
type: string;
|
||||||
|
location: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialises background tasks and logging, must be called before anything else!
|
||||||
|
* Can be called multiple times!
|
||||||
|
*/
|
||||||
|
export declare function init();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a new handle to the Revolt database
|
||||||
|
* @returns {Database} Handle
|
||||||
|
*/
|
||||||
|
export declare function database(): Database;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch user from database
|
||||||
|
* @param {string} userId User's ID
|
||||||
|
* @this {Database}
|
||||||
|
*/
|
||||||
|
export declare function database_fetch_user(userId: string): OpaqueUser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch user from database
|
||||||
|
* @param {string} username Username
|
||||||
|
* @param {string} discriminator Discriminator
|
||||||
|
* @this {Database}
|
||||||
|
*/
|
||||||
|
export declare function database_fetch_user_by_username(
|
||||||
|
username: string,
|
||||||
|
discriminator: string
|
||||||
|
): OpaqueUser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets model data as JSON
|
||||||
|
* @this {OpaqueUser}
|
||||||
|
*/
|
||||||
|
export declare function model_data(): User;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets error if the model failed to fetch
|
||||||
|
* @this {OpaqueUser}
|
||||||
|
*/
|
||||||
|
export declare function model_error(): Err;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a direct message channel between two users
|
||||||
|
* @param {string} userA User A ID
|
||||||
|
* @param {string} userB User B ID
|
||||||
|
* @returns Existing or newly created channel
|
||||||
|
*/
|
||||||
|
export declare function proc_channels_create_dm(
|
||||||
|
userA: string,
|
||||||
|
userB: string
|
||||||
|
): Promise<Channel & { error: Err }>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Suspend a user
|
||||||
|
* @param {string} user User
|
||||||
|
* @param {number} duration Duration (in days), set to 0 for indefinite
|
||||||
|
* @param {string} reason Pipe-separated list of reasons (e.g. reason1|reason2|reason3)
|
||||||
|
*/
|
||||||
|
export declare function proc_users_suspend(
|
||||||
|
user: OpaqueUser,
|
||||||
|
duration: number,
|
||||||
|
reason: string
|
||||||
|
): Promise<{ error: Err }>;
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"name": "revolt-nodejs-bindings",
|
||||||
|
"version": "0.7.15-rev0.0.3",
|
||||||
|
"description": "Node.js bindings for the Revolt software",
|
||||||
|
"main": "index.node",
|
||||||
|
"scripts": {
|
||||||
|
"test": "cargo test",
|
||||||
|
"cargo-build": "cargo build --message-format=json > cargo.log",
|
||||||
|
"cross-build": "cross build --message-format=json > cross.log",
|
||||||
|
"postcargo-build": "neon dist < cargo.log",
|
||||||
|
"postcross-build": "neon dist -m /target < cross.log",
|
||||||
|
"debug": "npm run cargo-build --",
|
||||||
|
"build": "npm run cargo-build -- --release",
|
||||||
|
"cross": "npm run cross-build -- --release"
|
||||||
|
},
|
||||||
|
"author": "Paul Makles",
|
||||||
|
"license": "AGPL-3.0",
|
||||||
|
"devDependencies": {
|
||||||
|
"@neon-rs/cli": "0.1.73"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/revoltchat/backend"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"revolt",
|
||||||
|
"chat"
|
||||||
|
],
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/revoltchat/backend/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/revoltchat/backend#readme",
|
||||||
|
"dependencies": {
|
||||||
|
"revolt-api": "^0.7.15"
|
||||||
|
}
|
||||||
|
}
|
||||||
Generated
+117
@@ -0,0 +1,117 @@
|
|||||||
|
lockfileVersion: '6.0'
|
||||||
|
|
||||||
|
settings:
|
||||||
|
autoInstallPeers: true
|
||||||
|
excludeLinksFromLockfile: false
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
revolt-api:
|
||||||
|
specifier: ^0.7.15
|
||||||
|
version: 0.7.15
|
||||||
|
|
||||||
|
devDependencies:
|
||||||
|
'@neon-rs/cli':
|
||||||
|
specifier: 0.1.73
|
||||||
|
version: 0.1.73
|
||||||
|
|
||||||
|
packages:
|
||||||
|
|
||||||
|
/@cargo-messages/android-arm-eabi@0.1.72:
|
||||||
|
resolution: {integrity: sha512-gGZxIM1mj+Y5x+ULND6ZCNr7f70OJi9wDlycSK8hGONy9wrChN6JAIHryddC5cqcwlYAoQ6IDcDFElnhAYbybA==}
|
||||||
|
cpu: [arm]
|
||||||
|
os: [android]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@cargo-messages/darwin-arm64@0.1.72:
|
||||||
|
resolution: {integrity: sha512-EAzN5MLaXPljZKZDO5qR+aBs44eSq2ZbEnS7AI/FziE3MzeXbrGOS3fLba5+7yWPFXJyZolXzePm8N1EBv8ovg==}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [darwin]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@cargo-messages/darwin-x64@0.1.72:
|
||||||
|
resolution: {integrity: sha512-RLo6j8s3nYbjdd1LDct4wamfChyRit7zokUuxtIYCu9XOlltkN5vnj1vwnrPvoqCMZ/7CbbuHFwSTn9A71de/w==}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [darwin]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@cargo-messages/linux-arm-gnueabihf@0.1.72:
|
||||||
|
resolution: {integrity: sha512-tHsRshuzfjrX6SDW3jg6al8vMNLTMgczGnVYl5RuBZf/yrAUuwe30KxA9ge6w6mW6Ox797DyBchzAc9OLgTgmQ==}
|
||||||
|
cpu: [arm]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@cargo-messages/linux-x64-gnu@0.1.72:
|
||||||
|
resolution: {integrity: sha512-VGtL6CCnUbhsP4aYuBNT5kfrAL7o0qjrxw97a+ax13t+nJd26tVEEIKHMu5drvvS/Nm/hn7sLT8zMnnCv0pvHg==}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@cargo-messages/win32-arm64-msvc@0.1.72:
|
||||||
|
resolution: {integrity: sha512-V93Cgz39K+yqa3MveNbhh29pYCp8izK5uEavjPoxlNxAbsMCWH+s0verGDdUcfGxjR1H2V7oZ4FszPqR2SqMRQ==}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [win32]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@cargo-messages/win32-x64-msvc@0.1.72:
|
||||||
|
resolution: {integrity: sha512-knz3uSrO0OSbq3U5VWfCY8FB4NsM43BOWLZ7x4sfaMOC1XWv+IyvDdkLe6DhJx8KUw46KIAimYs9YROrp6l46Q==}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [win32]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@neon-rs/cli@0.1.73:
|
||||||
|
resolution: {integrity: sha512-1kv8S/feB6UQWQQwsnGfkSkEBOtlFDNExnioL81E2BwvUWgjQPaseHgpi2EpWVgsPUgur5eBm4QowmlpWkD4/w==}
|
||||||
|
hasBin: true
|
||||||
|
optionalDependencies:
|
||||||
|
'@cargo-messages/android-arm-eabi': 0.1.72
|
||||||
|
'@cargo-messages/darwin-arm64': 0.1.72
|
||||||
|
'@cargo-messages/darwin-x64': 0.1.72
|
||||||
|
'@cargo-messages/linux-arm-gnueabihf': 0.1.72
|
||||||
|
'@cargo-messages/linux-x64-gnu': 0.1.72
|
||||||
|
'@cargo-messages/win32-arm64-msvc': 0.1.72
|
||||||
|
'@cargo-messages/win32-x64-msvc': 0.1.72
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/axios@0.26.1:
|
||||||
|
resolution: {integrity: sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==}
|
||||||
|
dependencies:
|
||||||
|
follow-redirects: 1.15.6
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- debug
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/follow-redirects@1.15.6:
|
||||||
|
resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==}
|
||||||
|
engines: {node: '>=4.0'}
|
||||||
|
peerDependencies:
|
||||||
|
debug: '*'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
debug:
|
||||||
|
optional: true
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/lodash.defaultsdeep@4.6.1:
|
||||||
|
resolution: {integrity: sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/revolt-api@0.7.15:
|
||||||
|
resolution: {integrity: sha512-rWRnjBFvoXt/RHRxHg9KuP+x1Jk61KdsOpKOczVJg5tIqGDmqp/6QZHw5rJTtG+wCH3Ah3YKwY+MM5NHfg1W3Q==}
|
||||||
|
dependencies:
|
||||||
|
axios: 0.26.1
|
||||||
|
lodash.defaultsdeep: 4.6.1
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- debug
|
||||||
|
dev: false
|
||||||
@@ -0,0 +1,221 @@
|
|||||||
|
#[macro_use]
|
||||||
|
extern crate serde;
|
||||||
|
|
||||||
|
use std::sync::OnceLock;
|
||||||
|
|
||||||
|
use neon::prelude::*;
|
||||||
|
use revolt_database::{Database, DatabaseInfo};
|
||||||
|
|
||||||
|
fn js_init(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
||||||
|
// static INIT: OnceLock<()> = OnceLock::new();
|
||||||
|
// if INIT.get().is_none() {
|
||||||
|
// INIT.get_or_init(|| {
|
||||||
|
// async_std::task::block_on(async {
|
||||||
|
// revolt_config::configure!(api);
|
||||||
|
|
||||||
|
// match DatabaseInfo::Auto.connect().await {
|
||||||
|
// Ok(db) => {
|
||||||
|
// let authifier_db = db.clone().to_authifier().await.database;
|
||||||
|
// revolt_database::tasks::start_workers(db, authifier_db);
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
|
// Err(err) => Err(err),
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// .or_else(|err| cx.throw_error(err))
|
||||||
|
// .unwrap();
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
Ok(cx.undefined())
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DatabaseBinding(Database, Channel);
|
||||||
|
impl Finalize for DatabaseBinding {}
|
||||||
|
impl DatabaseBinding {
|
||||||
|
fn take(&self) -> (Database, Channel) {
|
||||||
|
(self.0.clone(), self.1.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn js_database(mut cx: FunctionContext) -> JsResult<JsBox<DatabaseBinding>> {
|
||||||
|
let db = async_std::task::block_on(DatabaseInfo::Auto.connect())
|
||||||
|
.or_else(|err| cx.throw_error(err))?;
|
||||||
|
|
||||||
|
let channel = cx.channel();
|
||||||
|
Ok(cx.boxed(DatabaseBinding(db, channel)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implementations for models
|
||||||
|
#[derive(Clone)]
|
||||||
|
#[allow(clippy::large_enum_variant)]
|
||||||
|
enum Model {
|
||||||
|
User(revolt_database::User),
|
||||||
|
Error(revolt_result::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Model {
|
||||||
|
fn give(&self) -> Model {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Finalize for Model {}
|
||||||
|
|
||||||
|
macro_rules! shim_boxed {
|
||||||
|
($cx: ident, $name: ident, $model: ident, $( $variable: ident $type: ident $id: expr )+, $cmd: ident, $( $arg: expr, )+) => {
|
||||||
|
fn $name(mut cx: FunctionContext) -> JsResult<JsPromise> {
|
||||||
|
$(
|
||||||
|
let $variable = cx.argument::<$type>($id)?.value(&mut cx);
|
||||||
|
)+
|
||||||
|
|
||||||
|
let (db, channel) = cx.this::<JsBox<DatabaseBinding>>()?.take();
|
||||||
|
let (deferred, promise) = cx.promise();
|
||||||
|
|
||||||
|
async_std::task::spawn(async move {
|
||||||
|
let result = db.$cmd($($arg,)+).await;
|
||||||
|
deferred.settle_with(&channel, move |mut cx| {
|
||||||
|
Ok(cx.boxed(match result {
|
||||||
|
Ok(value) => Model::$model(value),
|
||||||
|
Err(error) => Model::Error(error)
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(promise)
|
||||||
|
}
|
||||||
|
|
||||||
|
$cx.export_function(stringify!($name), $name)?;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn js_data(mut cx: FunctionContext) -> JsResult<JsValue> {
|
||||||
|
match cx.this::<JsBox<Model>>()?.give() {
|
||||||
|
Model::Error(_) => neon_serde4::to_value(&mut cx, &None::<()>),
|
||||||
|
Model::User(user) => neon_serde4::to_value(&mut cx, &user),
|
||||||
|
}
|
||||||
|
.or_else(|e| cx.throw_error(e.to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn js_error(mut cx: FunctionContext) -> JsResult<JsValue> {
|
||||||
|
let value = match cx.this::<JsBox<Model>>()?.give() {
|
||||||
|
Model::Error(err) => Some(err),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
neon_serde4::to_value(&mut cx, &value).or_else(|e| cx.throw_error(e.to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Basic data implementation
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
struct ResultBinding<T> {
|
||||||
|
#[serde(flatten)]
|
||||||
|
value: Option<T>,
|
||||||
|
error: Option<revolt_result::Error>,
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! shim {
|
||||||
|
($cx: ident, $name: ident, $( $variable: ident $type: ident $id: expr )*, $( $model: ident $modelType: ident $modelId: expr )*, | $db: ident | $closure: expr, $( $arg: expr, )+) => {
|
||||||
|
fn $name(mut cx: FunctionContext) -> JsResult<JsPromise> {
|
||||||
|
$(
|
||||||
|
let $variable = cx.argument::<$type>($id)?.value(&mut cx);
|
||||||
|
)*
|
||||||
|
|
||||||
|
$(
|
||||||
|
let mut $model = if let Model::$modelType(value) = cx.argument::<JsBox<Model>>($modelId)?.give() {
|
||||||
|
value
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
)*
|
||||||
|
|
||||||
|
let (db, channel) = cx.this::<JsBox<DatabaseBinding>>()?.take();
|
||||||
|
let (deferred, promise) = cx.promise();
|
||||||
|
|
||||||
|
async_std::task::spawn(async move {
|
||||||
|
#[allow(clippy::redundant_closure_call)]
|
||||||
|
let result = (|$db: $crate::Database| $closure)(db.clone()).await;
|
||||||
|
deferred.settle_with(&channel, move |mut cx| {
|
||||||
|
neon_serde4::to_value(
|
||||||
|
&mut cx,
|
||||||
|
&match result {
|
||||||
|
Ok(value) => ResultBinding {
|
||||||
|
value: Some(value),
|
||||||
|
error: None,
|
||||||
|
},
|
||||||
|
Err(error) => ResultBinding {
|
||||||
|
value: None,
|
||||||
|
error: Some(error),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.or_else(|e| cx.throw_error(e.to_string()))
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(promise)
|
||||||
|
}
|
||||||
|
|
||||||
|
$cx.export_function(stringify!($name), $name)?;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[neon::main]
|
||||||
|
fn main(mut cx: ModuleContext) -> NeonResult<()> {
|
||||||
|
// initialise required background stuff
|
||||||
|
cx.export_function("init", js_init)?;
|
||||||
|
|
||||||
|
// database & model stuff
|
||||||
|
cx.export_function("database", js_database)?;
|
||||||
|
cx.export_function("model_data", js_data)?;
|
||||||
|
cx.export_function("model_error", js_error)?;
|
||||||
|
|
||||||
|
shim_boxed!(
|
||||||
|
cx,
|
||||||
|
database_fetch_user,
|
||||||
|
User,
|
||||||
|
user_id JsString 0,
|
||||||
|
fetch_user,
|
||||||
|
&user_id,
|
||||||
|
);
|
||||||
|
|
||||||
|
shim_boxed!(
|
||||||
|
cx,
|
||||||
|
database_fetch_user_by_username,
|
||||||
|
User,
|
||||||
|
username JsString 0
|
||||||
|
discriminator JsString 1,
|
||||||
|
fetch_user_by_username,
|
||||||
|
&username, &discriminator,
|
||||||
|
);
|
||||||
|
|
||||||
|
// procedure calls
|
||||||
|
shim!(
|
||||||
|
cx,
|
||||||
|
proc_channels_create_dm,
|
||||||
|
user_a JsString 0
|
||||||
|
user_b JsString 1,
|
||||||
|
,
|
||||||
|
|db| async move {
|
||||||
|
let user_a = db.fetch_user(&user_a).await?;
|
||||||
|
let user_b = db.fetch_user(&user_b).await?;
|
||||||
|
revolt_database::Channel::create_dm(&db, &user_a, &user_b).await
|
||||||
|
},
|
||||||
|
&userA, &userB,
|
||||||
|
);
|
||||||
|
|
||||||
|
shim!(
|
||||||
|
cx,
|
||||||
|
proc_users_suspend,
|
||||||
|
duration JsNumber 1
|
||||||
|
reason JsString 2,
|
||||||
|
user User 0,
|
||||||
|
|db| async move {
|
||||||
|
let duration = duration as usize;
|
||||||
|
user.suspend(&db, if duration == 0 { None } else { Some(duration) }, Some(reason.split('|').map(|x| x.to_owned()).collect())).await
|
||||||
|
},
|
||||||
|
&user,
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
const Internal = require(".");
|
||||||
|
|
||||||
|
// playing around with class wrapper, not practical
|
||||||
|
class Model {
|
||||||
|
constructor(model) {
|
||||||
|
this.model = model;
|
||||||
|
}
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return Internal.model_data.bind(this.model)();
|
||||||
|
}
|
||||||
|
|
||||||
|
error() {
|
||||||
|
return Internal.model_error.bind(this.model)();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class User extends Model {
|
||||||
|
constructor(db, user) {
|
||||||
|
super(user);
|
||||||
|
this.db = db;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Database {
|
||||||
|
constructor() {
|
||||||
|
this.db = Internal.database();
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetchUser(userId) {
|
||||||
|
return new User(
|
||||||
|
this,
|
||||||
|
await Internal.database_fetch_user.bind(this.db)(userId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetchUserByUsername(username, discriminator) {
|
||||||
|
return new User(
|
||||||
|
this,
|
||||||
|
await Internal.database_fetch_user_by_username.bind(this.db)(
|
||||||
|
username,
|
||||||
|
discriminator
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const db = new Database();
|
||||||
|
db.fetchUserByUsername("dos", "7624").then((user) => console.info(user.data()));
|
||||||
|
db.fetchUserByUsername("dos", "1111").then((user) => console.info(user.data()));
|
||||||
|
db.fetchUserByUsername("dos", "1111").then((user) =>
|
||||||
|
console.info(user.error())
|
||||||
|
);
|
||||||
Generated
+6
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"name": "bindings",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "revolt-bonfire"
|
name = "revolt-bonfire"
|
||||||
version = "0.8.5"
|
version = "0.8.4"
|
||||||
license = "AGPL-3.0-or-later"
|
license = "AGPL-3.0-or-later"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
@@ -36,12 +36,12 @@ async-std = { version = "1.8.0", features = [
|
|||||||
] }
|
] }
|
||||||
|
|
||||||
# core
|
# core
|
||||||
authifier = { version = "1.0.13" }
|
authifier = { version = "1.0.10" }
|
||||||
revolt-result = { path = "../core/result" }
|
revolt-result = { path = "../core/result" }
|
||||||
revolt-models = { path = "../core/models" }
|
revolt-models = { path = "../core/models" }
|
||||||
revolt-config = { path = "../core/config" }
|
revolt-config = { path = "../core/config" }
|
||||||
revolt-database = { path = "../core/database" }
|
revolt-database = { path = "../core/database" }
|
||||||
revolt-permissions = { version = "0.8.5", path = "../core/permissions" }
|
revolt-permissions = { version = "0.8.4", path = "../core/permissions" }
|
||||||
revolt-presence = { path = "../core/presence", features = ["redis-is-patched"] }
|
revolt-presence = { path = "../core/presence", features = ["redis-is-patched"] }
|
||||||
|
|
||||||
# redis
|
# redis
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "revolt-config"
|
name = "revolt-config"
|
||||||
version = "0.8.5"
|
version = "0.8.4"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
authors = ["Paul Makles <me@insrt.uk>"]
|
authors = ["Paul Makles <me@insrt.uk>"]
|
||||||
@@ -34,4 +34,4 @@ pretty_env_logger = "0.4.0"
|
|||||||
sentry = "0.31.5"
|
sentry = "0.31.5"
|
||||||
|
|
||||||
# Core
|
# Core
|
||||||
revolt-result = { version = "0.8.5", path = "../result", optional = true }
|
revolt-result = { version = "0.8.4", path = "../result", optional = true }
|
||||||
|
|||||||
@@ -54,8 +54,6 @@ authifier_shield_key = ""
|
|||||||
voso_legacy_token = ""
|
voso_legacy_token = ""
|
||||||
# Whether services are behind the Cloudflare network
|
# Whether services are behind the Cloudflare network
|
||||||
trust_cloudflare = false
|
trust_cloudflare = false
|
||||||
# easypwned endpoint
|
|
||||||
easypwned = ""
|
|
||||||
|
|
||||||
[api.security.captcha]
|
[api.security.captcha]
|
||||||
# hCaptcha configuration
|
# hCaptcha configuration
|
||||||
@@ -202,6 +200,7 @@ message_reactions = 20
|
|||||||
server_emoji = 100
|
server_emoji = 100
|
||||||
server_roles = 200
|
server_roles = 200
|
||||||
server_channels = 200
|
server_channels = 200
|
||||||
|
server_categories = 50
|
||||||
|
|
||||||
# How many hours since creation a user is considered new
|
# How many hours since creation a user is considered new
|
||||||
new_user_hours = 72
|
new_user_hours = 72
|
||||||
|
|||||||
@@ -123,7 +123,6 @@ pub struct ApiSmtp {
|
|||||||
pub reply_to: Option<String>,
|
pub reply_to: Option<String>,
|
||||||
pub port: Option<i32>,
|
pub port: Option<i32>,
|
||||||
pub use_tls: Option<bool>,
|
pub use_tls: Option<bool>,
|
||||||
pub use_starttls: Option<bool>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug, Clone)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
@@ -169,7 +168,6 @@ pub struct ApiSecurity {
|
|||||||
pub voso_legacy_token: String,
|
pub voso_legacy_token: String,
|
||||||
pub captcha: ApiSecurityCaptcha,
|
pub captcha: ApiSecurityCaptcha,
|
||||||
pub trust_cloudflare: bool,
|
pub trust_cloudflare: bool,
|
||||||
pub easypwned: String,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug, Clone)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
@@ -179,7 +177,7 @@ pub struct ApiWorkers {
|
|||||||
|
|
||||||
#[derive(Deserialize, Debug, Clone)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
pub struct ApiUsers {
|
pub struct ApiUsers {
|
||||||
pub early_adopter_cutoff: Option<u64>,
|
pub early_adopter_cutoff: Option<u64>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug, Clone)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
@@ -283,6 +281,7 @@ pub struct GlobalLimits {
|
|||||||
pub server_emoji: usize,
|
pub server_emoji: usize,
|
||||||
pub server_roles: usize,
|
pub server_roles: usize,
|
||||||
pub server_channels: usize,
|
pub server_channels: usize,
|
||||||
|
pub server_categories: usize,
|
||||||
|
|
||||||
pub new_user_hours: usize,
|
pub new_user_hours: usize,
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "revolt-database"
|
name = "revolt-database"
|
||||||
version = "0.8.5"
|
version = "0.8.4"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "AGPL-3.0-or-later"
|
license = "AGPL-3.0-or-later"
|
||||||
authors = ["Paul Makles <me@insrt.uk>"]
|
authors = ["Paul Makles <me@insrt.uk>"]
|
||||||
@@ -24,19 +24,19 @@ default = ["mongodb", "async-std-runtime", "tasks"]
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# Core
|
# Core
|
||||||
revolt-config = { version = "0.8.5", path = "../config", features = [
|
revolt-config = { version = "0.8.4", path = "../config", features = [
|
||||||
"report-macros",
|
"report-macros",
|
||||||
] }
|
] }
|
||||||
revolt-result = { version = "0.8.5", path = "../result" }
|
revolt-result = { version = "0.8.4", path = "../result" }
|
||||||
revolt-models = { version = "0.8.5", path = "../models", features = [
|
revolt-models = { version = "0.8.4", path = "../models", features = [
|
||||||
"validator",
|
"validator",
|
||||||
] }
|
] }
|
||||||
revolt-presence = { version = "0.8.5", path = "../presence" }
|
revolt-presence = { version = "0.8.4", path = "../presence" }
|
||||||
revolt-permissions = { version = "0.8.5", path = "../permissions", features = [
|
revolt-permissions = { version = "0.8.4", path = "../permissions", features = [
|
||||||
"serde",
|
"serde",
|
||||||
"bson",
|
"bson",
|
||||||
] }
|
] }
|
||||||
revolt-parser = { version = "0.1.1", path = "../parser" }
|
revolt-parser = { version = "0.1.0", path = "../parser" }
|
||||||
|
|
||||||
# Utility
|
# Utility
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
@@ -97,7 +97,7 @@ web-push = "0.10.0"
|
|||||||
revolt_a2 = { version = "0.10", default-features = false, features = ["ring"] }
|
revolt_a2 = { version = "0.10", default-features = false, features = ["ring"] }
|
||||||
|
|
||||||
# Authifier
|
# Authifier
|
||||||
authifier = { version = "1.0.13", features = ["rocket_impl"] }
|
authifier = { version = "1.0.10", features = ["rocket_impl"] }
|
||||||
|
|
||||||
# RabbitMQ
|
# RabbitMQ
|
||||||
amqprs = { version = "1.7.0" }
|
amqprs = { version = "1.7.0" }
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ mod reference;
|
|||||||
|
|
||||||
use authifier::config::Captcha;
|
use authifier::config::Captcha;
|
||||||
use authifier::config::EmailVerificationConfig;
|
use authifier::config::EmailVerificationConfig;
|
||||||
use authifier::config::PasswordScanning;
|
|
||||||
use authifier::config::ResolveIp;
|
use authifier::config::ResolveIp;
|
||||||
use authifier::config::SMTPSettings;
|
use authifier::config::SMTPSettings;
|
||||||
use authifier::config::Shield;
|
use authifier::config::Shield;
|
||||||
@@ -103,13 +102,6 @@ impl Database {
|
|||||||
let config = config().await;
|
let config = config().await;
|
||||||
|
|
||||||
let mut auth_config = authifier::Config {
|
let mut auth_config = authifier::Config {
|
||||||
password_scanning: if config.api.security.easypwned.is_empty() {
|
|
||||||
Default::default()
|
|
||||||
} else {
|
|
||||||
PasswordScanning::EasyPwned {
|
|
||||||
endpoint: config.api.security.easypwned,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
email_verification: if !config.api.smtp.host.is_empty() {
|
email_verification: if !config.api.smtp.host.is_empty() {
|
||||||
EmailVerificationConfig::Enabled {
|
EmailVerificationConfig::Enabled {
|
||||||
smtp: SMTPSettings {
|
smtp: SMTPSettings {
|
||||||
@@ -126,7 +118,6 @@ impl Database {
|
|||||||
),
|
),
|
||||||
port: config.api.smtp.port,
|
port: config.api.smtp.port,
|
||||||
use_tls: config.api.smtp.use_tls,
|
use_tls: config.api.smtp.use_tls,
|
||||||
use_starttls: config.api.smtp.use_starttls,
|
|
||||||
},
|
},
|
||||||
expiry: Default::default(),
|
expiry: Default::default(),
|
||||||
templates: if config.production {
|
templates: if config.production {
|
||||||
@@ -143,15 +134,6 @@ impl Database {
|
|||||||
url: format!("{}/login/reset/", config.hosts.app),
|
url: format!("{}/login/reset/", config.hosts.app),
|
||||||
html: Some(include_str!("../../templates/reset.html").into()),
|
html: Some(include_str!("../../templates/reset.html").into()),
|
||||||
},
|
},
|
||||||
reset_existing: Template {
|
|
||||||
title: "You already have a Revolt account, reset your password."
|
|
||||||
.into(),
|
|
||||||
text: include_str!("../../templates/reset-existing.txt").into(),
|
|
||||||
url: format!("{}/login/reset/", config.hosts.app),
|
|
||||||
html: Some(
|
|
||||||
include_str!("../../templates/reset-existing.html").into(),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
deletion: Template {
|
deletion: Template {
|
||||||
title: "Confirm account deletion.".into(),
|
title: "Confirm account deletion.".into(),
|
||||||
text: include_str!("../../templates/deletion.txt").into(),
|
text: include_str!("../../templates/deletion.txt").into(),
|
||||||
@@ -174,16 +156,9 @@ impl Database {
|
|||||||
url: format!("{}/login/reset/", config.hosts.app),
|
url: format!("{}/login/reset/", config.hosts.app),
|
||||||
html: None,
|
html: None,
|
||||||
},
|
},
|
||||||
reset_existing: Template {
|
|
||||||
title: "Reset your password.".into(),
|
|
||||||
text: include_str!("../../templates/reset.whitelabel.txt").into(),
|
|
||||||
url: format!("{}/login/reset/", config.hosts.app),
|
|
||||||
html: None,
|
|
||||||
},
|
|
||||||
deletion: Template {
|
deletion: Template {
|
||||||
title: "Confirm account deletion.".into(),
|
title: "Confirm account deletion.".into(),
|
||||||
text: include_str!("../../templates/deletion.whitelabel.txt")
|
text: include_str!("../../templates/deletion.whitelabel.txt").into(),
|
||||||
.into(),
|
|
||||||
url: format!("{}/delete/", config.hosts.app),
|
url: format!("{}/delete/", config.hosts.app),
|
||||||
html: None,
|
html: None,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -100,6 +100,10 @@ auto_derived!(
|
|||||||
)]
|
)]
|
||||||
role_permissions: HashMap<String, OverrideField>,
|
role_permissions: HashMap<String, OverrideField>,
|
||||||
|
|
||||||
|
/// Category the channel is in
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
parent: Option<String>,
|
||||||
|
|
||||||
/// Whether this channel is marked as not safe for work
|
/// Whether this channel is marked as not safe for work
|
||||||
#[serde(skip_serializing_if = "crate::if_false", default)]
|
#[serde(skip_serializing_if = "crate::if_false", default)]
|
||||||
nsfw: bool,
|
nsfw: bool,
|
||||||
@@ -131,6 +135,10 @@ auto_derived!(
|
|||||||
)]
|
)]
|
||||||
role_permissions: HashMap<String, OverrideField>,
|
role_permissions: HashMap<String, OverrideField>,
|
||||||
|
|
||||||
|
/// Category the channel is in
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
parent: Option<String>,
|
||||||
|
|
||||||
/// Whether this channel is marked as not safe for work
|
/// Whether this channel is marked as not safe for work
|
||||||
#[serde(skip_serializing_if = "crate::if_false", default)]
|
#[serde(skip_serializing_if = "crate::if_false", default)]
|
||||||
nsfw: bool,
|
nsfw: bool,
|
||||||
@@ -161,6 +169,8 @@ auto_derived!(
|
|||||||
pub default_permissions: Option<OverrideField>,
|
pub default_permissions: Option<OverrideField>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub last_message_id: Option<String>,
|
pub last_message_id: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub parent: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Optional fields on channel object
|
/// Optional fields on channel object
|
||||||
@@ -219,6 +229,7 @@ impl Channel {
|
|||||||
default_permissions: None,
|
default_permissions: None,
|
||||||
role_permissions: HashMap::new(),
|
role_permissions: HashMap::new(),
|
||||||
nsfw: data.nsfw.unwrap_or(false),
|
nsfw: data.nsfw.unwrap_or(false),
|
||||||
|
parent: None
|
||||||
},
|
},
|
||||||
v0::LegacyServerChannelType::Voice => Channel::VoiceChannel {
|
v0::LegacyServerChannelType::Voice => Channel::VoiceChannel {
|
||||||
id: id.clone(),
|
id: id.clone(),
|
||||||
@@ -229,6 +240,7 @@ impl Channel {
|
|||||||
default_permissions: None,
|
default_permissions: None,
|
||||||
role_permissions: HashMap::new(),
|
role_permissions: HashMap::new(),
|
||||||
nsfw: data.nsfw.unwrap_or(false),
|
nsfw: data.nsfw.unwrap_or(false),
|
||||||
|
parent: None
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -437,6 +449,13 @@ impl Channel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parent(&self) -> Option<&str> {
|
||||||
|
match self {
|
||||||
|
Channel::TextChannel { parent, .. } | Channel::VoiceChannel { parent, .. } => parent.as_deref(),
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Set role permission on a channel
|
/// Set role permission on a channel
|
||||||
pub async fn set_role_permission(
|
pub async fn set_role_permission(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
use revolt_models::v0::{self, DataCreateServerChannel};
|
use revolt_models::v0::{self, DataCreateCategory, DataCreateServerChannel, DataEditCategory};
|
||||||
use revolt_permissions::{OverrideField, DEFAULT_PERMISSION_SERVER};
|
use revolt_permissions::{OverrideField, DEFAULT_PERMISSION_SERVER};
|
||||||
use revolt_result::Result;
|
use revolt_result::Result;
|
||||||
use ulid::Ulid;
|
use ulid::Ulid;
|
||||||
@@ -26,8 +26,8 @@ auto_derived_partial!(
|
|||||||
// TODO: investigate if this is redundant and can be removed
|
// TODO: investigate if this is redundant and can be removed
|
||||||
pub channels: Vec<String>,
|
pub channels: Vec<String>,
|
||||||
/// Categories for this server
|
/// Categories for this server
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "HashMap::is_empty")]
|
||||||
pub categories: Option<Vec<Category>>,
|
pub categories: HashMap<String, Category>,
|
||||||
/// Configuration for sending system event messages
|
/// Configuration for sending system event messages
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub system_messages: Option<SystemMessageChannels>,
|
pub system_messages: Option<SystemMessageChannels>,
|
||||||
@@ -87,17 +87,29 @@ auto_derived_partial!(
|
|||||||
"PartialRole"
|
"PartialRole"
|
||||||
);
|
);
|
||||||
|
|
||||||
auto_derived!(
|
auto_derived_partial!(
|
||||||
/// Channel category
|
/// Channel category
|
||||||
pub struct Category {
|
pub struct Category {
|
||||||
/// Unique ID for this category
|
/// Unique ID for this category
|
||||||
pub id: String,
|
pub id: String,
|
||||||
/// Title for this category
|
/// Title for this category
|
||||||
pub title: String,
|
pub title: String,
|
||||||
|
/// Default permissions assigned to users in this category
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub default_permissions: Option<OverrideField>,
|
||||||
|
/// Permissions assigned based on role to this category
|
||||||
|
#[serde(
|
||||||
|
default = "HashMap::<String, OverrideField>::new",
|
||||||
|
skip_serializing_if = "HashMap::<String, OverrideField>::is_empty"
|
||||||
|
)]
|
||||||
|
pub role_permissions: HashMap<String, OverrideField>,
|
||||||
/// Channels in this category
|
/// Channels in this category
|
||||||
pub channels: Vec<String>,
|
pub channels: Vec<String>,
|
||||||
}
|
},
|
||||||
|
"PartialCategory"
|
||||||
|
);
|
||||||
|
|
||||||
|
auto_derived!(
|
||||||
/// System message channel assignments
|
/// System message channel assignments
|
||||||
pub struct SystemMessageChannels {
|
pub struct SystemMessageChannels {
|
||||||
/// ID of channel to send user join messages in
|
/// ID of channel to send user join messages in
|
||||||
@@ -127,6 +139,10 @@ auto_derived!(
|
|||||||
pub enum FieldsRole {
|
pub enum FieldsRole {
|
||||||
Colour,
|
Colour,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum FieldsCategory {
|
||||||
|
DefaultPermissions
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
#[allow(clippy::disallowed_methods)]
|
#[allow(clippy::disallowed_methods)]
|
||||||
@@ -149,7 +165,7 @@ impl Server {
|
|||||||
|
|
||||||
analytics: false,
|
analytics: false,
|
||||||
banner: None,
|
banner: None,
|
||||||
categories: None,
|
categories: HashMap::new(),
|
||||||
discoverable: false,
|
discoverable: false,
|
||||||
flags: None,
|
flags: None,
|
||||||
icon: None,
|
icon: None,
|
||||||
@@ -221,7 +237,7 @@ impl Server {
|
|||||||
pub fn remove_field(&mut self, field: &FieldsServer) {
|
pub fn remove_field(&mut self, field: &FieldsServer) {
|
||||||
match field {
|
match field {
|
||||||
FieldsServer::Description => self.description = None,
|
FieldsServer::Description => self.description = None,
|
||||||
FieldsServer::Categories => self.categories = None,
|
FieldsServer::Categories => self.categories.clear(),
|
||||||
FieldsServer::SystemMessages => self.system_messages = None,
|
FieldsServer::SystemMessages => self.system_messages = None,
|
||||||
FieldsServer::Icon => self.icon = None,
|
FieldsServer::Icon => self.icon = None,
|
||||||
FieldsServer::Banner => self.banner = None,
|
FieldsServer::Banner => self.banner = None,
|
||||||
@@ -334,6 +350,110 @@ impl Role {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Category {
|
||||||
|
pub fn remove_field(&mut self, field: FieldsCategory) {
|
||||||
|
match field {
|
||||||
|
FieldsCategory::DefaultPermissions => self.default_permissions = None
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn create(db: &Database, server: &mut Server, data: DataCreateCategory) -> Result<Category> {
|
||||||
|
let channels = data.channels.clone().unwrap_or_default()
|
||||||
|
.into_iter()
|
||||||
|
.filter(|c| server.channels.contains(&c))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let category = Category {
|
||||||
|
id: Ulid::new().to_string(),
|
||||||
|
title: data.title,
|
||||||
|
channels: channels,
|
||||||
|
default_permissions: None,
|
||||||
|
role_permissions: HashMap::new()
|
||||||
|
};
|
||||||
|
|
||||||
|
server.categories.insert(category.id.clone(), category.clone());
|
||||||
|
|
||||||
|
let partial_server = PartialServer { categories: Some(server.categories.clone()), ..Default::default() };
|
||||||
|
|
||||||
|
db.update_server(&server.id, &partial_server, Vec::new()).await?;
|
||||||
|
|
||||||
|
EventV1::ServerUpdate {
|
||||||
|
id: server.id.clone(),
|
||||||
|
data: partial_server.into(),
|
||||||
|
clear: Vec::new(),
|
||||||
|
}
|
||||||
|
.p(server.id.clone())
|
||||||
|
.await;
|
||||||
|
|
||||||
|
Ok(category)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn delete(&self, db: &Database, server: &mut Server) -> Result<()> {
|
||||||
|
// update the parent server model with the new category
|
||||||
|
server.categories.remove(&self.id);
|
||||||
|
|
||||||
|
let partial_server = PartialServer { categories: Some(server.categories.clone()), ..Default::default() };
|
||||||
|
|
||||||
|
db.update_server(&server.id, &partial_server, Vec::new()).await?;
|
||||||
|
|
||||||
|
EventV1::ServerUpdate {
|
||||||
|
id: server.id.clone(),
|
||||||
|
data: partial_server.into(),
|
||||||
|
clear: Vec::new(),
|
||||||
|
}
|
||||||
|
.p(server.id.clone())
|
||||||
|
.await;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn update(&mut self, db: &Database, server: &mut Server, partial: PartialCategory, remove: Vec<FieldsCategory>) -> Result<()> {
|
||||||
|
for field in remove {
|
||||||
|
self.remove_field(field);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.apply_options(partial);
|
||||||
|
|
||||||
|
// update the parent server model with the new category
|
||||||
|
server.categories.insert(self.id.clone(), self.clone());
|
||||||
|
|
||||||
|
let partial_server = PartialServer { categories: Some(server.categories.clone()), ..Default::default() };
|
||||||
|
|
||||||
|
db.update_server(&server.id, &partial_server, Vec::new()).await?;
|
||||||
|
|
||||||
|
EventV1::ServerUpdate {
|
||||||
|
id: server.id.clone(),
|
||||||
|
data: partial_server.into(),
|
||||||
|
clear: Vec::new(),
|
||||||
|
}
|
||||||
|
.p(server.id.clone())
|
||||||
|
.await;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn set_role_permission(&mut self, db: &Database, server: &mut Server, role_id: String, role_override: OverrideField) -> Result<()> {
|
||||||
|
self.role_permissions.insert(role_id, role_override);
|
||||||
|
|
||||||
|
// update the parent server model with the new category
|
||||||
|
server.categories.insert(self.id.clone(), self.clone());
|
||||||
|
|
||||||
|
let partial_server = PartialServer { categories: Some(server.categories.clone()), ..Default::default() };
|
||||||
|
|
||||||
|
db.update_server(&server.id, &partial_server, Vec::new()).await?;
|
||||||
|
|
||||||
|
EventV1::ServerUpdate {
|
||||||
|
id: server.id.clone(),
|
||||||
|
data: partial_server.into(),
|
||||||
|
clear: Vec::new(),
|
||||||
|
}
|
||||||
|
.p(server.id.clone())
|
||||||
|
.await;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl SystemMessageChannels {
|
impl SystemMessageChannels {
|
||||||
pub fn into_channel_ids(self) -> HashSet<String> {
|
pub fn into_channel_ids(self) -> HashSet<String> {
|
||||||
let mut ids = HashSet::new();
|
let mut ids = HashSet::new();
|
||||||
|
|||||||
@@ -187,6 +187,7 @@ impl From<crate::Channel> for Channel {
|
|||||||
last_message_id,
|
last_message_id,
|
||||||
default_permissions,
|
default_permissions,
|
||||||
role_permissions,
|
role_permissions,
|
||||||
|
parent,
|
||||||
nsfw,
|
nsfw,
|
||||||
} => Channel::TextChannel {
|
} => Channel::TextChannel {
|
||||||
id,
|
id,
|
||||||
@@ -197,6 +198,7 @@ impl From<crate::Channel> for Channel {
|
|||||||
last_message_id,
|
last_message_id,
|
||||||
default_permissions,
|
default_permissions,
|
||||||
role_permissions,
|
role_permissions,
|
||||||
|
parent,
|
||||||
nsfw,
|
nsfw,
|
||||||
},
|
},
|
||||||
crate::Channel::VoiceChannel {
|
crate::Channel::VoiceChannel {
|
||||||
@@ -207,6 +209,7 @@ impl From<crate::Channel> for Channel {
|
|||||||
icon,
|
icon,
|
||||||
default_permissions,
|
default_permissions,
|
||||||
role_permissions,
|
role_permissions,
|
||||||
|
parent,
|
||||||
nsfw,
|
nsfw,
|
||||||
} => Channel::VoiceChannel {
|
} => Channel::VoiceChannel {
|
||||||
id,
|
id,
|
||||||
@@ -216,6 +219,7 @@ impl From<crate::Channel> for Channel {
|
|||||||
icon: icon.map(|file| file.into()),
|
icon: icon.map(|file| file.into()),
|
||||||
default_permissions,
|
default_permissions,
|
||||||
role_permissions,
|
role_permissions,
|
||||||
|
parent,
|
||||||
nsfw,
|
nsfw,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -267,6 +271,7 @@ impl From<Channel> for crate::Channel {
|
|||||||
last_message_id,
|
last_message_id,
|
||||||
default_permissions,
|
default_permissions,
|
||||||
role_permissions,
|
role_permissions,
|
||||||
|
parent,
|
||||||
nsfw,
|
nsfw,
|
||||||
} => crate::Channel::TextChannel {
|
} => crate::Channel::TextChannel {
|
||||||
id,
|
id,
|
||||||
@@ -277,6 +282,7 @@ impl From<Channel> for crate::Channel {
|
|||||||
last_message_id,
|
last_message_id,
|
||||||
default_permissions,
|
default_permissions,
|
||||||
role_permissions,
|
role_permissions,
|
||||||
|
parent,
|
||||||
nsfw,
|
nsfw,
|
||||||
},
|
},
|
||||||
Channel::VoiceChannel {
|
Channel::VoiceChannel {
|
||||||
@@ -287,6 +293,7 @@ impl From<Channel> for crate::Channel {
|
|||||||
icon,
|
icon,
|
||||||
default_permissions,
|
default_permissions,
|
||||||
role_permissions,
|
role_permissions,
|
||||||
|
parent,
|
||||||
nsfw,
|
nsfw,
|
||||||
} => crate::Channel::VoiceChannel {
|
} => crate::Channel::VoiceChannel {
|
||||||
id,
|
id,
|
||||||
@@ -296,6 +303,7 @@ impl From<Channel> for crate::Channel {
|
|||||||
icon: icon.map(|file| file.into()),
|
icon: icon.map(|file| file.into()),
|
||||||
default_permissions,
|
default_permissions,
|
||||||
role_permissions,
|
role_permissions,
|
||||||
|
parent,
|
||||||
nsfw,
|
nsfw,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -315,6 +323,7 @@ impl From<crate::PartialChannel> for PartialChannel {
|
|||||||
role_permissions: value.role_permissions,
|
role_permissions: value.role_permissions,
|
||||||
default_permissions: value.default_permissions,
|
default_permissions: value.default_permissions,
|
||||||
last_message_id: value.last_message_id,
|
last_message_id: value.last_message_id,
|
||||||
|
parent: value.parent,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -332,6 +341,7 @@ impl From<PartialChannel> for crate::PartialChannel {
|
|||||||
role_permissions: value.role_permissions,
|
role_permissions: value.role_permissions,
|
||||||
default_permissions: value.default_permissions,
|
default_permissions: value.default_permissions,
|
||||||
last_message_id: value.last_message_id,
|
last_message_id: value.last_message_id,
|
||||||
|
parent: value.parent,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -729,9 +739,7 @@ impl From<crate::Server> for Server {
|
|||||||
name: value.name,
|
name: value.name,
|
||||||
description: value.description,
|
description: value.description,
|
||||||
channels: value.channels,
|
channels: value.channels,
|
||||||
categories: value
|
categories: value.categories.into_iter().map(|(k, v)| (k, v.into())).collect(),
|
||||||
.categories
|
|
||||||
.map(|categories| categories.into_iter().map(|v| v.into()).collect()),
|
|
||||||
system_messages: value.system_messages.map(|v| v.into()),
|
system_messages: value.system_messages.map(|v| v.into()),
|
||||||
roles: value
|
roles: value
|
||||||
.roles
|
.roles
|
||||||
@@ -757,9 +765,7 @@ impl From<Server> for crate::Server {
|
|||||||
name: value.name,
|
name: value.name,
|
||||||
description: value.description,
|
description: value.description,
|
||||||
channels: value.channels,
|
channels: value.channels,
|
||||||
categories: value
|
categories: value.categories.into_iter().map(|(k, v)| (k, v.into())).collect(),
|
||||||
.categories
|
|
||||||
.map(|categories| categories.into_iter().map(|v| v.into()).collect()),
|
|
||||||
system_messages: value.system_messages.map(|v| v.into()),
|
system_messages: value.system_messages.map(|v| v.into()),
|
||||||
roles: value
|
roles: value
|
||||||
.roles
|
.roles
|
||||||
@@ -785,9 +791,7 @@ impl From<crate::PartialServer> for PartialServer {
|
|||||||
name: value.name,
|
name: value.name,
|
||||||
description: value.description,
|
description: value.description,
|
||||||
channels: value.channels,
|
channels: value.channels,
|
||||||
categories: value
|
categories: value.categories.map(|x| x.into_iter().map(|(k, v)| (k, v.into())).collect()),
|
||||||
.categories
|
|
||||||
.map(|categories| categories.into_iter().map(|v| v.into()).collect()),
|
|
||||||
system_messages: value.system_messages.map(|v| v.into()),
|
system_messages: value.system_messages.map(|v| v.into()),
|
||||||
roles: value
|
roles: value
|
||||||
.roles
|
.roles
|
||||||
@@ -811,9 +815,7 @@ impl From<PartialServer> for crate::PartialServer {
|
|||||||
name: value.name,
|
name: value.name,
|
||||||
description: value.description,
|
description: value.description,
|
||||||
channels: value.channels,
|
channels: value.channels,
|
||||||
categories: value
|
categories: value.categories.map(|x| x.into_iter().map(|(k, v)| (k, v.into())).collect()),
|
||||||
.categories
|
|
||||||
.map(|categories| categories.into_iter().map(|v| v.into()).collect()),
|
|
||||||
system_messages: value.system_messages.map(|v| v.into()),
|
system_messages: value.system_messages.map(|v| v.into()),
|
||||||
roles: value
|
roles: value
|
||||||
.roles
|
.roles
|
||||||
@@ -859,6 +861,8 @@ impl From<crate::Category> for Category {
|
|||||||
id: value.id,
|
id: value.id,
|
||||||
title: value.title,
|
title: value.title,
|
||||||
channels: value.channels,
|
channels: value.channels,
|
||||||
|
role_permissions: value.role_permissions,
|
||||||
|
default_permissions: value.default_permissions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -869,6 +873,24 @@ impl From<Category> for crate::Category {
|
|||||||
id: value.id,
|
id: value.id,
|
||||||
title: value.title,
|
title: value.title,
|
||||||
channels: value.channels,
|
channels: value.channels,
|
||||||
|
role_permissions: value.role_permissions,
|
||||||
|
default_permissions: value.default_permissions,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<crate::FieldsCategory> for FieldsCategory {
|
||||||
|
fn from(value: crate::FieldsCategory) -> Self {
|
||||||
|
match value {
|
||||||
|
crate::FieldsCategory::DefaultPermissions => FieldsCategory::DefaultPermissions,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<FieldsCategory> for crate::FieldsCategory {
|
||||||
|
fn from(value: FieldsCategory) -> crate::FieldsCategory {
|
||||||
|
match value {
|
||||||
|
FieldsCategory::DefaultPermissions => crate::FieldsCategory::DefaultPermissions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use revolt_permissions::{
|
|||||||
DEFAULT_PERMISSION_DIRECT_MESSAGE,
|
DEFAULT_PERMISSION_DIRECT_MESSAGE,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{Channel, Database, Member, Server, User};
|
use crate::{Category, Channel, Database, Member, Server, User};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct BulkDatabasePermissionQuery<'a> {
|
pub struct BulkDatabasePermissionQuery<'a> {
|
||||||
@@ -197,7 +197,7 @@ async fn calculate_members_permissions<'a>(
|
|||||||
) -> HashMap<String, PermissionValue> {
|
) -> HashMap<String, PermissionValue> {
|
||||||
let mut resp = HashMap::new();
|
let mut resp = HashMap::new();
|
||||||
|
|
||||||
let (_, channel_role_permissions, channel_default_permissions) = match query
|
let (_, channel_role_permissions, channel_default_permissions, parent) = match query
|
||||||
.channel
|
.channel
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.expect("A channel must be assigned to calculate channel permissions")
|
.expect("A channel must be assigned to calculate channel permissions")
|
||||||
@@ -207,14 +207,16 @@ async fn calculate_members_permissions<'a>(
|
|||||||
id,
|
id,
|
||||||
role_permissions,
|
role_permissions,
|
||||||
default_permissions,
|
default_permissions,
|
||||||
|
parent,
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
| Channel::VoiceChannel {
|
| Channel::VoiceChannel {
|
||||||
id,
|
id,
|
||||||
role_permissions,
|
role_permissions,
|
||||||
default_permissions,
|
default_permissions,
|
||||||
|
parent,
|
||||||
..
|
..
|
||||||
} => (id, role_permissions, default_permissions),
|
} => (id, role_permissions, default_permissions, parent),
|
||||||
_ => panic!("Calculation of member permissions must be done on a server channel"),
|
_ => panic!("Calculation of member permissions must be done on a server channel"),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -268,6 +270,8 @@ async fn calculate_members_permissions<'a>(
|
|||||||
.map(|m| (&m.id.user, m)),
|
.map(|m| (&m.id.user, m)),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let category = parent.map(|parent| query.server.categories.get(&parent).expect("Channel parent doesnt exist"));
|
||||||
|
|
||||||
for user in users {
|
for user in users {
|
||||||
let member = members.get(&user.id);
|
let member = members.get(&user.id);
|
||||||
|
|
||||||
@@ -298,11 +302,39 @@ async fn calculate_members_permissions<'a>(
|
|||||||
// Get the user's server permissions
|
// Get the user's server permissions
|
||||||
let mut permission = calculate_server_permissions(&query.server, user, member);
|
let mut permission = calculate_server_permissions(&query.server, user, member);
|
||||||
|
|
||||||
|
// Apply category overrides
|
||||||
|
if let Some(category) = category {
|
||||||
|
if let Some(defaults) = category.default_permissions {
|
||||||
|
permission.apply(defaults.into());
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get the applicable role overrides for the category
|
||||||
|
let mut roles = category.role_permissions
|
||||||
|
.iter()
|
||||||
|
.filter(|(id, _)| member.roles.contains(id))
|
||||||
|
.filter_map(|(id, permission)| {
|
||||||
|
query.server.roles.get(id).map(|role| {
|
||||||
|
let v: Override = (*permission).into();
|
||||||
|
(role.rank, v)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect::<Vec<(i64, Override)>>();
|
||||||
|
|
||||||
|
roles.sort_by(|a, b| b.0.cmp(&a.0));
|
||||||
|
let overrides = roles.into_iter().map(|(_, v)| v);
|
||||||
|
|
||||||
|
for role_override in overrides {
|
||||||
|
permission.apply(role_override)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// apply channel overrides
|
||||||
|
|
||||||
if let Some(defaults) = channel_default_permissions {
|
if let Some(defaults) = channel_default_permissions {
|
||||||
permission.apply(defaults.into());
|
permission.apply(defaults.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the applicable role overrides
|
// Get the applicable role overrides for the channel
|
||||||
let mut roles = channel_role_permissions
|
let mut roles = channel_role_permissions
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(id, _)| member.roles.contains(id))
|
.filter(|(id, _)| member.roles.contains(id))
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use revolt_permissions::{
|
|||||||
RelationshipStatus, DEFAULT_PERMISSION_DIRECT_MESSAGE,
|
RelationshipStatus, DEFAULT_PERMISSION_DIRECT_MESSAGE,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{Channel, Database, Member, Server, User};
|
use crate::{Category, Channel, Database, Member, Server, User};
|
||||||
|
|
||||||
/// Permissions calculator
|
/// Permissions calculator
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -16,6 +16,7 @@ pub struct DatabasePermissionQuery<'a> {
|
|||||||
perspective: &'a User,
|
perspective: &'a User,
|
||||||
user: Option<Cow<'a, User>>,
|
user: Option<Cow<'a, User>>,
|
||||||
channel: Option<Cow<'a, Channel>>,
|
channel: Option<Cow<'a, Channel>>,
|
||||||
|
category: Option<Cow<'a, Category>>,
|
||||||
server: Option<Cow<'a, Server>>,
|
server: Option<Cow<'a, Server>>,
|
||||||
member: Option<Cow<'a, Member>>,
|
member: Option<Cow<'a, Member>>,
|
||||||
|
|
||||||
@@ -288,6 +289,40 @@ impl PermissionQuery for DatabasePermissionQuery<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_default_category_permissions(&mut self) -> Override {
|
||||||
|
if let Some(category) = &self.category {
|
||||||
|
category.default_permissions.unwrap_or_default().into()
|
||||||
|
} else {
|
||||||
|
Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_our_category_role_overrides(&mut self) -> Vec<Override> {
|
||||||
|
if let Some((server, category)) = self.server.as_ref().zip(self.category.as_ref()) {
|
||||||
|
let member_roles = self
|
||||||
|
.member
|
||||||
|
.as_ref()
|
||||||
|
.map(|member| member.roles.clone())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
let mut roles = category.role_permissions
|
||||||
|
.iter()
|
||||||
|
.filter(|(id, _)| member_roles.contains(id))
|
||||||
|
.filter_map(|(id, permission)| {
|
||||||
|
server.roles.get(id).map(|role| {
|
||||||
|
let v: Override = (*permission).into();
|
||||||
|
(role.rank, v)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect::<Vec<(i64, Override)>>();
|
||||||
|
|
||||||
|
roles.sort_by(|a, b| b.0.cmp(&a.0));
|
||||||
|
roles.into_iter().map(|(_, v)| v).collect()
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Do we own this group or saved messages channel if it is one of those?
|
/// Do we own this group or saved messages channel if it is one of those?
|
||||||
async fn do_we_own_the_channel(&mut self) -> bool {
|
async fn do_we_own_the_channel(&mut self) -> bool {
|
||||||
if let Some(channel) = &self.channel {
|
if let Some(channel) = &self.channel {
|
||||||
@@ -375,6 +410,14 @@ impl PermissionQuery for DatabasePermissionQuery<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn set_category_from_channel(&mut self) {
|
||||||
|
if let Some((server, channel)) = self.server.as_ref().zip(self.channel.as_ref()) {
|
||||||
|
let category = channel.parent().and_then(|id| server.categories.get(id)).cloned();
|
||||||
|
|
||||||
|
self.category = category.map(Cow::Owned);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> DatabasePermissionQuery<'a> {
|
impl<'a> DatabasePermissionQuery<'a> {
|
||||||
@@ -385,6 +428,7 @@ impl<'a> DatabasePermissionQuery<'a> {
|
|||||||
perspective,
|
perspective,
|
||||||
user: None,
|
user: None,
|
||||||
channel: None,
|
channel: None,
|
||||||
|
category: None,
|
||||||
server: None,
|
server: None,
|
||||||
member: None,
|
member: None,
|
||||||
|
|
||||||
@@ -443,6 +487,13 @@ impl<'a> DatabasePermissionQuery<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn category(self, category: &'a Category) -> DatabasePermissionQuery<'a> {
|
||||||
|
DatabasePermissionQuery {
|
||||||
|
category: Some(Cow::Borrowed(category)),
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Use member
|
/// Use member
|
||||||
pub fn member(self, member: &'a Member) -> DatabasePermissionQuery {
|
pub fn member(self, member: &'a Member) -> DatabasePermissionQuery {
|
||||||
DatabasePermissionQuery {
|
DatabasePermissionQuery {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use schemars::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Bot, Channel, Database, Emoji, Invite, Member, Message, Server, ServerBan, User, Webhook,
|
Bot, Category, Channel, Database, Emoji, Invite, Member, Message, Server, ServerBan, User, Webhook
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Reference to some object in the database
|
/// Reference to some object in the database
|
||||||
|
|||||||
@@ -1,188 +0,0 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!-- Compiled with Bootstrap Email version: 1.5.1 --><meta http-equiv="x-ua-compatible" content="ie=edge">
|
|
||||||
<meta name="x-apple-disable-message-reformatting">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<meta name="format-detection" content="telephone=no, date=no, address=no, email=no">
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
||||||
<style type="text/css">
|
|
||||||
body,table,td{font-family:Helvetica,Arial,sans-serif !important}.ExternalClass{width:100%}.ExternalClass,.ExternalClass p,.ExternalClass span,.ExternalClass font,.ExternalClass td,.ExternalClass div{line-height:150%}a{text-decoration:none}*{color:inherit}a[x-apple-data-detectors],u+#body a,#MessageViewBody a{color:inherit;text-decoration:none;font-size:inherit;font-family:inherit;font-weight:inherit;line-height:inherit}img{-ms-interpolation-mode:bicubic}table:not([class^=s-]){font-family:Helvetica,Arial,sans-serif;mso-table-lspace:0pt;mso-table-rspace:0pt;border-spacing:0px;border-collapse:collapse}table:not([class^=s-]) td{border-spacing:0px;border-collapse:collapse}@media screen and (max-width: 600px){.w-full,.w-full>tbody>tr>td{width:100% !important}.w-24,.w-24>tbody>tr>td{width:96px !important}.p-lg-10:not(table),.p-lg-10:not(.btn)>tbody>tr>td,.p-lg-10.btn td a{padding:0 !important}.p-3:not(table),.p-3:not(.btn)>tbody>tr>td,.p-3.btn td a{padding:12px !important}.p-6:not(table),.p-6:not(.btn)>tbody>tr>td,.p-6.btn td a{padding:24px !important}*[class*=s-lg-]>tbody>tr>td{font-size:0 !important;line-height:0 !important;height:0 !important}.s-4>tbody>tr>td{font-size:16px !important;line-height:16px !important;height:16px !important}.s-6>tbody>tr>td{font-size:24px !important;line-height:24px !important;height:24px !important}.s-10>tbody>tr>td{font-size:40px !important;line-height:40px !important;height:40px !important}}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body class="bg-light" style="outline: 0; width: 100%; min-width: 100%; height: 100%; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; font-family: Helvetica, Arial, sans-serif; line-height: 24px; font-weight: normal; font-size: 16px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; color: #000000; margin: 0; padding: 0; border-width: 0;" bgcolor="#f7fafc">
|
|
||||||
<table class="bg-light body" valign="top" role="presentation" border="0" cellpadding="0" cellspacing="0" style="outline: 0; width: 100%; min-width: 100%; height: 100%; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; font-family: Helvetica, Arial, sans-serif; line-height: 24px; font-weight: normal; font-size: 16px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; color: #000000; margin: 0; padding: 0; border-width: 0;" bgcolor="#f7fafc">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td valign="top" style="line-height: 24px; font-size: 16px; margin: 0;" align="left" bgcolor="#f7fafc">
|
|
||||||
<table class="container" role="presentation" border="0" cellpadding="0" cellspacing="0" style="width: 100%;">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td align="center" style="line-height: 24px; font-size: 16px; margin: 0; padding: 0 16px;">
|
|
||||||
<!--[if (gte mso 9)|(IE)]>
|
|
||||||
<table align="center" role="presentation">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td width="600">
|
|
||||||
<![endif]-->
|
|
||||||
<table align="center" role="presentation" border="0" cellpadding="0" cellspacing="0" style="width: 100%; max-width: 600px; margin: 0 auto;">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td style="line-height: 24px; font-size: 16px; margin: 0;" align="left">
|
|
||||||
<table class="s-10 w-full" role="presentation" border="0" cellpadding="0" cellspacing="0" style="width: 100%;" width="100%">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td style="line-height: 40px; font-size: 40px; width: 100%; height: 40px; margin: 0;" align="left" width="100%" height="40">
|
|
||||||
 
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<table class="ax-center" role="presentation" align="center" border="0" cellpadding="0" cellspacing="0" style="margin: 0 auto;">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td style="line-height: 24px; font-size: 16px; margin: 0;" align="left">
|
|
||||||
<img class="w-24" src="https://app.revolt.chat/assets/logo_round.png" style="height: auto; line-height: 100%; outline: none; text-decoration: none; display: block; width: 96px; border-style: none; border-width: 0;" width="96">
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<table class="s-10 w-full" role="presentation" border="0" cellpadding="0" cellspacing="0" style="width: 100%;" width="100%">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td style="line-height: 40px; font-size: 40px; width: 100%; height: 40px; margin: 0;" align="left" width="100%" height="40">
|
|
||||||
 
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<table class="card p-6 p-lg-10 space-y-4" role="presentation" border="0" cellpadding="0" cellspacing="0" style="border-radius: 6px; border-collapse: separate !important; width: 100%; overflow: hidden; border: 1px solid #e2e8f0;" bgcolor="#ffffff">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td style="line-height: 24px; font-size: 16px; width: 100%; margin: 0; padding: 40px;" align="left" bgcolor="#ffffff">
|
|
||||||
<h1 class="h3 fw-700" style="padding-top: 0; padding-bottom: 0; font-weight: 700 !important; vertical-align: baseline; font-size: 28px; line-height: 33.6px; margin: 0;" align="left">Password Reset</h1>
|
|
||||||
<table class="s-4 w-full" role="presentation" border="0" cellpadding="0" cellspacing="0" style="width: 100%;" width="100%">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td style="line-height: 16px; font-size: 16px; width: 100%; height: 16px; margin: 0;" align="left" width="100%" height="16">
|
|
||||||
 
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<p class="" style="line-height: 24px; font-size: 16px; width: 100%; margin: 0;" align="left">
|
|
||||||
You tried to create a new account with or try to re-verify this email
|
|
||||||
but there is already an existing verified account under this email.
|
|
||||||
</p>
|
|
||||||
<table class="s-4 w-full" role="presentation" border="0" cellpadding="0" cellspacing="0" style="width: 100%;" width="100%">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td style="line-height: 16px; font-size: 16px; width: 100%; height: 16px; margin: 0;" align="left" width="100%" height="16">
|
|
||||||
 
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<p class="" style="line-height: 24px; font-size: 16px; width: 100%; margin: 0;" align="left">
|
|
||||||
If you wish, you can now proceed to reset the password on it, click
|
|
||||||
below to continue.
|
|
||||||
</p>
|
|
||||||
<table class="s-4 w-full" role="presentation" border="0" cellpadding="0" cellspacing="0" style="width: 100%;" width="100%">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td style="line-height: 16px; font-size: 16px; width: 100%; height: 16px; margin: 0;" align="left" width="100%" height="16">
|
|
||||||
 
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<table class="btn btn-primary p-3 fw-700" role="presentation" border="0" cellpadding="0" cellspacing="0" style="border-radius: 6px; border-collapse: separate !important; font-weight: 700 !important;">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td style="line-height: 24px; font-size: 16px; border-radius: 6px; font-weight: 700 !important; margin: 0;" align="center" bgcolor="#0d6efd">
|
|
||||||
<a href="{{url}}" style="color: #ffffff; font-size: 16px; font-family: Helvetica, Arial, sans-serif; text-decoration: none; border-radius: 6px; line-height: 20px; display: block; font-weight: 700 !important; white-space: nowrap; background-color: #0d6efd; padding: 12px; border: 1px solid #0d6efd;">Reset</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<table class="s-6 w-full" role="presentation" border="0" cellpadding="0" cellspacing="0" style="width: 100%;" width="100%">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td style="line-height: 24px; font-size: 24px; width: 100%; height: 24px; margin: 0;" align="left" width="100%" height="24">
|
|
||||||
 
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<div class="text-muted text-center" style="color: #718096;" align="center">
|
|
||||||
This email is intended for {{email}}<br>
|
|
||||||
Sent from Revolt<br>
|
|
||||||
Made in Europe
|
|
||||||
</div>
|
|
||||||
<table class="s-6 w-full" role="presentation" border="0" cellpadding="0" cellspacing="0" style="width: 100%;" width="100%">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td style="line-height: 24px; font-size: 24px; width: 100%; height: 24px; margin: 0;" align="left" width="100%" height="24">
|
|
||||||
 
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<table class="s-6 w-full" role="presentation" border="0" cellpadding="0" cellspacing="0" style="width: 100%;" width="100%">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td style="line-height: 24px; font-size: 24px; width: 100%; height: 24px; margin: 0;" align="left" width="100%" height="24">
|
|
||||||
 
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<table class="ax-center" role="presentation" align="center" border="0" cellpadding="0" cellspacing="0" style="margin: 0 auto;">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td style="line-height: 24px; font-size: 16px; margin: 0;" align="left">
|
|
||||||
<div class="text-muted text-xs" style="color: #718096; font-size: 12px; line-height: 14.4px;">
|
|
||||||
Revolt Platforms Ltd. is a company incorporated and registered under the
|
|
||||||
laws of England and Wales.<br>
|
|
||||||
Registered Company Number: 16260658<br>
|
|
||||||
Registered Office:<br>
|
|
||||||
Suite 5703 Unit 3A, 34-35 Hatton Garden,<br>
|
|
||||||
Holborn, United Kingdom, EC1N 8DX
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<table class="s-6 w-full" role="presentation" border="0" cellpadding="0" cellspacing="0" style="width: 100%;" width="100%">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td style="line-height: 24px; font-size: 24px; width: 100%; height: 24px; margin: 0;" align="left" width="100%" height="24">
|
|
||||||
 
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<!--[if (gte mso 9)|(IE)]>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<![endif]-->
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
||||||
<style>
|
|
||||||
/* Add custom classes and styles that you want inlined here */
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body class="bg-light">
|
|
||||||
<div class="container">
|
|
||||||
<img
|
|
||||||
class="ax-center my-10 w-24"
|
|
||||||
src="https://app.revolt.chat/assets/logo_round.png"
|
|
||||||
/>
|
|
||||||
<div class="card p-6 p-lg-10 space-y-4">
|
|
||||||
<h1 class="h3 fw-700">Password Reset</h1>
|
|
||||||
<p>
|
|
||||||
You tried to create a new account with or try to re-verify this email
|
|
||||||
but there is already an existing verified account under this email.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
If you wish, you can now proceed to reset the password on it, click
|
|
||||||
below to continue.
|
|
||||||
</p>
|
|
||||||
<a class="btn btn-primary p-3 fw-700" href="{{url}}">Reset</a>
|
|
||||||
</div>
|
|
||||||
<div class="text-muted text-center my-6">
|
|
||||||
This email is intended for {{email}}<br />
|
|
||||||
Sent from Revolt<br />
|
|
||||||
Made in Europe
|
|
||||||
</div>
|
|
||||||
<div class="text-muted text-xs my-6 ax-center">
|
|
||||||
Revolt Platforms Ltd. is a company incorporated and registered under the
|
|
||||||
laws of England and Wales.<br />
|
|
||||||
Registered Company Number: 16260658<br />
|
|
||||||
Registered Office:<br />
|
|
||||||
Suite 5703 Unit 3A, 34-35 Hatton Garden,<br />
|
|
||||||
Holborn, United Kingdom, EC1N 8DX
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
You tried to create a new account with or try
|
|
||||||
to re-verify this email but there is already
|
|
||||||
an existing verified account under this email.
|
|
||||||
|
|
||||||
If you wish, you can now proceed to reset the
|
|
||||||
password on it, click below to continue.
|
|
||||||
|
|
||||||
Please navigate to: {{url}}
|
|
||||||
|
|
||||||
This email is intended for {{email}}
|
|
||||||
Sent by Revolt
|
|
||||||
Made in Europe
|
|
||||||
|
|
||||||
Revolt Platforms Ltd. is a company incorporated and registered under the laws of England and Wales.
|
|
||||||
|
|
||||||
Registration Number: 16260658
|
|
||||||
Registered Office:
|
|
||||||
Suite 5703 Unit 3A, 34-35 Hatton Garden,
|
|
||||||
Holborn, United Kingdom, EC1N 8DX
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "revolt-files"
|
name = "revolt-files"
|
||||||
version = "0.8.5"
|
version = "0.8.4"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "AGPL-3.0-or-later"
|
license = "AGPL-3.0-or-later"
|
||||||
authors = ["Paul Makles <me@insrt.uk>"]
|
authors = ["Paul Makles <me@insrt.uk>"]
|
||||||
@@ -20,10 +20,10 @@ typenum = "1.17.0"
|
|||||||
aws-config = "1.5.5"
|
aws-config = "1.5.5"
|
||||||
aws-sdk-s3 = { version = "1.46.0", features = ["behavior-version-latest"] }
|
aws-sdk-s3 = { version = "1.46.0", features = ["behavior-version-latest"] }
|
||||||
|
|
||||||
revolt-config = { version = "0.8.5", path = "../config", features = [
|
revolt-config = { version = "0.8.4", path = "../config", features = [
|
||||||
"report-macros",
|
"report-macros",
|
||||||
] }
|
] }
|
||||||
revolt-result = { version = "0.8.5", path = "../result" }
|
revolt-result = { version = "0.8.4", path = "../result" }
|
||||||
|
|
||||||
# image processing
|
# image processing
|
||||||
jxl-oxide = "0.8.1"
|
jxl-oxide = "0.8.1"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "revolt-models"
|
name = "revolt-models"
|
||||||
version = "0.8.5"
|
version = "0.8.4"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
authors = ["Paul Makles <me@insrt.uk>"]
|
authors = ["Paul Makles <me@insrt.uk>"]
|
||||||
@@ -20,8 +20,8 @@ default = ["serde", "partials", "rocket"]
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# Core
|
# Core
|
||||||
revolt-config = { version = "0.8.5", path = "../config" }
|
revolt-config = { version = "0.8.4", path = "../config" }
|
||||||
revolt-permissions = { version = "0.8.5", path = "../permissions" }
|
revolt-permissions = { version = "0.8.4", path = "../permissions" }
|
||||||
|
|
||||||
# Utility
|
# Utility
|
||||||
regex = "1.11"
|
regex = "1.11"
|
||||||
|
|||||||
@@ -101,6 +101,10 @@ auto_derived!(
|
|||||||
)]
|
)]
|
||||||
role_permissions: HashMap<String, OverrideField>,
|
role_permissions: HashMap<String, OverrideField>,
|
||||||
|
|
||||||
|
/// Category the channel is in
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
parent: Option<String>,
|
||||||
|
|
||||||
/// Whether this channel is marked as not safe for work
|
/// Whether this channel is marked as not safe for work
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde",
|
feature = "serde",
|
||||||
@@ -138,6 +142,10 @@ auto_derived!(
|
|||||||
)]
|
)]
|
||||||
role_permissions: HashMap<String, OverrideField>,
|
role_permissions: HashMap<String, OverrideField>,
|
||||||
|
|
||||||
|
/// Category the channel is in
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
parent: Option<String>,
|
||||||
|
|
||||||
/// Whether this channel is marked as not safe for work
|
/// Whether this channel is marked as not safe for work
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde",
|
feature = "serde",
|
||||||
@@ -170,6 +178,8 @@ auto_derived!(
|
|||||||
pub default_permissions: Option<OverrideField>,
|
pub default_permissions: Option<OverrideField>,
|
||||||
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
|
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
|
||||||
pub last_message_id: Option<String>,
|
pub last_message_id: Option<String>,
|
||||||
|
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
|
||||||
|
pub parent: Option<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Optional fields on channel object
|
/// Optional fields on channel object
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ auto_derived_partial!(
|
|||||||
// TODO: investigate if this is redundant and can be removed
|
// TODO: investigate if this is redundant and can be removed
|
||||||
pub channels: Vec<String>,
|
pub channels: Vec<String>,
|
||||||
/// Categories for this server
|
/// Categories for this server
|
||||||
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
|
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "HashMap::is_empty"))]
|
||||||
pub categories: Option<Vec<Category>>,
|
pub categories: HashMap<String, Category>,
|
||||||
/// Configuration for sending system event messages
|
/// Configuration for sending system event messages
|
||||||
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
|
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
|
||||||
pub system_messages: Option<SystemMessageChannels>,
|
pub system_messages: Option<SystemMessageChannels>,
|
||||||
@@ -126,15 +126,52 @@ auto_derived!(
|
|||||||
#[cfg_attr(feature = "validator", derive(Validate))]
|
#[cfg_attr(feature = "validator", derive(Validate))]
|
||||||
pub struct Category {
|
pub struct Category {
|
||||||
/// Unique ID for this category
|
/// Unique ID for this category
|
||||||
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 32)))]
|
|
||||||
pub id: String,
|
pub id: String,
|
||||||
/// Title for this category
|
/// Title for this category
|
||||||
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 32)))]
|
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 32)))]
|
||||||
pub title: String,
|
pub title: String,
|
||||||
|
/// Default permissions assigned to users in this channel
|
||||||
|
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
|
||||||
|
pub default_permissions: Option<OverrideField>,
|
||||||
|
/// Permissions assigned based on role to this channel
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "serde",
|
||||||
|
serde(
|
||||||
|
default = "HashMap::<String, OverrideField>::new",
|
||||||
|
skip_serializing_if = "HashMap::<String, OverrideField>::is_empty"
|
||||||
|
)
|
||||||
|
)]
|
||||||
|
pub role_permissions: HashMap<String, OverrideField>,
|
||||||
/// Channels in this category
|
/// Channels in this category
|
||||||
pub channels: Vec<String>,
|
pub channels: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "validator", derive(Validate))]
|
||||||
|
pub struct DataCreateCategory {
|
||||||
|
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 32)))]
|
||||||
|
pub title: String,
|
||||||
|
/// Channels in this category
|
||||||
|
pub channels: Option<Vec<String>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "validator", derive(Validate))]
|
||||||
|
pub struct DataEditCategory {
|
||||||
|
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 32)))]
|
||||||
|
pub title: Option<String>,
|
||||||
|
/// Channels in this category
|
||||||
|
pub channels: Option<Vec<String>>,
|
||||||
|
/// Fields to remove from category object
|
||||||
|
pub remove: Option<Vec<FieldsCategory>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum FieldsCategory {
|
||||||
|
DefaultPermissions
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DataDefaultCategoryPermissions {
|
||||||
|
pub permissions: Override
|
||||||
|
}
|
||||||
|
|
||||||
/// System message channel assignments
|
/// System message channel assignments
|
||||||
pub struct SystemMessageChannels {
|
pub struct SystemMessageChannels {
|
||||||
/// ID of channel to send user join messages in
|
/// ID of channel to send user join messages in
|
||||||
@@ -226,10 +263,6 @@ auto_derived!(
|
|||||||
pub icon: Option<String>,
|
pub icon: Option<String>,
|
||||||
/// Attachment Id for banner
|
/// Attachment Id for banner
|
||||||
pub banner: Option<String>,
|
pub banner: Option<String>,
|
||||||
|
|
||||||
/// Category structure for server
|
|
||||||
#[cfg_attr(feature = "validator", validate)]
|
|
||||||
pub categories: Option<Vec<Category>>,
|
|
||||||
/// System message configuration
|
/// System message configuration
|
||||||
pub system_messages: Option<SystemMessageChannels>,
|
pub system_messages: Option<SystemMessageChannels>,
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "revolt-parser"
|
name = "revolt-parser"
|
||||||
version = "0.1.1"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
logos = { version = "*" }
|
logos = { version = "*" }
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "revolt-permissions"
|
name = "revolt-permissions"
|
||||||
version = "0.8.5"
|
version = "0.8.4"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
authors = ["Paul Makles <me@insrt.uk>"]
|
authors = ["Paul Makles <me@insrt.uk>"]
|
||||||
@@ -21,7 +21,7 @@ async-std = { version = "1.8.0", features = ["attributes"] }
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# Core
|
# Core
|
||||||
revolt-result = { version = "0.8.5", path = "../result" }
|
revolt-result = { version = "0.8.4", path = "../result" }
|
||||||
|
|
||||||
# Utility
|
# Utility
|
||||||
auto_ops = "0.3.0"
|
auto_ops = "0.3.0"
|
||||||
|
|||||||
@@ -68,6 +68,26 @@ pub async fn calculate_server_permissions<P: PermissionQuery>(query: &mut P) ->
|
|||||||
permissions
|
permissions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn calculate_category_permissions<P: PermissionQuery>(query: &mut P) -> PermissionValue {
|
||||||
|
let mut permissions = calculate_server_permissions(query).await;
|
||||||
|
|
||||||
|
permissions.apply(query.get_default_category_permissions().await);
|
||||||
|
|
||||||
|
for role_override in query.get_our_category_role_overrides().await {
|
||||||
|
permissions.apply(role_override)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !permissions.has_channel_permission(ChannelPermission::ViewChannel) {
|
||||||
|
permissions.revoke_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
if query.are_we_timed_out().await {
|
||||||
|
permissions.restrict(*ALLOW_IN_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
permissions
|
||||||
|
}
|
||||||
|
|
||||||
/// Calculate permissions against a channel
|
/// Calculate permissions against a channel
|
||||||
pub async fn calculate_channel_permissions<P: PermissionQuery>(query: &mut P) -> PermissionValue {
|
pub async fn calculate_channel_permissions<P: PermissionQuery>(query: &mut P) -> PermissionValue {
|
||||||
if query.are_we_privileged().await {
|
if query.are_we_privileged().await {
|
||||||
@@ -109,11 +129,19 @@ pub async fn calculate_channel_permissions<P: PermissionQuery>(query: &mut P) ->
|
|||||||
}
|
}
|
||||||
ChannelType::ServerChannel => {
|
ChannelType::ServerChannel => {
|
||||||
query.set_server_from_channel().await;
|
query.set_server_from_channel().await;
|
||||||
|
query.set_category_from_channel().await;
|
||||||
|
|
||||||
if query.are_we_server_owner().await {
|
if query.are_we_server_owner().await {
|
||||||
ChannelPermission::GrantAllSafe.into()
|
ChannelPermission::GrantAllSafe.into()
|
||||||
} else if query.are_we_a_member().await {
|
} else if query.are_we_a_member().await {
|
||||||
let mut permissions = calculate_server_permissions(query).await;
|
let mut permissions = calculate_server_permissions(query).await;
|
||||||
|
|
||||||
|
permissions.apply(query.get_default_category_permissions().await);
|
||||||
|
|
||||||
|
for role_override in query.get_our_category_role_overrides().await {
|
||||||
|
permissions.apply(role_override)
|
||||||
|
}
|
||||||
|
|
||||||
permissions.apply(query.get_default_channel_permissions().await);
|
permissions.apply(query.get_default_channel_permissions().await);
|
||||||
|
|
||||||
for role_override in query.get_our_channel_role_overrides().await {
|
for role_override in query.get_our_channel_role_overrides().await {
|
||||||
@@ -135,4 +163,4 @@ pub async fn calculate_channel_permissions<P: PermissionQuery>(query: &mut P) ->
|
|||||||
}
|
}
|
||||||
ChannelType::Unknown => 0_u64.into(),
|
ChannelType::Unknown => 0_u64.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,8 +96,10 @@ pub enum ChannelPermission {
|
|||||||
/// Mention roles
|
/// Mention roles
|
||||||
MentionRoles = 1 << 38,
|
MentionRoles = 1 << 38,
|
||||||
|
|
||||||
|
MoveChannels = 1 << 39,
|
||||||
|
|
||||||
// * Misc. permissions
|
// * Misc. permissions
|
||||||
// % Bits 38 to 52: free area
|
// % Bits 40 to 52: free area
|
||||||
// % Bits 53 to 64: do not use
|
// % Bits 53 to 64: do not use
|
||||||
|
|
||||||
// * Grant all permissions
|
// * Grant all permissions
|
||||||
|
|||||||
@@ -91,6 +91,18 @@ async fn validate_user_permissions() {
|
|||||||
async fn set_server_from_channel(&mut self) {
|
async fn set_server_from_channel(&mut self) {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_default_category_permissions(&mut self) -> Override {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_our_category_role_overrides(&mut self) -> Vec<Override> {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn set_category_from_channel(&mut self) {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,6 +195,18 @@ async fn validate_group_permissions() {
|
|||||||
async fn set_server_from_channel(&mut self) {
|
async fn set_server_from_channel(&mut self) {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_default_category_permissions(&mut self) -> Override {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_our_category_role_overrides(&mut self) -> Vec<Override> {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn set_category_from_channel(&mut self) {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,6 +311,18 @@ async fn validate_server_permissions() {
|
|||||||
async fn set_server_from_channel(&mut self) {
|
async fn set_server_from_channel(&mut self) {
|
||||||
// no-op
|
// no-op
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_default_category_permissions(&mut self) -> Override {
|
||||||
|
Override { allow: 0, deny: 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_our_category_role_overrides(&mut self) -> Vec<Override> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn set_category_from_channel(&mut self) {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,5 +409,126 @@ async fn validate_timed_out_member() {
|
|||||||
async fn set_server_from_channel(&mut self) {
|
async fn set_server_from_channel(&mut self) {
|
||||||
// no-op
|
// no-op
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_default_category_permissions(&mut self) -> Override {
|
||||||
|
Override { allow: 0, deny: 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_our_category_role_overrides(&mut self) -> Vec<Override> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn set_category_from_channel(&mut self) {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_std::test]
|
||||||
|
async fn validate_category_permissions() {
|
||||||
|
/// Scenario in which we are in a channel in a server and has a role
|
||||||
|
/// Server defaults let us send messages, view channels
|
||||||
|
/// Category default denies sending, allows reacting
|
||||||
|
/// Category role allows sending message
|
||||||
|
struct Scenario {}
|
||||||
|
let mut query = Scenario {};
|
||||||
|
|
||||||
|
let perms = calculate_channel_permissions(&mut query).await;
|
||||||
|
let value: u64 = perms.into();
|
||||||
|
assert_eq!(value, ChannelPermission::ViewChannel as u64 | ChannelPermission::React as u64 | ChannelPermission::SendMessage as u64);
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl PermissionQuery for Scenario {
|
||||||
|
async fn are_we_privileged(&mut self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn are_we_a_bot(&mut self) -> bool {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn are_the_users_same(&mut self) -> bool {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn user_relationship(&mut self) -> RelationshipStatus {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn user_is_bot(&mut self) -> bool {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn have_mutual_connection(&mut self) -> bool {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn are_we_server_owner(&mut self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn are_we_a_member(&mut self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_default_server_permissions(&mut self) -> u64 {
|
||||||
|
ChannelPermission::SendMessage as u64 | ChannelPermission::ViewChannel as u64
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_our_server_role_overrides(&mut self) -> Vec<Override> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn are_we_timed_out(&mut self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_channel_type(&mut self) -> ChannelType {
|
||||||
|
ChannelType::ServerChannel
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_default_channel_permissions(&mut self) -> Override {
|
||||||
|
Override { allow: 0, deny: 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_our_channel_role_overrides(&mut self) -> Vec<Override> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn do_we_own_the_channel(&mut self) -> bool {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn are_we_part_of_the_channel(&mut self) -> bool {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn set_recipient_as_user(&mut self) {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn set_server_from_channel(&mut self) {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_default_category_permissions(&mut self) -> Override {
|
||||||
|
Override {
|
||||||
|
allow: ChannelPermission::React as u64,
|
||||||
|
deny: ChannelPermission::SendMessage as u64
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_our_category_role_overrides(&mut self) -> Vec<Override> {
|
||||||
|
vec![
|
||||||
|
Override {
|
||||||
|
allow: ChannelPermission::SendMessage as u64,
|
||||||
|
deny: 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn set_category_from_channel(&mut self) {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,12 @@ pub trait PermissionQuery {
|
|||||||
/// Get the ordered role overrides (from lowest to highest) for this member in this channel
|
/// Get the ordered role overrides (from lowest to highest) for this member in this channel
|
||||||
async fn get_our_channel_role_overrides(&mut self) -> Vec<Override>;
|
async fn get_our_channel_role_overrides(&mut self) -> Vec<Override>;
|
||||||
|
|
||||||
|
/// Get the default category permissions
|
||||||
|
async fn get_default_category_permissions(&mut self) -> Override;
|
||||||
|
|
||||||
|
/// Get the ordered role overrides (from lowest to highest) for this member in this category
|
||||||
|
async fn get_our_category_role_overrides(&mut self) -> Vec<Override>;
|
||||||
|
|
||||||
/// Do we own this group or saved messages channel if it is one of those?
|
/// Do we own this group or saved messages channel if it is one of those?
|
||||||
async fn do_we_own_the_channel(&mut self) -> bool;
|
async fn do_we_own_the_channel(&mut self) -> bool;
|
||||||
|
|
||||||
@@ -64,4 +70,7 @@ pub trait PermissionQuery {
|
|||||||
/// Set the current server as the server owning this channel
|
/// Set the current server as the server owning this channel
|
||||||
/// (this will only ever be called for server channels, use unimplemented!() for other code paths)
|
/// (this will only ever be called for server channels, use unimplemented!() for other code paths)
|
||||||
async fn set_server_from_channel(&mut self);
|
async fn set_server_from_channel(&mut self);
|
||||||
|
|
||||||
|
//// SEts the current category as the category the channel is in
|
||||||
|
async fn set_category_from_channel(&mut self);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "revolt-presence"
|
name = "revolt-presence"
|
||||||
version = "0.8.5"
|
version = "0.8.4"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "AGPL-3.0-or-later"
|
license = "AGPL-3.0-or-later"
|
||||||
authors = ["Paul Makles <me@insrt.uk>"]
|
authors = ["Paul Makles <me@insrt.uk>"]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "revolt-result"
|
name = "revolt-result"
|
||||||
version = "0.8.5"
|
version = "0.8.4"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
authors = ["Paul Makles <me@insrt.uk>"]
|
authors = ["Paul Makles <me@insrt.uk>"]
|
||||||
|
|||||||
@@ -42,12 +42,14 @@ impl IntoResponse for Error {
|
|||||||
ErrorType::Banned => StatusCode::FORBIDDEN,
|
ErrorType::Banned => StatusCode::FORBIDDEN,
|
||||||
ErrorType::AlreadyInServer => StatusCode::CONFLICT,
|
ErrorType::AlreadyInServer => StatusCode::CONFLICT,
|
||||||
ErrorType::CannotTimeoutYourself => StatusCode::BAD_REQUEST,
|
ErrorType::CannotTimeoutYourself => StatusCode::BAD_REQUEST,
|
||||||
|
ErrorType::UnknownCategory => StatusCode::NOT_FOUND,
|
||||||
|
|
||||||
ErrorType::TooManyServers { .. } => StatusCode::BAD_REQUEST,
|
ErrorType::TooManyServers { .. } => StatusCode::BAD_REQUEST,
|
||||||
ErrorType::TooManyEmbeds { .. } => StatusCode::BAD_REQUEST,
|
ErrorType::TooManyEmbeds { .. } => StatusCode::BAD_REQUEST,
|
||||||
ErrorType::TooManyEmoji { .. } => StatusCode::BAD_REQUEST,
|
ErrorType::TooManyEmoji { .. } => StatusCode::BAD_REQUEST,
|
||||||
ErrorType::TooManyChannels { .. } => StatusCode::BAD_REQUEST,
|
ErrorType::TooManyChannels { .. } => StatusCode::BAD_REQUEST,
|
||||||
ErrorType::TooManyRoles { .. } => StatusCode::BAD_REQUEST,
|
ErrorType::TooManyRoles { .. } => StatusCode::BAD_REQUEST,
|
||||||
|
ErrorType::TooManyCategories { .. } => StatusCode::BAD_REQUEST,
|
||||||
|
|
||||||
ErrorType::ReachedMaximumBots => StatusCode::BAD_REQUEST,
|
ErrorType::ReachedMaximumBots => StatusCode::BAD_REQUEST,
|
||||||
ErrorType::IsBot => StatusCode::BAD_REQUEST,
|
ErrorType::IsBot => StatusCode::BAD_REQUEST,
|
||||||
|
|||||||
@@ -115,6 +115,10 @@ pub enum ErrorType {
|
|||||||
TooManyRoles {
|
TooManyRoles {
|
||||||
max: usize,
|
max: usize,
|
||||||
},
|
},
|
||||||
|
TooManyCategories {
|
||||||
|
max: usize,
|
||||||
|
},
|
||||||
|
UnknownCategory,
|
||||||
AlreadyInServer,
|
AlreadyInServer,
|
||||||
CannotTimeoutYourself,
|
CannotTimeoutYourself,
|
||||||
|
|
||||||
|
|||||||
@@ -49,12 +49,14 @@ impl<'r> Responder<'r, 'static> for Error {
|
|||||||
ErrorType::Banned => Status::Forbidden,
|
ErrorType::Banned => Status::Forbidden,
|
||||||
ErrorType::AlreadyInServer => Status::Conflict,
|
ErrorType::AlreadyInServer => Status::Conflict,
|
||||||
ErrorType::CannotTimeoutYourself => Status::BadRequest,
|
ErrorType::CannotTimeoutYourself => Status::BadRequest,
|
||||||
|
ErrorType::UnknownCategory => Status::NotFound,
|
||||||
|
|
||||||
ErrorType::TooManyServers { .. } => Status::BadRequest,
|
ErrorType::TooManyServers { .. } => Status::BadRequest,
|
||||||
ErrorType::TooManyEmbeds { .. } => Status::BadRequest,
|
ErrorType::TooManyEmbeds { .. } => Status::BadRequest,
|
||||||
ErrorType::TooManyEmoji { .. } => Status::BadRequest,
|
ErrorType::TooManyEmoji { .. } => Status::BadRequest,
|
||||||
ErrorType::TooManyChannels { .. } => Status::BadRequest,
|
ErrorType::TooManyChannels { .. } => Status::BadRequest,
|
||||||
ErrorType::TooManyRoles { .. } => Status::BadRequest,
|
ErrorType::TooManyRoles { .. } => Status::BadRequest,
|
||||||
|
ErrorType::TooManyCategories { .. } => Status::BadRequest,
|
||||||
|
|
||||||
ErrorType::ReachedMaximumBots => Status::BadRequest,
|
ErrorType::ReachedMaximumBots => Status::BadRequest,
|
||||||
ErrorType::IsBot => Status::BadRequest,
|
ErrorType::IsBot => Status::BadRequest,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "revolt-crond"
|
name = "revolt-crond"
|
||||||
version = "0.8.5"
|
version = "0.8.4"
|
||||||
license = "AGPL-3.0-or-later"
|
license = "AGPL-3.0-or-later"
|
||||||
authors = ["Paul Makles <me@insrt.uk>"]
|
authors = ["Paul Makles <me@insrt.uk>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
@@ -16,7 +16,7 @@ log = "0.4"
|
|||||||
tokio = { version = "1" }
|
tokio = { version = "1" }
|
||||||
|
|
||||||
# Core
|
# Core
|
||||||
revolt-database = { version = "0.8.5", path = "../../core/database" }
|
revolt-database = { version = "0.8.4", path = "../../core/database" }
|
||||||
revolt-result = { version = "0.8.5", path = "../../core/result" }
|
revolt-result = { version = "0.8.4", path = "../../core/result" }
|
||||||
revolt-config = { version = "0.8.5", path = "../../core/config" }
|
revolt-config = { version = "0.8.4", path = "../../core/config" }
|
||||||
revolt-files = { version = "0.8.5", path = "../../core/files" }
|
revolt-files = { version = "0.8.4", path = "../../core/files" }
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "revolt-pushd"
|
name = "revolt-pushd"
|
||||||
version = "0.8.5"
|
version = "0.8.4"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "AGPL-3.0-or-later"
|
license = "AGPL-3.0-or-later"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
revolt-config = { version = "0.8.5", path = "../../core/config" }
|
revolt-config = { version = "0.8.4", path = "../../core/config" }
|
||||||
revolt-database = { version = "0.8.5", path = "../../core/database" }
|
revolt-database = { version = "0.8.4", path = "../../core/database" }
|
||||||
revolt-models = { version = "0.8.5", path = "../../core/models", features = [
|
revolt-models = { version = "0.8.4", path = "../../core/models", features = [
|
||||||
"validator",
|
"validator",
|
||||||
] }
|
] }
|
||||||
revolt-presence = { version = "0.8.5", path = "../../core/presence", features = [
|
revolt-presence = { version = "0.8.1", path = "../../core/presence", features = [
|
||||||
"redis-is-patched",
|
"redis-is-patched",
|
||||||
] }
|
] }
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "revolt-delta"
|
name = "revolt-delta"
|
||||||
version = "0.8.5"
|
version = "0.8.4"
|
||||||
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,11 +52,10 @@ async-std = { version = "1.8.0", features = [
|
|||||||
lettre = "0.10.0-alpha.4"
|
lettre = "0.10.0-alpha.4"
|
||||||
|
|
||||||
# web
|
# web
|
||||||
|
|
||||||
rocket = { version = "0.5.1", default-features = false, features = ["json"] }
|
rocket = { version = "0.5.1", default-features = false, features = ["json"] }
|
||||||
rocket_cors = { git = "https://github.com/lawliet89/rocket_cors", rev = "072d90359b23e9b291df6b672c07c93de9c46011" }
|
rocket_cors = { git = "https://github.com/lawliet89/rocket_cors", rev = "072d90359b23e9b291df6b672c07c93de9c46011" }
|
||||||
rocket_empty = { version = "0.1.1", features = ["schema"] }
|
rocket_empty = { version = "0.1.1", features = ["schema"] }
|
||||||
rocket_authifier = { version = "1.0.13" }
|
rocket_authifier = { version = "1.0.10" }
|
||||||
rocket_prometheus = "0.10.0-rc.3"
|
rocket_prometheus = "0.10.0-rc.3"
|
||||||
|
|
||||||
# spec generation
|
# spec generation
|
||||||
@@ -67,7 +66,7 @@ revolt_rocket_okapi = { version = "0.10.0", features = ["swagger"] }
|
|||||||
amqprs = { version = "1.7.0" }
|
amqprs = { version = "1.7.0" }
|
||||||
|
|
||||||
# core
|
# core
|
||||||
authifier = "1.0.13"
|
authifier = "1.0.10"
|
||||||
revolt-config = { path = "../core/config" }
|
revolt-config = { path = "../core/config" }
|
||||||
revolt-database = { path = "../core/database", features = [
|
revolt-database = { path = "../core/database", features = [
|
||||||
"rocket-impl",
|
"rocket-impl",
|
||||||
|
|||||||
@@ -192,6 +192,7 @@ mod test {
|
|||||||
d: ChannelPermission::ViewChannel as i64,
|
d: ChannelPermission::ViewChannel as i64,
|
||||||
}),
|
}),
|
||||||
last_message_id: None,
|
last_message_id: None,
|
||||||
|
parent: None,
|
||||||
};
|
};
|
||||||
locked_channel
|
locked_channel
|
||||||
.update(&harness.db, partial, vec![])
|
.update(&harness.db, partial, vec![])
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
use revolt_config::config;
|
||||||
|
use revolt_database::{
|
||||||
|
util::{permissions::DatabasePermissionQuery, reference::Reference}, Category, Database, Role, User
|
||||||
|
};
|
||||||
|
use revolt_models::v0;
|
||||||
|
use revolt_permissions::{calculate_server_permissions, ChannelPermission};
|
||||||
|
use revolt_result::{create_error, Result};
|
||||||
|
use rocket::{serde::json::Json, State};
|
||||||
|
use validator::Validate;
|
||||||
|
|
||||||
|
/// # Create a category
|
||||||
|
///
|
||||||
|
/// Creates a new server category.
|
||||||
|
#[openapi(tag = "Server Categories")]
|
||||||
|
#[post("/<target>/categories", data = "<data>")]
|
||||||
|
pub async fn create(
|
||||||
|
db: &State<Database>,
|
||||||
|
user: User,
|
||||||
|
target: Reference,
|
||||||
|
data: Json<v0::DataCreateCategory>,
|
||||||
|
) -> Result<Json<v0::Category>> {
|
||||||
|
let data = data.into_inner();
|
||||||
|
data.validate().map_err(|error| {
|
||||||
|
create_error!(FailedValidation {
|
||||||
|
error: error.to_string()
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let mut server = target.as_server(db).await?;
|
||||||
|
let mut query = DatabasePermissionQuery::new(db, &user).server(&server);
|
||||||
|
calculate_server_permissions(&mut query)
|
||||||
|
.await
|
||||||
|
.throw_if_lacking_channel_permission(ChannelPermission::ManageChannel)?;
|
||||||
|
|
||||||
|
let config = config().await;
|
||||||
|
if server.categories.len() >= config.features.limits.global.server_categories {
|
||||||
|
return Err(create_error!(TooManyCategories {
|
||||||
|
max: config.features.limits.global.server_categories,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
let category = Category::create(db, &mut server, data).await?;
|
||||||
|
|
||||||
|
Ok(Json(category.into()))
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
use revolt_config::config;
|
||||||
|
use revolt_database::{
|
||||||
|
util::{permissions::DatabasePermissionQuery, reference::Reference}, Category, Database, PartialCategory, Role, User
|
||||||
|
};
|
||||||
|
use revolt_models::v0::{self, DataEditCategory};
|
||||||
|
use revolt_permissions::{calculate_server_permissions, ChannelPermission};
|
||||||
|
use revolt_result::{create_error, Result};
|
||||||
|
use rocket::{serde::json::Json, State};
|
||||||
|
use rocket_empty::EmptyResponse;
|
||||||
|
use validator::Validate;
|
||||||
|
|
||||||
|
/// # Edits a category
|
||||||
|
///
|
||||||
|
/// Edits a server category.
|
||||||
|
#[openapi(tag = "Server Categories")]
|
||||||
|
#[delete("/<server>/categories/<category>")]
|
||||||
|
pub async fn delete(
|
||||||
|
db: &State<Database>,
|
||||||
|
user: User,
|
||||||
|
server: Reference,
|
||||||
|
category: String
|
||||||
|
) -> Result<EmptyResponse> {
|
||||||
|
let mut server = server.as_server(db).await?;
|
||||||
|
|
||||||
|
let category = server.categories
|
||||||
|
.get(&category)
|
||||||
|
.ok_or(create_error!(UnknownCategory))?
|
||||||
|
.clone();
|
||||||
|
|
||||||
|
let mut query = DatabasePermissionQuery::new(db, &user).server(&server);
|
||||||
|
calculate_server_permissions(&mut query)
|
||||||
|
.await
|
||||||
|
.throw_if_lacking_channel_permission(ChannelPermission::ManageChannel)?;
|
||||||
|
|
||||||
|
category.delete(db, &mut server).await?;
|
||||||
|
|
||||||
|
Ok(EmptyResponse)
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
use revolt_config::config;
|
||||||
|
use revolt_database::{
|
||||||
|
util::{permissions::DatabasePermissionQuery, reference::Reference}, Category, Channel, Database, PartialCategory, PartialChannel, Role, User
|
||||||
|
};
|
||||||
|
use revolt_models::v0::{self, DataEditCategory};
|
||||||
|
use revolt_permissions::{calculate_server_permissions, ChannelPermission};
|
||||||
|
use revolt_result::{create_error, Result};
|
||||||
|
use rocket::{serde::json::Json, State};
|
||||||
|
use validator::Validate;
|
||||||
|
|
||||||
|
/// # Edits a category
|
||||||
|
///
|
||||||
|
/// Edits a server category.
|
||||||
|
#[openapi(tag = "Server Categories")]
|
||||||
|
#[patch("/<server>/categories/<category>", data = "<data>")]
|
||||||
|
pub async fn edit(
|
||||||
|
db: &State<Database>,
|
||||||
|
user: User,
|
||||||
|
server: Reference,
|
||||||
|
category: String,
|
||||||
|
data: Json<v0::DataEditCategory>,
|
||||||
|
) -> Result<Json<v0::Category>> {
|
||||||
|
let data = data.into_inner();
|
||||||
|
data.validate().map_err(|error| {
|
||||||
|
create_error!(FailedValidation {
|
||||||
|
error: error.to_string()
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let mut server = server.as_server(db).await?;
|
||||||
|
|
||||||
|
let mut category = server.categories
|
||||||
|
.get(&category)
|
||||||
|
.ok_or(create_error!(UnknownCategory))?
|
||||||
|
.clone();
|
||||||
|
|
||||||
|
let mut query = DatabasePermissionQuery::new(db, &user).server(&server).category(&category);
|
||||||
|
let permissions = calculate_server_permissions(&mut query)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
permissions.throw_if_lacking_channel_permission(ChannelPermission::ManageChannel)?;
|
||||||
|
|
||||||
|
let DataEditCategory {
|
||||||
|
title,
|
||||||
|
mut channels,
|
||||||
|
remove
|
||||||
|
} = data;
|
||||||
|
|
||||||
|
if channels.is_some() {
|
||||||
|
permissions.throw_if_lacking_channel_permission(ChannelPermission::MoveChannels)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if any channel we are adding to this category are in another category we need to make sure we have MoveChannels in the category before moving it over.
|
||||||
|
for category in server.categories.values() {
|
||||||
|
if category.channels.iter().any(|c| channels.as_ref().is_some_and(|cs| cs.contains(c))) {
|
||||||
|
let mut category_query = query.clone().category(category);
|
||||||
|
|
||||||
|
calculate_server_permissions(&mut category_query)
|
||||||
|
.await
|
||||||
|
.throw_if_lacking_channel_permission(ChannelPermission::MoveChannels)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove the channels from any existing categories to avoid it having two
|
||||||
|
for category in server.categories.values_mut() {
|
||||||
|
category.channels.retain(|c| channels.as_ref().is_some_and(|cs| cs.contains(c)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// only keep channels which exist in the server
|
||||||
|
if let Some(channels) = &mut channels {
|
||||||
|
channels.retain(|c| server.channels.contains(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
// unset parent from all channels which are removed from the category
|
||||||
|
for channel_id in &category.channels {
|
||||||
|
if channels.as_ref().is_some_and(|cs| !cs.contains(channel_id)) {
|
||||||
|
db.update_channel(channel_id, &PartialChannel { parent: None, ..Default::default() }, Vec::new()).await?;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// update the category with the new values
|
||||||
|
category.update(
|
||||||
|
db,
|
||||||
|
&mut server,
|
||||||
|
PartialCategory {
|
||||||
|
title,
|
||||||
|
channels: channels.clone(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
remove
|
||||||
|
.map(|v| v.into_iter().map(Into::into).collect())
|
||||||
|
.unwrap_or_default()
|
||||||
|
).await?;
|
||||||
|
|
||||||
|
let channels = db.fetch_channels(&channels.unwrap_or_default()).await?;
|
||||||
|
|
||||||
|
// update all channels to have the parent set
|
||||||
|
for channel in channels {
|
||||||
|
if let Channel::TextChannel { ref parent, .. } | Channel::VoiceChannel { ref parent, .. } = channel {
|
||||||
|
if parent.as_ref() != Some(&category.id) {
|
||||||
|
db.update_channel(channel.id(), &PartialChannel { parent: Some(category.id.clone()), ..Default::default() }, Vec::new()).await?;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Json(category.into()))
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
use revolt_database::{
|
||||||
|
util::{permissions::DatabasePermissionQuery, reference::Reference}, Database, User
|
||||||
|
};
|
||||||
|
use revolt_models::v0;
|
||||||
|
use revolt_permissions::{calculate_category_permissions, ChannelPermission, Override};
|
||||||
|
use revolt_result::{create_error, Result};
|
||||||
|
use rocket::{serde::json::Json, State};
|
||||||
|
|
||||||
|
/// # Set Role Permission
|
||||||
|
///
|
||||||
|
/// Sets permissions for the specified role in this channel.
|
||||||
|
///
|
||||||
|
/// Channel must be a `TextChannel` or `VoiceChannel`.
|
||||||
|
#[openapi(tag = "Channel Permissions")]
|
||||||
|
#[put("/<server>/categories/<category>/permissions/<role_id>", data = "<data>", rank = 2)]
|
||||||
|
pub async fn set_role_permissions(
|
||||||
|
db: &State<Database>,
|
||||||
|
user: User,
|
||||||
|
server: Reference,
|
||||||
|
category: String,
|
||||||
|
role_id: String,
|
||||||
|
data: Json<v0::DataSetRolePermissions>,
|
||||||
|
) -> Result<Json<v0::Category>> {
|
||||||
|
let mut server = server.as_server(db).await?;
|
||||||
|
let mut category = server.categories.get(&category).ok_or(create_error!(UnknownCategory))?.clone();
|
||||||
|
|
||||||
|
let mut query = DatabasePermissionQuery::new(db, &user).server(&server).category(&category);
|
||||||
|
let permissions = calculate_category_permissions(&mut query).await;
|
||||||
|
|
||||||
|
permissions.throw_if_lacking_channel_permission(ChannelPermission::ManagePermissions)?;
|
||||||
|
|
||||||
|
if let Some(role) = server.roles.get(&role_id) {
|
||||||
|
if role.rank <= query.get_member_rank().unwrap_or(i64::MIN) {
|
||||||
|
return Err(create_error!(NotElevated));
|
||||||
|
}
|
||||||
|
|
||||||
|
let current_value: Override = role.permissions.into();
|
||||||
|
permissions
|
||||||
|
.throw_permission_override(current_value, &data.permissions)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
category
|
||||||
|
.set_role_permission(db, &mut server, role_id, data.permissions.clone().into())
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(Json(category.into()))
|
||||||
|
} else {
|
||||||
|
Err(create_error!(NotFound))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
use revolt_database::{
|
||||||
|
util::{permissions::DatabasePermissionQuery, reference::Reference}, Channel, Database, PartialCategory, PartialChannel, User
|
||||||
|
};
|
||||||
|
use revolt_models::v0::{self, DataDefaultChannelPermissions};
|
||||||
|
use revolt_permissions::{calculate_category_permissions, calculate_channel_permissions, ChannelPermission};
|
||||||
|
use revolt_result::{create_error, Result};
|
||||||
|
use rocket::{serde::json::Json, State};
|
||||||
|
|
||||||
|
/// # Set Default Permission
|
||||||
|
///
|
||||||
|
/// Sets permissions for the default role in this channel.
|
||||||
|
///
|
||||||
|
/// Channel must be a `Group`, `TextChannel` or `VoiceChannel`.
|
||||||
|
#[openapi(tag = "Category Permissions")]
|
||||||
|
#[put("/<server>/categories/<target>/permissions/default", data = "<data>", rank = 1)]
|
||||||
|
pub async fn set_default_permissions(
|
||||||
|
db: &State<Database>,
|
||||||
|
user: User,
|
||||||
|
server: Reference,
|
||||||
|
target: String,
|
||||||
|
data: Json<v0::DataDefaultCategoryPermissions>,
|
||||||
|
) -> Result<Json<v0::Category>> {
|
||||||
|
let data = data.into_inner();
|
||||||
|
|
||||||
|
let mut server = server.as_server(db).await?;
|
||||||
|
let mut category = server.categories.get(&target).ok_or(create_error!(UnknownCategory))?.clone();
|
||||||
|
|
||||||
|
let mut query = DatabasePermissionQuery::new(db, &user).server(&server).category(&category);
|
||||||
|
let permissions = calculate_category_permissions(&mut query).await;
|
||||||
|
|
||||||
|
permissions.throw_if_lacking_channel_permission(ChannelPermission::ManagePermissions)?;
|
||||||
|
|
||||||
|
permissions
|
||||||
|
.throw_permission_override(category.default_permissions.map(|x| x.into()), &data.permissions)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
category
|
||||||
|
.update(
|
||||||
|
db,
|
||||||
|
&mut server,
|
||||||
|
PartialCategory {
|
||||||
|
default_permissions: Some(data.permissions.into()),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
vec![],
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(Json(category.into()))
|
||||||
|
}
|
||||||
@@ -23,6 +23,11 @@ mod server_create;
|
|||||||
mod server_delete;
|
mod server_delete;
|
||||||
mod server_edit;
|
mod server_edit;
|
||||||
mod server_fetch;
|
mod server_fetch;
|
||||||
|
mod category_create;
|
||||||
|
mod category_edit;
|
||||||
|
mod category_delete;
|
||||||
|
mod category_permissions_set_default;
|
||||||
|
mod category_permissions_set;
|
||||||
|
|
||||||
pub fn routes() -> (Vec<Route>, OpenApi) {
|
pub fn routes() -> (Vec<Route>, OpenApi) {
|
||||||
openapi_get_routes_spec![
|
openapi_get_routes_spec![
|
||||||
@@ -47,6 +52,11 @@ pub fn routes() -> (Vec<Route>, OpenApi) {
|
|||||||
roles_delete::delete,
|
roles_delete::delete,
|
||||||
permissions_set::set_role_permission,
|
permissions_set::set_role_permission,
|
||||||
permissions_set_default::set_default_permissions,
|
permissions_set_default::set_default_permissions,
|
||||||
emoji_list::list_emoji
|
emoji_list::list_emoji,
|
||||||
|
category_create::create,
|
||||||
|
category_edit::edit,
|
||||||
|
category_delete::delete,
|
||||||
|
category_permissions_set_default::set_default_permissions,
|
||||||
|
category_permissions_set::set_role_permissions,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use std::collections::HashSet;
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
use revolt_database::{
|
use revolt_database::{
|
||||||
util::{permissions::DatabasePermissionQuery, reference::Reference},
|
util::{permissions::DatabasePermissionQuery, reference::Reference},
|
||||||
@@ -38,7 +38,6 @@ pub async fn edit(
|
|||||||
&& data.icon.is_none()
|
&& data.icon.is_none()
|
||||||
&& data.banner.is_none()
|
&& data.banner.is_none()
|
||||||
&& data.system_messages.is_none()
|
&& data.system_messages.is_none()
|
||||||
&& data.categories.is_none()
|
|
||||||
// && data.nsfw.is_none()
|
// && data.nsfw.is_none()
|
||||||
&& data.flags.is_none()
|
&& data.flags.is_none()
|
||||||
&& data.analytics.is_none()
|
&& data.analytics.is_none()
|
||||||
@@ -63,18 +62,11 @@ pub async fn edit(
|
|||||||
{
|
{
|
||||||
return Err(create_error!(NotPrivileged));
|
return Err(create_error!(NotPrivileged));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Changing categories requires manage channel
|
|
||||||
if data.categories.is_some() {
|
|
||||||
permissions.throw_if_lacking_channel_permission(ChannelPermission::ManageChannel)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let v0::DataEditServer {
|
let v0::DataEditServer {
|
||||||
name,
|
name,
|
||||||
description,
|
description,
|
||||||
icon,
|
icon,
|
||||||
banner,
|
banner,
|
||||||
categories,
|
|
||||||
system_messages,
|
system_messages,
|
||||||
flags,
|
flags,
|
||||||
// nsfw,
|
// nsfw,
|
||||||
@@ -86,7 +78,6 @@ pub async fn edit(
|
|||||||
let mut partial = PartialServer {
|
let mut partial = PartialServer {
|
||||||
name,
|
name,
|
||||||
description,
|
description,
|
||||||
categories: categories.map(|v| v.into_iter().map(Into::into).collect()),
|
|
||||||
system_messages: system_messages.map(Into::into),
|
system_messages: system_messages.map(Into::into),
|
||||||
flags,
|
flags,
|
||||||
// nsfw,
|
// nsfw,
|
||||||
@@ -119,23 +110,6 @@ pub async fn edit(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(categories) = &mut partial.categories {
|
|
||||||
let mut channel_ids = HashSet::new();
|
|
||||||
for category in categories {
|
|
||||||
for channel in &category.channels {
|
|
||||||
if channel_ids.contains(channel) {
|
|
||||||
return Err(create_error!(InvalidOperation));
|
|
||||||
}
|
|
||||||
|
|
||||||
channel_ids.insert(channel.to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
category
|
|
||||||
.channels
|
|
||||||
.retain(|item| server.channels.contains(item));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Apply new icon
|
// 3. Apply new icon
|
||||||
if let Some(icon) = icon {
|
if let Some(icon) = icon {
|
||||||
partial.icon = Some(File::use_server_icon(db, &icon, &server.id, &user.id).await?);
|
partial.icon = Some(File::use_server_icon(db, &icon, &server.id, &user.id).await?);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "revolt-autumn"
|
name = "revolt-autumn"
|
||||||
version = "0.8.5"
|
version = "0.8.4"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "AGPL-3.0-or-later"
|
license = "AGPL-3.0-or-later"
|
||||||
|
|
||||||
@@ -43,12 +43,12 @@ tracing = "0.1"
|
|||||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||||
|
|
||||||
# Core crates
|
# Core crates
|
||||||
revolt-files = { version = "0.8.5", path = "../../core/files" }
|
revolt-files = { version = "0.8.4", path = "../../core/files" }
|
||||||
revolt-config = { version = "0.8.5", path = "../../core/config" }
|
revolt-config = { version = "0.8.4", path = "../../core/config" }
|
||||||
revolt-database = { version = "0.8.5", path = "../../core/database", features = [
|
revolt-database = { version = "0.8.4", path = "../../core/database", features = [
|
||||||
"axum-impl",
|
"axum-impl",
|
||||||
] }
|
] }
|
||||||
revolt-result = { version = "0.8.5", path = "../../core/result", features = [
|
revolt-result = { version = "0.8.4", path = "../../core/result", features = [
|
||||||
"utoipa",
|
"utoipa",
|
||||||
"axum",
|
"axum",
|
||||||
] }
|
] }
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "revolt-january"
|
name = "revolt-january"
|
||||||
version = "0.8.5"
|
version = "0.8.4"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "AGPL-3.0-or-later"
|
license = "AGPL-3.0-or-later"
|
||||||
|
|
||||||
@@ -32,13 +32,13 @@ tracing = "0.1"
|
|||||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||||
|
|
||||||
# Core crates
|
# Core crates
|
||||||
revolt-config = { version = "0.8.5", path = "../../core/config" }
|
revolt-config = { version = "0.8.4", path = "../../core/config" }
|
||||||
revolt-models = { version = "0.8.5", path = "../../core/models" }
|
revolt-models = { version = "0.8.4", path = "../../core/models" }
|
||||||
revolt-result = { version = "0.8.5", path = "../../core/result", features = [
|
revolt-result = { version = "0.8.4", path = "../../core/result", features = [
|
||||||
"utoipa",
|
"utoipa",
|
||||||
"axum",
|
"axum",
|
||||||
] }
|
] }
|
||||||
revolt-files = { version = "0.8.5", path = "../../core/files" }
|
revolt-files = { version = "0.8.4", path = "../../core/files" }
|
||||||
|
|
||||||
# Axum / web server
|
# Axum / web server
|
||||||
axum = { version = "0.7.5" }
|
axum = { version = "0.7.5" }
|
||||||
|
|||||||
@@ -22,13 +22,13 @@ tools() {
|
|||||||
|
|
||||||
deps() {
|
deps() {
|
||||||
mkdir -p \
|
mkdir -p \
|
||||||
|
crates/bindings/node/src \
|
||||||
crates/bonfire/src \
|
crates/bonfire/src \
|
||||||
crates/delta/src \
|
crates/delta/src \
|
||||||
crates/core/config/src \
|
crates/core/config/src \
|
||||||
crates/core/database/src \
|
crates/core/database/src \
|
||||||
crates/core/files/src \
|
crates/core/files/src \
|
||||||
crates/core/models/src \
|
crates/core/models/src \
|
||||||
crates/core/parser/src \
|
|
||||||
crates/core/permissions/src \
|
crates/core/permissions/src \
|
||||||
crates/core/presence/src \
|
crates/core/presence/src \
|
||||||
crates/core/result/src \
|
crates/core/result/src \
|
||||||
@@ -44,19 +44,19 @@ deps() {
|
|||||||
tee crates/daemons/crond/src/main.rs |
|
tee crates/daemons/crond/src/main.rs |
|
||||||
tee crates/daemons/pushd/src/main.rs
|
tee crates/daemons/pushd/src/main.rs
|
||||||
echo '' |
|
echo '' |
|
||||||
|
tee crates/bindings/node/src/lib.rs |
|
||||||
tee crates/core/config/src/lib.rs |
|
tee crates/core/config/src/lib.rs |
|
||||||
tee crates/core/database/src/lib.rs |
|
tee crates/core/database/src/lib.rs |
|
||||||
tee crates/core/files/src/lib.rs |
|
tee crates/core/files/src/lib.rs |
|
||||||
tee crates/core/models/src/lib.rs |
|
tee crates/core/models/src/lib.rs |
|
||||||
tee crates/core/parser/src/lib.rs |
|
|
||||||
tee crates/core/permissions/src/lib.rs |
|
tee crates/core/permissions/src/lib.rs |
|
||||||
tee crates/core/presence/src/lib.rs |
|
tee crates/core/presence/src/lib.rs |
|
||||||
tee crates/core/result/src/lib.rs
|
tee crates/core/result/src/lib.rs
|
||||||
|
|
||||||
if [ -z "$TARGETARCH" ]; then
|
if [ -z "$TARGETARCH" ]; then
|
||||||
cargo build -j 10 --locked --release
|
cargo build --locked --release
|
||||||
else
|
else
|
||||||
cargo build -j 10 --locked --release --target "${BUILD_TARGET}"
|
cargo build --locked --release --target "${BUILD_TARGET}"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,15 +69,14 @@ apps() {
|
|||||||
crates/core/config/src/lib.rs \
|
crates/core/config/src/lib.rs \
|
||||||
crates/core/database/src/lib.rs \
|
crates/core/database/src/lib.rs \
|
||||||
crates/core/models/src/lib.rs \
|
crates/core/models/src/lib.rs \
|
||||||
crates/core/parser/src/lib.rs \
|
|
||||||
crates/core/permissions/src/lib.rs \
|
crates/core/permissions/src/lib.rs \
|
||||||
crates/core/presence/src/lib.rs \
|
crates/core/presence/src/lib.rs \
|
||||||
crates/core/result/src/lib.rs
|
crates/core/result/src/lib.rs
|
||||||
|
|
||||||
if [ -z "$TARGETARCH" ]; then
|
if [ -z "$TARGETARCH" ]; then
|
||||||
cargo build -j 10 --locked --release
|
cargo build --locked --release
|
||||||
else
|
else
|
||||||
cargo build -j 10 --locked --release --target "${BUILD_TARGET}"
|
cargo build --locked --release --target "${BUILD_TARGET}"
|
||||||
mv target _target && mv _target/"${BUILD_TARGET}" target
|
mv target _target && mv _target/"${BUILD_TARGET}" target
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user