Browse Source

Merge upstream tag v0.7.57

Merge Notes:
* Lemmy server does not compile.
  It took several hours to go through the merge process, so I want to commit the
  project in its current state and have a place to revert to if anything goes
  wrong.
** API structs need to be double checked for correctness.
   They were all moved to a submodule, and Git did not catch the diffs.  On the
   bright side, this provides us a great opportunity to mark all of our API
   changes as we update the vanilla upstream API structs.

* Two new migrations were added upstream.
  I don't think these clobber any of our changes, but they modify existing
  records. In particular, the fake activitypub records get replaced with newly
  generated unique entries.  We're going to want to make sure these migrations
  work correctly.

* Endpoints need to be reviewed for security and correctness
  This is not an exaustive list.

** Comment
*** GetComments
    Looks like it can leak comments from private communities. We don't have any
    private communities, but we're going to want to fix this.
** Community
*** EditCommunity
    The permissions logic could be more concise.
*** BanFromCommunity
    Admins cannot ban mods from communities.  This should be changed.
** User
*** Register
    Review Register endpoint and make sure there are no security regressions.
    The recent changes apparently make it impossible to bootstrap the website.

* Other TODOs
** Add a site_mod helper function
   Site-mod permissions are broken.  A helper function should make an easy
   drop-in replacement for many of the current admin checks, but it would be
   inappropriate to simply change the definition of the is_admin function.

   That said, is_mod_or_admin should be fair game.
feature/settings-cleanup
Porkroll Posadist 1 year ago
parent
commit
9e467b50ca
  1. 3
      ansible/VERSION
  2. 14
      ansible/templates/nginx.conf
  3. 38
      docker/dev/Dockerfile
  4. 12
      docker/dev/docker-compose.yml
  5. 6
      docker/dev/docker_update.sh
  6. 20
      docker/federation-test/servers.sh
  7. 10
      docker/federation-test/tests.sh
  8. 17
      docker/federation/Dockerfile
  9. 79
      docker/federation/docker-compose.yml
  10. 62
      docker/federation/nginx.conf
  11. 28
      docker/federation/run-federation-test.bash
  12. 24
      docker/federation/run-tests.sh
  13. 11
      docker/federation/start-local-instances.bash
  14. 9
      docker/prod/Dockerfile
  15. 4
      docker/prod/docker-compose.yml
  16. 76
      docker/travis/docker-compose.yml
  17. 4
      docker/travis/docker_push.sh
  18. 6
      docker/travis/run-tests.sh
  19. 34
      docs/src/about_guide.md
  20. 40
      docs/src/contributing_federation_development.md
  21. 447
      docs/src/contributing_websocket_http_api.md
  22. 423
      server/Cargo.lock
  23. 15
      server/Cargo.toml
  24. 8
      server/config/defaults.hjson
  25. 14
      server/lemmy_api_structs/Cargo.toml
  26. 77
      server/lemmy_api_structs/src/comment.rs
  27. 131
      server/lemmy_api_structs/src/community.rs
  28. 24
      server/lemmy_api_structs/src/lib.rs
  29. 105
      server/lemmy_api_structs/src/post.rs
  30. 127
      server/lemmy_api_structs/src/site.rs
  31. 300
      server/lemmy_api_structs/src/user.rs
  32. 4
      server/lemmy_db/Cargo.toml
  33. 10
      server/lemmy_db/src/activity.rs
  34. 4
      server/lemmy_db/src/category.rs
  35. 137
      server/lemmy_db/src/comment.rs
  36. 23
      server/lemmy_db/src/comment_view.rs
  37. 78
      server/lemmy_db/src/community.rs
  38. 28
      server/lemmy_db/src/community_view.rs
  39. 15
      server/lemmy_db/src/lib.rs
  40. 69
      server/lemmy_db/src/moderator.rs
  41. 18
      server/lemmy_db/src/password_reset_request.rs
  42. 117
      server/lemmy_db/src/post.rs
  43. 31
      server/lemmy_db/src/post_view.rs
  44. 33
      server/lemmy_db/src/private_message.rs
  45. 5
      server/lemmy_db/src/site.rs
  46. 40
      server/lemmy_db/src/user.rs
  47. 19
      server/lemmy_db/src/user_mention.rs
  48. 57
      server/lemmy_db/src/user_view.rs
  49. 19
      server/lemmy_rate_limit/Cargo.toml
  50. 15
      server/lemmy_rate_limit/src/lib.rs
  51. 6
      server/lemmy_rate_limit/src/rate_limiter.rs
  52. 6
      server/lemmy_utils/Cargo.toml
  53. 69
      server/lemmy_utils/src/lib.rs
  54. 41
      server/lemmy_utils/src/settings.rs
  55. 100
      server/migrations/2020-08-06-205355_update_community_post_count/down.sql
  56. 100
      server/migrations/2020-08-06-205355_update_community_post_count/up.sql
  57. 27
      server/migrations/2020-08-25-132005_add_unique_ap_ids/down.sql
  58. 56
      server/migrations/2020-08-25-132005_add_unique_ap_ids/up.sql
  59. 11
      server/src/api/claims.rs
  60. 503
      server/src/api/comment.rs
  61. 629
      server/src/api/community.rs
  62. 121
      server/src/api/mod.rs
  63. 552
      server/src/api/post.rs
  64. 397
      server/src/api/site.rs
  65. 1051
      server/src/api/user.rs
  66. 75
      server/src/apub/activities.rs
  67. 130
      server/src/apub/activity_queue.rs
  68. 343
      server/src/apub/comment.rs
  69. 305
      server/src/apub/community.rs
  70. 4
      server/src/apub/extensions/group_extensions.rs
  71. 30
      server/src/apub/extensions/signatures.rs
  72. 299
      server/src/apub/fetcher.rs
  73. 37
      server/src/apub/inbox/activities/announce.rs
  74. 109
      server/src/apub/inbox/activities/create.rs
  75. 157
      server/src/apub/inbox/activities/delete.rs
  76. 111
      server/src/apub/inbox/activities/dislike.rs
  77. 98
      server/src/apub/inbox/activities/like.rs
  78. 167
      server/src/apub/inbox/activities/remove.rs
  79. 545
      server/src/apub/inbox/activities/undo.rs
  80. 122
      server/src/apub/inbox/activities/update.rs
  81. 95
      server/src/apub/inbox/shared_inbox.rs
  82. 261
      server/src/apub/mod.rs
  83. 434
      server/src/apub/post.rs
  84. 138
      server/src/apub/private_message.rs
  85. 177
      server/src/apub/user.rs
  86. 14
      server/src/code_migrations.rs
  87. 84
      server/src/lib.rs
  88. 39
      server/src/main.rs
  89. 20
      server/src/request.rs
  90. 59
      server/src/routes/api.rs
  91. 80
      server/src/routes/feeds.rs
  92. 2
      server/src/routes/images.rs
  93. 3
      server/src/routes/index.rs
  94. 13
      server/src/routes/mod.rs
  95. 8
      server/src/routes/nodeinfo.rs
  96. 23
      server/src/routes/webfinger.rs
  97. 12
      server/src/routes/websocket.rs
  98. 2
      server/src/version.rs
  99. 551
      server/src/websocket/chat_server.rs
  100. 292
      server/src/websocket/handlers.rs

3
ansible/VERSION

@ -1 +1,2 @@
v0.7.41
v0.7.57

14
ansible/templates/nginx.conf

@ -51,9 +51,6 @@ server {
# Upload limit for pictrs
client_max_body_size 20M;
# Rate limit
limit_req zone=lemmy_ratelimit burst=30 nodelay;
location / {
proxy_pass http://0.0.0.0:8536;
proxy_set_header X-Real-IP $remote_addr;
@ -67,6 +64,9 @@ server {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Rate limit
limit_req zone=lemmy_ratelimit burst=30 nodelay;
}
# Redirect pictshare images to pictrs
@ -74,6 +74,14 @@ server {
return 301 /pictrs/image/$1;
}
# Separate location block to disable rate limiting for images
location /pictrs {
proxy_pass http://0.0.0.0:8536/pictrs;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /iframely/ {
proxy_pass http://0.0.0.0:8061/;
proxy_set_header X-Real-IP $remote_addr;

38
docker/dev/Dockerfile

@ -12,30 +12,44 @@ COPY .git/ ./.git/
RUN yarn build
RUN su && rm -rf .git
FROM ekidd/rust-musl-builder:1.42.0-openssl11 as rust
FROM ekidd/rust-musl-builder:nightly-2020-05-07 as rust
# Cache deps
WORKDIR /app
RUN sudo chown -R rust:rust .
RUN USER=root cargo new server
# Install cargo-build-deps
RUN cargo install --git https://github.com/romac/cargo-build-deps.git
WORKDIR /app/server
COPY server/Cargo.toml server/Cargo.lock server/build.rs ./
COPY server/lemmy_db ./lemmy_db
COPY server/lemmy_utils ./lemmy_utils
COPY .git/ ./.git/
RUN mkdir -p ./src/bin \
&& echo 'fn main() { println!("Dummy") }' > ./src/bin/main.rs
RUN cargo build
RUN find target/debug -type f -name "$(echo "lemmy_server" | tr '-' '_')*" -exec touch -t 200001010000 {} +
RUN mkdir -p lemmy_db/src/ \
lemmy_utils/src/ \
lemmy_api_structs/src/ \
lemmy_rate_limit/src/ \
lemmy
# Copy the cargo tomls
COPY server/Cargo.toml server/Cargo.lock ./
COPY server/lemmy_db/Cargo.toml ./lemmy_db/
COPY server/lemmy_utils/Cargo.toml ./lemmy_utils/
COPY server/lemmy_api_structs/Cargo.toml ./lemmy_api_structs/
COPY server/lemmy_rate_limit/Cargo.toml ./lemmy_rate_limit/
# Cache the deps
RUN cargo build-deps
# Copy the src folders
COPY server/src ./src/
COPY server/lemmy_db/src ./lemmy_db/src/
COPY server/lemmy_utils/src/ ./lemmy_utils/src/
COPY server/lemmy_api_structs/src/ ./lemmy_api_structs/src/
COPY server/lemmy_rate_limit/src/ ./lemmy_rate_limit/src/
COPY server/migrations ./migrations/
# Build for debug
RUN cargo build
RUN sudo rm -rf .git
FROM ekidd/rust-musl-builder:1.42.0-openssl11 as docs
FROM ekidd/rust-musl-builder:nightly-2020-05-07 as docs
WORKDIR /app
COPY docs ./docs
RUN sudo chown -R rust:rust .

12
docker/dev/docker-compose.yml

@ -3,11 +3,9 @@ version: '3.3'
services:
lemmy:
build:
context: ../../
dockerfile: docker/dev/Dockerfile
image: lemmy-dev:latest
ports:
- "127.0.0.1:8536:8536"
- "8536:8536"
restart: always
environment:
- RUST_LOG=debug
@ -22,7 +20,7 @@ services:
image: postgres:12-alpine
ports:
# use a different port so it doesnt conflict with postgres running on the host
- "127.0.0.1:5433:5432"
- "5433:5432"
environment:
- POSTGRES_USER=lemmy
- POSTGRES_PASSWORD=password
@ -34,7 +32,7 @@ services:
pictrs:
image: asonix/pictrs:v0.1.13-r0
ports:
- "127.0.0.1:8537:8080"
- "8537:8080"
user: 991:991
volumes:
- ./volumes/pictrs:/mnt
@ -43,7 +41,7 @@ services:
iframely:
image: jolt/iframely:v1.4.3
ports:
- "127.0.0.1:8061:80"
- "8061:80"
volumes:
- ../iframely.config.local.js:/iframely/config.local.js:ro
restart: always

6
docker/dev/docker_update.sh

@ -1,6 +1,6 @@
#!/bin/sh
set -e
export COMPOSE_DOCKER_CLI_BUILD=1
export DOCKER_BUILDKIT=1
docker-compose up -d --no-deps --build
sudo chown -R 991:991 volumes/pictrs
sudo docker build ../../ --file ../dev/Dockerfile -t lemmy-dev:latest
sudo docker-compose up -d

20
docker/federation-test/servers.sh

@ -1,20 +0,0 @@
#!/bin/bash
set -e
sudo docker-compose --file ../federation/docker-compose.yml --project-directory . down
sudo rm -rf volumes
pushd ../../server/
cargo build
popd
pushd ../../ui
yarn
popd
mkdir -p volumes/pictrs_{alpha,beta,gamma}
sudo chown -R 991:991 volumes/pictrs_{alpha,beta,gamma}
sudo docker build ../../ --file ../federation/Dockerfile --tag lemmy-federation:latest
sudo docker-compose --file ../federation/docker-compose.yml --project-directory . up

10
docker/federation-test/tests.sh

@ -1,10 +0,0 @@
#!/bin/bash
set -xe
pushd ../../ui
echo "Waiting for Lemmy to start..."
while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8540/api/v1/site')" != "200" ]]; do sleep 1; done
while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8550/api/v1/site')" != "200" ]]; do sleep 1; done
while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8560/api/v1/site')" != "200" ]]; do sleep 1; done
yarn api-test || true
popd

17
docker/federation/Dockerfile

@ -1,17 +0,0 @@
FROM ekidd/rust-musl-builder:1.42.0-openssl11
USER root
RUN mkdir /app/dist/documentation/ -p \
&& addgroup --gid 1001 lemmy \
&& adduser --gecos "" --disabled-password --shell /bin/sh -u 1001 --ingroup lemmy lemmy
# Copy resources
COPY server/config/defaults.hjson /app/config/defaults.hjson
COPY ui/dist /app/dist
COPY server/target/debug/lemmy_server /app/lemmy
RUN chown lemmy:lemmy /app/ -R
USER lemmy
EXPOSE 8536
WORKDIR /app
CMD ["/app/lemmy"]

79
docker/federation/docker-compose.yml

@ -7,16 +7,19 @@ services:
- "8540:8540"
- "8550:8550"
- "8560:8560"
- "8570:8570"
- "8580:8580"
volumes:
# Hack to make this work from both docker/federation/ and docker/federation-test/
- ../federation/nginx.conf:/etc/nginx/nginx.conf
- ./nginx.conf:/etc/nginx/nginx.conf
restart: on-failure
depends_on:
- lemmy-alpha
- pictrs
- iframely
- lemmy-alpha
- lemmy-beta
- lemmy-gamma
- iframely
- lemmy-delta
- lemmy-epsilon
pictrs:
restart: always
@ -34,7 +37,7 @@ services:
- LEMMY_FRONT_END_DIR=/app/dist
- LEMMY_FEDERATION__ENABLED=true
- LEMMY_FEDERATION__TLS_ENABLED=false
- LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-beta,lemmy-gamma
- LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-beta,lemmy-gamma,lemmy-delta,lemmy-epsilon
- LEMMY_PORT=8540
- LEMMY_SETUP__ADMIN_USERNAME=lemmy_alpha
- LEMMY_SETUP__ADMIN_PASSWORD=lemmy
@ -64,7 +67,7 @@ services:
- LEMMY_FRONT_END_DIR=/app/dist
- LEMMY_FEDERATION__ENABLED=true
- LEMMY_FEDERATION__TLS_ENABLED=false
- LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-alpha,lemmy-gamma
- LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-alpha,lemmy-gamma,lemmy-delta,lemmy-epsilon
- LEMMY_PORT=8550
- LEMMY_SETUP__ADMIN_USERNAME=lemmy_beta
- LEMMY_SETUP__ADMIN_PASSWORD=lemmy
@ -94,7 +97,7 @@ services:
- LEMMY_FRONT_END_DIR=/app/dist
- LEMMY_FEDERATION__ENABLED=true
- LEMMY_FEDERATION__TLS_ENABLED=false
- LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-alpha,lemmy-beta
- LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-alpha,lemmy-beta,lemmy-delta,lemmy-epsilon
- LEMMY_PORT=8560
- LEMMY_SETUP__ADMIN_USERNAME=lemmy_gamma
- LEMMY_SETUP__ADMIN_PASSWORD=lemmy
@ -115,6 +118,68 @@ services:
volumes:
- ./volumes/postgres_gamma:/var/lib/postgresql/data
# An instance with only an allowlist for beta
lemmy-delta:
image: lemmy-federation:latest
environment:
- LEMMY_HOSTNAME=lemmy-delta:8570
- LEMMY_DATABASE_URL=postgres://lemmy:[email protected]_delta:5432/lemmy
- LEMMY_JWT_SECRET=changeme
- LEMMY_FRONT_END_DIR=/app/dist
- LEMMY_FEDERATION__ENABLED=true
- LEMMY_FEDERATION__TLS_ENABLED=false
- LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-beta
- LEMMY_PORT=8570
- LEMMY_SETUP__ADMIN_USERNAME=lemmy_delta
- LEMMY_SETUP__ADMIN_PASSWORD=lemmy
- LEMMY_SETUP__SITE_NAME=lemmy-delta
- LEMMY_RATE_LIMIT__POST=99999
- LEMMY_RATE_LIMIT__REGISTER=99999
- LEMMY_CAPTCHA__ENABLED=false
- RUST_BACKTRACE=1
- RUST_LOG=debug
depends_on:
- postgres_delta
postgres_delta:
image: postgres:12-alpine
environment:
- POSTGRES_USER=lemmy
- POSTGRES_PASSWORD=password
- POSTGRES_DB=lemmy
volumes:
- ./volumes/postgres_delta:/var/lib/postgresql/data
# An instance who has a blocklist, with lemmy-alpha blocked
lemmy-epsilon:
image: lemmy-federation:latest
environment:
- LEMMY_HOSTNAME=lemmy-epsilon:8580
- LEMMY_DATABASE_URL=postgres://lemmy:[email protected]_epsilon:5432/lemmy
- LEMMY_JWT_SECRET=changeme
- LEMMY_FRONT_END_DIR=/app/dist
- LEMMY_FEDERATION__ENABLED=true
- LEMMY_FEDERATION__TLS_ENABLED=false
- LEMMY_FEDERATION__BLOCKED_INSTANCES=lemmy-alpha
- LEMMY_PORT=8580
- LEMMY_SETUP__ADMIN_USERNAME=lemmy_epsilon
- LEMMY_SETUP__ADMIN_PASSWORD=lemmy
- LEMMY_SETUP__SITE_NAME=lemmy-epsilon
- LEMMY_RATE_LIMIT__POST=99999
- LEMMY_RATE_LIMIT__REGISTER=99999
- LEMMY_CAPTCHA__ENABLED=false
- RUST_BACKTRACE=1
- RUST_LOG=debug
depends_on:
- postgres_epsilon
postgres_epsilon:
image: postgres:12-alpine
environment:
- POSTGRES_USER=lemmy
- POSTGRES_PASSWORD=password
- POSTGRES_DB=lemmy
volumes:
- ./volumes/postgres_epsilon:/var/lib/postgresql/data
iframely:
image: jolt/iframely:v1.4.3
volumes:

62
docker/federation/nginx.conf

@ -95,4 +95,66 @@ http {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
server {
listen 8570;
server_name 127.0.0.1;
access_log off;
# Upload limit for pictshare
client_max_body_size 50M;
location / {
proxy_pass http://lemmy-delta:8570;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Cuts off the trailing slash on URLs to make them valid
rewrite ^(.+)/+$ $1 permanent;
# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /iframely/ {
proxy_pass http://iframely:80/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
server {
listen 8580;
server_name 127.0.0.1;
access_log off;
# Upload limit for pictshare
client_max_body_size 50M;
location / {
proxy_pass http://lemmy-epsilon:8580;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Cuts off the trailing slash on URLs to make them valid
rewrite ^(.+)/+$ $1 permanent;
# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /iframely/ {
proxy_pass http://iframely:80/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}

28
docker/federation/run-federation-test.bash

@ -1,28 +0,0 @@
#!/bin/bash
set -e
# already start rust build in the background
pushd ../../server/ || exit
cargo build &
popd || exit
if [ "$1" = "-yarn" ]; then
pushd ../../ui/ || exit
yarn
yarn build
popd || exit
fi
# wait for rust build to finish
pushd ../../server/ || exit
cargo build
popd || exit
sudo docker build ../../ --file Dockerfile -t lemmy-federation:latest
for Item in alpha beta gamma ; do
sudo mkdir -p volumes/pictrs_$Item
sudo chown -R 991:991 volumes/pictrs_$Item
done
sudo docker-compose up

docker/federation-test/run-tests.sh → docker/federation/run-tests.sh

11
docker/federation/start-local-instances.bash

@ -0,0 +1,11 @@
#!/bin/bash
set -e
sudo docker build ../../ --file ../dev/Dockerfile -t lemmy-federation:latest
for Item in alpha beta gamma delta epsilon ; do
sudo mkdir -p volumes/pictrs_$Item
sudo chown -R 991:991 volumes/pictrs_$Item
done
sudo docker-compose up

9
docker/prod/Dockerfile

@ -10,10 +10,11 @@ WORKDIR /app
RUN sudo chown -R rust:rust .
RUN USER=root cargo new server
WORKDIR /app/server
COPY server/Cargo.toml server/Cargo.lock server/build.rs ./
COPY server/Cargo.toml server/Cargo.lock ./
COPY server/lemmy_db ./lemmy_db
COPY server/lemmy_utils ./lemmy_utils
COPY .git/ ./.git/
COPY server/lemmy_api_structs ./lemmy_api_structs
COPY server/lemmy_rate_limit ./lemmy_rate_limit
RUN mkdir -p ./src/bin \
&& echo 'fn main() { println!("Dummy") }' > ./src/bin/main.rs
RUN cargo build --release
@ -25,8 +26,6 @@ COPY server/migrations ./migrations/
# workaround for https://github.com/rust-lang/rust/issues/62896
RUN cargo build --frozen --release
RUN sudo rm -rf .git
# reduce binary size
RUN strip ./target/$CARGO_BUILD_TARGET/$RUSTRELEASEDIR/lemmy_server
@ -47,9 +46,7 @@ RUN yarn install --pure-lockfile --network-timeout 600000
# Build
COPY ui /app/ui
COPY .git/ ./.git/
RUN yarn build
RUN su && rm -rf .git
FROM alpine:3.12 as lemmy

4
docker/prod/docker-compose.yml

@ -12,7 +12,7 @@ services:
restart: always
lemmy:
image: dessalines/lemmy:v0.7.41
image: dessalines/lemmy:v0.7.57
ports:
- "127.0.0.1:8536:8536"
restart: always
@ -35,7 +35,7 @@ services:
restart: always
iframely:
image: jolt/iframely:v1.4.3
image: dogbin/iframely:latest
ports:
- "127.0.0.1:8061:80"
volumes:

76
docker/travis/docker-compose.yml

@ -7,16 +7,20 @@ services:
- "8540:8540"
- "8550:8550"
- "8560:8560"
- "8570:8570"
- "8580:8580"
volumes:
# Hack to make this work from both docker/federation/ and docker/federation-test/
- ../federation/nginx.conf:/etc/nginx/nginx.conf
restart: on-failure
depends_on:
- lemmy-alpha
- pictrs
- iframely
- lemmy-alpha
- lemmy-beta
- lemmy-gamma
- iframely
- lemmy-delta
- lemmy-epsilon
pictrs:
restart: always
@ -34,7 +38,7 @@ services:
- LEMMY_FRONT_END_DIR=/app/dist
- LEMMY_FEDERATION__ENABLED=true
- LEMMY_FEDERATION__TLS_ENABLED=false
- LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-beta,lemmy-gamma
- LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-beta,lemmy-gamma,lemmy-delta,lemmy-epsilon
- LEMMY_PORT=8540
- LEMMY_SETUP__ADMIN_USERNAME=lemmy_alpha
- LEMMY_SETUP__ADMIN_PASSWORD=lemmy
@ -64,7 +68,7 @@ services:
- LEMMY_FRONT_END_DIR=/app/dist
- LEMMY_FEDERATION__ENABLED=true
- LEMMY_FEDERATION__TLS_ENABLED=false
- LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-alpha,lemmy-gamma
- LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-alpha,lemmy-gamma,lemmy-delta,lemmy-epsilon
- LEMMY_PORT=8550
- LEMMY_SETUP__ADMIN_USERNAME=lemmy_beta
- LEMMY_SETUP__ADMIN_PASSWORD=lemmy
@ -94,7 +98,7 @@ services:
- LEMMY_FRONT_END_DIR=/app/dist
- LEMMY_FEDERATION__ENABLED=true
- LEMMY_FEDERATION__TLS_ENABLED=false
- LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-alpha,lemmy-beta
- LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-alpha,lemmy-beta,lemmy-delta,lemmy-epsilon
- LEMMY_PORT=8560
- LEMMY_SETUP__ADMIN_USERNAME=lemmy_gamma
- LEMMY_SETUP__ADMIN_PASSWORD=lemmy
@ -115,6 +119,68 @@ services:
volumes:
- ./volumes/postgres_gamma:/var/lib/postgresql/data
# An instance with only an allowlist for beta
lemmy-delta:
image: dessalines/lemmy:travis
environment:
- LEMMY_HOSTNAME=lemmy-delta:8570
- LEMMY_DATABASE_URL=postgres://lemmy:[email protected]_delta:5432/lemmy
- LEMMY_JWT_SECRET=changeme
- LEMMY_FRONT_END_DIR=/app/dist
- LEMMY_FEDERATION__ENABLED=true
- LEMMY_FEDERATION__TLS_ENABLED=false
- LEMMY_FEDERATION__ALLOWED_INSTANCES=lemmy-beta
- LEMMY_PORT=8570
- LEMMY_SETUP__ADMIN_USERNAME=lemmy_delta
- LEMMY_SETUP__ADMIN_PASSWORD=lemmy
- LEMMY_SETUP__SITE_NAME=lemmy-delta
- LEMMY_RATE_LIMIT__POST=99999
- LEMMY_RATE_LIMIT__REGISTER=99999
- LEMMY_CAPTCHA__ENABLED=false
- RUST_BACKTRACE=1
- RUST_LOG=debug
depends_on:
- postgres_delta
postgres_delta:
image: postgres:12-alpine
environment:
- POSTGRES_USER=lemmy
- POSTGRES_PASSWORD=password
- POSTGRES_DB=lemmy
volumes:
- ./volumes/postgres_delta:/var/lib/postgresql/data
# An instance who has a blocklist, with lemmy-alpha blocked
lemmy-epsilon:
image: dessalines/lemmy:travis
environment:
- LEMMY_HOSTNAME=lemmy-epsilon:8580
- LEMMY_DATABASE_URL=postgres://lemmy:[email protected]_epsilon:5432/lemmy
- LEMMY_JWT_SECRET=changeme
- LEMMY_FRONT_END_DIR=/app/dist
- LEMMY_FEDERATION__ENABLED=true
- LEMMY_FEDERATION__TLS_ENABLED=false
- LEMMY_FEDERATION__BLOCKED_INSTANCES=lemmy-alpha
- LEMMY_PORT=8580
- LEMMY_SETUP__ADMIN_USERNAME=lemmy_epsilon
- LEMMY_SETUP__ADMIN_PASSWORD=lemmy
- LEMMY_SETUP__SITE_NAME=lemmy-epsilon
- LEMMY_RATE_LIMIT__POST=99999
- LEMMY_RATE_LIMIT__REGISTER=99999
- LEMMY_CAPTCHA__ENABLED=false
- RUST_BACKTRACE=1
- RUST_LOG=debug
depends_on:
- postgres_epsilon
postgres_epsilon:
image: postgres:12-alpine
environment:
- POSTGRES_USER=lemmy
- POSTGRES_PASSWORD=password
- POSTGRES_DB=lemmy
volumes:
- ./volumes/postgres_epsilon:/var/lib/postgresql/data
iframely:
image: dogbin/iframely:latest
volumes:

4
docker/travis/docker_push.sh

@ -1,5 +1,5 @@
#!/bin/sh
echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
docker tag dessalines/lemmy:travis \
dessalines/lemmy:v0.7.41
docker push dessalines/lemmy:v0.7.41
dessalines/lemmy:v0.7.57
docker push dessalines/lemmy:v0.7.57

6
docker/travis/run-tests.sh

@ -5,8 +5,8 @@ set -e
sudo docker-compose down
sudo rm -rf volumes
mkdir -p volumes/pictrs_{alpha,beta,gamma}
sudo chown -R 991:991 volumes/pictrs_{alpha,beta,gamma}
mkdir -p volumes/pictrs_{alpha,beta,gamma,delta,epsilon}
sudo chown -R 991:991 volumes/pictrs_{alpha,beta,gamma,delta,epsilon}
sudo docker build ../../ --file ../prod/Dockerfile --tag dessalines/lemmy:travis
@ -17,6 +17,8 @@ echo "Waiting for Lemmy to start..."
while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8540/api/v1/site')" != "200" ]]; do sleep 1; done
while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8550/api/v1/site')" != "200" ]]; do sleep 1; done
while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8560/api/v1/site')" != "200" ]]; do sleep 1; done
while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8570/api/v1/site')" != "200" ]]; do sleep 1; done
while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8580/api/v1/site')" != "200" ]]; do sleep 1; done
yarn
yarn api-test
popd

34
docs/src/about_guide.md

@ -21,22 +21,22 @@ For more detail, check the [Post and Comment Ranking details](about_ranking.md).
## Markdown Guide
| Type | Or | … to Get |
| ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------- |
| \*Italic\* | \_Italic\_ | _Italic_ |
| \*\*Bold\*\* | \_\_Bold\_\_ | **Bold** |
| \# Heading 1 | Heading 1 <br> ========= | <h4>Heading 1</h4> |
| \## Heading 2 | Heading 2 <br>--------- | <h5>Heading 2</h5> |
| \[Link\](http://a.com) | \[Link\]\[1\]<br><br>\[1\]: http://b.org | [Link](https://commonmark.org/) |
| !\[Image\](http://url/a.png) | !\[Image\]\[1\]<br><br>\[1\]: http://url/b.jpg | ![Markdown](https://commonmark.org/help/images/favicon.png) |
| \> Blockquote | | <blockquote>Blockquote</blockquote> |
| \* List <br>\* List <br>\* List | \- List <br>\- List <br>\- List <br> | _ List <br>_ List <br>\* List <br> |
| 1\. One <br>2\. Two <br>3\. Three | 1) One<br>2) Two<br>3) Three | 1. One<br>2. Two<br>3. Three |
| Horizontal Rule <br>\--- | Horizontal Rule<br>\*\*\* | Horizontal Rule <br><hr> |
| \`Inline code\` with backticks | | `Inline code` with backticks |
| \`\`\`<br>\# code block <br>print '3 backticks or'<br>print 'indent 4 spaces' <br>\`\`\` | ····\# code block<br>····print '3 backticks or'<br>····print 'indent 4 spaces' | \# code block <br>print '3 backticks or'<br>print 'indent 4 spaces' |
| ::: spoiler hidden or nsfw stuff<br>_a bunch of spoilers here_<br>::: | | <details><summary> hidden or nsfw stuff </summary><p><em>a bunch of spoilers here</em></p></details> |
| Some ~subscript~ text | | Some <sub>subscript</sub> text |
| Some ^superscript^ text | | Some <sup>superscript</sup> text |
Type | Or | … to Get
--- | --- | ---
\*Italic\* | \_Italic\_ | _Italic_
\*\*Bold\*\* | \_\_Bold\_\_ | **Bold**
\# Heading 1 | Heading 1 <br> ========= | <h4>Heading 1</h4>
\## Heading 2 | Heading 2 <br>--------- | <h5>Heading 2</h5>
\[Link\](http://a.com) | \[Link\]\[1\]<br><br>\[1\]: http://b.org | [Link](https://commonmark.org/)
!\[Image\](http://url/a.png) | !\[Image\]\[1\]<br><br>\[1\]: http://url/b.jpg | ![Markdown](https://commonmark.org/help/images/favicon.png)
\> Blockquote | | <blockquote>Blockquote</blockquote>
\* List <br>\* List <br>\* List | \- List <br>\- List <br>\- List <br> | * List <br>* List <br>* List <br>
1\. One <br>2\. Two <br>3\. Three | 1) One<br>2) Two<br>3) Three | 1. One<br>2. Two<br>3. Three
Horizontal Rule <br>\--- | Horizontal Rule<br>\*\*\* | Horizontal Rule <br><hr>
\`Inline code\` with backticks | |`Inline code` with backticks
\`\`\`<br>\# code block <br>print '3 backticks or'<br>print 'indent 4 spaces' <br>\`\`\` | ····\# code block<br>····print '3 backticks or'<br>····print 'indent 4 spaces' | \# code block <br>print '3 backticks or'<br>print 'indent 4 spaces'
::: spoiler hidden or nsfw stuff<br>*a bunch of spoilers here*<br>::: | | <details><summary> hidden or nsfw stuff </summary><p><em>a bunch of spoilers here</em></p></details>
Some ~subscript~ text | | Some <sub>subscript</sub> text
Some ^superscript^ text | | Some <sup>superscript</sup> text
[CommonMark Tutorial](https://commonmark.org/help/tutorial/)

40
docs/src/contributing_federation_development.md

@ -14,25 +14,30 @@ You need to have the following packages installed, the Docker service needs to b
- docker
- docker-compose
- cargo
- yarn
Then run the following
```bash
cd docker/federation
./run-federation-test.bash -yarn
./start-local-instances.bash
```
The federation test sets up 3 instances:
The federation test sets up 5 instances:
Instance / Username | Location
--- | ---
lemmy_alpha | [127.0.0.1:8540](http://127.0.0.1:8540)
lemmy_beta | [127.0.0.1:8550](http://127.0.0.1:8550)
lemmy_gamma | [127.0.0.1:8560](http://127.0.0.1:8560)
Instance | Username | Location | Notes
--- | --- | --- | ---
lemmy-alpha | lemmy_alpha | [127.0.0.1:8540](http://127.0.0.1:8540) | federated with all other instances
lemmy-beta | lemmy_beta | [127.0.0.1:8550](http://127.0.0.1:8550) | federated with all other instances
lemmy-gamma | lemmy_gamma | [127.0.0.1:8560](http://127.0.0.1:8560) | federated with all other instances
lemmy-delta | lemmy_delta | [127.0.0.1:8570](http://127.0.0.1:8570) | only allows federation with lemmy-beta
lemmy-epsilon | lemmy_epsilon | [127.0.0.1:8580](http://127.0.0.1:8580) | uses blocklist, has lemmy-alpha blocked
You can log into each using the instance name, and `lemmy` as the password, IE (`lemmy_alpha`, `lemmy`).
To start federation between instances, visit one of them and search for a user, community or post, like this:
- `[email protected]:8540`
- `http://lemmy-beta:8550/post/3`
- `@[email protected]:8560`
Firefox containers are a good way to test them interacting.
## Integration tests
@ -40,8 +45,8 @@ Firefox containers are a good way to test them interacting.
To run a suite of suite of federation integration tests:
```bash
cd docker/federation-test
./run-tests.sh
cd docker/federation
./run-tests.bash
```
## Running on a server
@ -68,3 +73,16 @@ cd /lemmy/
sudo docker-compose pull
sudo docker-compose up -d
```
## Security Model
- HTTP signature verify: This ensures that activity really comes from the activity that it claims
- check_is_apub_valid : Makes sure its in our allowed instances list
- Lower level checks: To make sure that the user that creates/updates/removes a post is actually on the same instance as that post
For the last point, note that we are *not* checking whether the actor that sends the create activity for a post is
actually identical to the post's creator, or that the user that removes a post is a mod/admin. These things are checked
by the API code, and its the responsibility of each instance to check user permissions. This does not leave any attack
vector, as a normal instance user cant do actions that violate the API rules. The only one who could do that is the
admin (and the software deployed by the admin). But the admin can do anything on the instance, including send activities
from other user accounts. So we wouldnt actually gain any security by checking mod permissions or similar.

447
docs/src/contributing_websocket_http_api.md

@ -4,190 +4,242 @@
<!-- toc -->
- [Lemmy API](#lemmy-api)
- [Data types](#data-types)
- [Basic usage](#basic-usage)
- [WebSocket](#websocket)
- [Testing with Websocat](#testing-with-websocat)
- [Testing with the WebSocket JavaScript API](#testing-with-the-websocket-javascript-api)
- [HTTP](#http)
- [Testing with Curl](#testing-with-curl)
- [Get Example](#get-example)
- [Post Example](#post-example)
- [Rate limits](#rate-limits)
- [Errors](#errors)
- [API documentation](#api-documentation)
- [Sort Types](#sort-types)
- [Websocket vs HTTP](#websocket-vs-http)
- [User / Authentication / Admin actions](#user--authentication--admin-actions)
- [Login](#login)
- [Request](#request)
- [Response](#response)
- [HTTP](#http-1)
- [Register](#register)
- [Request](#request-1)
- [Response](#response-1)
- [HTTP](#http-2)
- [Get User Details](#get-user-details)
- [Request](#request-2)
- [Response](#response-2)
- [HTTP](#http-3)
- [Save User Settings](#save-user-settings)
- [Request](#request-3)
- [Response](#response-3)
- [HTTP](#http-4)
- [Get Replies / Inbox](#get-replies--inbox)
- [Request](#request-4)
- [Response](#response-4)
- [HTTP](#http-5)
- [Get User Mentions](#get-user-mentions)
- [Request](#request-5)
- [Response](#response-5)
- [HTTP](#http-6)
- [Edit User Mention](#edit-user-mention)
- [Request](#request-6)
- [Response](#response-6)
- [HTTP](#http-7)
- [Mark All As Read](#mark-all-as-read)
- [Request](#request-7)
- [Response](#response-7)
- [HTTP](#http-8)
- [Delete Account](#delete-account)
- [Request](#request-8)
- [Response](#response-8)
- [HTTP](#http-9)
- [Add admin](#add-admin)
- [Request](#request-9)
- [Response](#response-9)
- [HTTP](#http-10)
- [Add sitemod](#add-sitemod)
- [Request](#request-10)
- [Response](#response-10)
- [HTTP](#http-11)
- [Ban user](#ban-user)
- [Request](#request-11)
- [Response](#response-11)
- [HTTP](#http-12)
- [Site](#site)
- [List Categories](#list-categories)
- [Request](#request-12)
- [Response](#response-12)
- [HTTP](#http-13)
- [Search](#search)
- [Request](#request-13)
- [Response](#response-13)
- [HTTP](#http-14)
- [Get Modlog](#get-modlog)
- [Request](#request-14)
- [Response](#response-14)
- [HTTP](#http-15)
- [Create Site](#create-site)
- [Request](#request-15)
- [Response](#response-15)
- [HTTP](#http-16)
- [Edit Site](#edit-site)
- [Request](#request-16)
- [Response](#response-16)
- [HTTP](#http-17)
- [Get Site](#get-site)
- [Request](#request-17)
- [Response](#response-17)
- [HTTP](#http-18)
- [Transfer Site](#transfer-site)
- [Request](#request-18)
- [Response](#response-18)
- [HTTP](#http-19)
- [Get Site Config](#get-site-config)
- [Request](#request-19)
- [Response](#response-19)
- [HTTP](#http-20)
- [Save Site Config](#save-site-config)
- [Request](#request-20)
- [Response](#response-20)
- [HTTP](#http-21)
- [Community](#community)
- [Get Community](#get-community)
- [Request](#request-21)
- [Response](#response-21)
- [HTTP](#http-22)
- [Create Community](#create-community)
- [Request](#request-22)
- [Response](#response-22)
- [HTTP](#http-23)
- [List Communities](#list-communities)
- [Request](#request-23)
- [Response](#response-23)
- [HTTP](#http-24)
- [Ban from Community](#ban-from-community)
- [Request](#request-24)
- [Response](#response-24)
- [HTTP](#http-25)
- [Add Mod to Community](#add-mod-to-community)
- [Request](#request-25)
- [Response](#response-25)
- [HTTP](#http-26)
- [Edit Community](#edit-community)
- [Request](#request-26)
- [Response](#response-26)
- [HTTP](#http-27)
- [Follow Community](#follow-community)
- [Request](#request-27)
- [Response](#response-27)
- [HTTP](#http-28)
- [Get Followed Communities](#get-followed-communities)
- [Request](#request-28)
- [Response](#response-28)
- [HTTP](#http-29)
- [Transfer Community](#transfer-community)
- [Request](#request-29)
- [Response](#response-29)
- [HTTP](#http-30)
- [Post](#post)
- [Create Post](#create-post)
- [Request](#request-30)
- [Response](#response-30)
- [HTTP](#http-31)
- [Get Post](#get-post)
- [Request](#request-31)
- [Response](#response-31)
- [HTTP](#http-32)
- [Get Posts](#get-posts)
- [Request](#request-32)
- [Response](#response-32)
- [HTTP](#http-33)
- [Create Post Like](#create-post-like)
- [Request](#request-33)
- [Response](#response-33)
- [HTTP](#http-34)
- [Edit Post](#edit-post)
- [Request](#request-34)
- [Response](#response-34)
- [HTTP](#http-35)
- [Save Post](#save-post)
- [Request](#request-35)
- [Response](#response-35)
- [HTTP](#http-36)
- [Comment](#comment)
- [Create Comment](#create-comment)
- [Request](#request-36)
- [Response](#response-36)
- [HTTP](#http-37)
- [Edit Comment](#edit-comment)
- [Request](#request-37)
- [Response](#response-37)
- [HTTP](#http-38)
- [Save Comment](#save-comment)
- [Request](#request-38)
- [Response](#response-38)
- [HTTP](#http-39)
- [Create Comment Like](#create-comment-like)
- [Request](#request-39)
- [Response](#response-39)
- [HTTP](#http-40)
- [RSS / Atom feeds](#rss--atom-feeds)
- [All](#all)
- [Community](#community-1)
- [User](#user)
- [Data types](#data-types)
- [Basic usage](#basic-usage)
* [WebSocket](#websocket)
+ [Testing with Websocat](#testing-with-websocat)
+ [Testing with the WebSocket JavaScript API](#testing-with-the-websocket-javascript-api)
* [HTTP](#http)
+ [Testing with Curl](#testing-with-curl)
- [Get Example](#get-example)
- [Post Example](#post-example)
- [Rate limits](#rate-limits)
- [Errors](#errors)
- [API documentation](#api-documentation)
* [Sort Types](#sort-types)
* [Undoing actions](#undoing-actions)
* [Websocket vs HTTP](#websocket-vs-http)
* [User / Authentication / Admin actions](#user--authentication--admin-actions)
+ [Login](#login)
- [Request](#request)
- [Response](#response)
- [HTTP](#http-1)
+ [Register](#register)
- [Request](#request-1)
- [Response](#response-1)
- [HTTP](#http-2)
+ [Get User Details](#get-user-details)
- [Request](#request-2)
- [Response](#response-2)
- [HTTP](#http-3)
+ [Save User Settings](#save-user-settings)
- [Request](#request-3)
- [Response](#response-3)
- [HTTP](#http-4)
+ [Get Replies / Inbox](#get-replies--inbox)
- [Request](#request-4)
- [Response](#response-4)
- [HTTP](#http-5)
+ [Get User Mentions](#get-user-mentions)
- [Request](#request-5)
- [Response](#response-5)
- [HTTP](#http-6)
+ [Mark User Mention as read](#mark-user-mention-as-read)
- [Request](#request-6)
- [Response](#response-6)
- [HTTP](#http-7)
+ [Get Private Messages](#get-private-messages)
- [Request](#request-7)
- [Response](#response-7)
- [HTTP](#http-8)
+ [Create Private Message](#create-private-message)
- [Request](#request-8)
- [Response](#response-8)
- [HTTP](#http-9)
+ [Edit Private Message](#edit-private-message)
- [Request](#request-9)
- [Response](#response-9)
- [HTTP](#http-10)
+ [Delete Private Message](#delete-private-message)
- [Request](#request-10)
- [Response](#response-10)
- [HTTP](#http-11)
+ [Mark Private Message as Read](#mark-private-message-as-read)
- [Request](#request-11)
- [Response](#response-11)
- [HTTP](#http-12)
+ [Mark All As Read](#mark-all-as-read)
- [Request](#request-12)
- [Response](#response-12)
- [HTTP](#http-13)
+ [Delete Account](#delete-account)
- [Request](#request-13)
- [Response](#response-13)
- [HTTP](#http-14)
+ [Add admin](#add-admin)
- [Request](#request-14)
- [Response](#response-14)
- [HTTP](#http-15)
+ [Ban user](#ban-user)
- [Request](#request-15)
- [Response](#response-15)
- [HTTP](#http-16)
* [Site](#site)
+ [List Categories](#list-categories)
- [Request](#request-16)
- [Response](#response-16)
- [HTTP](#http-17)
+ [Search](#search)
- [Request](#request-17)
- [Response](#response-17)
- [HTTP](#http-18)
+ [Get Modlog](#get-modlog)
- [Request](#request-18)
- [Response](#response-18)
- [HTTP](#http-19)
+ [Create Site](#create-site)
- [Request](#request-19)
- [Response](#response-19)
- [HTTP](#http-20)
+ [Edit Site](#edit-site)
- [Request](#request-20)
- [Response](#response-20)
- [HTTP](#http-21)
+ [Get Site](#get-site)
- [Request](#request-21)
- [Response](#response-21)
- [HTTP](#http-22)
+ [Transfer Site](#transfer-site)
- [Request](#request-22)
- [Response](#response-22)
- [HTTP](#http-23)
+ [Get Site Config](#get-site-config)
- [Request](#request-23)
- [Response](#response-23)
- [HTTP](#http-24)
+ [Save Site Config](#save-site-config)
- [Request](#request-24)
- [Response](#response-24)
- [HTTP](#http-25)
* [Community](#community)
+ [Get Community](#get-community)
- [Request](#request-25)
- [Response](#response-25)
- [HTTP](#http-26)
+ [Create Community](#create-community)
- [Request](#request-26)
- [Response](#response-26)
- [HTTP](#http-27)
+ [List Communities](#list-communities)
- [Request](#request-27)
- [Response](#response-27)
- [HTTP](#http-28)
+ [Ban from Community](#ban-from-community)
- [Request](#request-28)
- [Response](#response-28)
- [HTTP](#http-29)
+ [Add Mod to Community](#add-mod-to-community)
- [Request](#request-29)
- [Response](#response-29)
- [HTTP](#http-30)
+ [Edit Community](#edit-community)
- [Request](#request-30)
- [Response](#response-30)
- [HTTP](#http-31)
+ [Delete Community](#delete-community)
- [Request](#request-31)
- [Response](#response-31)
- [HTTP](#http-32)
+ [Remove Community](#remove-community)
- [Request](#request-32)
- [Response](#response-32)
- [HTTP](#http-33)
+ [Follow Community](#follow-community)
- [Request](#request-33)
- [Response](#response-33)
- [HTTP](#http-34)
+ [Get Followed Communities](#get-followed-communities)
- [Request](#request-34)
- [Response](#response-34)
- [HTTP](#http-35)
+ [Transfer Community](#transfer-community)
- [Request](#request-35)
- [Response](#response-35)
- [HTTP](#http-36)
* [Post](#post)
+ [Create Post](#create-post)
- [Request](#request-36)
- [Response](#response-36)
- [HTTP](#http-37)
+ [Get Post](#get-post)
- [Request](#request-37)
- [Response](#response-37)
- [HTTP](#http-38)
+ [Get Posts](#get-posts)
- [Request](#request-38)
- [Response](#response-38)
- [HTTP](#http-39)
+ [Create Post Like](#create-post-like)
- [Request](#request-39)
- [Response](#response-39)
- [HTTP](#http-40)
+ [Edit Post](#edit-post)
- [Request](#request-40)
- [Response](#response-40)
- [HTTP](#http-41)
+ [Delete Post](#delete-post)
- [Request](#request-41)
- [Response](#response-41)
- [HTTP](#http-42)
+ [Remove Post](#remove-post)
- [Request](#request-42)
- [Response](#response-42)
- [HTTP](#http-43)
+ [Lock Post](#lock-post)
- [Request](#request-43)
- [Response](#response-43)
- [HTTP](#http-44)
+ [Sticky Post](#sticky-post)
- [Request](#request-44)
- [Response](#response-44)
- [HTTP](#http-45)
+ [Save Post](#save-post)
- [Request](#request-45)
- [Response](#response-45)
- [HTTP](#http-46)
* [Comment](#comment)
+ [Create Comment](#create-comment)
- [Request](#request-46)
- [Response](#response-46)
- [HTTP](#http-47)
+ [Edit Comment](#edit-comment)
- [Request](#request-47)
- [Response](#response-47)
- [HTTP](#http-48)
+ [Delete Comment](#delete-comment)
- [Request](#request-48)
- [Response](#response-48)
- [HTTP](#http-49)
+ [Remove Comment](#remove-comment)
- [Request](#request-49)
- [Response](#response-49)
- [HTTP](#http-50)
+ [Mark Comment as Read](#mark-comment-as-read)
- [Request](#request-50)
- [Response](#response-50)
- [HTTP](#http-51)
+ [Save Comment](#save-comment)
- [Request](#request-51)
- [Response](#response-51)
- [HTTP](#http-52)
+ [Create Comment Like](#create-comment-like)
- [Request](#request-52)
- [Response](#response-52)
- [HTTP](#http-53)
* [RSS / Atom feeds](#rss--atom-feeds)
+ [All](#all)
+ [Community](#community-1)
+ [User](#user)
<!-- tocstop -->
@ -758,31 +810,6 @@ Marks all user replies and mentions as read.
`POST /admin/add`
#### Add sitemod
##### Request
```rust
{
op: "AddSitemod",
data: {
user_id: i32,
added: bool,
auth: String
}
}
```
##### Response
```rust
{
op: "AddSitemod",
data: {
sitemods: Vec<UserView>,
}
}
```
##### HTTP
`POST /sitemod/add`
#### Ban user
##### Request
```rust
@ -791,6 +818,7 @@ Marks all user replies and mentions as read.
data: {
user_id: i32,
ban: bool,
remove_data: Option<bool>, // Removes/Restores their comments, posts, and communities
reason: Option<String>,
expires: Option<i64>,
auth: String
@ -1150,6 +1178,7 @@ Search types are `All, Comments, Posts, Communities, Users, Url`
community_id: i32,
user_id: i32,
ban: bool,
remove_data: Option<bool>, // Removes/Restores their comments and posts for that community
reason: Option<String>,
expires: Option<i64>,
auth: String

423
server/Cargo.lock
File diff suppressed because it is too large
View File

15
server/Cargo.toml

@ -10,13 +10,17 @@ lto = true
[workspace]
members = [
"lemmy_utils",
"lemmy_db"
"lemmy_db",
"lemmy_api_structs",
"lemmy_rate_limit",
]
[dependencies]
# Internal deps
lemmy_utils = { path = "./lemmy_utils" }
lemmy_db = { path = "./lemmy_db" }
lemmy_api_structs = { path = "./lemmy_api_structs" }
lemmy_rate_limit = { path = "./lemmy_rate_limit" }
activitystreams = "0.7.0-alpha.3"
activitystreams-ext = "0.1.0-alpha.2"
@ -25,10 +29,13 @@ actix-files = "0.3.0-alpha.1"
actix-rt = "1.1.1"
actix-web = { version = "3.0.0-alpha.3", features = ["rustls"] }
actix-web-actors = "3.0.0-alpha.1"
anyhow = "1.0.32"
async-trait = "0.1.36"
awc = "2.0.0-alpha.2"
background-jobs = " 0.8.0-alpha.2"
base64 = "0.12.1"
bcrypt = "0.8.0"
captcha = "0.0.7"
chrono = { version = "0.4.7", features = ["serde"] }
comrak = "0.7"
config = {version = "0.10.1", default-features = false, features = ["hjson"] }
@ -51,19 +58,17 @@ openssl = "0.10"
percent-encoding = "2.1.0"
rand = "0.7.3"
regex = "1.3.5"
reqwest = { version = "0.10.6", features = ["blocking", "json"] }
reqwest = { version = "0.10", features = ["json"] }
rss = "1.9.0"
serde = { version = "1.0.105", features = ["derive"] }
serde_json = { version = "1.0.52", features = ["preserve_order"]}
sha2 = "0.9"
strum = "0.18.0"
strum_macros = "0.18.0"
thiserror = "1.0.20"
tokio = "0.2.21"
url = { version = "2.1.1", features = ["serde"] }
uuid = { version = "0.6", features = ["serde", "v4"] }
captcha = "0.0.7"
anyhow = "1.0.32"
thiserror = "1.0.20"
[build-dependencies]
vergen = "3"

8
server/config/defaults.hjson

@ -62,8 +62,14 @@
enabled: false
# whether tls is required for activitypub. only disable this for debugging, never for producion.
tls_enabled: true
# comma seperated list of instances with which federation is allowed
# comma separated list of instances with which federation is allowed
allowed_instances: ""
# comma separated list of instances which are blocked from federating
blocked_instances: ""
}
captcha: {
enabled: true
difficulty: medium # Can be easy, medium, or hard
}
captcha: {
enabled: true

14
server/lemmy_api_structs/Cargo.toml

@ -0,0 +1,14 @@
[package]
name = "lemmy_api_structs"
version = "0.1.0"
authors = ["Felix Ableitner <[email protected]>"]
edition = "2018"
[lib]
name = "lemmy_api_structs"
path = "src/lib.rs"
[dependencies]
lemmy_db = { path = "../lemmy_db" }
serde = { version = "1.0.105", features = ["derive"] }
thiserror = "1.0.20"

77
server/lemmy_api_structs/src/comment.rs

@ -0,0 +1,77 @@
use lemmy_db::comment_view::CommentView;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
pub struct CreateComment {
pub content: String,
pub parent_id: Option<i32>,
pub post_id: i32,
pub form_id: Option<String>,
pub auth: String,
}
#[derive(Serialize, Deserialize)]
pub struct EditComment {
pub content: String,
pub edit_id: i32,
pub form_id: Option<String>,
pub auth: String,
}
#[derive(Serialize, Deserialize)]
pub struct DeleteComment {
pub edit_id: i32,
pub deleted: bool,
pub auth: String,
}
#[derive(Serialize, Deserialize)]
pub struct RemoveComment {
pub edit_id: i32,
pub removed: bool,
pub reason: Option<String>,
pub auth: String,
}
#[derive(Serialize, Deserialize)]
pub struct MarkCommentAsRead {
pub edit_id: i32,
pub read: bool,
pub auth: String,
}
#[derive(Serialize, Deserialize)]
pub struct SaveComment {
pub comment_id: i32,
pub save: bool,
pub auth: String,
}
#[derive(Serialize, Deserialize, Clone)]
pub struct CommentResponse {
pub comment: CommentView,
pub recipient_ids: Vec<i32>,
pub form_id: Option<String>,
}
#[derive(Serialize, Deserialize)]
pub struct CreateCommentLike {
pub comment_id: i32,
pub score: i16,
pub auth: String,
}
#[derive(Serialize, Deserialize)]
pub struct GetComments {
pub type_: String,
pub sort: String,
pub page: Option<i64>,
pub limit: Option<i64>,
pub community_id: Option<i32>,
pub auth: Option<String>,
}
#[derive(Serialize, Deserialize)]
pub struct GetCommentsResponse {
pub comments: Vec<CommentView>,
}

131
server/lemmy_api_structs/src/community.rs

@ -0,0 +1,131 @@
use lemmy_db::{
community_view::{CommunityFollowerView, CommunityModeratorView, CommunityView},
user_view::UserView,
};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
pub struct GetCommunity {
pub id: Option<i32>,
pub name: Option<String>,
pub auth: Option<String>,
}
#[derive(Serialize, Deserialize)]
pub struct GetCommunityResponse {
pub community: CommunityView,
pub moderators: Vec<CommunityModeratorView>,
pub online: usize,
}
#[derive(Serialize, Deserialize)]
pub struct CreateCommunity {
pub name: String,
pub title: String,
pub description: Option<String>,
pub icon: Option<String>,
pub banner: Option<String>,
pub category_id: i32,
pub nsfw: bool,
pub auth: String,
}
#[derive(Serialize, Deserialize, Clone)]
pub struct CommunityResponse {
pub community: CommunityView,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct ListCommunities {
pub sort: String,
pub page: Option<i64>,
pub limit: Option<i64>,
pub auth: Option<String>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct ListCommunitiesResponse {
pub communities: Vec<CommunityView>,
}
#[derive(Serialize, Deserialize, Clone)]
pub struct BanFromCommunity {
pub community_id: i32,
pub user_id: i32,
pub ban: bool,
pub remove_data: Option<bool>,
pub reason: Option<String>,
pub expires: Option<i64>,
pub auth: String,
}
#[derive(Serialize, Deserialize, Clone)]
pub struct BanFromCommunityResponse {
pub user: UserView,
pub banned: bool,
}
#[derive(Serialize, Deserialize)]
pub struct AddModToCommunity {
pub community_id: i32,
pub user_id: i32,
pub added: bool,
pub auth: String,
}
#[derive(Serialize, Deserialize, Clone)]
pub struct AddModToCommunityResponse {
pub moderators: Vec<CommunityModeratorView>,
}
#[derive(Serialize, Deserialize)]
pub struct EditCommunity {
pub edit_id: i32,
pub title: String,
pub description: Option<String>,
pub icon: Option<String>,
pub banner: Option<String>,
pub category_id: i32,
pub nsfw: bool,
pub auth: String,
}
#[derive(Serialize, Deserialize)]
pub struct DeleteCommunity {
pub edit_id: i32,
pub deleted: bool,
pub auth: String,
}
#[derive(Serialize, Deserialize)]
pub struct RemoveCommunity {
pub edit_id: i32,
pub removed: bool,
pub reason: Option<String>,
pub expires: Option<i64>,
pub auth: String,
}
#[derive(Serialize, Deserialize)]
pub struct FollowCommunity {
pub community_id: i32,
pub follow: bool,
pub auth: String,
}
#[derive(Serialize, Deserialize)]
pub struct GetFollowedCommunities {
pub auth: String,
}
#[derive(Serialize, Deserialize)]