Isomorphic docker (#1124)

* Adding a way to GetComments for a community given its name only.

* Adding getcomments to api docs.

* A first pass at locally working isomorphic integration.

* Testing out cargo-husky.

* Testing a fail hook.

* Revert "Testing a fail hook."

This reverts commit 0941cf1736.

* Moving server to top level, now that UI is gone.

* Running cargo fmt using old way.

* Adding nginx, fixing up docker-compose files, fixing docs.

* Trying to re-add API tests.

* Fixing prod dockerfile.

* Redoing nightly fmt

* Trying to fix private message api test.

* Adding CommunityJoin, PostJoin instead of joins from GetComments, etc.

- Fixes #1122

* Fixing fmt.

* Fixing up docs.

* Removing translations.

* Adding apps / clients to readme.

* Fixing main image.

* Using new lemmy-isomorphic-ui with better javascript disabled.

* Try to fix image uploads in federation test

* Revert "Try to fix image uploads in federation test"

This reverts commit a2ddf2a90b.

* Fix post url federation

* Adding some more tests, some still broken.

* Don't need gitattributes anymore.

* Update local federation test setup

* Fixing tests.

* Fixing travis build.

* Fixing travis build, again.

* Changing lemmy-isomorphic-ui to lemmy-ui

* Error in travis build again.

Co-authored-by: Felix Ableitner <me@nutomic.com>
pull/1138/head
Dessalines 4 years ago committed by GitHub
parent b69524b498
commit 5c6258390c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

2
.gitattributes vendored

@ -1,2 +0,0 @@
* linguist-vendored
*.rs linguist-vendored=false

19
.gitignore vendored

@ -6,16 +6,17 @@ ansible/passwords/
# docker build files
docker/lemmy_mine.hjson
docker/dev/env_deploy.sh
docker/federation/volumes
docker/federation-test/volumes
docker/dev/volumes
# local build files
build/
ui/src/translations
volumes
# ide config
.idea/
.vscode/
.idea
.vscode
# local build files
target
env_setup.sh
query_testing/*.json
query_testing/*.json.old
# API tests
api_tests/node_modules

@ -794,6 +794,12 @@ dependencies = [
"time 0.1.44",
]
[[package]]
name = "cargo-husky"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b02b629252fe8ef6460461409564e2c21d0c8e77e0944f3d189ff06c4e932ad"
[[package]]
name = "cc"
version = "1.0.59"
@ -1875,6 +1881,7 @@ dependencies = [
"base64 0.12.3",
"bcrypt",
"captcha",
"cargo-husky",
"chrono",
"diesel",
"diesel_migrations",

@ -59,3 +59,8 @@ anyhow = "1.0.32"
thiserror = "1.0.20"
background-jobs = " 0.8.0-alpha.2"
reqwest = { version = "0.10", features = ["json"] }
[dev-dependencies.cargo-husky]
version = "1"
default-features = false # Disable features which are enabled by default
features = ["precommit-hook", "run-cargo-fmt", "run-cargo-clippy"]

@ -11,7 +11,7 @@
<p align="center">
<a href="https://dev.lemmy.ml/" rel="noopener">
<img width=200px height=200px src="ui/assets/favicon.svg"></a>
<img width=200px height=200px src="https://raw.githubusercontent.com/LemmyNet/lemmy-ui/main/src/assets/icons/favicon.svg"></a>
<h3 align="center"><a href="https://dev.lemmy.ml">Lemmy</a></h3>
<p align="center">
@ -108,12 +108,15 @@ Each Lemmy server can set its own moderation policy; appointing site-wide admins
### Apps
- [lemmy-ui - The official web app for lemmy](https://github.com/LemmyNet/lemmy-ui)
- [Lemmur - A flutter lemmy app ( under development )](https://github.com/krawieck/lemmur)
- [Lemmy-mobile (Android / IOS) - React native ( under development )](https://github.com/koredefashokun/lemmy-mobile)
### Libraries
- [lemmy-js-client](https://github.com/LemmyNet/lemmy-js-client)
- [Kotlin API ( under development )](https://github.com/eiknat/lemmy-client)
- [Dart API client ( under development )](https://github.com/krawieck/lemmy_api_client)
## Support / Donate

@ -13,8 +13,6 @@
hostname: "{{ domain }}"
# json web token for authorization between server and client
jwt_secret: "{{ jwt_password }}"
# The location of the frontend
front_end_dir: "/app/dist"
# email sending configuration
email: {
# hostname of the smtp server

@ -51,23 +51,41 @@ server {
# Upload limit for pictrs
client_max_body_size 20M;
# lemmy api
location /api/v1 {
proxy_pass http://0.0.0.0:8536/api/v1;
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";
# Rate limit
limit_req zone=lemmy_ratelimit burst=30 nodelay;
}
# Docs
location /docs {
proxy_pass http://0.0.0.0:8536/docs;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# lemmy-ui
location / {
proxy_pass http://0.0.0.0:8536;
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";
# Rate limit
limit_req zone=lemmy_ratelimit burst=30 nodelay;
}
proxy_pass http://0.0.0.0:1235;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Redirect pictshare images to pictrs
location ~ /pictshare/(.*)$ {

@ -0,0 +1,4 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
};

@ -0,0 +1,20 @@
{
"name": "api_tests",
"version": "0.0.1",
"description": "API tests for lemmy backend",
"main": "index.js",
"repository": "https://github.com/LemmyNet/lemmy",
"author": "Dessalines",
"license": "AGPL-3.0",
"scripts": {
"api-test": "jest src/ -i --verbose"
},
"devDependencies": {
"@types/jest": "^26.0.13",
"jest": "^26.4.2",
"lemmy-js-client": "^1.0.11",
"node-fetch": "^2.6.1",
"ts-jest": "^26.3.0",
"typescript": "^4.0.2"
}
}

@ -235,7 +235,7 @@ test('Reply to a comment', async () => {
test('Mention beta', async () => {
// Create a mention on alpha
let mentionContent = 'A test mention of @lemmy_beta@lemmy-beta:8550';
let mentionContent = 'A test mention of @lemmy_beta@lemmy-beta:8551';
let commentRes = await createComment(alpha, postRes.post.id);
await delay();
let mentionRes = await createComment(
@ -275,7 +275,7 @@ test('A and G subscribe to B (center) A posts, G mentions B, it gets announced t
let gammaPost = search.posts[0];
let commentContent =
'A jest test federated comment announce, lets mention @lemmy_beta@lemmy-beta:8550';
'A jest test federated comment announce, lets mention @lemmy_beta@lemmy-beta:8551';
let commentRes = await createComment(
gamma,
gammaPost.id,

@ -1,8 +1,10 @@
jest.setTimeout(120000);
import {
alpha,
beta,
setupLogins,
searchForBetaCommunity,
searchForCommunity,
createCommunity,
deleteCommunity,
removeCommunity,
@ -21,6 +23,17 @@ test('Create community', async () => {
let prevName = communityRes.community.name;
let communityRes2 = await createCommunity(alpha, prevName);
expect(communityRes2['error']).toBe('community_already_exists');
await delay();
// Cache the community on beta, make sure it has the other fields
let searchShort = `!${prevName}@lemmy-alpha:8541`;
let search = await searchForCommunity(beta, searchShort);
let communityOnBeta = search.communities[0];
expect(communityOnBeta.name).toBe(communityRes.community.name);
expect(communityOnBeta.title).toBe(communityRes.community.title);
expect(communityOnBeta.description).toBe(communityRes.community.description);
expect(communityOnBeta.icon).toBe(communityRes.community.icon);
expect(communityOnBeta.banner).toBe(communityRes.community.banner);
});
test('Delete community', async () => {

@ -1,3 +1,4 @@
jest.setTimeout(120000);
import {
alpha,
setupLogins,

@ -56,6 +56,10 @@ test('Create a post', async () => {
expect(betaPost.community_local).toBe(true);
expect(betaPost.creator_local).toBe(false);
expect(betaPost.score).toBe(1);
expect(betaPost.name).toBe(postRes.post.name);
expect(betaPost.body).toBe(postRes.post.body);
expect(betaPost.url).toBe(postRes.post.url);
expect(betaPost.nsfw).toBe(postRes.post.nsfw);
// Delta only follows beta, so it should not see an alpha ap_id
let searchDelta = await searchPost(delta, postRes.post);

@ -50,23 +50,23 @@ export interface API {
}
export let alpha: API = {
client: new LemmyHttp('http://localhost:8540/api/v1'),
client: new LemmyHttp('http://localhost:8541/api/v1'),
};
export let beta: API = {
client: new LemmyHttp('http://localhost:8550/api/v1'),
client: new LemmyHttp('http://localhost:8551/api/v1'),
};
export let gamma: API = {
client: new LemmyHttp('http://localhost:8560/api/v1'),
client: new LemmyHttp('http://localhost:8561/api/v1'),
};
export let delta: API = {
client: new LemmyHttp('http://localhost:8570/api/v1'),
client: new LemmyHttp('http://localhost:8571/api/v1'),
};
export let epsilon: API = {
client: new LemmyHttp('http://localhost:8580/api/v1'),
client: new LemmyHttp('http://localhost:8581/api/v1'),
};
export async function setupLogins() {
@ -120,8 +120,12 @@ export async function createPost(
community_id: number
): Promise<PostResponse> {
let name = 'A jest test post';
let body = 'Some body';
let url = 'https://google.com/';
let form: PostForm = {
name,
url,
body,
auth: api.auth,
community_id,
nsfw: false,
@ -232,7 +236,20 @@ export async function searchForBetaCommunity(
// Make sure lemmy-beta/c/main is cached on lemmy_alpha
// Use short-hand search url
let form: SearchForm = {
q: '!main@lemmy-beta:8550',
q: '!main@lemmy-beta:8551',
type_: SearchType.Communities,
sort: SortType.TopAll,
};
return api.client.search(form);
}
export async function searchForCommunity(
api: API,
q: string,
): Promise<SearchResponse> {
// Use short-hand search url
let form: SearchForm = {
q,
type_: SearchType.Communities,
sort: SortType.TopAll,
};
@ -369,9 +386,15 @@ export async function createCommunity(
api: API,
name_: string = randomString(5)
): Promise<CommunityResponse> {
let description = 'a sample description';
let icon = 'https://image.flaticon.com/icons/png/512/35/35896.png';
let banner = 'https://image.flaticon.com/icons/png/512/35/35896.png';
let form: CommunityForm = {
name: name_,
title: name_,
description,
icon,
banner,
category_id: 1,
nsfw: false,
auth: api.auth,

@ -1,3 +1,4 @@
jest.setTimeout(120000);
import {
alpha,
beta,
@ -17,7 +18,7 @@ test('Create user', async () => {
let site = await getSite(alpha, auth);
expect(site.my_user).toBeDefined();
apShortname = `@${site.my_user.name}@lemmy-alpha:8540`;
apShortname = `@${site.my_user.name}@lemmy-alpha:8541`;
});
test('Save user settings, check changed bio from beta', async () => {

File diff suppressed because it is too large Load Diff

@ -33,8 +33,6 @@
port: 8536
# json web token for authorization between server and client
jwt_secret: "changeme"
# The location of the frontend
front_end_dir: "../ui/dist"
# address where pictrs is available
pictrs_url: "http://pictrs:8080"
# rate limits for various user actions, by user ip

@ -1,15 +1,3 @@
FROM node:10-jessie as node
WORKDIR /app/ui
# Cache deps
COPY ui/package.json ui/yarn.lock ./
RUN yarn install --pure-lockfile
# Build
COPY ui /app/ui
RUN yarn build
FROM ekidd/rust-musl-builder:nightly-2020-05-07 as rust
# Cache deps
@ -27,22 +15,22 @@ RUN mkdir -p lemmy_db/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/
COPY Cargo.toml Cargo.lock ./
COPY lemmy_db/Cargo.toml ./lemmy_db/
COPY lemmy_utils/Cargo.toml ./lemmy_utils/
COPY lemmy_api_structs/Cargo.toml ./lemmy_api_structs/
COPY 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/
COPY src ./src/
COPY lemmy_db/src ./lemmy_db/src/
COPY lemmy_utils/src/ ./lemmy_utils/src/
COPY lemmy_api_structs/src/ ./lemmy_api_structs/src/
COPY lemmy_rate_limit/src/ ./lemmy_rate_limit/src/
COPY migrations ./migrations/
# Build for debug
RUN cargo build
@ -62,10 +50,9 @@ RUN apk add libpq
RUN apk add espeak
# Copy resources
COPY server/config/defaults.hjson /config/defaults.hjson
COPY config/defaults.hjson /config/defaults.hjson
COPY --from=rust /app/server/target/x86_64-unknown-linux-musl/debug/lemmy_server /app/lemmy
COPY --from=docs /app/docs/book/ /app/dist/documentation/
COPY --from=node /app/ui/dist /app/dist
COPY --from=docs /app/docs/book/ /app/documentation/
RUN addgroup -g 1000 lemmy
RUN adduser -D -s /bin/sh -u 1000 -G lemmy lemmy

@ -15,6 +15,16 @@ services:
- pictrs
- postgres
- iframely
lemmy-ui:
image: dessalines/lemmy-ui:v0.0.14
ports:
- "1235:1234"
environment:
- LEMMY_INTERNAL_HOST=lemmy:8536
- LEMMY_EXTERNAL_HOST=localhost:8536
- LEMMY_HTTPS=false
depends_on:
- lemmy
postgres:
image: postgres:12-alpine

@ -28,17 +28,24 @@ services:
volumes:
- ./volumes/pictrs_alpha:/mnt
lemmy-alpha-ui:
image: dessalines/lemmy-ui:v0.0.14
environment:
- LEMMY_INTERNAL_HOST=lemmy-alpha:8541
- LEMMY_EXTERNAL_HOST=localhost:8541
- LEMMY_HTTPS=false
depends_on:
- lemmy-alpha
lemmy-alpha:
image: lemmy-federation:latest
environment:
- LEMMY_HOSTNAME=lemmy-alpha:8540
- LEMMY_HOSTNAME=lemmy-alpha:8541
- LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_alpha: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-gamma,lemmy-delta,lemmy-epsilon
- LEMMY_PORT=8540
- LEMMY_PORT=8541
- LEMMY_SETUP__ADMIN_USERNAME=lemmy_alpha
- LEMMY_SETUP__ADMIN_PASSWORD=lemmy
- LEMMY_SETUP__SITE_NAME=lemmy-alpha
@ -49,6 +56,8 @@ services:
- RUST_LOG=debug
depends_on:
- postgres_alpha
ports:
- "8541:8541"
postgres_alpha:
image: postgres:12-alpine
environment:
@ -58,17 +67,24 @@ services:
volumes:
- ./volumes/postgres_alpha:/var/lib/postgresql/data
lemmy-beta-ui:
image: dessalines/lemmy-ui:v0.0.14
environment:
- LEMMY_INTERNAL_HOST=lemmy-beta:8551
- LEMMY_EXTERNAL_HOST=localhost:8551
- LEMMY_HTTPS=false
depends_on:
- lemmy-beta
lemmy-beta:
image: lemmy-federation:latest
environment:
- LEMMY_HOSTNAME=lemmy-beta:8550
- LEMMY_HOSTNAME=lemmy-beta:8551
- LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_beta: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-alpha,lemmy-gamma,lemmy-delta,lemmy-epsilon
- LEMMY_PORT=8550
- LEMMY_PORT=8551
- LEMMY_SETUP__ADMIN_USERNAME=lemmy_beta
- LEMMY_SETUP__ADMIN_PASSWORD=lemmy
- LEMMY_SETUP__SITE_NAME=lemmy-beta
@ -79,6 +95,8 @@ services:
- RUST_LOG=debug
depends_on:
- postgres_beta
ports:
- "8551:8551"
postgres_beta:
image: postgres:12-alpine
environment:
@ -88,17 +106,24 @@ services:
volumes:
- ./volumes/postgres_beta:/var/lib/postgresql/data
lemmy-gamma-ui:
image: dessalines/lemmy-ui:v0.0.14
environment:
- LEMMY_INTERNAL_HOST=lemmy-gamma:8561
- LEMMY_EXTERNAL_HOST=localhost:8561
- LEMMY_HTTPS=false
depends_on:
- lemmy-gamma
lemmy-gamma:
image: lemmy-federation:latest
environment:
- LEMMY_HOSTNAME=lemmy-gamma:8560
- LEMMY_HOSTNAME=lemmy-gamma:8561
- LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_gamma: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-alpha,lemmy-beta,lemmy-delta,lemmy-epsilon
- LEMMY_PORT=8560
- LEMMY_PORT=8561
- LEMMY_SETUP__ADMIN_USERNAME=lemmy_gamma
- LEMMY_SETUP__ADMIN_PASSWORD=lemmy
- LEMMY_SETUP__SITE_NAME=lemmy-gamma
@ -109,6 +134,8 @@ services:
- RUST_LOG=debug
depends_on:
- postgres_gamma
ports:
- "8561:8561"
postgres_gamma:
image: postgres:12-alpine
environment:
@ -119,17 +146,24 @@ services:
- ./volumes/postgres_gamma:/var/lib/postgresql/data
# An instance with only an allowlist for beta
lemmy-delta-ui:
image: dessalines/lemmy-ui:v0.0.14
environment:
- LEMMY_INTERNAL_HOST=lemmy-delta:8571
- LEMMY_EXTERNAL_HOST=localhost:8571
- LEMMY_HTTPS=false
depends_on:
- lemmy-delta
lemmy-delta:
image: lemmy-federation:latest
environment:
- LEMMY_HOSTNAME=lemmy-delta:8570
- LEMMY_HOSTNAME=lemmy-delta:8571
- LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_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_PORT=8571
- LEMMY_SETUP__ADMIN_USERNAME=lemmy_delta
- LEMMY_SETUP__ADMIN_PASSWORD=lemmy
- LEMMY_SETUP__SITE_NAME=lemmy-delta
@ -140,6 +174,8 @@ services:
- RUST_LOG=debug
depends_on:
- postgres_delta
ports:
- "8571:8571"
postgres_delta:
image: postgres:12-alpine
environment:
@ -150,17 +186,24 @@ services:
- ./volumes/postgres_delta:/var/lib/postgresql/data
# An instance who has a blocklist, with lemmy-alpha blocked
lemmy-epsilon-ui:
image: dessalines/lemmy-ui:v0.0.14
environment:
- LEMMY_INTERNAL_HOST=lemmy-epsilon:8581
- LEMMY_EXTERNAL_HOST=localhost:8581
- LEMMY_HTTPS=false
depends_on:
- lemmy-epsilon
lemmy-epsilon:
image: lemmy-federation:latest
environment:
- LEMMY_HOSTNAME=lemmy-epsilon:8580
- LEMMY_HOSTNAME=lemmy-epsilon:8581
- LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_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_PORT=8581
- LEMMY_SETUP__ADMIN_USERNAME=lemmy_epsilon
- LEMMY_SETUP__ADMIN_PASSWORD=lemmy
- LEMMY_SETUP__SITE_NAME=lemmy-epsilon
@ -171,6 +214,8 @@ services:
- RUST_LOG=debug
depends_on:
- postgres_epsilon
ports:
- "8581:8581"
postgres_epsilon:
image: postgres:12-alpine
environment:

@ -11,21 +11,21 @@ http {
# Upload limit for pictshare
client_max_body_size 50M;
location /api/v1 {
proxy_pass http://lemmy-alpha:8541/api/v1;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location / {
proxy_pass http://lemmy-alpha:8540;
proxy_pass http://lemmy-alpha-ui:1234;
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;
@ -42,21 +42,21 @@ http {
# Upload limit for pictshare
client_max_body_size 50M;
location /api/v1 {
proxy_pass http://lemmy-beta:8551/api/v1;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location / {
proxy_pass http://lemmy-beta:8550;
proxy_pass http://lemmy-beta-ui:1234;
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;
@ -73,21 +73,21 @@ http {
# Upload limit for pictshare
client_max_body_size 50M;
location /api/v1 {
proxy_pass http://lemmy-gamma:8561/api/v1;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location / {
proxy_pass http://lemmy-gamma:8560;
proxy_pass http://lemmy-gamma-ui:1234;
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;
@ -104,21 +104,21 @@ http {
# Upload limit for pictshare
client_max_body_size 50M;
location /api/v1 {
proxy_pass http://lemmy-delta:8571/api/v1;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location / {
proxy_pass http://lemmy-delta:8570;
proxy_pass http://lemmy-delta-ui:1234;
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;
@ -135,21 +135,21 @@ http {
# Upload limit for pictshare
client_max_body_size 50M;
location /api/v1 {
proxy_pass http://lemmy-epsilon:8581/api/v1;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location / {
proxy_pass http://lemmy-epsilon:8580;
proxy_pass http://lemmy-epsilon-ui:1234;
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;

@ -15,13 +15,14 @@ sudo chown -R 991:991 volumes/pictrs_alpha
sudo docker-compose up -d
pushd ../../ui
pushd ../../api_tests
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
while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8541/api/v1/site')" != "200" ]]; do sleep 1; done
while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8551/api/v1/site')" != "200" ]]; do sleep 1; done
while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8561/api/v1/site')" != "200" ]]; do sleep 1; done
while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8571/api/v1/site')" != "200" ]]; do sleep 1; done
while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8581/api/v1/site')" != "200" ]]; do sleep 1; done
yarn
yarn api-test || true
popd

@ -30,8 +30,6 @@
# host where postgres is running
host: "postgres"
}
# The location of the frontend
front_end_dir: "/app/dist"
# # optional: email sending configuration
# email: {
# # hostname of the smtp server

@ -10,17 +10,17 @@ WORKDIR /app
RUN sudo chown -R rust:rust .
RUN USER=root cargo new server
WORKDIR /app/server
COPY server/Cargo.toml server/Cargo.lock ./
COPY server/lemmy_db ./lemmy_db
COPY server/lemmy_utils ./lemmy_utils
COPY server/lemmy_api_structs ./lemmy_api_structs
COPY server/lemmy_rate_limit ./lemmy_rate_limit
COPY Cargo.toml Cargo.lock ./
COPY lemmy_db ./lemmy_db
COPY lemmy_utils ./lemmy_utils
COPY lemmy_api_structs ./lemmy_api_structs
COPY lemmy_rate_limit ./lemmy_rate_limit
RUN mkdir -p ./src/bin \
&& echo 'fn main() { println!("Dummy") }' > ./src/bin/main.rs
RUN cargo build --release
RUN find target/$CARGO_BUILD_TARGET/$RUSTRELEASEDIR -type f -name "$(echo "lemmy_server" | tr '-' '_')*" -exec touch -t 200001010000 {} +
COPY server/src ./src/
COPY server/migrations ./migrations/
COPY src ./src/
COPY migrations ./migrations/
# build for release
# workaround for https://github.com/rust-lang/rust/issues/62896
@ -36,18 +36,6 @@ WORKDIR /app
COPY --chown=rust:rust docs ./docs
RUN mdbook build docs/
FROM node:12-buster as node
WORKDIR /app/ui
# Cache deps
COPY ui/package.json ui/yarn.lock ./
RUN yarn install --pure-lockfile --network-timeout 600000
# Build
COPY ui /app/ui
RUN yarn build
FROM alpine:3.12 as lemmy
# Install libpq for postgres
@ -60,10 +48,9 @@ RUN addgroup -g 1000 lemmy
RUN adduser -D -s /bin/sh -u 1000 -G lemmy lemmy
# Copy resources
COPY --chown=lemmy:lemmy server/config/defaults.hjson /config/defaults.hjson
COPY --chown=lemmy:lemmy config/defaults.hjson /config/defaults.hjson
COPY --chown=lemmy:lemmy --from=rust /app/server/lemmy_server /app/lemmy
COPY --chown=lemmy:lemmy --from=docs /app/docs/book/ /app/dist/documentation/
COPY --chown=lemmy:lemmy --from=node /app/ui/dist /app/dist
COPY --chown=lemmy:lemmy --from=docs /app/docs/book/ /app/documentation/
RUN chown lemmy:lemmy /app/lemmy
USER lemmy

@ -13,8 +13,8 @@ third_semver=$(echo $new_tag | cut -d "." -f 3)
# Setting the version on the front end
cd ../../
# Setting the version on the backend
echo "pub const VERSION: &str = \"$new_tag\";" > "server/src/version.rs"
git add "server/src/version.rs"
echo "pub const VERSION: &str = \"$new_tag\";" > "src/version.rs"
git add "src/version.rs"
# Setting the version for Ansible
echo $new_tag > "ansible/VERSION"
git add "ansible/VERSION"

@ -25,6 +25,17 @@ services:
- pictrs
- iframely
lemmy-ui:
image: dessalines/lemmy-ui:v0.0.14
ports:
- "1235:1234"
environment:
- LEMMY_INTERNAL_HOST=lemmy:8536
- LEMMY_EXTERNAL_HOST=localhost:8536
- LEMMY_HTTPS=false
depends_on:
- lemmy
pictrs:
image: asonix/pictrs:v0.1.13-r0
ports:

@ -1,45 +1,16 @@
version: '3.3'
services:
nginx:
image: nginx:1.17-alpine
ports:
- "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:
- pictrs
- iframely
- lemmy-alpha
- lemmy-beta
- lemmy-gamma
- lemmy-delta
- lemmy-epsilon
pictrs:
restart: always
image: asonix/pictrs:v0.1.13-r0
user: 991:991
volumes:
- ./volumes/pictrs_alpha:/mnt
lemmy-alpha:
image: dessalines/lemmy:travis
environment:
- LEMMY_HOSTNAME=lemmy-alpha:8540
- LEMMY_HOSTNAME=lemmy-alpha:8541
- LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_alpha: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-gamma,lemmy-delta,lemmy-epsilon
- LEMMY_PORT=8540
- LEMMY_PORT=8541
- LEMMY_SETUP__ADMIN_USERNAME=lemmy_alpha
- LEMMY_SETUP__ADMIN_PASSWORD=lemmy
- LEMMY_SETUP__SITE_NAME=lemmy-alpha
@ -50,6 +21,8 @@ services:
- RUST_LOG=debug
depends_on:
- postgres_alpha
ports:
- "8541:8541"
postgres_alpha:
image: postgres:12-alpine
environment:
@ -62,14 +35,13 @@ services:
lemmy-beta:
image: dessalines/lemmy:travis
environment:
- LEMMY_HOSTNAME=lemmy-beta:8550
- LEMMY_HOSTNAME=lemmy-beta:8551
- LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_beta: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-alpha,lemmy-gamma,lemmy-delta,lemmy-epsilon
- LEMMY_PORT=8550
- LEMMY_PORT=8551
- LEMMY_SETUP__ADMIN_USERNAME=lemmy_beta
- LEMMY_SETUP__ADMIN_PASSWORD=lemmy
- LEMMY_SETUP__SITE_NAME=lemmy-beta
@ -80,6 +52,8 @@ services:
- RUST_LOG=debug
depends_on:
- postgres_beta
ports:
- "8551:8551"
postgres_beta:
image: postgres:12-alpine
environment:
@ -92,14 +66,13 @@ services:
lemmy-gamma:
image: dessalines/lemmy:travis
environment:
- LEMMY_HOSTNAME=lemmy-gamma:8560
- LEMMY_HOSTNAME=lemmy-gamma:8561
- LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_gamma: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-alpha,lemmy-beta,lemmy-delta,lemmy-epsilon
- LEMMY_PORT=8560
- LEMMY_PORT=8561
- LEMMY_SETUP__ADMIN_USERNAME=lemmy_gamma
- LEMMY_SETUP__ADMIN_PASSWORD=lemmy
- LEMMY_SETUP__SITE_NAME=lemmy-gamma
@ -110,6 +83,8 @@ services:
- RUST_LOG=debug
depends_on:
- postgres_gamma
ports:
- "8561:8561"
postgres_gamma:
image: postgres:12-alpine
environment:
@ -123,14 +98,13 @@ services:
lemmy-delta:
image: dessalines/lemmy:travis
environment:
- LEMMY_HOSTNAME=lemmy-delta:8570
- LEMMY_HOSTNAME=lemmy-delta:8571
- LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_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_PORT=8571
- LEMMY_SETUP__ADMIN_USERNAME=lemmy_delta
- LEMMY_SETUP__ADMIN_PASSWORD=lemmy
- LEMMY_SETUP__SITE_NAME=lemmy-delta
@ -141,6 +115,8 @@ services:
- RUST_LOG=debug
depends_on:
- postgres_delta
ports:
- "8571:8571"
postgres_delta:
image: postgres:12-alpine
environment:
@ -154,14 +130,13 @@ services:
lemmy-epsilon:
image: dessalines/lemmy:travis
environment:
- LEMMY_HOSTNAME=lemmy-epsilon:8580
- LEMMY_HOSTNAME=lemmy-epsilon:8581
- LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_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_PORT=8581
- LEMMY_SETUP__ADMIN_USERNAME=lemmy_epsilon
- LEMMY_SETUP__ADMIN_PASSWORD=lemmy
- LEMMY_SETUP__SITE_NAME=lemmy-epsilon
@ -172,6 +147,8 @@ services:
- RUST_LOG=debug
depends_on:
- postgres_epsilon
ports:
- "8581:8581"
postgres_epsilon:
image: postgres:12-alpine
environment:
@ -180,9 +157,3 @@ services:
- POSTGRES_DB=lemmy
volumes:
- ./volumes/postgres_epsilon:/var/lib/postgresql/data
iframely:
image: dogbin/iframely:latest
volumes:
- ../iframely.config.local.js:/iframely/config.local.js:ro
restart: always

@ -12,13 +12,13 @@ sudo docker build ../../ --file ../prod/Dockerfile --tag dessalines/lemmy:travis
sudo docker-compose up -d
pushd ../../ui
pushd ../../api_tests
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
while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8541/api/v1/site')" != "200" ]]; do sleep 1; done
while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8551/api/v1/site')" != "200" ]]; do sleep 1; done
while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8561/api/v1/site')" != "200" ]]; do sleep 1; done
while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8571/api/v1/site')" != "200" ]]; do sleep 1; done
while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8581/api/v1/site')" != "200" ]]; do sleep 1; done
yarn
yarn api-test
popd

@ -31,4 +31,5 @@
- High performance.
- Server is written in rust.
- Front end is `~80kB` gzipped.
- Front end works without javascript (read-only).
- Supports arm64 / Raspberry Pi.

@ -1,7 +1,7 @@
# Configuration
The configuration is based on the file
[defaults.hjson](https://yerbamate.dev/LemmyNet/lemmy/src/branch/main/server/config/defaults.hjson).
[defaults.hjson](https://yerbamate.dev/LemmyNet/lemmy/src/branch/main/config/defaults.hjson).
This file also contains documentation for all the available options. To override the defaults, you
can copy the options you want to change into your local `config.hjson` file.

@ -18,13 +18,14 @@ Check out [Lemmy's Weblate](https://weblate.yerbamate.dev/projects/lemmy/) for t
### Front end
- The front end is written in `typescript`, using a react-like framework called [inferno](https://infernojs.org/). All UI elements are reusable `.tsx` components.
- The main page and routing are in `ui/src/index.tsx`.
- The components are located in `ui/src/components`.
- The front end repository is [lemmy-ui](https://github.com/LemmyNet/lemmy-ui).
- The routes are at `src/shared/routes.ts`.
- The components are located in `src/shared/components`.
### Back end
- The back end is written in `rust`, using `diesel`, and `actix`.
- The server source code is split into main sections in `server/src`. These include:
- The server source code is split into main sections in `src`. These include:
- `db` - The low level database actions.
- Database additions are done using diesel migrations. Run `diesel migration generate xxxxx` to add new things.
- `api` - The high level user interactions (things like `CreateComment`)

@ -9,7 +9,9 @@ cd lemmy/docker/dev
sudo docker-compose up --no-deps --build
```
and go to http://localhost:8536.
and go to http://localhost:1235.
*Note: many features (like docs and pictures) will not work without using an nginx profile like that in `ansible/templates/nginx.conf`.
To speed up the Docker compile, add the following to `/etc/docker/daemon.json` and restart Docker.
```

@ -20,28 +20,22 @@ Finally, install Node and Yarn.
brew install node yarn
```
### Get the source code
### Get the back end source code
```
git clone https://github.com/LemmyNet/lemmy.git
# or alternatively from gitea
# git clone https://yerbamate.dev/LemmyNet/lemmy.git
```
All the following commands need to be run either in `lemmy/server` or `lemmy/ui`, as indicated
by the `cd` command.
### Build the backend (Rust)
```
cd server
cargo build
# for development, use `cargo check` instead)
```
### Build the frontend (Typescript)
### Get the front end source code
```
cd ui
yarn
yarn build
git clone https://github.com/LemmyNet/lemmy-ui.git
```
### Setup postgresql
@ -50,7 +44,7 @@ yarn build
sudo apt install postgresql
sudo systemctl start postgresql
# Either execute server/db-init.sh, or manually initialize the postgres database:
# Either execute db-init.sh, or manually initialize the postgres database:
sudo -u postgres psql -c "create user lemmy with password 'password' superuser;" -U postgres
sudo -u postgres psql -c 'create database lemmy with owner lemmy;' -U postgres
export LEMMY_DATABASE_URL=postgres://lemmy:password@localhost:5432/lemmy
@ -62,7 +56,7 @@ brew install postgresql
brew services start postgresql
/usr/local/opt/postgres/bin/createuser -s postgres
# Either execute server/db-init.sh, or manually initialize the postgres database:
# Either execute db-init.sh, or manually initialize the postgres database:
psql -c "create user lemmy with password 'password' superuser;" -U postgres
psql -c 'create database lemmy with owner lemmy;' -U postgres
export LEMMY_DATABASE_URL=postgres://lemmy:password@localhost:5432/lemmy
@ -70,21 +64,22 @@ export LEMMY_DATABASE_URL=postgres://lemmy:password@localhost:5432/lemmy
### Run a local development instance
```
# run each of these in a seperate terminal
cd server && cargo run
cd ui && yarn start
cd lemmy
cargo run
```
Then open [localhost:4444](http://localhost:4444) in your browser. It will auto-refresh if you edit
any frontend files. For backend coding, you will have to rerun `cargo run`. You can use
`cargo check` as a faster way to find compilation errors.
Then open [localhost:1235](http://localhost:1235) in your browser. To reload back-end changes, you will have to rerun `cargo run`. You can use `cargo check` as a faster way to find compilation errors.
To do front end development:
To speed up incremental builds, you can add the following to `~/.cargo/config`:
```
[target.x86_64-unknown-linux-gnu]
rustflags = ["-Clink-arg=-fuse-ld=lld"]
cd lemmy-ui
yarn
yarn dev
```
and goto [localhost:1234](http://localhost:1234). Front end saves should rebuild the project.
Note that this setup doesn't include image uploads or link previews (provided by pict-rs and
iframely respectively). If you want to test those, you should use the
[Docker development](contributing_docker_development.md).

@ -3,7 +3,7 @@
#### Rust
After installing [local development dependencies](contributing_local_development.md), run the
following commands in the `server` subfolder:
following commands:
```bash
psql -U lemmy -c "DROP SCHEMA public CASCADE; CREATE SCHEMA public;"

@ -12,7 +12,8 @@ Lemmy uses [Bootstrap v4](https://getbootstrap.com/), and very few custom css cl
## Adding
1. Copy `{my-theme-name}.min.css` to `ui/assets/css/themes`. (You can also copy the `_variables.scss` here if you want).
1. Go to `ui/src/utils.ts` and add `{my-theme-name}` to the themes list.
1. Fork the [lemmy-ui](https://github.com/LemmyNet/lemmy-ui).
1. Copy `{my-theme-name}.min.css` to `src/assets/css/themes`. (You can also copy the `_variables.scss` here if you want).
1. Go to `src/shared/utils.ts` and add `{my-theme-name}` to the themes list.
1. Test locally
1. Do a pull request with those changes.

@ -1,6 +1,6 @@
# Lemmy API
*Note: this may lag behind the actual API endpoints [here](../server/src/api). The API should be considered unstable and may change any time.*
*Note: this may lag behind the actual API endpoints [here](../src/api). The API should be considered unstable and may change any time.*
<!-- toc -->
@ -28,214 +28,234 @@
- [Request](#request-1)
- [Response](#response-1)
- [HTTP](#http-2)
+ [Get User Details](#get-user-details)
+ [Get Captcha](#get-captcha)
- [Request](#request-2)
- [Response](#response-2)
- [HTTP](#http-3)
+ [Save User Settings](#save-user-settings)
+ [Get User Details](#get-user-details)
- [Request](#request-3)
- [Response](#response-3)
- [HTTP](#http-4)
+ [Get Replies / Inbox](#get-replies--inbox)
+ [Save User Settings](#save-user-settings)
- [Request](#request-4)
- [Response](#response-4)
- [HTTP](#http-5)
+ [Get User Mentions](#get-user-mentions)
+ [Get Replies / Inbox](#get-replies--inbox)
- [Request](#request-5)
- [Response](#response-5)
- [HTTP](#http-6)
+ [Mark User Mention as read](#mark-user-mention-as-read)
+ [Get User Mentions](#get-user-mentions)
- [Request](#request-6)
- [Response](#response-6)
- [HTTP](#http-7)
+ [Get Private Messages](#get-private-messages)
+ [Mark User Mention as read](#mark-user-mention-as-read)
- [Request](#request-7)
- [Response](#response-7)
- [HTTP](#http-8)
+ [Create Private Message](#create-private-message)
+ [Get Private Messages](#get-private-messages)
- [Request](#request-8)
- [Response](#response-8)
- [HTTP](#http-9)
+ [Edit Private Message](#edit-private-message)
+ [Create Private Message](#create-private-message)
- [Request](#request-9)
- [Response](#response-9)
- [HTTP](#http-10)
+ [Delete Private Message](#delete-private-message)
+ [Edit Private Message](#edit-private-message)
- [Request](#request-10)
- [Response](#response-10)
- [HTTP](#http-11)
+ [Mark Private Message as Read](#mark-private-message-as-read)
+ [Delete Private Message](#delete-private-message)
- [Request](#request-11)
- [Response](#response-11)
- [HTTP](#http-12)
+ [Mark All As Read](#mark-all-as-read)
+ [Mark Private Message as Read](#mark-private-message-as-read)
- [Request](#request-12)
- [Response](#response-12)
- [HTTP](#http-13)
+ [Delete Account](#delete-account)
+ [Mark All As Read](#mark-all-as-read)
- [Request](#request-13)
- [Response](#response-13)
- [HTTP](#http-14)
+ [Add admin](#add-admin)
+ [Delete Account](#delete-account)
- [Request](#request-14)
- [Response](#response-14)
- [HTTP](#http-15)
+ [Ban user](#ban-user)
+ [Add admin](#add-admin)
- [Request](#request-15)
- [Response](#response-15)
- [HTTP](#http-16)
* [Site](#site)
+ [List Categories](#list-categories)
+ [Ban user](#ban-user)
- [Request](#request-16)
- [Response](#response-16)
- [HTTP](#http-17)
+ [Search](#search)
+ [User Join](#user-join)
- [Request](#request-17)
- [Response](#response-17)
- [HTTP](#http-18)
+ [Get Modlog](#get-modlog)
* [Site](#site)
+ [List Categories](#list-categories)
- [Request](#request-18)
- [Response](#response-18)
- [HTTP](#http-19)
+ [Create Site](#create-site)
+ [Search](#search)
- [Request](#request-19)
- [Response](#response-19)
- [HTTP](#http-20)
+ [Edit Site](#edit-site)
+ [Get Modlog](#get-modlog)
- [Request](#request-20)
- [Response](#response-20)
- [HTTP](#http-21)
+ [Get Site](#get-site)
+ [Create Site](#create-site)
- [Request](#request-21)
- [Response](#response-21)
- [HTTP](#http-22)
+ [Transfer Site](#transfer-site)
+ [Edit Site](#edit-site)
- [Request](#request-22)
- [Response](#response-22)
- [HTTP](#http-23)
+ [Get Site Config](#get-site-config)
+ [Get Site](#get-site)
- [Request](#request-23)
- [Response](#response-23)
- [HTTP](#http-24)
+ [Save Site Config](#save-site-config)
+ [Transfer Site](#transfer-site)
- [Request](#request-24)
- [Response](#response-24)
- [HTTP](#http-25)
* [Community](#community)
+ [Get Community](#get-community)
+ [Get Site Config](#get-site-config)
- [Request](#request-25)
- [Response](#response-25)
- [HTTP](#http-26)
+ [Create Community](#create-community)
+ [Save Site Config](#save-site-config)
- [Request](#request-26)
- [Response](#response-26)
- [HTTP](#http-27)
+ [List Communities](#list-communities)
* [Community](#community)
+ [Get Community](#get-community)
- [Request](#request-27)
- [Response](#response-27)
- [HTTP](#http-28)
+ [Ban from Community](#ban-from-community)
+ [Create Community](#create-community)
- [Request](#request-28)
- [Response](#response-28)
- [HTTP](#http-29)
+ [Add Mod to Community](#add-mod-to-community)
+ [List Communities](#list-communities)
- [Request](#request-29)
- [Response](#response-29)
- [HTTP](#http-30)
+ [Edit Community](#edit-community)
+ [Ban from Community](#ban-from-community)
- [Request](#request-30)
- [Response](#response-30)
- [HTTP](#http-31)
+ [Delete Community](#delete-community)
+ [Add Mod to Community](#add-mod-to-community)
- [Request](#request-31)
- [Response](#response-31)
- [HTTP](#http-32)
+ [Remove Community](#remove-community)
+ [Edit Community](#edit-community)
- [Request](#request-32)
- [Response](#response-32)
- [HTTP](#http-33)
+ [Follow Community](#follow-community)
+ [Delete Community](#delete-community)
- [Request](#request-33)
- [Response](#response-33)
- [HTTP](#http-34)
+ [Get Followed Communities](#get-followed-communities)
+ [Remove Community](#remove-community)
- [Request](#request-34)
- [Response](#response-34)
- [HTTP](#http-35)
+ [Transfer Community](#transfer-community)
+ [Follow Community](#follow-community)
- [Request](#request-35)
- [Response](#response-35)
- [HTTP](#http-36)
* [Post](#post)
+ [Create Post](#create-post)
+ [Get Followed Communities](#get-followed-communities)
- [Request](#request-36)
- [Response](#response-36)
- [HTTP](#http-37)
+ [Get Post](#get-post)
+ [Transfer Community](#transfer-community)
- [Request](#request-37)
- [Response](#response-37)
- [HTTP](#http-38)
+ [Get Posts](#get-posts)
+ [Community Join](#community-join)
- [Request](#request-38)
- [Response](#response-38)
- [HTTP](#http-39)
+ [Create Post Like](#create-post-like)
* [Post](#post)
+ [Create Post](#create-post)
- [Request](#request-39)
- [Response](#response-39)
- [HTTP](#http-40)
+ [Edit Post](#edit-post)
+ [Get Post](#get-post)
- [Request](#request-40)
- [Response](#response-40)
- [HTTP](#http-41)
+ [Delete Post](#delete-post)
+ [Get Posts](#get-posts)
- [Request](#request-41)
- [Response](#response-41)
- [HTTP](#http-42)
+ [Remove Post](#remove-post)
+ [Create Post Like](#create-post-like)
- [Request](#request-42)
- [Response](#response-42)
- [HTTP](#http-43)
+ [Lock Post](#lock-post)
+ [Edit Post](#edit-post)
- [Request](#request-43)
- [Response](#response-43)
- [HTTP](#http-44)
+ [Sticky Post](#sticky-post)
+ [Delete Post](#delete-post)
- [Request](#request-44)
- [Response](#response-44)
- [HTTP](#http-45)
+ [Save Post](#save-post)
+ [Remove Post](#remove-post)
- [Request](#request-45)
- [Response](#response-45)
- [HTTP](#http-46)
* [Comment](#comment)
+ [Create Comment](#create-comment)
+ [Lock Post](#lock-post)
- [Request](#request-46)
- [Response](#response-46)
- [HTTP](#http-47)
+ [Edit Comment](#edit-comment)
+ [Sticky Post](#sticky-post)
- [Request](#request-47)
- [Response](#response-47)
- [HTTP](#http-48)
+ [Delete Comment](#delete-comment)
+ [Save Post](#save-post)
- [Request](#request-48)
- [Response](#response-48)
- [HTTP](#http-49)
+ [Remove Comment](#remove-comment)
+ [Post Join](#post-join)
- [Request](#request-49)
- [Response](#response-49)
- [HTTP](#http-50)
+ [Mark Comment as Read](#mark-comment-as-read)
* [Comment](#comment)
+ [Create Comment](#create-comment)
- [Request](#request-50)
- [Response](#response-50)
- [HTTP](#http-51)
+ [Save Comment](#save-comment)
+ [Edit Comment](#edit-comment)
- [Request](#request-51)
- [Response](#response-51)
- [HTTP](#http-52)
+ [Create Comment Like](#create-comment-like)
+ [Delete Comment](#delete-comment)
- [Request](#request-52)
- [Response](#response-52)
- [HTTP](#http-53)
+ [Remove Comment](#remove-comment)
- [Request](#request-53)
- [Response](#response-53)
- [HTTP](#http-54)
+ [Get Comments](#get-comments)
- [Request](#request-54)
- [Response](#response-54)
- [HTTP](#http-55)
+ [Mark Comment as Read](#mark-comment-as-read)
- [Request](#request-55)
- [Response](#response-55)
- [HTTP](#http-56)
+ [Save Comment](#save-comment)
- [Request](#request-56)
- [Response](#response-56)
- [HTTP](#http-57)
+ [Create Comment Like](#create-comment-like)
- [Request](#request-57)
- [Response](#response-57)
- [HTTP](#http-58)
* [RSS / Atom feeds](#rss--atom-feeds)
+ [All](#all)
+ [Community](#community-1)
@ -249,7 +269,7 @@
- <code>Option<***SomeType***></code> designates an option which may be omitted in requests and not be present in responses. It will be of type ***SomeType***.
- <code>Vec<***SomeType***></code> is a list which contains objects of type ***SomeType***.
- `chrono::NaiveDateTime` is a timestamp string in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format. Timestamps will be UTC.
- Other data types are listed [here](../server/src/db).
- Other data types are listed [here](../src/db).
## Basic usage
@ -261,6 +281,12 @@ Connect to <code>ws://***host***/api/v1/ws</code> to get started.
If the ***`host`*** supports secure connections, you can use <code>wss://***host***/api/v1/ws</code>.
To receive websocket messages, you must join a room / context. The three available are:
- [UserJoin](#user-join). Receives replies, private messages, etc.
- [PostJoin](#post-join). Receives new comments on a post.
- [CommunityJoin](#community-join). Receives front page / community posts.
#### Testing with Websocat
[Websocat link](https://github.com/vi/websocat)
@ -839,6 +865,29 @@ Marks all user replies and mentions as read.
`POST /user/ban`
#### User Join
##### Request
```rust
{
op: "UserJoin",
data: {
auth: String
}
}
```
##### Response
```rust
{
op: "UserJoin",
data: {
joined: bool,
}
}
```
##### HTTP
`POST /user/join`
### Site
#### List Categories
##### Request
@ -1387,6 +1436,32 @@ Only admins can remove a community.
`POST /community/transfer`
#### Community Join
The main / frontpage community is `community_id: 0`.
##### Request
```rust
{
op: "CommunityJoin",
data: {
community_id: i32
}
}
```
##### Response
```rust
{
op: "CommunityJoin",
data: {
joined: bool,
}
}
```
##### HTTP
`POST /community/join`
### Post
#### Create Post
##### Request
@ -1671,6 +1746,29 @@ Only admins and mods can sticky a post.
`POST /post/save`
#### Post Join
##### Request
```rust
{
op: "PostJoin",
data: {
post_id: i32
}
}
```
##### Response
```rust
{
op: "PostJoin",
data: {
joined: bool,
}
}
```
##### HTTP
`POST /post/join`
### Comment
#### Create Comment
##### Request
@ -1787,6 +1885,38 @@ Only a mod or admin can remove the comment.
`POST /comment/remove`
#### Get Comments
Comment listing types are `All, Subscribed, Community`
##### Request
```rust
{
op: "GetComments",
data: {
type_: String,
sort: String,
page: Option<i64>,
limit: Option<i64>,
community_id: Option<i32>,
community_name: Option<String>,
auth: Option<String>
}
}
```
##### Response
```rust
{
op: "GetComments",
data: {
comments: Vec<CommentView>,
}
}
```
##### HTTP
`GET /comment/list`
#### Mark Comment as Read
Only the recipient can do this.

@ -29,7 +29,7 @@ ask_to_init_db() {
done
if [ "$init_db_final" = 1 ]
then
source ./server/db-init.sh
source ./db-init.sh
read -n 1 -s -r -p "Press ANY KEY to continue execution of this script, press CTRL+C to quit..."
echo
fi

@ -68,6 +68,7 @@ pub struct GetComments {
pub page: Option<i64>,
pub limit: Option<i64>,
pub community_id: Option<i32>,
pub community_name: Option<String>,
pub auth: Option<String>,
}

@ -129,3 +129,13 @@ pub struct TransferCommunity {
pub user_id: i32,
pub auth: String,
}
#[derive(Deserialize, Debug)]
pub struct CommunityJoin {
pub community_id: i32,
}
#[derive(Serialize, Clone)]
pub struct CommunityJoinResponse {
pub joined: bool,
}

@ -1,7 +1,7 @@
extern crate serde;
extern crate log;
extern crate diesel;
extern crate actix_web;
extern crate diesel;
extern crate log;
extern crate serde;
pub mod comment;
pub mod community;
@ -9,22 +9,22 @@ pub mod post;
pub mod site;
pub mod user;
use lemmy_db::comment::Comment;
use lemmy_db::user::User_;
use lemmy_db::post::Post;
use lemmy_db::user_mention::{UserMentionForm, UserMention};
use log::error;
use lemmy_db::{Crud, DbPool};
use lemmy_utils::utils::MentionData;
use lemmy_utils::settings::Settings;
use lemmy_utils::email::send_email;
use diesel::PgConnection;
use lemmy_utils::LemmyError;
use lemmy_db::{
comment::Comment,
post::Post,
user::User_,
user_mention::{UserMention, UserMentionForm},
Crud,
DbPool,
};
use lemmy_utils::{email::send_email, settings::Settings, utils::MentionData, LemmyError};
use log::error;
pub async fn blocking<F, T>(pool: &DbPool, f: F) -> Result<T, LemmyError>
where
F: FnOnce(&diesel::PgConnection) -> T + Send + 'static,
T: Send + 'static,
where
F: FnOnce(&diesel::PgConnection) -> T + Send + 'static,
T: Send + 'static,
{
let pool = pool.clone();
let res = actix_web::web::block(move || {
@ -32,7 +32,7 @@ pub async fn blocking<F, T>(pool: &DbPool, f: F) -> Result<T, LemmyError>
let res = (f)(&conn);
Ok(res) as Result<_, LemmyError>
})
.await?;
.await?;
Ok(res)
}
@ -49,7 +49,7 @@ pub async fn send_local_notifs(
let ids = blocking(pool, move |conn| {
do_send_local_notifs(conn, &mentions, &comment, &user2, &post, do_send_email)
})
.await?;
.await?;
Ok(ids)
}

@ -103,3 +103,13 @@ pub struct SavePost {
pub save: bool,
pub auth: String,
}
#[derive(Deserialize, Debug)]
pub struct PostJoin {
pub post_id: i32,
}
#[derive(Serialize, Clone)]
pub struct PostJoinResponse {
pub joined: bool,
}

@ -235,5 +235,5 @@ pub struct UserJoin {
#[derive(Serialize, Clone)]
pub struct UserJoinResponse {
pub user_id: i32,
pub joined: bool,
}

@ -130,6 +130,7 @@ pub struct CommentQueryBuilder<'a> {
listing_type: ListingType,
sort: &'a SortType,
for_community_id: Option<i32>,
for_community_name: Option<String>,
for_post_id: Option<i32>,
for_creator_id: Option<i32>,
search_term: Option<String>,
@ -151,6 +152,7 @@ impl<'a> CommentQueryBuilder<'a> {
listing_type: ListingType::All,
sort: &SortType::New,
for_community_id: None,
for_community_name: None,
for_post_id: None,
for_creator_id: None,
search_term: None,
@ -186,6 +188,11 @@ impl<'a> CommentQueryBuilder<'a> {
self
}
pub fn for_community_name<T: MaybeOptional<String>>(mut self, for_community_name: T) -> Self {
self.for_community_name = for_community_name.get_optional();
self
}
pub fn search_term<T: MaybeOptional<String>>(mut self, search_term: T) -> Self {
self.search_term = search_term.get_optional();
self
@ -231,6 +238,10 @@ impl<'a> CommentQueryBuilder<'a> {
query = query.filter(community_id.eq(for_community_id));
}
if let Some(for_community_name) = self.for_community_name {
query = query.filter(community_name.eq(for_community_name));
}
if let Some(for_post_id) = self.for_post_id {
query = query.filter(post_id.eq(for_post_id));
};

@ -523,36 +523,36 @@ joinable!(user_mention -> comment (comment_id));
joinable!(user_mention -> user_ (recipient_id));
allow_tables_to_appear_in_same_query!(
activity,
category,
comment,
comment_aggregates_fast,
comment_like,
comment_saved,
community,
community_aggregates_fast,
community_follower,
community_moderator,
community_user_ban,
mod_add,
mod_add_community,
mod_ban,
mod_ban_from_community,
mod_lock_post,
mod_remove_comment,
mod_remove_community,
mod_remove_post,
mod_sticky_post,
password_reset_request,
post,
post_aggregates_fast,
post_like,
post_read,
post_saved,
private_message,
site,
user_,
user_ban,
user_fast,
user_mention,
activity,
category,
comment,
comment_aggregates_fast,
comment_like,
comment_saved,
community,
community_aggregates_fast,
community_follower,
community_moderator,
community_user_ban,
mod_add,
mod_add_community,
mod_ban,
mod_ban_from_community,
mod_lock_post,
mod_remove_comment,
mod_remove_community,
mod_remove_post,
mod_sticky_post,
password_reset_request,
post,
post_aggregates_fast,
post_like,
post_read,
post_saved,
private_message,
site,
user_,
user_ban,
user_fast,
user_mention,
);

@ -13,7 +13,6 @@ pub struct Settings {
pub bind: IpAddr,
pub port: u16,
pub jwt_secret: String,
pub front_end_dir: String,
pub pictrs_url: String,
pub rate_limit: RateLimitConfig,
pub email: Option<EmailConfig>,
@ -88,7 +87,7 @@ impl Settings {
/// added to the config.
///
/// Note: The env var `LEMMY_DATABASE_URL` is parsed in
/// `server/lemmy_db/src/lib.rs::get_database_url_from_env()`
/// `lemmy_db/src/lib.rs::get_database_url_from_env()`
fn init() -> Result<Self, ConfigError> {
let mut s = Config::new();

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save