Merge branch 'main' into move-websocket-to-workspace

This commit is contained in:
Felix Ableitner 2020-09-23 19:39:35 +02:00
commit bca55ff775
39 changed files with 372 additions and 98 deletions

View file

@ -9,6 +9,8 @@ assignees: ''
Found a bug? Please fill out the sections below. 👍 Found a bug? Please fill out the sections below. 👍
For front end issues, use [lemmy-ui](https://github.com/LemmyNet/lemmy-ui)
### Issue Summary ### Issue Summary
A summary of the bug. A summary of the bug.

View file

@ -7,6 +7,8 @@ assignees: ''
--- ---
For front end issues, use [lemmy-ui](https://github.com/LemmyNet/lemmy-ui)
### Is your proposal related to a problem? ### Is your proposal related to a problem?
<!-- <!--

View file

@ -20,7 +20,7 @@ before_install:
# Change dir # Change dir
- cd docker/travis - cd docker/travis
script: script:
- "./run-tests.sh" - "./run-tests.bash"
deploy: deploy:
provider: script provider: script
script: bash docker_push.sh script: bash docker_push.sh

98
Cargo.lock generated
View file

@ -81,8 +81,11 @@ dependencies = [
"futures-util", "futures-util",
"http", "http",
"log", "log",
"rustls",
"tokio-rustls",
"trust-dns-proto", "trust-dns-proto",
"trust-dns-resolver", "trust-dns-resolver",
"webpki",
] ]
[[package]] [[package]]
@ -117,6 +120,7 @@ dependencies = [
"actix-rt", "actix-rt",
"actix-service", "actix-service",
"actix-threadpool", "actix-threadpool",
"actix-tls",
"actix-utils", "actix-utils",
"base64 0.12.3", "base64 0.12.3",
"bitflags 1.2.1", "bitflags 1.2.1",
@ -150,7 +154,7 @@ dependencies = [
"serde_urlencoded", "serde_urlencoded",
"sha-1 0.9.1", "sha-1 0.9.1",
"slab", "slab",
"time 0.2.19", "time 0.2.20",
] ]
[[package]] [[package]]
@ -260,6 +264,10 @@ dependencies = [
"actix-service", "actix-service",
"actix-utils", "actix-utils",
"futures-util", "futures-util",
"rustls",
"tokio-rustls",
"webpki",
"webpki-roots",
] ]
[[package]] [[package]]
@ -312,11 +320,12 @@ dependencies = [
"mime", "mime",
"pin-project", "pin-project",
"regex", "regex",
"rustls",
"serde 1.0.116", "serde 1.0.116",
"serde_json", "serde_json",
"serde_urlencoded", "serde_urlencoded",
"socket2", "socket2",
"time 0.2.19", "time 0.2.20",
"tinyvec", "tinyvec",
"url", "url",
] ]
@ -483,6 +492,7 @@ dependencies = [
"mime", "mime",
"percent-encoding", "percent-encoding",
"rand 0.7.3", "rand 0.7.3",
"rustls",
"serde 1.0.116", "serde 1.0.116",
"serde_json", "serde_json",
"serde_urlencoded", "serde_urlencoded",
@ -769,9 +779,9 @@ checksum = "7b02b629252fe8ef6460461409564e2c21d0c8e77e0944f3d189ff06c4e932ad"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.59" version = "1.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66120af515773fb005778dc07c261bd201ec8ce50bd6e7144c927753fe013381" checksum = "ef611cc68ff783f18535d77ddd080185275713d852c4f5cbb6122c462a7a825c"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
@ -874,7 +884,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1373a16a4937bc34efec7b391f9c1500c30b8478a701a4f44c9165cc0475a6e0" checksum = "1373a16a4937bc34efec7b391f9c1500c30b8478a701a4f44c9165cc0475a6e0"
dependencies = [ dependencies = [
"percent-encoding", "percent-encoding",
"time 0.2.19", "time 0.2.20",
"version_check 0.9.2", "version_check 0.9.2",
] ]
@ -1111,9 +1121,9 @@ checksum = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b"
[[package]] [[package]]
name = "either" name = "either"
version = "1.6.0" version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd56b59865bce947ac5958779cfa508f6c3b9497cc762b7e24a12d11ccde2c4f" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]] [[package]]
name = "email" name = "email"
@ -1588,6 +1598,12 @@ version = "1.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9"
[[package]]
name = "httpdate"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47"
[[package]] [[package]]
name = "humantime" name = "humantime"
version = "1.3.0" version = "1.3.0"
@ -1599,9 +1615,9 @@ dependencies = [
[[package]] [[package]]
name = "hyper" name = "hyper"
version = "0.13.7" version = "0.13.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e68a8dd9716185d9e64ea473ea6ef63529252e3e27623295a0378a19665d5eb" checksum = "2f3afcfae8af5ad0576a31e768415edb627824129e8e5a29b8bfccb2f234e835"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-channel", "futures-channel",
@ -1611,10 +1627,10 @@ dependencies = [
"http", "http",
"http-body", "http-body",
"httparse", "httparse",
"httpdate",
"itoa", "itoa",
"pin-project", "pin-project",
"socket2", "socket2",
"time 0.1.44",
"tokio", "tokio",
"tower-service", "tower-service",
"tracing", "tracing",
@ -2825,9 +2841,9 @@ dependencies = [
[[package]] [[package]]
name = "rayon-core" name = "rayon-core"
version = "1.8.0" version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91739a34c4355b5434ce54c9086c5895604a9c278586d1f1aa95e04f66b525a0" checksum = "e8c4fec834fb6e6d2dd5eece3c7b432a52f0ba887cf40e595190c4107edc08bf"
dependencies = [ dependencies = [
"crossbeam-channel", "crossbeam-channel",
"crossbeam-deque", "crossbeam-deque",
@ -2973,6 +2989,19 @@ dependencies = [
"semver", "semver",
] ]
[[package]]
name = "rustls"
version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d1126dcf58e93cee7d098dbda643b5f92ed724f1f6a63007c1116eed6700c81"
dependencies = [
"base64 0.12.3",
"log",
"ring",
"sct",
"webpki",
]
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.5" version = "1.0.5"
@ -3016,6 +3045,16 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "sct"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c"
dependencies = [
"ring",
"untrusted",
]
[[package]] [[package]]
name = "security-framework" name = "security-framework"
version = "0.4.4" version = "0.4.4"
@ -3415,9 +3454,9 @@ dependencies = [
[[package]] [[package]]
name = "time" name = "time"
version = "0.2.19" version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80c1a1fd93112fc50b11c43a1def21f926be3c18884fad676ea879572da070a1" checksum = "0d4953c513c9bf1b97e9cdd83f11d60c4b0a83462880a360d80d96953a953fee"
dependencies = [ dependencies = [
"const_fn", "const_fn",
"libc", "libc",
@ -3478,6 +3517,18 @@ dependencies = [
"winapi 0.3.9", "winapi 0.3.9",
] ]
[[package]]
name = "tokio-rustls"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e12831b255bcfa39dc0436b01e19fea231a37db570686c06ee72c423479f889a"
dependencies = [
"futures-core",
"rustls",
"tokio",
"webpki",
]
[[package]] [[package]]
name = "tokio-tls" name = "tokio-tls"
version = "0.3.1" version = "0.3.1"
@ -3853,6 +3904,25 @@ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
[[package]]
name = "webpki"
version = "0.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab146130f5f790d45f82aeeb09e55a256573373ec64409fc19a6fb82fb1032ae"
dependencies = [
"ring",
"untrusted",
]
[[package]]
name = "webpki-roots"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f20dea7535251981a9670857150d571846545088359b28e4951d350bdaf179f"
dependencies = [
"webpki",
]
[[package]] [[package]]
name = "widestring" name = "widestring"
version = "0.4.2" version = "0.4.2"

View file

@ -32,7 +32,7 @@ chrono = { version = "0.4", features = ["serde"] }
serde_json = { version = "1.0", features = ["preserve_order"]} serde_json = { version = "1.0", features = ["preserve_order"]}
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
actix = "0.10" actix = "0.10"
actix-web = { version = "3.0", default-features = false } actix-web = { version = "3.0", default-features = false, features = ["rustls"] }
actix-files = { version = "0.3", default-features = false } actix-files = { version = "0.3", default-features = false }
actix-web-actors = { version = "3.0", default-features = false } actix-web-actors = { version = "3.0", default-features = false }
actix-rt = { version = "1.1", default-features = false } actix-rt = { version = "1.1", default-features = false }

View file

@ -1 +1 @@
v0.7.57 v0.7.59

View file

@ -51,17 +51,27 @@ server {
# Upload limit for pictrs # Upload limit for pictrs
client_max_body_size 20M; client_max_body_size 20M;
# lemmy api # frontend
location /api/v1 { location / {
proxy_pass http://0.0.0.0:8536/api/v1;
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host; proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Cuts off the trailing slash on URLs to make them valid set $proxpass "http://0.0.0.0:{{ lemmy_ui_port }}";
rewrite ^(.+)/+$ $1 permanent; if ($http_accept = "application/activity+json") {
set $proxpass "http://0.0.0.0:{{ lemmy_port }}";
}
if ($request_method = POST) {
set $proxpass "http://0.0.0.0:{{ lemmy_port }}";
}
proxy_pass $proxpass;
# WebSocket support rewrite ^(.+)/+$ $1 permanent;
}
# backend
location ~ ^/(api|docs|pictrs|feeds|nodeinfo|.well-known) {
proxy_pass http://0.0.0.0:{{ lemmy_port }};
proxy_http_version 1.1; proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade"; proxy_set_header Connection "upgrade";
@ -70,36 +80,12 @@ server {
limit_req zone=lemmy_ratelimit burst=30 nodelay; 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: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 # Redirect pictshare images to pictrs
location ~ /pictshare/(.*)$ { location ~ /pictshare/(.*)$ {
return 301 /pictrs/image/$1; 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/ { location /iframely/ {
proxy_pass http://0.0.0.0:8061/; proxy_pass http://0.0.0.0:8061/;
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;

View file

@ -25,6 +25,7 @@ function assertUserFederation(
expect(userOne.actor_id).toBe(userTwo.actor_id); expect(userOne.actor_id).toBe(userTwo.actor_id);
expect(userOne.avatar).toBe(userTwo.avatar); expect(userOne.avatar).toBe(userTwo.avatar);
expect(userOne.banner).toBe(userTwo.banner); expect(userOne.banner).toBe(userTwo.banner);
expect(userOne.published).toBe(userTwo.published);
} }
test('Create user', async () => { test('Create user', async () => {

View file

@ -1,18 +1,14 @@
#!/bin/bash #!/bin/bash
set -e set -e
BRANCH=$1
git checkout $BRANCH
export COMPOSE_DOCKER_CLI_BUILD=1 export COMPOSE_DOCKER_CLI_BUILD=1
export DOCKER_BUILDKIT=1 export DOCKER_BUILDKIT=1
# Rebuilding dev docker # Rebuilding dev docker
sudo docker build ../../ -f . -t "dessalines/lemmy:$BRANCH" sudo docker build ../../ -f . -t "dessalines/lemmy:dev"
sudo docker push "dessalines/lemmy:$BRANCH" sudo docker push "dessalines/lemmy:dev"
# Run the playbook # Run the playbook
pushd ../../../lemmy-ansible # pushd ../../../lemmy-ansible
ansible-playbook -i test playbooks/site.yml # ansible-playbook -i test playbooks/site.yml
popd # popd

View file

@ -2,10 +2,6 @@
set -e set -e
git checkout main git checkout main
# Import translations
git fetch weblate
git merge weblate/main
# Creating the new tag # Creating the new tag
new_tag="$1" new_tag="$1"
third_semver=$(echo $new_tag | cut -d "." -f 3) third_semver=$(echo $new_tag | cut -d "." -f 3)

View file

@ -12,7 +12,7 @@ services:
restart: always restart: always
lemmy: lemmy:
image: dessalines/lemmy:v0.7.57 image: dessalines/lemmy:v0.7.59
ports: ports:
- "127.0.0.1:8536:8536" - "127.0.0.1:8536:8536"
restart: always restart: always

View file

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

View file

@ -1,10 +1,16 @@
# Docker Development # Docker Development
## Dependencies (on Ubuntu)
```bash
sudo apt install git docker-compose
sudo systemctl start docker
git clone https://github.com/LemmyNet/lemmy
```
## Running ## Running
```bash ```bash
sudo apt install git docker-compose
git clone https://github.com/LemmyNet/lemmy
cd lemmy/docker/dev cd lemmy/docker/dev
sudo docker-compose up --no-deps --build sudo docker-compose up --no-deps --build
``` ```

View file

@ -1,21 +1,9 @@
# Federation Development # Federation Development
## Setup
If you don't have a local clone of the Lemmy repo yet, just run the following command:
```bash
git clone https://github.com/LemmyNet/lemmy
```
## Running locally ## Running locally
You need to have the following packages installed, the Docker service needs to be running. Install the dependencies as described in [Docker development](contributing_docker_development.md). Then run the following
- docker
- docker-compose
Then run the following
```bash ```bash
cd docker/federation cd docker/federation
./start-local-instances.bash ./start-local-instances.bash
@ -40,15 +28,6 @@ To start federation between instances, visit one of them and search for a user,
Firefox containers are a good way to test them interacting. Firefox containers are a good way to test them interacting.
## Integration tests
To run a suite of suite of federation integration tests:
```bash
cd docker/federation
./run-tests.bash
```
## Running on a server ## Running on a server
Note that federation is currently in alpha. **Only use it for testing**, not on any production server, and be aware that turning on federation may break your instance. Note that federation is currently in alpha. **Only use it for testing**, not on any production server, and be aware that turning on federation may break your instance.

View file

@ -12,5 +12,9 @@ psql -U lemmy -c "DROP SCHEMA public CASCADE; CREATE SCHEMA public;"
### Federation ### Federation
Install the [Docker development dependencies](contributing_docker_development.md), and execute Install the [Docker development dependencies](contributing_docker_development.md), and execute:
`docker/federation-test/run-tests.sh`
```
cd docker/federation
./run-tests.bash
```

View file

@ -488,15 +488,21 @@ impl Perform for FollowCommunity {
return Err(APIError::err("community_follower_already_exists").into()); return Err(APIError::err("community_follower_already_exists").into());
} }
} }
// TODO: this needs to return a "pending" state, until Accept is received from the remote server
let community_id = data.community_id; let community_id = data.community_id;
let user_id = user.id; let user_id = user.id;
let community_view = blocking(context.pool(), move |conn| { let mut community_view = blocking(context.pool(), move |conn| {
CommunityView::read(conn, community_id, Some(user_id)) CommunityView::read(conn, community_id, Some(user_id))
}) })
.await??; .await??;
// TODO: this needs to return a "pending" state, until Accept is received from the remote server
// For now, just assume that remote follows are accepted.
// Otherwise, the subscribed will be null
if !community.local {
community_view.subscribed = Some(data.follow);
}
Ok(CommunityResponse { Ok(CommunityResponse {
community: community_view, community: community_view,
}) })

View file

@ -167,6 +167,7 @@ impl Perform for Register {
banner: None, banner: None,
password_encrypted: data.password.to_owned(), password_encrypted: data.password.to_owned(),
preferred_username: None, preferred_username: None,
published: None,
updated: None, updated: None,
admin: data.admin, admin: data.admin,
banned: false, banned: false,
@ -401,6 +402,7 @@ impl Perform for SaveUserSettings {
banner, banner,
password_encrypted, password_encrypted,
preferred_username, preferred_username,
published: Some(read_user.published),
updated: Some(naive_now()), updated: Some(naive_now()),
admin: read_user.admin, admin: read_user.admin,
banned: read_user.banned, banned: read_user.banned,

View file

@ -1 +1 @@
pub const VERSION: &str = "v0.7.57"; pub const VERSION: &str = "v0.7.59";

View file

@ -79,7 +79,6 @@ impl ActixJob for SendActivityTask {
.post(to_url.as_str()) .post(to_url.as_str())
.header("Content-Type", "application/json"); .header("Content-Type", "application/json");
// TODO: i believe we have to do the signing in here because it is only valid for a few seconds
let signed = sign( let signed = sign(
request, request,
self.activity.clone(), self.activity.clone(),

View file

@ -260,6 +260,7 @@ impl FromApub for UserForm {
email: None, email: None,
avatar, avatar,
banner, banner,
published: person.inner.published().map(|u| u.to_owned().naive_local()),
updated: person.updated().map(|u| u.to_owned().naive_local()), updated: person.updated().map(|u| u.to_owned().naive_local()),
show_nsfw: false, show_nsfw: false,
theme: "".to_string(), theme: "".to_string(),

View file

@ -105,6 +105,7 @@ mod tests {
banner: None, banner: None,
admin: false, admin: false,
banned: false, banned: false,
published: None,
updated: None, updated: None,
show_nsfw: false, show_nsfw: false,
theme: "darkly".into(), theme: "darkly".into(),

View file

@ -281,6 +281,7 @@ mod tests {
banner: None, banner: None,
admin: false, admin: false,
banned: false, banned: false,
published: None,
updated: None, updated: None,
show_nsfw: false, show_nsfw: false,
theme: "darkly".into(), theme: "darkly".into(),

View file

@ -520,6 +520,7 @@ mod tests {
banner: None, banner: None,
admin: false, admin: false,
banned: false, banned: false,
published: None,
updated: None, updated: None,
show_nsfw: false, show_nsfw: false,
theme: "darkly".into(), theme: "darkly".into(),

View file

@ -321,6 +321,7 @@ mod tests {
banner: None, banner: None,
admin: false, admin: false,
banned: false, banned: false,
published: None,
updated: None, updated: None,
show_nsfw: false, show_nsfw: false,
theme: "darkly".into(), theme: "darkly".into(),

View file

@ -417,6 +417,7 @@ mod tests {
banner: None, banner: None,
admin: false, admin: false,
banned: false, banned: false,
published: None,
updated: None, updated: None,
show_nsfw: false, show_nsfw: false,
theme: "darkly".into(), theme: "darkly".into(),
@ -445,6 +446,7 @@ mod tests {
banner: None, banner: None,
admin: false, admin: false,
banned: false, banned: false,
published: None,
updated: None, updated: None,
show_nsfw: false, show_nsfw: false,
theme: "darkly".into(), theme: "darkly".into(),

View file

@ -101,6 +101,7 @@ mod tests {
banner: None, banner: None,
admin: false, admin: false,
banned: false, banned: false,
published: None,
updated: None, updated: None,
show_nsfw: false, show_nsfw: false,
theme: "darkly".into(), theme: "darkly".into(),

View file

@ -350,6 +350,7 @@ mod tests {
banner: None, banner: None,
admin: false, admin: false,
banned: false, banned: false,
published: None,
updated: None, updated: None,
show_nsfw: false, show_nsfw: false,
theme: "darkly".into(), theme: "darkly".into(),

View file

@ -413,6 +413,7 @@ mod tests {
matrix_user_id: None, matrix_user_id: None,
avatar: None, avatar: None,
banner: None, banner: None,
published: None,
updated: None, updated: None,
admin: false, admin: false,
banned: false, banned: false,

View file

@ -158,6 +158,7 @@ mod tests {
banner: None, banner: None,
admin: false, admin: false,
banned: false, banned: false,
published: None,
updated: None, updated: None,
show_nsfw: false, show_nsfw: false,
theme: "darkly".into(), theme: "darkly".into(),
@ -186,6 +187,7 @@ mod tests {
banner: None, banner: None,
admin: false, admin: false,
banned: false, banned: false,
published: None,
updated: None, updated: None,
show_nsfw: false, show_nsfw: false,
theme: "darkly".into(), theme: "darkly".into(),

View file

@ -48,6 +48,7 @@ pub struct UserForm {
pub banned: bool, pub banned: bool,
pub email: Option<Option<String>>, pub email: Option<Option<String>>,
pub avatar: Option<Option<String>>, pub avatar: Option<Option<String>>,
pub published: Option<chrono::NaiveDateTime>,
pub updated: Option<chrono::NaiveDateTime>, pub updated: Option<chrono::NaiveDateTime>,
pub show_nsfw: bool, pub show_nsfw: bool,
pub theme: String, pub theme: String,
@ -181,6 +182,7 @@ mod tests {
banner: None, banner: None,
admin: false, admin: false,
banned: false, banned: false,
published: None,
updated: None, updated: None,
show_nsfw: false, show_nsfw: false,
theme: "darkly".into(), theme: "darkly".into(),

View file

@ -97,6 +97,7 @@ mod tests {
banner: None, banner: None,
admin: false, admin: false,
banned: false, banned: false,
published: None,
updated: None, updated: None,
show_nsfw: false, show_nsfw: false,
theme: "darkly".into(), theme: "darkly".into(),
@ -125,6 +126,7 @@ mod tests {
banner: None, banner: None,
admin: false, admin: false,
banned: false, banned: false,
published: None,
updated: None, updated: None,
show_nsfw: false, show_nsfw: false,
theme: "darkly".into(), theme: "darkly".into(),

View file

@ -14,5 +14,5 @@ tokio = "0.2"
strum = "0.19" strum = "0.19"
strum_macros = "0.19" strum_macros = "0.19"
futures = "0.3.5" futures = "0.3.5"
actix-web = { version = "3.0", default-features = false } actix-web = { version = "3.0", default-features = false, features = ["rustls"] }
log = "0.4" log = "0.4"

View file

@ -25,6 +25,6 @@ comrak = "0.8"
lazy_static = "1.3" lazy_static = "1.3"
openssl = "0.10" openssl = "0.10"
url = { version = "2.1", features = ["serde"] } url = { version = "2.1", features = ["serde"] }
actix-web = {version = "3.0", default-features = false } actix-web = { version = "3.0", default-features = false, features = ["rustls"] }
anyhow = "1.0" anyhow = "1.0"
reqwest = { version = "0.10", features = ["json"] } reqwest = { version = "0.10", features = ["json"] }

View file

@ -47,7 +47,7 @@ impl APIError {
#[derive(Debug)] #[derive(Debug)]
pub struct LemmyError { pub struct LemmyError {
inner: anyhow::Error, pub inner: anyhow::Error,
} }
impl<T> From<T> for LemmyError impl<T> From<T> for LemmyError

View file

@ -54,6 +54,7 @@ fn user_updates_2020_04_02(conn: &PgConnection) -> Result<(), LemmyError> {
banner: Some(cuser.banner.to_owned()), banner: Some(cuser.banner.to_owned()),
password_encrypted: cuser.password_encrypted.to_owned(), password_encrypted: cuser.password_encrypted.to_owned(),
preferred_username: cuser.preferred_username.to_owned(), preferred_username: cuser.preferred_username.to_owned(),
published: Some(cuser.published),
updated: None, updated: None,
admin: cuser.admin, admin: cuser.admin,
banned: cuser.banned, banned: cuser.banned,

208
tests/integration_test.rs Normal file
View file

@ -0,0 +1,208 @@
extern crate lemmy_server;
use activitystreams::{
activity::{
kind::{CreateType, FollowType},
ActorAndObject,
},
base::{BaseExt, ExtendsExt},
object::{Note, ObjectExt},
};
use actix::prelude::*;
use actix_web::{test::TestRequest, web, web::Path, HttpRequest};
use chrono::Utc;
use diesel::{
r2d2::{ConnectionManager, Pool},
PgConnection,
};
use http_signature_normalization_actix::PrepareVerifyError;
use lemmy_db::{
community::{Community, CommunityForm},
user::{User_, *},
Crud,
ListingType,
SortType,
};
use lemmy_rate_limit::{rate_limiter::RateLimiter, RateLimit};
use lemmy_server::{
apub::{
activity_queue::create_activity_queue,
inbox::{
community_inbox,
community_inbox::community_inbox,
shared_inbox,
shared_inbox::shared_inbox,
user_inbox,
user_inbox::user_inbox,
},
},
websocket::chat_server::ChatServer,
LemmyContext,
};
use lemmy_utils::{apub::generate_actor_keypair, settings::Settings};
use reqwest::Client;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use tokio::sync::Mutex;
use url::Url;
fn create_context() -> LemmyContext {
let settings = Settings::get();
let db_url = settings.get_database_url();
let manager = ConnectionManager::<PgConnection>::new(&db_url);
let pool = Pool::builder()
.max_size(settings.database.pool_size)
.build(manager)
.unwrap();
let rate_limiter = RateLimit {
rate_limiter: Arc::new(Mutex::new(RateLimiter::default())),
};
let activity_queue = create_activity_queue();
let chat_server = ChatServer::startup(
pool.clone(),
rate_limiter.clone(),
Client::default(),
activity_queue.clone(),
)
.start();
LemmyContext::new(
pool,
chat_server,
Client::default(),
create_activity_queue(),
)
}
fn create_user(conn: &PgConnection, name: &str) -> User_ {
let user_keypair = generate_actor_keypair().unwrap();
let new_user = UserForm {
name: name.into(),
preferred_username: None,
password_encrypted: "nope".into(),
email: None,
matrix_user_id: None,
avatar: None,
banner: None,
admin: false,
banned: false,
updated: None,
show_nsfw: false,
theme: "darkly".into(),
default_sort_type: SortType::Hot as i16,
default_listing_type: ListingType::Subscribed as i16,
lang: "browser".into(),
show_avatars: true,
send_notifications_to_email: false,
actor_id: Some(format!("http://localhost:8536/u/{}", name).to_string()),
bio: None,
local: true,
private_key: Some(user_keypair.private_key),
public_key: Some(user_keypair.public_key),
last_refreshed_at: None,
};
User_::create(&conn, &new_user).unwrap()
}
fn create_community(conn: &PgConnection, creator_id: i32) -> Community {
let new_community = CommunityForm {
name: "test_community".into(),
creator_id,
title: "test_community".to_owned(),
description: None,
category_id: 1,
nsfw: false,
removed: None,
deleted: None,
updated: None,
actor_id: None,
local: true,
private_key: None,
public_key: None,
last_refreshed_at: None,
published: None,
icon: None,
banner: None,
};
Community::create(&conn, &new_community).unwrap()
}
fn create_activity<'a, Activity, Return>(user_id: String) -> web::Json<Return>
where
for<'de> Return: Deserialize<'de> + 'a,
Activity: std::default::Default + Serialize,
{
let mut activity = ActorAndObject::<Activity>::new(user_id, Note::new().into_any_base().unwrap());
activity
.set_id(Url::parse("http://localhost:8536/create/1").unwrap())
.set_many_ccs(vec![Url::parse("http://localhost:8536/c/main").unwrap()]);
let activity = serde_json::to_value(&activity).unwrap();
let activity: Return = serde_json::from_value(activity).unwrap();
web::Json(activity)
}
fn create_http_request() -> HttpRequest {
let time1 = Utc::now().timestamp();
let time2 = Utc::now().timestamp();
let signature = format!(
r#"keyId="my-key-id",algorithm="hs2019",created="{}",expires="{}",headers="(request-target) (created) (expires) date content-type",signature="blah blah blah""#,
time1, time2
);
TestRequest::post()
.uri("http://localhost:8536/")
.header("Signature", signature)
.to_http_request()
}
#[actix_rt::test]
async fn test_shared_inbox_expired_signature() {
let request = create_http_request();
let context = create_context();
let connection = &context.pool().get().unwrap();
let user = create_user(connection, "shared_inbox_rvgfd");
let activity =
create_activity::<CreateType, ActorAndObject<shared_inbox::ValidTypes>>(user.actor_id);
let response = shared_inbox(request, activity, web::Data::new(context)).await;
assert_eq!(
format!("{}", response.err().unwrap()),
format!("{}", PrepareVerifyError::Expired)
);
User_::delete(connection, user.id).unwrap();
}
#[actix_rt::test]
async fn test_user_inbox_expired_signature() {
let request = create_http_request();
let context = create_context();
let connection = &context.pool().get().unwrap();
let user = create_user(connection, "user_inbox_cgsax");
let activity =
create_activity::<CreateType, ActorAndObject<user_inbox::ValidTypes>>(user.actor_id);
let path = Path::<String> {
0: "username".to_string(),
};
let response = user_inbox(request, activity, path, web::Data::new(context)).await;
assert_eq!(
format!("{}", response.err().unwrap()),
format!("{}", PrepareVerifyError::Expired)
);
User_::delete(connection, user.id).unwrap();
}
#[actix_rt::test]
async fn test_community_inbox_expired_signature() {
let context = create_context();
let connection = &context.pool().get().unwrap();
let user = create_user(connection, "community_inbox_hrxa");
let community = create_community(connection, user.id);
let request = create_http_request();
let activity =
create_activity::<FollowType, ActorAndObject<community_inbox::ValidTypes>>(user.actor_id);
let path = Path::<String> { 0: community.name };
let response = community_inbox(request, activity, path, web::Data::new(context)).await;
assert_eq!(
format!("{}", response.err().unwrap()),
format!("{}", PrepareVerifyError::Expired)
);
User_::delete(connection, user.id).unwrap();
Community::delete(connection, community.id).unwrap();
}