Compare commits

..

1 commit

Author SHA1 Message Date
1751337d82 wip: try workbench 2020-06-10 16:18:47 +02:00
107 changed files with 1225 additions and 1632 deletions

2
CODE_OF_CONDUCT.md vendored
View file

@ -30,6 +30,6 @@ In the Lemmy community we strive to go the extra step to look out for each other
And if someone takes issue with something you said or did, resist the urge to be defensive. Just stop doing what it was they complained about and apologize. Even if you feel you were misinterpreted or unfairly accused, chances are good there was something you couldve communicated better — remember that its your responsibility to make others comfortable. Everyone wants to get along and we are all here first and foremost because we want to talk about cool technology. You will find that people will be eager to assume good intent and forgive as long as you earn their trust.
The enforcement policies listed above apply to all official Lemmy venues; including git repositories under [github.com/LemmyNet/lemmy](https://github.com/LemmyNet/lemmy) and [yerbamate.dev/LemmyNet/lemmy](https://yerbamate.dev/LemmyNet/lemmy), the [Matrix channel](https://matrix.to/#/!BZVTUuEiNmRcbFeLeI:matrix.org?via=matrix.org&via=privacytools.io&via=permaweb.io); and all instances under lemmy.ml. For other projects adopting the Rust Code of Conduct, please contact the maintainers of those projects for enforcement. If you wish to use this code of conduct for your own project, consider explicitly mentioning your moderation policy or making a copy with your own moderation policy so as to avoid confusion.
The enforcement policies listed above apply to all official Lemmy venues; including git repositories under [github.com/LemmyNet/lemmy](https://github.com/LemmyNet/lemmy) and [yerbamate.dev/dessalines/lemmy](https://yerbamate.dev/dessalines/lemmy), the [Matrix channel](https://matrix.to/#/!BZVTUuEiNmRcbFeLeI:matrix.org?via=matrix.org&via=privacytools.io&via=permaweb.io); and all instances under lemmy.ml. For other projects adopting the Rust Code of Conduct, please contact the maintainers of those projects for enforcement. If you wish to use this code of conduct for your own project, consider explicitly mentioning your moderation policy or making a copy with your own moderation policy so as to avoid confusion.
Adapted from the [Rust Code of Conduct](https://www.rust-lang.org/policies/code-of-conduct), which is based on the [Node.js Policy on Trolling](http://blog.izs.me/post/30036893703/policy-on-trolling) as well as the [Contributor Covenant v1.3.0](https://www.contributor-covenant.org/version/1/3/0/).

63
RELEASES.md vendored
View file

@ -1,66 +1,3 @@
# Lemmy v0.7.0 Release (2020-06-23)
This release replaces [pictshare](https://github.com/HaschekSolutions/pictshare)
with [pict-rs](https://git.asonix.dog/asonix/pict-rs), which improves performance
and security.
Overall, since our last major release in January (v0.6.0), we have closed over
[100 issues!](https://github.com/LemmyNet/lemmy/milestone/16?closed=1)
- Site-wide list of recent comments
- Reconnecting websockets
- Many more themes, including a default light one.
- Expandable embeds for post links (and thumbnails), from
[iframely](https://github.com/itteco/iframely)
- Better icons
- Emoji autocomplete to post and message bodies, and an Emoji Picker
- Post body now searchable
- Community title and description is now searchable
- Simplified cross-posts
- Better documentation
- LOTS more languages
- Lots of bugs squashed
- And more ...
## Upgrading
Before starting the upgrade, make sure that you have a working backup of your
database and image files. See our
[documentation](https://dev.lemmy.ml/docs/administration_backup_and_restore.html)
for backup instructions.
**With Ansible:**
```
# deploy with ansible from your local lemmy git repo
git pull
cd ansible
ansible-playbook lemmy.yml
# connect via ssh to run the migration script
ssh your-server
cd /lemmy/
wget https://raw.githubusercontent.com/LemmyNet/lemmy/master/docker/prod/migrate-pictshare-to-pictrs.bash
chmod +x migrate-pictshare-to-pictrs.bash
sudo ./migrate-pictshare-to-pictrs.bash
```
**With manual Docker installation:**
```
# run these commands on your server
cd /lemmy
wget https://raw.githubusercontent.com/LemmyNet/lemmy/master/ansible/templates/nginx.conf
# Replace the {{ vars }}
sudo mv nginx.conf /etc/nginx/sites-enabled/lemmy.conf
sudo nginx -s reload
wget https://raw.githubusercontent.com/LemmyNet/lemmy/master/docker/prod/docker-compose.yml
wget https://raw.githubusercontent.com/LemmyNet/lemmy/master/docker/prod/migrate-pictshare-to-pictrs.bash
chmod +x migrate-pictshare-to-pictrs.bash
sudo bash migrate-pictshare-to-pictrs.bash
```
**Note:** After upgrading, all users need to reload the page, then logout and
login again, so that images are loaded correctly.
# Lemmy v0.6.0 Release (2020-01-16)
`v0.6.0` is here, and we've closed [41 issues!](https://github.com/LemmyNet/lemmy/milestone/15?closed=1)

2
ansible/VERSION vendored
View file

@ -1 +1 @@
v0.7.1
v0.6.71

1
ansible/ansible.cfg vendored
View file

@ -1,6 +1,5 @@
[defaults]
inventory=inventory
interpreter_python=/usr/bin/python3
[ssh_connection]
pipelining = True

8
ansible/lemmy.yml vendored
View file

@ -24,11 +24,10 @@
creates: '/etc/letsencrypt/live/{{domain}}/privkey.pem'
- name: create lemmy folder
file: path={{item.path}} {{item.owner}} state=directory
file: path={{item.path}} state=directory
with_items:
- { path: '/lemmy/', owner: 'root' }
- { path: '/lemmy/volumes/', owner: 'root' }
- { path: '/lemmy/volumes/pictrs/', owner: '991' }
- { path: '/lemmy/' }
- { path: '/lemmy/volumes/' }
- block:
- name: add template files
@ -60,7 +59,6 @@
project_src: /lemmy/
state: present
pull: yes
remove_orphans: yes
- name: reload nginx with new config
shell: nginx -s reload

View file

@ -26,11 +26,10 @@
creates: '/etc/letsencrypt/live/{{domain}}/privkey.pem'
- name: create lemmy folder
file: path={{item.path}} owner={{item.owner}} state=directory
file: path={{item.path}} state=directory
with_items:
- { path: '/lemmy/', owner: 'root' }
- { path: '/lemmy/volumes/', owner: 'root' }
- { path: '/lemmy/volumes/pictrs/', owner: '991' }
- { path: '/lemmy/' }
- { path: '/lemmy/volumes/' }
- block:
- name: add template files
@ -89,7 +88,6 @@
project_src: /lemmy/
state: present
recreate: always
remove_orphans: yes
ignore_errors: yes
- name: reload nginx with new config

View file

@ -12,7 +12,7 @@ services:
- ./lemmy.hjson:/config/config.hjson:ro
depends_on:
- postgres
- pictrs
- pictshare
- iframely
postgres:
@ -25,13 +25,12 @@ services:
- ./volumes/postgres:/var/lib/postgresql/data
restart: always
pictrs:
image: asonix/pictrs:amd64-v0.1.0-r9
user: 991:991
pictshare:
image: hascheksolutions/pictshare:latest
ports:
- "127.0.0.1:8537:8080"
- "127.0.0.1:8537:80"
volumes:
- ./volumes/pictrs:/mnt
- ./volumes/pictshare:/usr/share/nginx/html/data
restart: always
iframely:

View file

@ -48,8 +48,8 @@ server {
add_header X-Frame-Options "DENY";
add_header X-XSS-Protection "1; mode=block";
# Upload limit for pictrs
client_max_body_size 20M;
# Upload limit for pictshare
client_max_body_size 50M;
location / {
proxy_pass http://0.0.0.0:8536;
@ -70,21 +70,15 @@ server {
proxy_cache_min_uses 5;
}
# Redirect pictshare images to pictrs
location ~ /pictshare/(.*)$ {
return 301 /pictrs/image/$1;
}
location /pictshare/ {
proxy_pass http://0.0.0.0:8537/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# pict-rs images
location /pictrs {
location /pictrs/image {
proxy_pass http://0.0.0.0:8537/image;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Block the import
return 403;
if ($request_uri ~ \.(?:ico|gif|jpe?g|png|webp|bmp|mp4)$) {
add_header Cache-Control "public, max-age=31536000, immutable";
}
}
location /iframely/ {

15
docker/dev/Dockerfile vendored
View file

@ -21,13 +21,17 @@ COPY server/Cargo.toml server/Cargo.lock ./
RUN sudo chown -R rust:rust .
RUN mkdir -p ./src/bin \
&& echo 'fn main() { println!("Dummy") }' > ./src/bin/main.rs
RUN cargo build
RUN cargo build --release
RUN rm -f ./target/x86_64-unknown-linux-musl/release/deps/lemmy_server*
COPY server/src ./src/
COPY server/migrations ./migrations/
# Build for debug
RUN cargo build
# Build for release
RUN cargo build --frozen --release
# Get diesel-cli on there just in case
# RUN cargo install diesel_cli --no-default-features --features postgres
FROM ekidd/rust-musl-builder:1.42.0-openssl11 as docs
WORKDIR /app
@ -35,14 +39,15 @@ COPY docs ./docs
RUN sudo chown -R rust:rust .
RUN mdbook build docs/
FROM alpine:3.12
FROM alpine:3.10
# Install libpq for postgres
RUN apk add libpq
# Copy resources
COPY server/config/defaults.hjson /config/defaults.hjson
COPY --from=rust /app/server/target/x86_64-unknown-linux-musl/debug/lemmy_server /app/lemmy
COPY --from=rust /app/server/target/x86_64-unknown-linux-musl/release/lemmy_server /app/lemmy
COPY --from=docs /app/docs/book/ /app/dist/documentation/
COPY --from=node /app/ui/dist /app/dist

79
docker/dev/Dockerfile.aarch64 vendored Normal file
View file

@ -0,0 +1,79 @@
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
# contains qemu-*-static for cross-compilation
FROM multiarch/qemu-user-static as qemu
FROM arm64v8/rust:1.40-buster as rust
COPY --from=qemu /usr/bin/qemu-aarch64-static /usr/bin
#COPY --from=qemu /usr/bin/qemu-arm-static /usr/bin
# Install musl
#RUN apt-get update && apt-get install -y mc
#RUN apt-get install -y musl-tools mc
#libpq-dev mc
#RUN rustup target add ${TARGET}
# Cache deps
WORKDIR /app
RUN USER=root cargo new server
WORKDIR /app/server
COPY server/Cargo.toml server/Cargo.lock ./
RUN mkdir -p ./src/bin \
&& echo 'fn main() { println!("Dummy") }' > ./src/bin/main.rs
RUN cargo build --release
# RUN cargo build
COPY server/src ./src/
COPY server/migrations ./migrations/
RUN rm -f ./target/release/deps/lemmy_server* ; rm -f ./target/debug/deps/lemmy_server*
# build for release
RUN cargo build --frozen --release
# RUN cargo build --frozen
# Get diesel-cli on there just in case
# RUN cargo install diesel_cli --no-default-features --features postgres
# RUN cp /app/server/target/debug/lemmy_server /app/server/ready
RUN cp /app/server/target/release/lemmy_server /app/server/ready
#FROM alpine:3.10
# debian because build with dynamic linking with debian:buster
FROM arm64v8/debian:buster-slim as lemmy
#COPY --from=qemu /usr/bin/qemu-arm-static /usr/bin
COPY --from=qemu /usr/bin/qemu-aarch64-static /usr/bin
# Install libpq for postgres
#RUN apk add libpq
RUN apt-get update && apt-get install -y libpq5
RUN addgroup --gid 1000 lemmy
# for alpine
#RUN adduser -D -s /bin/sh -u 1000 -G lemmy lemmy
# for debian
RUN adduser --disabled-password --shell /bin/sh --uid 1000 --ingroup lemmy lemmy
# Copy resources
COPY server/config/defaults.hjson /config/defaults.hjson
COPY --from=rust /app/server/ready /app/lemmy
COPY --from=node /app/ui/dist /app/dist
RUN chown lemmy:lemmy /app/lemmy
USER lemmy
EXPOSE 8536
CMD ["/app/lemmy"]

79
docker/dev/Dockerfile.armv7hf vendored Normal file
View file

@ -0,0 +1,79 @@
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
# contains qemu-*-static for cross-compilation
FROM multiarch/qemu-user-static as qemu
FROM arm32v7/rust:1.37-buster as rust
#COPY --from=qemu /usr/bin/qemu-aarch64-static /usr/bin
COPY --from=qemu /usr/bin/qemu-arm-static /usr/bin
# Install musl
#RUN apt-get update && apt-get install -y mc
#RUN apt-get install -y musl-tools mc
#libpq-dev mc
#RUN rustup target add ${TARGET}
# Cache deps
WORKDIR /app
RUN USER=root cargo new server
WORKDIR /app/server
COPY server/Cargo.toml server/Cargo.lock ./
RUN mkdir -p ./src/bin \
&& echo 'fn main() { println!("Dummy") }' > ./src/bin/main.rs
#RUN cargo build --release
# RUN cargo build
RUN RUSTFLAGS='-Ccodegen-units=1' cargo build
COPY server/src ./src/
COPY server/migrations ./migrations/
RUN rm -f ./target/release/deps/lemmy_server* ; rm -f ./target/debug/deps/lemmy_server*
# build for release
#RUN cargo build --frozen --release
RUN cargo build --frozen
# Get diesel-cli on there just in case
# RUN cargo install diesel_cli --no-default-features --features postgres
RUN cp /app/server/target/debug/lemmy_server /app/server/ready
#RUN cp /app/server/target/release/lemmy_server /app/server/ready
#FROM alpine:3.10
# debian because build with dynamic linking with debian:buster
FROM arm32v7/debian:buster-slim as lemmy
COPY --from=qemu /usr/bin/qemu-arm-static /usr/bin
# Install libpq for postgres
#RUN apk add libpq
RUN apt-get update && apt-get install -y libpq5
RUN addgroup --gid 1000 lemmy
# for alpine
#RUN adduser -D -s /bin/sh -u 1000 -G lemmy lemmy
# for debian
RUN adduser --disabled-password --shell /bin/sh --uid 1000 --ingroup lemmy lemmy
# Copy resources
COPY server/config/defaults.hjson /config/defaults.hjson
COPY --from=rust /app/server/ready /app/lemmy
COPY --from=node /app/ui/dist /app/dist
RUN chown lemmy:lemmy /app/lemmy
USER lemmy
EXPOSE 8536
CMD ["/app/lemmy"]

88
docker/dev/Dockerfile.libc vendored Normal file
View file

@ -0,0 +1,88 @@
# can be build on x64, arm32, arm64 platforms
# to build on target platform run
# docker build -f Dockerfile.libc -t dessalines/lemmy:version ../..
#
# to use docker buildx run
# docker buildx build --platform linux/amd64,linux/arm64 -f Dockerfile.libc -t YOURNAME/lemmy --push ../..
FROM node:12-buster as node
# use this if use docker buildx
#FROM --platform=$BUILDPLATFORM node:12-buster as node
WORKDIR /app/ui
# Cache deps
COPY ui/package.json ui/yarn.lock ./
RUN yarn install --pure-lockfile --network-timeout 100000
# Build
COPY ui /app/ui
RUN yarn build
FROM rust:1.42 as rust
# Cache deps
WORKDIR /app
RUN USER=root cargo new server
WORKDIR /app/server
COPY server/Cargo.toml server/Cargo.lock ./
RUN mkdir -p ./src/bin \
&& echo 'fn main() { println!("Dummy") }' > ./src/bin/main.rs
RUN cargo build --release
#RUN cargo build && \
# rm -f ./target/release/deps/lemmy_server* ; rm -f ./target/debug/deps/lemmy_server*
COPY server/src ./src/
COPY server/migrations ./migrations/
# build for release
# workaround for https://github.com/rust-lang/rust/issues/62896
#RUN RUSTFLAGS='-Ccodegen-units=1' cargo build --release
RUN cargo build --release --frozen
#RUN cargo build --frozen
# Get diesel-cli on there just in case
# RUN cargo install diesel_cli --no-default-features --features postgres
# make result place always the same for lemmy container
RUN cp /app/server/target/release/lemmy_server /app/server/ready
#RUN cp /app/server/target/debug/lemmy_server /app/server/ready
FROM rust:1.42 as docs
WORKDIR /app
# Build docs
COPY docs ./docs
RUN cargo install mdbook
RUN mdbook build docs/
#FROM alpine:3.10
# debian because build with dynamic linking with debian:buster
FROM debian:buster as lemmy
# Install libpq for postgres
#RUN apk add libpq
RUN apt-get update && apt-get install -y libpq5
RUN addgroup --gid 1000 lemmy
# for alpine
#RUN adduser -D -s /bin/sh -u 1000 -G lemmy lemmy
# for debian
RUN adduser --disabled-password --shell /bin/sh --uid 1000 --ingroup lemmy lemmy
# Copy resources
COPY server/config/defaults.hjson /config/defaults.hjson
COPY --from=node /app/ui/dist /app/dist
COPY --from=docs /app/docs/book/ /app/dist/documentation/
COPY --from=rust /app/server/ready /app/lemmy
RUN chown lemmy:lemmy /app/lemmy
USER lemmy
EXPOSE 8536
CMD ["/app/lemmy"]

View file

@ -1,5 +1,4 @@
#!/bin/sh
set -e
git checkout master
# Import translations
@ -21,7 +20,7 @@ git add "server/src/version.rs"
echo $new_tag > "ansible/VERSION"
git add "ansible/VERSION"
cd docker/prod || exit
cd docker/dev || exit
# Changing the docker-compose prod
sed -i "s/dessalines\/lemmy:.*/dessalines\/lemmy:$new_tag/" ../prod/docker-compose.yml
@ -33,24 +32,41 @@ git add ../../ansible/templates/docker-compose.yml
git commit -m"Version $new_tag"
git tag $new_tag
export COMPOSE_DOCKER_CLI_BUILD=1
export DOCKER_BUILDKIT=1
# Rebuilding docker
docker-compose build
docker tag dev_lemmy:latest dessalines/lemmy:x64-$new_tag
docker push dessalines/lemmy:x64-$new_tag
# Build for Raspberry Pi / other archs
# Arm currently not working
# docker build -t lemmy:armv7hf -f Dockerfile.armv7hf ../../
# docker tag lemmy:armv7hf dessalines/lemmy:armv7hf-$new_tag
# docker push dessalines/lemmy:armv7hf-$new_tag
# aarch64
# Only do this on major releases (IE the third semver is 0)
if [ $third_semver -eq 0 ]; then
# TODO get linux/arm/v7 build working
# Build for Raspberry Pi / other archs too
docker buildx build --platform linux/amd64,linux/arm64 ../../ \
--file Dockerfile \
--tag dessalines/lemmy:$new_tag \
--push
else
docker buildx build --platform linux/amd64 ../../ \
--file Dockerfile \
--tag dessalines/lemmy:$new_tag \
--push
# Registering qemu binaries
docker run --rm --privileged multiarch/qemu-user-static:register --reset
docker build -t lemmy:aarch64 -f Dockerfile.aarch64 ../../
docker tag lemmy:aarch64 dessalines/lemmy:arm64-$new_tag
docker push dessalines/lemmy:arm64-$new_tag
fi
# Creating the manifest for the multi-arch build
if [ $third_semver -eq 0 ]; then
docker manifest create dessalines/lemmy:$new_tag \
dessalines/lemmy:x64-$new_tag \
dessalines/lemmy:arm64-$new_tag
else
docker manifest create dessalines/lemmy:$new_tag \
dessalines/lemmy:x64-$new_tag
fi
docker manifest push dessalines/lemmy:$new_tag
# Push
git push origin $new_tag
git push

View file

@ -1,6 +1,15 @@
version: '3.3'
services:
postgres:
image: postgres:12-alpine
environment:
- POSTGRES_USER=lemmy
- POSTGRES_PASSWORD=password
- POSTGRES_DB=lemmy
volumes:
- ./volumes/postgres:/var/lib/postgresql/data
restart: always
lemmy:
build:
@ -14,27 +23,16 @@ services:
volumes:
- ../lemmy.hjson:/config/config.hjson
depends_on:
- pictrs
- postgres
- pictshare
- iframely
postgres:
image: postgres:12-alpine
environment:
- POSTGRES_USER=lemmy
- POSTGRES_PASSWORD=password
- POSTGRES_DB=lemmy
pictshare:
image: hascheksolutions/pictshare:latest
ports:
- "127.0.0.1:8537:80"
volumes:
- ./volumes/postgres:/var/lib/postgresql/data
restart: always
pictrs:
image: asonix/pictrs:v0.1.13-r0
ports:
- "127.0.0.1:8537:8080"
user: 991:991
volumes:
- ./volumes/pictrs:/mnt
- ./volumes/pictshare:/usr/share/nginx/html/data
restart: always
iframely:

View file

@ -1,6 +1,2 @@
#!/bin/sh
set -e
export COMPOSE_DOCKER_CLI_BUILD=1
export DOCKER_BUILDKIT=1
docker-compose up -d --no-deps --build

View file

@ -1,8 +1,4 @@
#!/bin/sh
set -e
export COMPOSE_DOCKER_CLI_BUILD=1
export DOCKER_BUILDKIT=1
# Rebuilding dev docker
docker-compose build

View file

@ -1,64 +0,0 @@
ARG RUST_BUILDER_IMAGE=shtripok/rust-musl-builder:arm
FROM $RUST_BUILDER_IMAGE as rust
#ARG RUSTRELEASEDIR="debug"
ARG RUSTRELEASEDIR="release"
# Cache deps
WORKDIR /app
RUN sudo chown -R rust:rust .
RUN USER=root cargo new server
WORKDIR /app/server
COPY --chown=rust:rust server/Cargo.toml server/Cargo.lock ./
#RUN sudo chown -R rust:rust .
RUN mkdir -p ./src/bin \
&& echo 'fn main() { println!("Dummy") }' > ./src/bin/main.rs
RUN cargo build --release
RUN rm -f ./target/$CARGO_BUILD_TARGET/$RUSTRELEASEDIR/deps/lemmy_server*
COPY --chown=rust:rust server/src ./src/
COPY --chown=rust:rust server/migrations ./migrations/
# build for release
# workaround for https://github.com/rust-lang/rust/issues/62896
RUN cargo build --frozen --release
# reduce binary size
RUN strip ./target/$CARGO_BUILD_TARGET/$RUSTRELEASEDIR/lemmy_server
RUN cp ./target/$CARGO_BUILD_TARGET/$RUSTRELEASEDIR/lemmy_server /app/server/
FROM $RUST_BUILDER_IMAGE as docs
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
RUN apk add libpq
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 --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
RUN chown lemmy:lemmy /app/lemmy
USER lemmy
EXPOSE 8536
CMD ["/app/lemmy"]

View file

@ -12,7 +12,7 @@ services:
restart: always
lemmy:
image: dessalines/lemmy:v0.7.1
image: dessalines/lemmy:v0.6.71
ports:
- "127.0.0.1:8536:8536"
restart: always
@ -22,17 +22,17 @@ services:
- ./lemmy.hjson:/config/config.hjson
depends_on:
- postgres
- pictrs
- pictshare
- iframely
pictrs:
image: asonix/pictrs:v0.1.13-r0
ports:
- "127.0.0.1:8537:8080"
user: 991:991
pictshare:
image: hascheksolutions/pictshare:latest
ports:
- "127.0.0.1:8537:80"
volumes:
- ./volumes/pictrs:/mnt
- ./volumes/pictshare:/usr/share/nginx/html/data
restart: always
mem_limit: 100m
iframely:
image: dogbin/iframely:latest

View file

@ -1,60 +0,0 @@
#!/bin/bash
set -e
if [[ $(id -u) != 0 ]]; then
echo "This migration needs to be run as root"
exit
fi
if [[ ! -f docker-compose.yml ]]; then
echo "No docker-compose.yml found in current directory. Is this the right folder?"
exit
fi
# Fixing pictrs permissions
mkdir -p volumes/pictrs
sudo chown -R 991:991 volumes/pictrs
echo "Restarting docker-compose, making sure that pictrs is started and pictshare is removed"
docker-compose up -d --remove-orphans
if [[ -z $(docker-compose ps | grep pictrs) ]]; then
echo "Pict-rs is not running, make sure you update Lemmy first"
exit
fi
# echo "Stopping Lemmy so that users dont upload new images during the migration"
# docker-compose stop lemmy
pushd volumes/pictshare/
echo "Importing pictshare images to pict-rs..."
IMAGE_NAMES=*
for image in $IMAGE_NAMES; do
IMAGE_PATH="$(pwd)/$image/$image"
if [[ ! -f $IMAGE_PATH ]]; then
continue
fi
echo -e "\nImporting $IMAGE_PATH"
ret=0
curl --silent --fail -F "images[]=@$IMAGE_PATH" http://127.0.0.1:8537/import || ret=$?
if [[ $ret != 0 ]]; then
echo "Error for $IMAGE_PATH : $ret"
fi
done
echo "Fixing permissions on pictshare folder"
find . -type d -exec chmod 755 {} \;
find . -type f -exec chmod 644 {} \;
popd
echo "Rewrite image links in Lemmy database"
docker-compose exec -u postgres postgres psql -U lemmy -c "UPDATE user_ SET avatar = REPLACE(avatar, 'pictshare', 'pictrs/image') WHERE avatar is not null;"
docker-compose exec -u postgres postgres psql -U lemmy -c "UPDATE post SET url = REPLACE(url, 'pictshare', 'pictrs/image') WHERE url is not null;"
echo "Moving pictshare data folder to pictshare_backup"
mv volumes/pictshare volumes/pictshare_backup
echo "Migration done, starting Lemmy again"
echo "If everything went well, you can delete ./volumes/pictshare_backup/"
docker-compose start lemmy

View file

@ -6,25 +6,20 @@ Make sure you have both docker and docker-compose(>=`1.24.0`) installed. On Ubun
# create a folder for the lemmy files. the location doesnt matter, you can put this anywhere you want
mkdir /lemmy
cd /lemmy
# download default config files
wget https://raw.githubusercontent.com/LemmyNet/lemmy/master/docker/prod/docker-compose.yml
wget https://raw.githubusercontent.com/LemmyNet/lemmy/master/docker/lemmy.hjson
wget https://raw.githubusercontent.com/LemmyNet/lemmy/master/docker/iframely.config.local.js
# Set correct permissions for pictrs folder
mkdir -p volumes/pictrs
sudo chown -R 991:991 volumes/pictrs
wget https://raw.githubusercontent.com/dessalines/lemmy/master/docker/prod/docker-compose.yml
wget https://raw.githubusercontent.com/dessalines/lemmy/master/docker/lemmy.hjson
wget https://raw.githubusercontent.com/dessalines/lemmy/master/docker/iframely.config.local.js
```
After this, have a look at the [config file](administration_configuration.md) named `lemmy.hjson`, and adjust it, in particular the hostname, and possibly the db password. Then run:
`docker-compose up -d`
To make Lemmy available outside the server, you need to setup a reverse proxy, like Nginx. [A sample nginx config](https://raw.githubusercontent.com/LemmyNet/lemmy/master/ansible/templates/nginx.conf), could be setup with:
To make Lemmy available outside the server, you need to setup a reverse proxy, like Nginx. [A sample nginx config](https://raw.githubusercontent.com/dessalines/lemmy/master/ansible/templates/nginx.conf), could be setup with:
```bash
wget https://raw.githubusercontent.com/LemmyNet/lemmy/master/ansible/templates/nginx.conf
wget https://raw.githubusercontent.com/dessalines/lemmy/master/ansible/templates/nginx.conf
# Replace the {{ vars }}
sudo mv nginx.conf /etc/nginx/sites-enabled/lemmy.conf
```
@ -36,6 +31,6 @@ You will also need to setup TLS, for example with [Let's Encrypt](https://letsen
To update to the newest version, you can manually change the version in `docker-compose.yml`. Alternatively, fetch the latest version from our git repo:
```bash
wget https://raw.githubusercontent.com/LemmyNet/lemmy/master/docker/prod/docker-compose.yml
wget https://raw.githubusercontent.com/dessalines/lemmy/master/docker/prod/docker-compose.yml
docker-compose up -d
```

View file

@ -4,9 +4,9 @@ Information about contributing to Lemmy, whether it is translating, testing, des
## Issue tracking / Repositories
- [GitHub (for issues and pull requests)](https://github.com/LemmyNet/lemmy)
- [Gitea (only for pull requests)](https://yerbamate.dev/LemmyNet/lemmy)
- [GitLab (only code-mirror)](https://gitlab.com/dessalines/lemmy)
- [GitHub (for issues)](https://github.com/LemmyNet/lemmy)
- [Gitea](https://yerbamate.dev/dessalines/lemmy)
- [GitLab](https://gitlab.com/dessalines/lemmy)
## Translating

View file

@ -3,22 +3,11 @@
## Running
```bash
sudo apt install git docker-compose
git clone https://github.com/LemmyNet/lemmy
cd lemmy/docker/dev
sudo docker-compose up --no-deps --build
./docker_update.sh # This builds and runs it, updating for your changes
```
and go to http://localhost:8536.
To speed up the Docker compile, add the following to `/etc/docker/daemon.json` and restart Docker.
```
{
"features": {
"buildkit": true
}
}
```
If the build is still too slow, you will have to use a
[local build](contributing_local_development.md) instead.
Note that compile times when changing `Cargo.toml` are relatively long with Docker, because builds can't be incrementally cached. If this is a problem for you, you should use [Local Development](contributing_local_development.md).

View file

@ -1,67 +1,31 @@
### Ubuntu
#### Requirements
- [Rust](https://www.rust-lang.org/)
- [Yarn](https://yarnpkg.com/en/)
- [Postgres](https://www.postgresql.org/)
#### Build requirements:
```
sudo apt install git cargo libssl-dev pkg-config libpq-dev yarn curl gnupg2 git
# install yarn
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt update && sudo apt install yarn
```
#### Set up Postgres DB
#### Get the 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)
```
```bash
cd server
cargo build
# for development, use `cargo check` instead)
./db-init.sh
```
#### Build the frontend (Typescript)
```
cd ui
yarn
yarn build
```
Or run the commands manually:
#### Setup postgresql
```
sudo apt install postgresql
sudo systemctl start postgresql
# initialize 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
```bash
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
# or execute server/db-init.sh
```
#### Run a local development instance
```
# run each of these in a seperate terminal
cd server && cargo run
ui & yarn start
```
#### Running
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.
To speed up incremental builds, you can add the following to `~/.cargo/config`:
```bash
git clone https://github.com/LemmyNet/lemmy
cd lemmy
./install.sh
# For live coding, where both the front and back end, automagically reload on any save, do:
# cd ui && yarn start
# cd server && cargo watch -x run
```
[target.x86_64-unknown-linux-gnu]
rustflags = ["-Clink-arg=-fuse-ld=lld"]
```
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).

View file

@ -49,7 +49,5 @@
## Member List / Contact Info
General Contact [@LemmyDev Mastodon](https://mastodon.social/@LemmyDev)
- [Dessalines](https://dev.lemmy.ml/u/dessalines)
- [Nutomic](https://dev.lemmy.ml/u/nutomic)
- [AgreeableLandscape](https://dev.lemmy.ml/u/AgreeableLandscape)
- [fruechtchen](https://dev.lemmy.ml/u/fruechtchen)
- Dessalines [Matrix](https://matrix.to/#/@happydooby:matrix.org)
- Nutomic [Matrix](https://matrix.to/#/@nutomic:matrix.org), [Mastodon](https://radical.town/@felix)

401
server/Cargo.lock generated vendored
View file

@ -30,7 +30,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
"thiserror 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
"thiserror 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -364,6 +364,14 @@ name = "adler32"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "aho-corasick"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "aho-corasick"
version = "0.7.10"
@ -408,19 +416,6 @@ dependencies = [
"syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "attohttpc"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"rustls 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
"url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)",
"webpki-roots 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "atty"
version = "0.2.14"
@ -681,8 +676,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"nom 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rust-ini 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
"serde-hjson 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
"yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -731,6 +730,35 @@ dependencies = [
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "curl"
version = "0.4.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"curl-sys 0.4.30+curl-7.69.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.55 (registry+https://github.com/rust-lang/crates.io-index)",
"schannel 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
"socket2 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "curl-sys"
version = "0.4.30+curl-7.69.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
"libnghttp2-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.55 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
"vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "darling"
version = "0.10.2"
@ -763,6 +791,23 @@ dependencies = [
"syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "db"
version = "0.1.0"
dependencies = [
"bcrypt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"diesel 1.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"diesel_migrations 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonwebtoken 7.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"schema 0.1.0",
"serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
"sha2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"strum 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
"strum_macros 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
"utils 0.1.0",
]
[[package]]
name = "derive_builder"
version = "0.9.0"
@ -836,11 +881,27 @@ dependencies = [
"generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "docopt"
version = "0.6.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
"strsim 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "dotenv"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "dtoa"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "dtoa"
version = "0.4.5"
@ -1181,6 +1242,17 @@ dependencies = [
"libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "hjson"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"docopt 0.6.86 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)",
"serde-hjson 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "hostname"
version = "0.1.5"
@ -1270,6 +1342,33 @@ dependencies = [
"winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "isahc"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"curl 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)",
"curl-sys 0.4.30+curl-7.69.1 (registry+https://github.com/rust-lang/crates.io-index)",
"encoding_rs 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-io 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"sluice 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "itoa"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "itoa"
version = "0.4.5"
@ -1310,6 +1409,11 @@ name = "language-tags"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lazy_static"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lazy_static"
version = "1.4.0"
@ -1325,33 +1429,31 @@ dependencies = [
"actix-rt 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"actix-web 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"actix-web-actors 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"attohttpc 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bcrypt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"comrak 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"config 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"diesel 1.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"diesel_migrations 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"db 0.1.0",
"dotenv 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"failure 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonwebtoken 7.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"isahc 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lettre 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
"lettre_email 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"r2d2 0.8.8 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"rss 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
"sha2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"strum 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
"strum_macros 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
"utils 0.1.0",
]
[[package]]
@ -1401,6 +1503,26 @@ name = "libc"
version = "0.2.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libnghttp2-sys"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "libz-sys"
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
"vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "linked-hash-map"
version = "0.3.0"
@ -1459,6 +1581,14 @@ name = "maybe-uninit"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memchr"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "memchr"
version = "2.3.3"
@ -1554,10 +1684,10 @@ dependencies = [
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl 0.10.29 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.58 (registry+https://github.com/rust-lang/crates.io-index)",
"schannel 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
"security-framework 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"security-framework-sys 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.55 (registry+https://github.com/rust-lang/crates.io-index)",
"schannel 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
"security-framework 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"security-framework-sys 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1654,7 +1784,7 @@ dependencies = [
"foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.58 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.55 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -1664,7 +1794,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "openssl-sys"
version = "0.9.58"
version = "0.9.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2004,6 +2134,18 @@ name = "redox_syscall"
version = "0.1.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "regex"
version = "0.1.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex"
version = "1.3.7"
@ -2015,6 +2157,11 @@ dependencies = [
"thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex-syntax"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "regex-syntax"
version = "0.6.17"
@ -2060,11 +2207,21 @@ dependencies = [
"quick-xml 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rust-ini"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc-demangle"
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc-serialize"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc_version"
version = "0.2.3"
@ -2073,18 +2230,6 @@ dependencies = [
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustls"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"ring 0.16.12 (registry+https://github.com/rust-lang/crates.io-index)",
"sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ryu"
version = "1.0.3"
@ -2097,7 +2242,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "schannel"
version = "0.1.19"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2112,35 +2257,33 @@ dependencies = [
"parking_lot 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "schema"
version = "0.1.0"
dependencies = [
"diesel 1.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "sct"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ring 0.16.12 (registry+https://github.com/rust-lang/crates.io-index)",
"untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "security-framework"
version = "0.4.4"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
"security-framework-sys 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"security-framework-sys 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "security-framework-sys"
version = "0.4.3"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2173,6 +2316,18 @@ dependencies = [
"serde_derive 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde-hjson"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde-hjson"
version = "0.9.1"
@ -2195,11 +2350,23 @@ dependencies = [
"syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_json"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"dtoa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_json"
version = "1.0.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"ryu 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2275,6 +2442,17 @@ name = "slab"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "sluice"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"futures-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-io 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "smallvec"
version = "1.3.0"
@ -2301,6 +2479,11 @@ name = "static_assertions"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "strsim"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "strsim"
version = "0.8.0"
@ -2379,15 +2562,15 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.19"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"thiserror-impl 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
"thiserror-impl 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "thiserror-impl"
version = "1.0.19"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2395,6 +2578,23 @@ dependencies = [
"syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "thread-id"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "thread_local"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "thread_local"
version = "1.0.1"
@ -2467,6 +2667,14 @@ dependencies = [
"tokio 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "toml"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "trust-dns-proto"
version = "0.18.0-alpha.2"
@ -2592,6 +2800,24 @@ dependencies = [
"percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "utf8-ranges"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "utils"
version = "0.1.0"
dependencies = [
"chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"config 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"failure 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"hjson 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "uuid"
version = "0.7.4"
@ -2711,23 +2937,6 @@ dependencies = [
"wasm-bindgen 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "webpki"
version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ring 0.16.12 (registry+https://github.com/rust-lang/crates.io-index)",
"untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "webpki-roots"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "widestring"
version = "0.4.0"
@ -2795,6 +3004,14 @@ dependencies = [
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "yaml-rust"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[metadata]
"checksum activitypub 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d538a21b137ec0f63cc579ef4afa4ab13aa85b4f8af15a033683edd97c50718d"
"checksum activitystreams-derive 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "65608fdeae5eb05485d5b71a3d2242d76b2b7413608c196d47eb4dff3eed7b85"
@ -2819,13 +3036,13 @@ dependencies = [
"checksum actix-web-codegen 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4f00371942083469785f7e28c540164af1913ee7c96a4534acb9cea92c39f057"
"checksum actix_derive 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b95aceadaf327f18f0df5962fedc1bde2f870566a0b9f65c89508a3b1f79334c"
"checksum adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2"
"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66"
"checksum aho-corasick 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada"
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
"checksum arc-swap 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d663a8e9a99154b5fb793032533f6328da35e23aac63d5c152279aa8ba356825"
"checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9"
"checksum ascii_utils 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "71938f30533e4d95a6d17aa530939da3842c2ab6f4f84b9dae68447e4129f74a"
"checksum async-trait 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "da71fef07bc806586090247e971229289f64c210a278ee5ae419314eb386b31d"
"checksum attohttpc 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "93610ce1c035e8a273fe56a19852e42798f3c019ca2726e52d2971197f116525"
"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
@ -2863,6 +3080,8 @@ dependencies = [
"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
"checksum crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cced8691919c02aac3cb0a1bc2e9b73d89e832bf9a06fc579d4e71b68a2da061"
"checksum crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
"checksum curl 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)" = "eda1c0c03cacf3365d84818a40293f0e3f3953db8759c9c565a3b434edf0b52e"
"checksum curl-sys 0.4.30+curl-7.69.1 (registry+https://github.com/rust-lang/crates.io-index)" = "923b38e423a8f47a4058e96f2a1fa2865a6231097ee860debd678d244277d50c"
"checksum darling 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858"
"checksum darling_core 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b"
"checksum darling_macro 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72"
@ -2873,7 +3092,9 @@ dependencies = [
"checksum diesel_derives 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3"
"checksum diesel_migrations 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3cde8413353dc7f5d72fa8ce0b99a560a359d2c5ef1e5817ca731cd9008f4c"
"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
"checksum docopt 0.6.86 (registry+https://github.com/rust-lang/crates.io-index)" = "4a7ef30445607f6fc8720f0a0a2c7442284b629cf0d049286860fae23e71c4d9"
"checksum dotenv 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
"checksum dtoa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0dd841b58510c9618291ffa448da2e4e0f699d984d436122372f446dae62263d"
"checksum dtoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3"
"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
"checksum email 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "91549a51bb0241165f13d57fc4c72cef063b4088fb078b019ecbf464a45f22e4"
@ -2914,6 +3135,7 @@ dependencies = [
"checksum h2 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "377038bf3c89d18d6ca1431e7a5027194fbd724ca10592b9487ede5e8e144f42"
"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
"checksum hermit-abi 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8a0d737e0f947a1864e93d33fdef4af8445a00d1ed8dc0c8ddb73139ea6abf15"
"checksum hjson 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0849d73a64ec77d1c8354aff489cf31943c4b4d3716de1eabfba572c70fde530"
"checksum hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e"
"checksum hostname 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867"
"checksum htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163"
@ -2925,16 +3147,21 @@ dependencies = [
"checksum indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292"
"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
"checksum ipconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa79fa216fbe60834a9c0737d7fcd30425b32d1c58854663e24d4c4b328ed83f"
"checksum isahc 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "50bdb3bdcbf6d534daaad1a686eda0d0dc1946818fa71e3edd3124d001adfdc2"
"checksum itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae3088ea4baeceb0284ee9eea42f591226e6beaecf65373e41b38d95a1b8e7a1"
"checksum itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e"
"checksum js-sys 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)" = "6a27d435371a2fa5b6d2b028a74bbdb1234f308da363226a2854ca3ff8ba7055"
"checksum jsonwebtoken 7.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d11f9e80a85927748a334df8e4f6782a04033517bb28f3863a563daad882da7f"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
"checksum lettre 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bf43f3202a879fbdab4ecafec3349b0139f81d31c626246d53bcbb546253ffaa"
"checksum lettre_email 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fd02480f8dcf48798e62113974d6ccca2129a51d241fa20f1ea349c8a42559d5"
"checksum lexical-core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d7043aa5c05dd34fb73b47acb8c3708eac428de4545ea3682ed2f11293ebd890"
"checksum libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)" = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005"
"checksum libnghttp2-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b359f5ec8106bc297694c9a562ace312be2cfd17a5fc68dc12249845aa144b11"
"checksum libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe"
"checksum linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d262045c5b87c0861b3f004610afd0e2c851e2908d08b6c870cbb9d5f494ecd"
"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"
"checksum lock_api 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75"
@ -2944,6 +3171,7 @@ dependencies = [
"checksum match_cfg 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
"checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
"checksum memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
"checksum migrations_internals 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2b4fc84e4af020b837029e017966f86a1c2d5e83e64b589963d5047525995860"
"checksum migrations_macros 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9753f12909fd8d923f75ae5c3258cae1ed3c8ec052e1b38c93c21a6d157f789c"
@ -2966,7 +3194,7 @@ dependencies = [
"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
"checksum openssl 0.10.29 (registry+https://github.com/rust-lang/crates.io-index)" = "cee6d85f4cb4c4f59a6a85d5b68a233d280c82e29e822913b9c8b129fbf20bdd"
"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
"checksum openssl-sys 0.9.58 (registry+https://github.com/rust-lang/crates.io-index)" = "a842db4709b604f0fe5d1170ae3565899be2ad3d9cbc72dedc789ac0511f78de"
"checksum openssl-sys 0.9.55 (registry+https://github.com/rust-lang/crates.io-index)" = "7717097d810a0f2e2323f9e5d11e71608355e24828410b55b9d4f18aa5f9a5d8"
"checksum parking_lot 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e"
"checksum parking_lot_core 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e136c1904604defe99ce5fd71a28d473fa60a12255d511aa78a9ddf11237aeb"
"checksum pem 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a1581760c757a756a41f0ee3ff01256227bdf64cb752839779b95ffb01c59793"
@ -3006,29 +3234,33 @@ dependencies = [
"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
"checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f"
"checksum regex 1.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a6020f034922e3194c711b82a627453881bc4682166cabb07134a10c26ba7692"
"checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957"
"checksum regex-syntax 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae"
"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
"checksum resolv-conf 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "11834e137f3b14e309437a8276714eed3a80d1ef894869e510f2c0c0b98b9f4a"
"checksum ring 0.16.12 (registry+https://github.com/rust-lang/crates.io-index)" = "1ba5a8ec64ee89a76c98c549af81ff14813df09c3e6dc4766c3856da48597a0c"
"checksum rss 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "99979205510c60f80a119dedbabd0b8426517384edf205322f8bcd51796bcef9"
"checksum rust-ini 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e52c148ef37f8c375d49d5a73aa70713125b7f19095948a923f80afdeb22ec2"
"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
"checksum rustls 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d4a31f5d68413404705d6982529b0e11a9aacd4839d1d6222ee3b8cb4015e1"
"checksum ryu 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76"
"checksum safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072"
"checksum schannel 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75"
"checksum schannel 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "039c25b130bd8c1321ee2d7de7fde2659fa9c2744e4bb29711cfc852ea53cd19"
"checksum scheduled-thread-pool 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0988d7fdf88d5e5fcf5923a0f1e8ab345f3e98ab4bc6bc45a2d5ff7f7458fbf6"
"checksum scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
"checksum sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c"
"checksum security-framework 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "64808902d7d99f78eaddd2b4e2509713babc3dc3c85ad6f4c447680f3c01e535"
"checksum security-framework-sys 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "17bf11d99252f512695eb468de5516e5cf75455521e69dfe343f3b74e4748405"
"checksum security-framework 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "572dfa3a0785509e7a44b5b4bebcf94d41ba34e9ed9eb9df722545c3b3c4144a"
"checksum security-framework-sys 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8ddb15a5fec93b7021b8a9e96009c5d8d51c15673569f7c0f6b7204e5b7b404f"
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
"checksum serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8"
"checksum serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)" = "36df6ac6412072f67cf767ebbde4133a5b2e88e76dc6187fa7104cd16f783399"
"checksum serde-hjson 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0b833c5ad67d52ced5f5938b2980f32a9c1c5ef047f0b4fb3127e7a423c76153"
"checksum serde-hjson 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6a3a4e0ea8a88553209f6cc6cfe8724ecad22e1acf372793c27d995290fe74f8"
"checksum serde_derive 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)" = "9e549e3abf4fb8621bd1609f11dfc9f5e50320802273b12f3811a67e6716ea6c"
"checksum serde_json 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)" = "67f7d2e9edc3523a9c8ec8cd6ec481b3a27810aafee3e625d311febd3e656b4c"
"checksum serde_json 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)" = "a7894c8ed05b7a3a279aeb79025fdec1d3158080b75b98a08faf2806bb799edd"
"checksum serde_test 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "110b3dbdf8607ec493c22d5d947753282f3bae73c0f56d322af1e8c78e4c23d5"
"checksum serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97"
@ -3038,10 +3270,12 @@ dependencies = [
"checksum signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41"
"checksum simple_asn1 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2b25ecba7165254f0c97d6c22a64b1122a03634b18d20a34daf21e18f892e618"
"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
"checksum sluice 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fed13b7cb46f13a15db2c4740f087a848acc8b31af89f95844d40137451f89b1"
"checksum smallvec 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05720e22615919e4734f6a99ceae50d00226c3c5aca406e102ebc33298214e0a"
"checksum socket2 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918"
"checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
"checksum static_assertions 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7f3eb36b47e512f8f1c9e3d10c2c1965bc992bd9cdb024fa581e2194501c83d3"
"checksum strsim 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "67f84c44fbb2f91db7fef94554e6b2ac05909c9c0b0bc23bb98d3a1aebfe7f7c"
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
"checksum strsim 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
"checksum strum 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "57bd81eb48f4c437cadc685403cad539345bf703d78e63707418431cecd4522b"
@ -3051,14 +3285,17 @@ dependencies = [
"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
"checksum termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
"checksum thiserror 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "b13f926965ad00595dd129fa12823b04bbf866e9085ab0a5f2b05b850fbfc344"
"checksum thiserror-impl 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "893582086c2f98cde18f906265a65b5030a074b1046c674ae898be6519a7f479"
"checksum thiserror 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "54b3d3d2ff68104100ab257bb6bb0cb26c901abe4bd4ba15961f3bf867924012"
"checksum thiserror-impl 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972988113b7715266f91250ddb98070d033c62a011fa0fcc57434a649310dd"
"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
"checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5"
"checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
"checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865"
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
"checksum tokio 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "05c1d570eb1a36f0345a5ce9c6c6e665b70b73d11236912c0b477616aeec47b1"
"checksum tokio-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "571da51182ec208780505a32528fc5512a8fe1443ab960b3f2f3ef093cd16930"
"checksum tokio-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499"
"checksum toml 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a"
"checksum trust-dns-proto 0.18.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2a7f3a2ab8a919f5eca52a468866a67ed7d3efa265d48a652a9a3452272b413f"
"checksum trust-dns-resolver 0.18.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6f90b1502b226f8b2514c6d5b37bafa8c200d7ca4102d57dc36ee0f3b7a04a2f"
"checksum twoway 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6b40075910de3a912adbd80b5d8bad6ad10a23eeb1f5bf9d4006839e899ba5bc"
@ -3075,6 +3312,7 @@ dependencies = [
"checksum unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
"checksum untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60369ef7a31de49bcb3f6ca728d4ba7300d9a1658f94c727d4cab8c8d9f4aece"
"checksum url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb"
"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f"
"checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a"
"checksum v_escape 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "660b101c07b5d0863deb9e7fb3138777e858d6d2a79f9e6049a27d1cc77c6da6"
"checksum v_escape_derive 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c2ca2a14bc3fc5b64d188b087a7d3a927df87b152e941ccfbc66672e20c467ae"
@ -3090,8 +3328,6 @@ dependencies = [
"checksum wasm-bindgen-macro-support 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d68a5b36eef1be7868f668632863292e37739656a80fc4b9acec7b0bd35a4931"
"checksum wasm-bindgen-shared 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "daf76fe7d25ac79748a37538b7daeed1c7a6867c92d3245c12c6222e4a20d639"
"checksum web-sys 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)" = "2d6f51648d8c56c366144378a33290049eafdd784071077f6fe37dae64c1c4cb"
"checksum webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1f50e1972865d6b1adb54167d1c8ed48606004c2c9d0ea5f1eeb34d95e863ef"
"checksum webpki-roots 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8eff4b7516a57307f9349c64bf34caa34b940b66fed4b2fb3136cb7386e5739"
"checksum widestring 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effc0e4ff8085673ea7b9b2e3c73f6bd4d118810c9009ed8f1e16bd96c331db6"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
@ -3102,3 +3338,4 @@ dependencies = [
"checksum winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9"
"checksum winutil 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7daf138b6b14196e3830a588acf1e86966c694d3e8fb026fb105b8b5dca07e6e"
"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
"checksum yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d"

50
server/Cargo.toml vendored
View file

@ -1,43 +1,7 @@
[package]
name = "lemmy_server"
version = "0.0.1"
authors = ["Dessalines <tyhou13@gmx.com>"]
edition = "2018"
[profile.release]
lto = true
[dependencies]
diesel = { version = "1.4.2", features = ["postgres","chrono", "r2d2", "64-column-tables"] }
diesel_migrations = "1.4.0"
dotenv = "0.15.0"
bcrypt = "0.7.0"
activitypub = "0.2.0"
chrono = "0.4.7"
failure = "0.1.8"
serde_json = "1.0.52"
serde = "1.0.105"
actix = "0.9.0"
actix-web = "2.0.0"
actix-files = "0.2.1"
actix-web-actors = "2.0.0"
actix-rt = "1.1.1"
log = "0.4.0"
env_logger = "0.7.1"
rand = "0.7.3"
strum = "0.18.0"
strum_macros = "0.18.0"
jsonwebtoken = "7.0.1"
regex = "1.3.5"
lazy_static = "1.3.0"
lettre = "0.9.3"
lettre_email = "0.9.4"
sha2 = "0.8.1"
rss = "1.9.0"
htmlescape = "0.3.1"
config = {version = "0.10.1", default-features = false, features = ["hjson"] }
percent-encoding = "2.1.0"
attohttpc = { version = "0.14.0", default-features = false, features = ["tls-rustls"] }
comrak = "0.7"
tokio = "0.2.20"
futures = "0.3.4"
[workspace]
members = [
"lemmy_server",
"db",
"schema",
"utils",
]

20
server/db/Cargo.toml vendored Normal file
View file

@ -0,0 +1,20 @@
[package]
name = "db"
version = "0.1.0"
authors = ["Felix Ableitner <me@nutomic.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
utils = { path = "../utils" }
schema = { path = "../schema" }
diesel = { version = "1.4.2", features = ["postgres","chrono", "r2d2", "64-column-tables"] }
diesel_migrations = "1.4.0"
chrono = { version = "0.4.7", features = ["serde"] }
serde = { version = "1.0.105", features = ["derive"] }
strum = "0.18.0"
strum_macros = "0.18.0"
sha2 = "0.8.1"
bcrypt = "0.7.0"
jsonwebtoken = "7.0.1"

View file

@ -1,6 +1,6 @@
use super::*;
use crate::schema::category;
use crate::schema::category::dsl::*;
use schema::schema::category;
use schema::schema::category::dsl::*;
#[derive(Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize)]
#[table_name = "category"]

View file

@ -1,6 +1,6 @@
use super::post::Post;
use super::*;
use crate::schema::{comment, comment_like, comment_saved};
use schema::schema::{comment, comment_like, comment_saved};
// WITH RECURSIVE MyTree AS (
// SELECT * FROM comment WHERE parent_id IS NULL
@ -40,17 +40,17 @@ pub struct CommentForm {
impl Crud<CommentForm> for Comment {
fn read(conn: &PgConnection, comment_id: i32) -> Result<Self, Error> {
use crate::schema::comment::dsl::*;
use schema::schema::comment::dsl::*;
comment.find(comment_id).first::<Self>(conn)
}
fn delete(conn: &PgConnection, comment_id: i32) -> Result<usize, Error> {
use crate::schema::comment::dsl::*;
use schema::schema::comment::dsl::*;
diesel::delete(comment.find(comment_id)).execute(conn)
}
fn create(conn: &PgConnection, comment_form: &CommentForm) -> Result<Self, Error> {
use crate::schema::comment::dsl::*;
use schema::schema::comment::dsl::*;
insert_into(comment)
.values(comment_form)
.get_result::<Self>(conn)
@ -61,7 +61,7 @@ impl Crud<CommentForm> for Comment {
comment_id: i32,
comment_form: &CommentForm,
) -> Result<Self, Error> {
use crate::schema::comment::dsl::*;
use schema::schema::comment::dsl::*;
diesel::update(comment.find(comment_id))
.set(comment_form)
.get_result::<Self>(conn)
@ -91,20 +91,20 @@ pub struct CommentLikeForm {
impl Likeable<CommentLikeForm> for CommentLike {
fn read(conn: &PgConnection, comment_id_from: i32) -> Result<Vec<Self>, Error> {
use crate::schema::comment_like::dsl::*;
use schema::schema::comment_like::dsl::*;
comment_like
.filter(comment_id.eq(comment_id_from))
.load::<Self>(conn)
}
fn like(conn: &PgConnection, comment_like_form: &CommentLikeForm) -> Result<Self, Error> {
use crate::schema::comment_like::dsl::*;
use schema::schema::comment_like::dsl::*;
insert_into(comment_like)
.values(comment_like_form)
.get_result::<Self>(conn)
}
fn remove(conn: &PgConnection, comment_like_form: &CommentLikeForm) -> Result<usize, Error> {
use crate::schema::comment_like::dsl::*;
use schema::schema::comment_like::dsl::*;
diesel::delete(
comment_like
.filter(comment_id.eq(comment_like_form.comment_id))
@ -116,7 +116,7 @@ impl Likeable<CommentLikeForm> for CommentLike {
impl CommentLike {
pub fn from_post(conn: &PgConnection, post_id_from: i32) -> Result<Vec<Self>, Error> {
use crate::schema::comment_like::dsl::*;
use schema::schema::comment_like::dsl::*;
comment_like
.filter(post_id.eq(post_id_from))
.load::<Self>(conn)
@ -142,13 +142,13 @@ pub struct CommentSavedForm {
impl Saveable<CommentSavedForm> for CommentSaved {
fn save(conn: &PgConnection, comment_saved_form: &CommentSavedForm) -> Result<Self, Error> {
use crate::schema::comment_saved::dsl::*;
use schema::schema::comment_saved::dsl::*;
insert_into(comment_saved)
.values(comment_saved_form)
.get_result::<Self>(conn)
}
fn unsave(conn: &PgConnection, comment_saved_form: &CommentSavedForm) -> Result<usize, Error> {
use crate::schema::comment_saved::dsl::*;
use schema::schema::comment_saved::dsl::*;
diesel::delete(
comment_saved
.filter(comment_id.eq(comment_saved_form.comment_id))

View file

@ -1,5 +1,6 @@
use super::*;
use crate::schema::{community, community_follower, community_moderator, community_user_ban};
use schema::schema::{community, community_follower, community_moderator, community_user_ban};
use utils::settings::Settings;
#[derive(Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize)]
#[table_name = "community"]
@ -33,17 +34,17 @@ pub struct CommunityForm {
impl Crud<CommunityForm> for Community {
fn read(conn: &PgConnection, community_id: i32) -> Result<Self, Error> {
use crate::schema::community::dsl::*;
use schema::schema::community::dsl::*;
community.find(community_id).first::<Self>(conn)
}
fn delete(conn: &PgConnection, community_id: i32) -> Result<usize, Error> {
use crate::schema::community::dsl::*;
use schema::schema::community::dsl::*;
diesel::delete(community.find(community_id)).execute(conn)
}
fn create(conn: &PgConnection, new_community: &CommunityForm) -> Result<Self, Error> {
use crate::schema::community::dsl::*;
use schema::schema::community::dsl::*;
insert_into(community)
.values(new_community)
.get_result::<Self>(conn)
@ -54,7 +55,7 @@ impl Crud<CommunityForm> for Community {
community_id: i32,
new_community: &CommunityForm,
) -> Result<Self, Error> {
use crate::schema::community::dsl::*;
use schema::schema::community::dsl::*;
diesel::update(community.find(community_id))
.set(new_community)
.get_result::<Self>(conn)
@ -63,7 +64,7 @@ impl Crud<CommunityForm> for Community {
impl Community {
pub fn read_from_name(conn: &PgConnection, community_name: String) -> Result<Self, Error> {
use crate::schema::community::dsl::*;
use schema::schema::community::dsl::*;
community
.filter(name.eq(community_name))
.first::<Self>(conn)
@ -96,7 +97,7 @@ impl Joinable<CommunityModeratorForm> for CommunityModerator {
conn: &PgConnection,
community_user_form: &CommunityModeratorForm,
) -> Result<Self, Error> {
use crate::schema::community_moderator::dsl::*;
use schema::schema::community_moderator::dsl::*;
insert_into(community_moderator)
.values(community_user_form)
.get_result::<Self>(conn)
@ -106,7 +107,7 @@ impl Joinable<CommunityModeratorForm> for CommunityModerator {
conn: &PgConnection,
community_user_form: &CommunityModeratorForm,
) -> Result<usize, Error> {
use crate::schema::community_moderator::dsl::*;
use schema::schema::community_moderator::dsl::*;
diesel::delete(
community_moderator
.filter(community_id.eq(community_user_form.community_id))
@ -118,7 +119,7 @@ impl Joinable<CommunityModeratorForm> for CommunityModerator {
impl CommunityModerator {
pub fn delete_for_community(conn: &PgConnection, for_community_id: i32) -> Result<usize, Error> {
use crate::schema::community_moderator::dsl::*;
use schema::schema::community_moderator::dsl::*;
diesel::delete(community_moderator.filter(community_id.eq(for_community_id))).execute(conn)
}
}
@ -145,7 +146,7 @@ impl Bannable<CommunityUserBanForm> for CommunityUserBan {
conn: &PgConnection,
community_user_ban_form: &CommunityUserBanForm,
) -> Result<Self, Error> {
use crate::schema::community_user_ban::dsl::*;
use schema::schema::community_user_ban::dsl::*;
insert_into(community_user_ban)
.values(community_user_ban_form)
.get_result::<Self>(conn)
@ -155,7 +156,7 @@ impl Bannable<CommunityUserBanForm> for CommunityUserBan {
conn: &PgConnection,
community_user_ban_form: &CommunityUserBanForm,
) -> Result<usize, Error> {
use crate::schema::community_user_ban::dsl::*;
use schema::schema::community_user_ban::dsl::*;
diesel::delete(
community_user_ban
.filter(community_id.eq(community_user_ban_form.community_id))
@ -187,7 +188,7 @@ impl Followable<CommunityFollowerForm> for CommunityFollower {
conn: &PgConnection,
community_follower_form: &CommunityFollowerForm,
) -> Result<Self, Error> {
use crate::schema::community_follower::dsl::*;
use schema::schema::community_follower::dsl::*;
insert_into(community_follower)
.values(community_follower_form)
.get_result::<Self>(conn)
@ -196,7 +197,7 @@ impl Followable<CommunityFollowerForm> for CommunityFollower {
conn: &PgConnection,
community_follower_form: &CommunityFollowerForm,
) -> Result<usize, Error> {
use crate::schema::community_follower::dsl::*;
use schema::schema::community_follower::dsl::*;
diesel::delete(
community_follower
.filter(community_id.eq(&community_follower_form.community_id))

View file

@ -1,4 +1,11 @@
use crate::settings::Settings;
#[macro_use]
pub extern crate diesel;
#[macro_use]
pub extern crate strum_macros;
#[macro_use]
extern crate diesel_migrations;
use utils::settings::Settings;
use diesel::dsl::*;
use diesel::result::Error;
use diesel::*;
@ -23,6 +30,10 @@ pub mod user_mention;
pub mod user_mention_view;
pub mod user_view;
// TODO: need to execute this
embed_migrations!();
//embedded_migrations::run(&conn).unwrap();
pub trait Crud<T> {
fn create(conn: &PgConnection, form: &T) -> Result<Self, Error>
where

View file

@ -1,5 +1,5 @@
use super::*;
use crate::schema::{
use schema::schema::{
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,
};
@ -26,24 +26,24 @@ pub struct ModRemovePostForm {
impl Crud<ModRemovePostForm> for ModRemovePost {
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
use crate::schema::mod_remove_post::dsl::*;
use schema::schema::mod_remove_post::dsl::*;
mod_remove_post.find(from_id).first::<Self>(conn)
}
fn delete(conn: &PgConnection, from_id: i32) -> Result<usize, Error> {
use crate::schema::mod_remove_post::dsl::*;
use schema::schema::mod_remove_post::dsl::*;
diesel::delete(mod_remove_post.find(from_id)).execute(conn)
}
fn create(conn: &PgConnection, form: &ModRemovePostForm) -> Result<Self, Error> {
use crate::schema::mod_remove_post::dsl::*;
use schema::schema::mod_remove_post::dsl::*;
insert_into(mod_remove_post)
.values(form)
.get_result::<Self>(conn)
}
fn update(conn: &PgConnection, from_id: i32, form: &ModRemovePostForm) -> Result<Self, Error> {
use crate::schema::mod_remove_post::dsl::*;
use schema::schema::mod_remove_post::dsl::*;
diesel::update(mod_remove_post.find(from_id))
.set(form)
.get_result::<Self>(conn)
@ -70,24 +70,24 @@ pub struct ModLockPostForm {
impl Crud<ModLockPostForm> for ModLockPost {
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
use crate::schema::mod_lock_post::dsl::*;
use schema::schema::mod_lock_post::dsl::*;
mod_lock_post.find(from_id).first::<Self>(conn)
}
fn delete(conn: &PgConnection, from_id: i32) -> Result<usize, Error> {
use crate::schema::mod_lock_post::dsl::*;
use schema::schema::mod_lock_post::dsl::*;
diesel::delete(mod_lock_post.find(from_id)).execute(conn)
}
fn create(conn: &PgConnection, form: &ModLockPostForm) -> Result<Self, Error> {
use crate::schema::mod_lock_post::dsl::*;
use schema::schema::mod_lock_post::dsl::*;
insert_into(mod_lock_post)
.values(form)
.get_result::<Self>(conn)
}
fn update(conn: &PgConnection, from_id: i32, form: &ModLockPostForm) -> Result<Self, Error> {
use crate::schema::mod_lock_post::dsl::*;
use schema::schema::mod_lock_post::dsl::*;
diesel::update(mod_lock_post.find(from_id))
.set(form)
.get_result::<Self>(conn)
@ -114,24 +114,24 @@ pub struct ModStickyPostForm {
impl Crud<ModStickyPostForm> for ModStickyPost {
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
use crate::schema::mod_sticky_post::dsl::*;
use schema::schema::mod_sticky_post::dsl::*;
mod_sticky_post.find(from_id).first::<Self>(conn)
}
fn delete(conn: &PgConnection, from_id: i32) -> Result<usize, Error> {
use crate::schema::mod_sticky_post::dsl::*;
use schema::schema::mod_sticky_post::dsl::*;
diesel::delete(mod_sticky_post.find(from_id)).execute(conn)
}
fn create(conn: &PgConnection, form: &ModStickyPostForm) -> Result<Self, Error> {
use crate::schema::mod_sticky_post::dsl::*;
use schema::schema::mod_sticky_post::dsl::*;
insert_into(mod_sticky_post)
.values(form)
.get_result::<Self>(conn)
}
fn update(conn: &PgConnection, from_id: i32, form: &ModStickyPostForm) -> Result<Self, Error> {
use crate::schema::mod_sticky_post::dsl::*;
use schema::schema::mod_sticky_post::dsl::*;
diesel::update(mod_sticky_post.find(from_id))
.set(form)
.get_result::<Self>(conn)
@ -160,24 +160,24 @@ pub struct ModRemoveCommentForm {
impl Crud<ModRemoveCommentForm> for ModRemoveComment {
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
use crate::schema::mod_remove_comment::dsl::*;
use schema::schema::mod_remove_comment::dsl::*;
mod_remove_comment.find(from_id).first::<Self>(conn)
}
fn delete(conn: &PgConnection, from_id: i32) -> Result<usize, Error> {
use crate::schema::mod_remove_comment::dsl::*;
use schema::schema::mod_remove_comment::dsl::*;
diesel::delete(mod_remove_comment.find(from_id)).execute(conn)
}
fn create(conn: &PgConnection, form: &ModRemoveCommentForm) -> Result<Self, Error> {
use crate::schema::mod_remove_comment::dsl::*;
use schema::schema::mod_remove_comment::dsl::*;
insert_into(mod_remove_comment)
.values(form)
.get_result::<Self>(conn)
}
fn update(conn: &PgConnection, from_id: i32, form: &ModRemoveCommentForm) -> Result<Self, Error> {
use crate::schema::mod_remove_comment::dsl::*;
use schema::schema::mod_remove_comment::dsl::*;
diesel::update(mod_remove_comment.find(from_id))
.set(form)
.get_result::<Self>(conn)
@ -208,17 +208,17 @@ pub struct ModRemoveCommunityForm {
impl Crud<ModRemoveCommunityForm> for ModRemoveCommunity {
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
use crate::schema::mod_remove_community::dsl::*;
use schema::schema::mod_remove_community::dsl::*;
mod_remove_community.find(from_id).first::<Self>(conn)
}
fn delete(conn: &PgConnection, from_id: i32) -> Result<usize, Error> {
use crate::schema::mod_remove_community::dsl::*;
use schema::schema::mod_remove_community::dsl::*;
diesel::delete(mod_remove_community.find(from_id)).execute(conn)
}
fn create(conn: &PgConnection, form: &ModRemoveCommunityForm) -> Result<Self, Error> {
use crate::schema::mod_remove_community::dsl::*;
use schema::schema::mod_remove_community::dsl::*;
insert_into(mod_remove_community)
.values(form)
.get_result::<Self>(conn)
@ -229,7 +229,7 @@ impl Crud<ModRemoveCommunityForm> for ModRemoveCommunity {
from_id: i32,
form: &ModRemoveCommunityForm,
) -> Result<Self, Error> {
use crate::schema::mod_remove_community::dsl::*;
use schema::schema::mod_remove_community::dsl::*;
diesel::update(mod_remove_community.find(from_id))
.set(form)
.get_result::<Self>(conn)
@ -262,17 +262,17 @@ pub struct ModBanFromCommunityForm {
impl Crud<ModBanFromCommunityForm> for ModBanFromCommunity {
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
use crate::schema::mod_ban_from_community::dsl::*;
use schema::schema::mod_ban_from_community::dsl::*;
mod_ban_from_community.find(from_id).first::<Self>(conn)
}
fn delete(conn: &PgConnection, from_id: i32) -> Result<usize, Error> {
use crate::schema::mod_ban_from_community::dsl::*;
use schema::schema::mod_ban_from_community::dsl::*;
diesel::delete(mod_ban_from_community.find(from_id)).execute(conn)
}
fn create(conn: &PgConnection, form: &ModBanFromCommunityForm) -> Result<Self, Error> {
use crate::schema::mod_ban_from_community::dsl::*;
use schema::schema::mod_ban_from_community::dsl::*;
insert_into(mod_ban_from_community)
.values(form)
.get_result::<Self>(conn)
@ -283,7 +283,7 @@ impl Crud<ModBanFromCommunityForm> for ModBanFromCommunity {
from_id: i32,
form: &ModBanFromCommunityForm,
) -> Result<Self, Error> {
use crate::schema::mod_ban_from_community::dsl::*;
use schema::schema::mod_ban_from_community::dsl::*;
diesel::update(mod_ban_from_community.find(from_id))
.set(form)
.get_result::<Self>(conn)
@ -314,22 +314,22 @@ pub struct ModBanForm {
impl Crud<ModBanForm> for ModBan {
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
use crate::schema::mod_ban::dsl::*;
use schema::schema::mod_ban::dsl::*;
mod_ban.find(from_id).first::<Self>(conn)
}
fn delete(conn: &PgConnection, from_id: i32) -> Result<usize, Error> {
use crate::schema::mod_ban::dsl::*;
use schema::schema::mod_ban::dsl::*;
diesel::delete(mod_ban.find(from_id)).execute(conn)
}
fn create(conn: &PgConnection, form: &ModBanForm) -> Result<Self, Error> {
use crate::schema::mod_ban::dsl::*;
use schema::schema::mod_ban::dsl::*;
insert_into(mod_ban).values(form).get_result::<Self>(conn)
}
fn update(conn: &PgConnection, from_id: i32, form: &ModBanForm) -> Result<Self, Error> {
use crate::schema::mod_ban::dsl::*;
use schema::schema::mod_ban::dsl::*;
diesel::update(mod_ban.find(from_id))
.set(form)
.get_result::<Self>(conn)
@ -358,24 +358,24 @@ pub struct ModAddCommunityForm {
impl Crud<ModAddCommunityForm> for ModAddCommunity {
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
use crate::schema::mod_add_community::dsl::*;
use schema::schema::mod_add_community::dsl::*;
mod_add_community.find(from_id).first::<Self>(conn)
}
fn delete(conn: &PgConnection, from_id: i32) -> Result<usize, Error> {
use crate::schema::mod_add_community::dsl::*;
use schema::schema::mod_add_community::dsl::*;
diesel::delete(mod_add_community.find(from_id)).execute(conn)
}
fn create(conn: &PgConnection, form: &ModAddCommunityForm) -> Result<Self, Error> {
use crate::schema::mod_add_community::dsl::*;
use schema::schema::mod_add_community::dsl::*;
insert_into(mod_add_community)
.values(form)
.get_result::<Self>(conn)
}
fn update(conn: &PgConnection, from_id: i32, form: &ModAddCommunityForm) -> Result<Self, Error> {
use crate::schema::mod_add_community::dsl::*;
use schema::schema::mod_add_community::dsl::*;
diesel::update(mod_add_community.find(from_id))
.set(form)
.get_result::<Self>(conn)
@ -402,22 +402,22 @@ pub struct ModAddForm {
impl Crud<ModAddForm> for ModAdd {
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
use crate::schema::mod_add::dsl::*;
use schema::schema::mod_add::dsl::*;
mod_add.find(from_id).first::<Self>(conn)
}
fn delete(conn: &PgConnection, from_id: i32) -> Result<usize, Error> {
use crate::schema::mod_add::dsl::*;
use schema::schema::mod_add::dsl::*;
diesel::delete(mod_add.find(from_id)).execute(conn)
}
fn create(conn: &PgConnection, form: &ModAddForm) -> Result<Self, Error> {
use crate::schema::mod_add::dsl::*;
use schema::schema::mod_add::dsl::*;
insert_into(mod_add).values(form).get_result::<Self>(conn)
}
fn update(conn: &PgConnection, from_id: i32, form: &ModAddForm) -> Result<Self, Error> {
use crate::schema::mod_add::dsl::*;
use schema::schema::mod_add::dsl::*;
diesel::update(mod_add.find(from_id))
.set(form)
.get_result::<Self>(conn)

View file

@ -1,6 +1,6 @@
use super::*;
use crate::schema::password_reset_request;
use crate::schema::password_reset_request::dsl::*;
use schema::schema::password_reset_request;
use schema::schema::password_reset_request::dsl::*;
use sha2::{Digest, Sha256};
#[derive(Queryable, Identifiable, PartialEq, Debug)]
@ -21,7 +21,7 @@ pub struct PasswordResetRequestForm {
impl Crud<PasswordResetRequestForm> for PasswordResetRequest {
fn read(conn: &PgConnection, password_reset_request_id: i32) -> Result<Self, Error> {
use crate::schema::password_reset_request::dsl::*;
use schema::schema::password_reset_request::dsl::*;
password_reset_request
.find(password_reset_request_id)
.first::<Self>(conn)

View file

@ -1,5 +1,5 @@
use super::*;
use crate::schema::{post, post_like, post_read, post_saved};
use schema::schema::{post, post_like, post_read, post_saved};
#[derive(Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize)]
#[table_name = "post"]
@ -45,22 +45,22 @@ pub struct PostForm {
impl Crud<PostForm> for Post {
fn read(conn: &PgConnection, post_id: i32) -> Result<Self, Error> {
use crate::schema::post::dsl::*;
use schema::schema::post::dsl::*;
post.find(post_id).first::<Self>(conn)
}
fn delete(conn: &PgConnection, post_id: i32) -> Result<usize, Error> {
use crate::schema::post::dsl::*;
use schema::schema::post::dsl::*;
diesel::delete(post.find(post_id)).execute(conn)
}
fn create(conn: &PgConnection, new_post: &PostForm) -> Result<Self, Error> {
use crate::schema::post::dsl::*;
use schema::schema::post::dsl::*;
insert_into(post).values(new_post).get_result::<Self>(conn)
}
fn update(conn: &PgConnection, post_id: i32, new_post: &PostForm) -> Result<Self, Error> {
use crate::schema::post::dsl::*;
use schema::schema::post::dsl::*;
diesel::update(post.find(post_id))
.set(new_post)
.get_result::<Self>(conn)
@ -88,19 +88,19 @@ pub struct PostLikeForm {
impl Likeable<PostLikeForm> for PostLike {
fn read(conn: &PgConnection, post_id_from: i32) -> Result<Vec<Self>, Error> {
use crate::schema::post_like::dsl::*;
use schema::schema::post_like::dsl::*;
post_like
.filter(post_id.eq(post_id_from))
.load::<Self>(conn)
}
fn like(conn: &PgConnection, post_like_form: &PostLikeForm) -> Result<Self, Error> {
use crate::schema::post_like::dsl::*;
use schema::schema::post_like::dsl::*;
insert_into(post_like)
.values(post_like_form)
.get_result::<Self>(conn)
}
fn remove(conn: &PgConnection, post_like_form: &PostLikeForm) -> Result<usize, Error> {
use crate::schema::post_like::dsl::*;
use schema::schema::post_like::dsl::*;
diesel::delete(
post_like
.filter(post_id.eq(post_like_form.post_id))
@ -129,13 +129,13 @@ pub struct PostSavedForm {
impl Saveable<PostSavedForm> for PostSaved {
fn save(conn: &PgConnection, post_saved_form: &PostSavedForm) -> Result<Self, Error> {
use crate::schema::post_saved::dsl::*;
use schema::schema::post_saved::dsl::*;
insert_into(post_saved)
.values(post_saved_form)
.get_result::<Self>(conn)
}
fn unsave(conn: &PgConnection, post_saved_form: &PostSavedForm) -> Result<usize, Error> {
use crate::schema::post_saved::dsl::*;
use schema::schema::post_saved::dsl::*;
diesel::delete(
post_saved
.filter(post_id.eq(post_saved_form.post_id))
@ -164,13 +164,13 @@ pub struct PostReadForm {
impl Readable<PostReadForm> for PostRead {
fn mark_as_read(conn: &PgConnection, post_read_form: &PostReadForm) -> Result<Self, Error> {
use crate::schema::post_read::dsl::*;
use schema::schema::post_read::dsl::*;
insert_into(post_read)
.values(post_read_form)
.get_result::<Self>(conn)
}
fn mark_as_unread(conn: &PgConnection, post_read_form: &PostReadForm) -> Result<usize, Error> {
use crate::schema::post_read::dsl::*;
use schema::schema::post_read::dsl::*;
diesel::delete(
post_read
.filter(post_id.eq(post_read_form.post_id))

View file

@ -1,5 +1,5 @@
use super::*;
use crate::schema::private_message;
use schema::schema::private_message;
#[derive(Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize)]
#[table_name = "private_message"]
@ -27,17 +27,17 @@ pub struct PrivateMessageForm {
impl Crud<PrivateMessageForm> for PrivateMessage {
fn read(conn: &PgConnection, private_message_id: i32) -> Result<Self, Error> {
use crate::schema::private_message::dsl::*;
use schema::schema::private_message::dsl::*;
private_message.find(private_message_id).first::<Self>(conn)
}
fn delete(conn: &PgConnection, private_message_id: i32) -> Result<usize, Error> {
use crate::schema::private_message::dsl::*;
use schema::schema::private_message::dsl::*;
diesel::delete(private_message.find(private_message_id)).execute(conn)
}
fn create(conn: &PgConnection, private_message_form: &PrivateMessageForm) -> Result<Self, Error> {
use crate::schema::private_message::dsl::*;
use schema::schema::private_message::dsl::*;
insert_into(private_message)
.values(private_message_form)
.get_result::<Self>(conn)
@ -48,7 +48,7 @@ impl Crud<PrivateMessageForm> for PrivateMessage {
private_message_id: i32,
private_message_form: &PrivateMessageForm,
) -> Result<Self, Error> {
use crate::schema::private_message::dsl::*;
use schema::schema::private_message::dsl::*;
diesel::update(private_message.find(private_message_id))
.set(private_message_form)
.get_result::<Self>(conn)

View file

@ -1,5 +1,5 @@
use super::*;
use crate::schema::site;
use schema::schema::site;
#[derive(Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize)]
#[table_name = "site"]
@ -29,22 +29,22 @@ pub struct SiteForm {
impl Crud<SiteForm> for Site {
fn read(conn: &PgConnection, _site_id: i32) -> Result<Self, Error> {
use crate::schema::site::dsl::*;
use schema::schema::site::dsl::*;
site.first::<Self>(conn)
}
fn delete(conn: &PgConnection, site_id: i32) -> Result<usize, Error> {
use crate::schema::site::dsl::*;
use schema::schema::site::dsl::*;
diesel::delete(site.find(site_id)).execute(conn)
}
fn create(conn: &PgConnection, new_site: &SiteForm) -> Result<Self, Error> {
use crate::schema::site::dsl::*;
use schema::schema::site::dsl::*;
insert_into(site).values(new_site).get_result::<Self>(conn)
}
fn update(conn: &PgConnection, site_id: i32, new_site: &SiteForm) -> Result<Self, Error> {
use crate::schema::site::dsl::*;
use schema::schema::site::dsl::*;
diesel::update(site.find(site_id))
.set(new_site)
.get_result::<Self>(conn)

View file

@ -1,7 +1,7 @@
use super::*;
use crate::schema::user_;
use crate::schema::user_::dsl::*;
use crate::{is_email_regex, Settings};
use schema::schema::user_;
use schema::schema::user_::dsl::*;
use utils::{is_email_regex, settings::Settings};
use bcrypt::{hash, DEFAULT_COST};
use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, TokenData, Validation};

View file

@ -1,6 +1,6 @@
use super::comment::Comment;
use super::*;
use crate::schema::user_mention;
use schema::schema::user_mention;
#[derive(Queryable, Associations, Identifiable, PartialEq, Debug, Serialize, Deserialize)]
#[belongs_to(Comment)]
@ -23,17 +23,17 @@ pub struct UserMentionForm {
impl Crud<UserMentionForm> for UserMention {
fn read(conn: &PgConnection, user_mention_id: i32) -> Result<Self, Error> {
use crate::schema::user_mention::dsl::*;
use schema::schema::user_mention::dsl::*;
user_mention.find(user_mention_id).first::<Self>(conn)
}
fn delete(conn: &PgConnection, user_mention_id: i32) -> Result<usize, Error> {
use crate::schema::user_mention::dsl::*;
use schema::schema::user_mention::dsl::*;
diesel::delete(user_mention.find(user_mention_id)).execute(conn)
}
fn create(conn: &PgConnection, user_mention_form: &UserMentionForm) -> Result<Self, Error> {
use crate::schema::user_mention::dsl::*;
use schema::schema::user_mention::dsl::*;
insert_into(user_mention)
.values(user_mention_form)
.get_result::<Self>(conn)
@ -44,7 +44,7 @@ impl Crud<UserMentionForm> for UserMention {
user_mention_id: i32,
user_mention_form: &UserMentionForm,
) -> Result<Self, Error> {
use crate::schema::user_mention::dsl::*;
use schema::schema::user_mention::dsl::*;
diesel::update(user_mention.find(user_mention_id))
.set(user_mention_form)
.get_result::<Self>(conn)

38
server/lemmy_server/Cargo.toml vendored Normal file
View file

@ -0,0 +1,38 @@
[package]
name = "lemmy_server"
version = "0.0.1"
authors = ["Dessalines <tyhou13@gmx.com>"]
edition = "2018"
[dependencies]
utils = { path = "../utils" }
db = { path = "../db" }
r2d2 = { version = ">= 0.8, < 0.9" }
chrono = { version = "0.4.7", features = ["serde"] }
serde_json = { version = "1.0.52", features = ["preserve_order"]}
serde = { version = "1.0.105", features = ["derive"] }
strum = "0.18.0"
strum_macros = "0.18.0"
dotenv = "0.15.0"
activitypub = "0.2.0"
failure = "0.1.8"
actix = "0.9.0"
actix-web = "2.0.0"
actix-files = "0.2.1"
actix-web-actors = "2.0.0"
actix-rt = "1.1.1"
log = "0.4.0"
env_logger = "0.7.1"
rand = "0.7.3"
regex = "1.3.5"
lazy_static = "1.3.0"
lettre = "0.9.3"
lettre_email = "0.9.4"
rss = "1.9.0"
htmlescape = "0.3.1"
percent-encoding = "2.1.0"
isahc = "0.9"
comrak = "0.7"
tokio = "0.2.20"
futures = "0.3.4"
bcrypt = "0.7.0"

View file

@ -1,5 +1,4 @@
use super::*;
use crate::is_valid_community_name;
#[derive(Serialize, Deserialize)]
pub struct GetCommunity {
@ -221,10 +220,6 @@ impl Perform for Oper<CreateCommunity> {
}
}
if !is_valid_community_name(&data.name) {
return Err(APIError::err("invalid_community_name").into());
}
let user_id = claims.id;
let conn = pool.get()?;
@ -311,10 +306,6 @@ impl Perform for Oper<EditCommunity> {
Err(_e) => return Err(APIError::err("not_logged_in").into()),
};
if !is_valid_community_name(&data.name) {
return Err(APIError::err("invalid_community_name").into());
}
let user_id = claims.id;
let conn = pool.get()?;

View file

@ -1,28 +1,28 @@
use crate::db::category::*;
use crate::db::comment::*;
use crate::db::comment_view::*;
use crate::db::community::*;
use crate::db::community_view::*;
use crate::db::moderator::*;
use crate::db::moderator_views::*;
use crate::db::password_reset_request::*;
use crate::db::post::*;
use crate::db::post_view::*;
use crate::db::private_message::*;
use crate::db::private_message_view::*;
use crate::db::site::*;
use crate::db::site_view::*;
use crate::db::user::*;
use crate::db::user_mention::*;
use crate::db::user_mention_view::*;
use crate::db::user_view::*;
use crate::db::*;
use db::category::*;
use db::comment::*;
use db::comment_view::*;
use db::community::*;
use db::community_view::*;
use db::moderator::*;
use db::moderator_views::*;
use db::password_reset_request::*;
use db::post::*;
use db::post_view::*;
use db::private_message::*;
use db::private_message_view::*;
use db::site::*;
use db::site_view::*;
use db::user::*;
use db::user_mention::*;
use db::user_mention_view::*;
use db::user_view::*;
use db::*;
use crate::{
extract_usernames, fetch_iframely_and_pictrs_data, generate_random_string, naive_from_unix,
extract_usernames, fetch_iframely_and_pictshare_data, generate_random_string, naive_from_unix,
naive_now, remove_slurs, send_email, slur_check, slurs_vec_to_str,
};
use crate::settings::Settings;
use utils::settings::Settings;
use crate::websocket::UserOperation;
use crate::websocket::{
server::{

View file

@ -116,9 +116,9 @@ impl Perform for Oper<CreatePost> {
return Err(APIError::err("site_ban").into());
}
// Fetch Iframely and pictrs cached image
let (iframely_title, iframely_description, iframely_html, pictrs_thumbnail) =
fetch_iframely_and_pictrs_data(data.url.to_owned());
// Fetch Iframely and Pictshare cached image
let (iframely_title, iframely_description, iframely_html, pictshare_thumbnail) =
fetch_iframely_and_pictshare_data(data.url.to_owned());
let post_form = PostForm {
name: data.name.to_owned(),
@ -135,7 +135,7 @@ impl Perform for Oper<CreatePost> {
embed_title: iframely_title,
embed_description: iframely_description,
embed_html: iframely_html,
thumbnail_url: pictrs_thumbnail,
thumbnail_url: pictshare_thumbnail,
};
let inserted_post = match Post::create(&conn, &post_form) {
@ -450,9 +450,9 @@ impl Perform for Oper<EditPost> {
return Err(APIError::err("site_ban").into());
}
// Fetch Iframely and Pictrs cached image
let (iframely_title, iframely_description, iframely_html, pictrs_thumbnail) =
fetch_iframely_and_pictrs_data(data.url.to_owned());
// Fetch Iframely and Pictshare cached image
let (iframely_title, iframely_description, iframely_html, pictshare_thumbnail) =
fetch_iframely_and_pictshare_data(data.url.to_owned());
let post_form = PostForm {
name: data.name.to_owned(),
@ -469,7 +469,7 @@ impl Perform for Oper<EditPost> {
embed_title: iframely_title,
embed_description: iframely_description,
embed_html: iframely_html,
thumbnail_url: pictrs_thumbnail,
thumbnail_url: pictshare_thumbnail,
};
let _updated_post = match Post::update(&conn, data.edit_id, &post_form) {

View file

@ -5,15 +5,13 @@ pub extern crate strum_macros;
pub extern crate lazy_static;
#[macro_use]
pub extern crate failure;
#[macro_use]
pub extern crate diesel;
pub extern crate actix;
pub extern crate actix_web;
pub extern crate bcrypt;
//pub extern crate bcrypt;
pub extern crate chrono;
pub extern crate comrak;
pub extern crate dotenv;
pub extern crate jsonwebtoken;
//pub extern crate jsonwebtoken;
pub extern crate lettre;
pub extern crate lettre_email;
pub extern crate rand;
@ -21,21 +19,16 @@ pub extern crate regex;
pub extern crate rss;
pub extern crate serde;
pub extern crate serde_json;
pub extern crate sha2;
pub extern crate strum;
pub mod api;
pub mod apub;
pub mod db;
pub mod rate_limit;
pub mod routes;
pub mod schema;
pub mod settings;
pub mod version;
pub mod websocket;
use actix_web::dev::ConnectionInfo;
use chrono::{DateTime, NaiveDateTime, Utc};
use isahc::prelude::*;
use lettre::smtp::authentication::{Credentials, Mechanism};
use lettre::smtp::extension::ClientId;
use lettre::smtp::ConnectionReuseParameters;
@ -48,7 +41,7 @@ use rand::{thread_rng, Rng};
use regex::{Regex, RegexBuilder};
use serde::Deserialize;
use crate::settings::Settings;
use utils::settings::Settings;
pub type ConnectionId = usize;
pub type PostId = i32;
@ -56,6 +49,49 @@ pub type CommunityId = i32;
pub type UserId = i32;
pub type IPAddr = String;
pub fn send_email(
subject: &str,
to_email: &str,
to_username: &str,
html: &str,
) -> Result<(), String> {
let email_config = Settings::get().email.ok_or("no_email_setup")?;
let email = Email::builder()
.to((to_email, to_username))
.from(email_config.smtp_from_address.to_owned())
.subject(subject)
.html(html)
.build()
.unwrap();
let mailer = if email_config.use_tls {
SmtpClient::new_simple(&email_config.smtp_server).unwrap()
} else {
SmtpClient::new(&email_config.smtp_server, ClientSecurity::None).unwrap()
}
.hello_name(ClientId::Domain(Settings::get().hostname))
.smtp_utf8(true)
.authentication_mechanism(Mechanism::Plain)
.connection_reuse(ConnectionReuseParameters::ReuseUnlimited);
let mailer = if let (Some(login), Some(password)) =
(&email_config.smtp_login, &email_config.smtp_password)
{
mailer.credentials(Credentials::new(login.to_owned(), password.to_owned()))
} else {
mailer
};
let mut transport = mailer.transport();
let result = transport.send(email.into());
transport.close();
match result {
Ok(_) => Ok(()),
Err(e) => Err(e.to_string()),
}
}
pub fn to_datetime_utc(ndt: NaiveDateTime) -> DateTime<Utc> {
DateTime::<Utc>::from_utc(ndt, Utc)
}
@ -68,13 +104,8 @@ pub fn naive_from_unix(time: i64) -> NaiveDateTime {
NaiveDateTime::from_timestamp(time, 0)
}
pub fn is_email_regex(test: &str) -> bool {
EMAIL_REGEX.is_match(test)
}
pub fn is_image_content_type(test: &str) -> Result<(), failure::Error> {
if attohttpc::get(test)
.send()?
if isahc::get(test)?
.headers()
.get("Content-Type")
.ok_or_else(|| format_err!("No Content-Type header"))?
@ -129,49 +160,6 @@ pub fn generate_random_string() -> String {
thread_rng().sample_iter(&Alphanumeric).take(30).collect()
}
pub fn send_email(
subject: &str,
to_email: &str,
to_username: &str,
html: &str,
) -> Result<(), String> {
let email_config = Settings::get().email.ok_or("no_email_setup")?;
let email = Email::builder()
.to((to_email, to_username))
.from(email_config.smtp_from_address.to_owned())
.subject(subject)
.html(html)
.build()
.unwrap();
let mailer = if email_config.use_tls {
SmtpClient::new_simple(&email_config.smtp_server).unwrap()
} else {
SmtpClient::new(&email_config.smtp_server, ClientSecurity::None).unwrap()
}
.hello_name(ClientId::Domain(Settings::get().hostname))
.smtp_utf8(true)
.authentication_mechanism(Mechanism::Plain)
.connection_reuse(ConnectionReuseParameters::ReuseUnlimited);
let mailer = if let (Some(login), Some(password)) =
(&email_config.smtp_login, &email_config.smtp_password)
{
mailer.credentials(Credentials::new(login.to_owned(), password.to_owned()))
} else {
mailer
};
let mut transport = mailer.transport();
let result = transport.send(email.into());
transport.close();
match result {
Ok(_) => Ok(()),
Err(e) => Err(e.to_string()),
}
}
#[derive(Deserialize, Debug)]
pub struct IframelyResponse {
title: Option<String>,
@ -182,40 +170,30 @@ pub struct IframelyResponse {
pub fn fetch_iframely(url: &str) -> Result<IframelyResponse, failure::Error> {
let fetch_url = format!("http://iframely/oembed?url={}", url);
let text: String = attohttpc::get(&fetch_url).send()?.text()?;
let text = isahc::get(&fetch_url)?.text()?;
let res: IframelyResponse = serde_json::from_str(&text)?;
Ok(res)
}
#[derive(Deserialize, Debug, Clone)]
pub struct PictrsResponse {
files: Vec<PictrsFile>,
msg: String,
#[derive(Deserialize, Debug)]
pub struct PictshareResponse {
status: String,
url: String,
}
#[derive(Deserialize, Debug, Clone)]
pub struct PictrsFile {
file: String,
delete_token: String,
}
pub fn fetch_pictrs(image_url: &str) -> Result<PictrsResponse, failure::Error> {
pub fn fetch_pictshare(image_url: &str) -> Result<PictshareResponse, failure::Error> {
is_image_content_type(image_url)?;
let fetch_url = format!(
"http://pictrs:8080/image/download?url={}",
utf8_percent_encode(image_url, NON_ALPHANUMERIC) // TODO this might not be needed
"http://pictshare/api/geturl.php?url={}",
utf8_percent_encode(image_url, NON_ALPHANUMERIC)
);
let text = attohttpc::get(&fetch_url).send()?.text()?;
let res: PictrsResponse = serde_json::from_str(&text)?;
if res.msg == "ok" {
Ok(res)
} else {
Err(format_err!("{}", &res.msg))
}
let text = isahc::get(&fetch_url)?.text()?;
let res: PictshareResponse = serde_json::from_str(&text)?;
Ok(res)
}
fn fetch_iframely_and_pictrs_data(
fn fetch_iframely_and_pictshare_data(
url: Option<String>,
) -> (
Option<String>,
@ -235,20 +213,20 @@ fn fetch_iframely_and_pictrs_data(
}
};
// Fetch pictrs thumbnail
let pictrs_thumbnail = match iframely_thumbnail_url {
Some(iframely_thumbnail_url) => match fetch_pictrs(&iframely_thumbnail_url) {
Ok(res) => Some(res.files[0].file.to_owned()),
// Fetch pictshare thumbnail
let pictshare_thumbnail = match iframely_thumbnail_url {
Some(iframely_thumbnail_url) => match fetch_pictshare(&iframely_thumbnail_url) {
Ok(res) => Some(res.url),
Err(e) => {
error!("pictrs err: {}", e);
error!("pictshare err: {}", e);
None
}
},
// Try to generate a small thumbnail if iframely is not supported
None => match fetch_pictrs(&url) {
Ok(res) => Some(res.files[0].file.to_owned()),
None => match fetch_pictshare(&url) {
Ok(res) => Some(res.url),
Err(e) => {
error!("pictrs err: {}", e);
error!("pictshare err: {}", e);
None
}
},
@ -258,7 +236,7 @@ fn fetch_iframely_and_pictrs_data(
iframely_title,
iframely_description,
iframely_html,
pictrs_thumbnail,
pictshare_thumbnail,
)
}
None => (None, None, None, None),
@ -283,15 +261,11 @@ pub fn is_valid_username(name: &str) -> bool {
VALID_USERNAME_REGEX.is_match(name)
}
pub fn is_valid_community_name(name: &str) -> bool {
VALID_COMMUNITY_NAME_REGEX.is_match(name)
}
#[cfg(test)]
mod tests {
use crate::{
extract_usernames, is_email_regex, is_image_content_type, is_valid_community_name,
is_valid_username, remove_slurs, slur_check, slurs_vec_to_str,
extract_usernames, is_email_regex, is_image_content_type, is_valid_username, remove_slurs,
slur_check, slurs_vec_to_str,
};
#[test]
@ -300,7 +274,7 @@ mod tests {
assert!(is_image_content_type(
"https://twitter.com/BenjaminNorton/status/1259922424272957440?s=20"
)
.is_err());
.is_err());
}
#[test]
@ -318,15 +292,6 @@ mod tests {
assert!(!is_valid_username(""));
}
#[test]
fn test_valid_community_name() {
assert!(is_valid_community_name("example"));
assert!(is_valid_community_name("example_community"));
assert!(!is_valid_community_name("Example"));
assert!(!is_valid_community_name("Ex"));
assert!(!is_valid_community_name(""));
}
#[test]
fn test_slur_filter() {
let test =
@ -385,9 +350,7 @@ mod tests {
}
lazy_static! {
static ref EMAIL_REGEX: Regex = Regex::new(r"^[a-zA-Z0-9.!#$%&*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$").unwrap();
static ref SLUR_REGEX: Regex = RegexBuilder::new(r"(fag(g|got|tard)?|maricos?|cock\s?sucker(s|ing)?|nig(\b|g?(a|er)?(s|z)?)\b|dindu(s?)|mudslime?s?|kikes?|mongoloids?|towel\s*heads?|\bspi(c|k)s?\b|\bchinks?|niglets?|beaners?|\bnips?\b|\bcoons?\b|jungle\s*bunn(y|ies?)|jigg?aboo?s?|\bpakis?\b|rag\s*heads?|gooks?|cunts?|bitch(es|ing|y)?|puss(y|ies?)|twats?|feminazis?|whor(es?|ing)|\bslut(s|t?y)?|\btrann?(y|ies?)|ladyboy(s?)|\b(b|re|r)tard(ed)?s?)").case_insensitive(true).build().unwrap();
static ref USERNAME_MATCHES_REGEX: Regex = Regex::new(r"/u/[a-zA-Z][0-9a-zA-Z_]*").unwrap();
static ref VALID_USERNAME_REGEX: Regex = Regex::new(r"^[a-zA-Z0-9_]{3,20}$").unwrap();
static ref VALID_COMMUNITY_NAME_REGEX: Regex = Regex::new(r"^[a-z0-9_]{3,20}$").unwrap();
}
}

View file

@ -1,7 +1,5 @@
extern crate lemmy_server;
#[macro_use]
extern crate diesel_migrations;
#[macro_use]
pub extern crate lazy_static;
use crate::lemmy_server::actix_web::dev::Service;
@ -11,17 +9,18 @@ use actix_web::dev::{ServiceRequest, ServiceResponse};
use actix_web::http::header::CONTENT_TYPE;
use actix_web::http::{header::CACHE_CONTROL, HeaderValue};
use actix_web::*;
use diesel::r2d2::{ConnectionManager, Pool};
use diesel::PgConnection;
use lemmy_server::{
rate_limit::{rate_limiter::RateLimiter, RateLimit},
routes::{api, federation, feeds, index, nodeinfo, webfinger},
settings::Settings,
routes::{api, feeds, index, nodeinfo, webfinger},
websocket::server::*,
};
use utils::settings::Settings;
use regex::Regex;
use std::{io, sync::Arc};
use tokio::sync::Mutex;
use db::diesel::r2d2::ConnectionManager;
use r2d2::Pool;
use db::diesel::PgConnection;
lazy_static! {
static ref CACHE_CONTROL_REGEX: Regex =
@ -31,10 +30,9 @@ lazy_static! {
static ref CACHE_CONTROL_VALUE: String = format!("public, max-age={}", 60 * 60);
}
embed_migrations!();
#[actix_rt::main]
async fn main() -> io::Result<()> {
println!("test");
env_logger::init();
let settings = Settings::get();
@ -45,10 +43,6 @@ async fn main() -> io::Result<()> {
.build(manager)
.unwrap_or_else(|_| panic!("Error connecting to {}", settings.get_database_url()));
// Run the migrations from code
let conn = pool.get().unwrap();
embedded_migrations::run(&conn).unwrap();
// Set up the rate limiter
let rate_limiter = RateLimit {
rate_limiter: Arc::new(Mutex::new(RateLimiter::default())),
@ -73,7 +67,6 @@ async fn main() -> io::Result<()> {
.data(server.clone())
// The routes
.configure(move |cfg| api::config(cfg, &rate_limiter))
.configure(federation::config)
.configure(feeds::config)
.configure(index::config)
.configure(nodeinfo::config)

View file

@ -1,9 +1,10 @@
pub mod rate_limiter;
use super::{IPAddr, Settings};
use super::IPAddr;
use utils::settings::Settings;
use crate::api::APIError;
use crate::get_ip;
use crate::settings::RateLimitConfig;
use utils::settings::RateLimitConfig;
use actix_web::dev::{Service, ServiceRequest, ServiceResponse, Transform};
use failure::Error;
use futures::future::{ok, Ready};

View file

@ -1,11 +1,11 @@
use super::*;
use crate::db::comment_view::{ReplyQueryBuilder, ReplyView};
use crate::db::community::Community;
use crate::db::post_view::{PostQueryBuilder, PostView};
use crate::db::site_view::SiteView;
use crate::db::user::{Claims, User_};
use crate::db::user_mention_view::{UserMentionQueryBuilder, UserMentionView};
use crate::db::{ListingType, SortType};
use db::comment_view::{ReplyQueryBuilder, ReplyView};
use db::community::Community;
use db::post_view::{PostQueryBuilder, PostView};
use db::site_view::SiteView;
use db::user::{Claims, User_};
use db::user_mention_view::{UserMentionQueryBuilder, UserMentionView};
use db::{ListingType, SortType};
#[derive(Deserialize)]
pub struct Params {

View file

@ -1,5 +1,5 @@
use crate::api::{Oper, Perform};
use crate::db::site_view::SiteView;
use db::site_view::SiteView;
use crate::rate_limit::rate_limiter::RateLimiter;
use crate::websocket::{server::ChatServer, WebsocketInfo};
use crate::{get_ip, markdown_to_html, version, Settings};
@ -8,10 +8,6 @@ use actix_files::NamedFile;
use actix_web::{body::Body, error::ErrorBadRequest, web::Query, *};
use actix_web_actors::ws;
use chrono::{DateTime, NaiveDateTime, Utc};
use diesel::{
r2d2::{ConnectionManager, Pool},
PgConnection,
};
use log::{error, info};
use regex::Regex;
use rss::{CategoryBuilder, ChannelBuilder, GuidBuilder, Item, ItemBuilder};
@ -21,13 +17,15 @@ use std::str::FromStr;
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};
use strum::ParseError;
use db::diesel::r2d2::ConnectionManager;
use r2d2::Pool;
use db::diesel::PgConnection;
pub type DbPoolParam = web::Data<Pool<ConnectionManager<PgConnection>>>;
pub type RateLimitParam = web::Data<Arc<Mutex<RateLimiter>>>;
pub type ChatServerParam = web::Data<Addr<ChatServer>>;
pub mod api;
pub mod federation;
pub mod feeds;
pub mod index;
pub mod nodeinfo;

View file

@ -1,5 +1,6 @@
use super::*;
use crate::db::community::Community;
use db::community::Community;
use db::diesel::r2d2::ConnectionManager;
#[derive(Deserialize)]
pub struct Params {

View file

@ -0,0 +1 @@
pub const VERSION: &str = "v0.6.71";

View file

@ -2,8 +2,6 @@ pub mod server;
use crate::ConnectionId;
use actix::prelude::*;
use diesel::r2d2::{ConnectionManager, Pool};
use diesel::PgConnection;
use failure::Error;
use log::{error, info};
use rand::{rngs::ThreadRng, Rng};

View file

@ -12,6 +12,9 @@ use crate::api::*;
use crate::rate_limit::RateLimit;
use crate::websocket::UserOperation;
use crate::{CommunityId, ConnectionId, IPAddr, PostId, UserId};
use r2d2::Pool;
use db::diesel::r2d2::ConnectionManager;
use db::diesel::PgConnection;
/// Chat server sends this messages to session
#[derive(Message)]

10
server/schema/Cargo.toml vendored Normal file
View file

@ -0,0 +1,10 @@
[package]
name = "schema"
version = "0.1.0"
authors = ["Felix Ableitner <me@nutomic.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
diesel = { version = "1.4.2", features = ["postgres", "64-column-tables"] }

4
server/schema/src/lib.rs Normal file
View file

@ -0,0 +1,4 @@
#[macro_use]
pub extern crate diesel;
pub mod schema;

View file

@ -1,109 +0,0 @@
use crate::apub::make_apub_endpoint;
use crate::db::community::Community;
use crate::db::community_view::CommunityFollowerView;
use crate::db::establish_unpooled_connection;
use crate::to_datetime_utc;
use activitypub::{actor::Group, collection::UnorderedCollection, context};
use actix_web::body::Body;
use actix_web::web::Path;
use actix_web::HttpResponse;
use serde::Deserialize;
impl Community {
pub fn as_group(&self) -> Group {
let base_url = make_apub_endpoint("c", &self.name);
let mut group = Group::default();
group.object_props.set_context_object(context()).ok();
group.object_props.set_id_string(base_url.to_string()).ok();
group
.object_props
.set_name_string(self.name.to_owned())
.ok();
group
.object_props
.set_published_utctime(to_datetime_utc(self.published))
.ok();
if let Some(updated) = self.updated {
group
.object_props
.set_updated_utctime(to_datetime_utc(updated))
.ok();
}
if let Some(description) = &self.description {
group
.object_props
.set_summary_string(description.to_string())
.ok();
}
group
.ap_actor_props
.set_inbox_string(format!("{}/inbox", &base_url))
.ok();
group
.ap_actor_props
.set_outbox_string(format!("{}/outbox", &base_url))
.ok();
group
.ap_actor_props
.set_followers_string(format!("{}/followers", &base_url))
.ok();
group
}
pub fn followers_as_collection(&self) -> UnorderedCollection {
let base_url = make_apub_endpoint("c", &self.name);
let mut collection = UnorderedCollection::default();
collection.object_props.set_context_object(context()).ok();
collection.object_props.set_id_string(base_url).ok();
let connection = establish_unpooled_connection();
//As we are an object, we validated that the community id was valid
let community_followers = CommunityFollowerView::for_community(&connection, self.id).unwrap();
let ap_followers = community_followers
.iter()
.map(|follower| make_apub_endpoint("u", &follower.user_name))
.collect();
collection
.collection_props
.set_items_string_vec(ap_followers)
.unwrap();
collection
}
}
#[derive(Deserialize)]
pub struct CommunityQuery {
community_name: String,
}
pub async fn get_apub_community(info: Path<CommunityQuery>) -> HttpResponse<Body> {
let connection = establish_unpooled_connection();
if let Ok(community) = Community::read_from_name(&connection, info.community_name.to_owned()) {
HttpResponse::Ok()
.content_type("application/activity+json")
.body(serde_json::to_string(&community.as_group()).unwrap())
} else {
HttpResponse::NotFound().finish()
}
}
pub async fn get_apub_community_followers(info: Path<CommunityQuery>) -> HttpResponse<Body> {
let connection = establish_unpooled_connection();
if let Ok(community) = Community::read_from_name(&connection, info.community_name.to_owned()) {
HttpResponse::Ok()
.content_type("application/activity+json")
.body(serde_json::to_string(&community.followers_as_collection()).unwrap())
} else {
HttpResponse::NotFound().finish()
}
}

View file

@ -1,107 +0,0 @@
pub mod community;
pub mod post;
pub mod user;
use crate::Settings;
use std::fmt::Display;
#[cfg(test)]
mod tests {
use crate::db::community::Community;
use crate::db::post::Post;
use crate::db::user::User_;
use crate::db::{ListingType, SortType};
use crate::{naive_now, Settings};
#[test]
fn test_person() {
let user = User_ {
id: 52,
name: "thom".into(),
fedi_name: "rrf".into(),
preferred_username: None,
password_encrypted: "here".into(),
email: None,
matrix_user_id: None,
avatar: None,
published: naive_now(),
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,
};
let person = user.as_person();
assert_eq!(
format!("https://{}/federation/u/thom", Settings::get().hostname),
person.object_props.id_string().unwrap()
);
}
#[test]
fn test_community() {
let community = Community {
id: 42,
name: "Test".into(),
title: "Test Title".into(),
description: Some("Test community".into()),
category_id: 32,
creator_id: 52,
removed: false,
published: naive_now(),
updated: Some(naive_now()),
deleted: false,
nsfw: false,
};
let group = community.as_group();
assert_eq!(
format!("https://{}/federation/c/Test", Settings::get().hostname),
group.object_props.id_string().unwrap()
);
}
#[test]
fn test_post() {
let post = Post {
id: 62,
name: "A test post".into(),
url: None,
body: None,
creator_id: 52,
community_id: 42,
published: naive_now(),
removed: false,
locked: false,
stickied: false,
nsfw: false,
deleted: false,
updated: None,
embed_title: None,
embed_description: None,
embed_html: None,
thumbnail_url: None,
};
let page = post.as_page();
assert_eq!(
format!("https://{}/federation/post/62", Settings::get().hostname),
page.object_props.id_string().unwrap()
);
}
}
pub fn make_apub_endpoint<S: Display, T: Display>(point: S, value: T) -> String {
format!(
"https://{}/federation/{}/{}",
Settings::get().hostname,
point,
value
)
}

View file

@ -1,38 +0,0 @@
use crate::apub::make_apub_endpoint;
use crate::db::post::Post;
use crate::to_datetime_utc;
use activitypub::{context, object::Page};
impl Post {
pub fn as_page(&self) -> Page {
let base_url = make_apub_endpoint("post", self.id);
let mut page = Page::default();
page.object_props.set_context_object(context()).ok();
page.object_props.set_id_string(base_url).ok();
page.object_props.set_name_string(self.name.to_owned()).ok();
if let Some(body) = &self.body {
page.object_props.set_content_string(body.to_owned()).ok();
}
if let Some(url) = &self.url {
page.object_props.set_url_string(url.to_owned()).ok();
}
//page.object_props.set_attributed_to_string
page
.object_props
.set_published_utctime(to_datetime_utc(self.published))
.ok();
if let Some(updated) = self.updated {
page
.object_props
.set_updated_utctime(to_datetime_utc(updated))
.ok();
}
page
}
}

View file

@ -1,74 +0,0 @@
use crate::apub::make_apub_endpoint;
use crate::db::establish_unpooled_connection;
use crate::db::user::User_;
use crate::to_datetime_utc;
use activitypub::{actor::Person, context};
use actix_web::body::Body;
use actix_web::web::Path;
use actix_web::HttpResponse;
use serde::Deserialize;
impl User_ {
pub fn as_person(&self) -> Person {
let base_url = make_apub_endpoint("u", &self.name);
let mut person = Person::default();
person.object_props.set_context_object(context()).ok();
person.object_props.set_id_string(base_url.to_string()).ok();
person
.object_props
.set_name_string(self.name.to_owned())
.ok();
person
.object_props
.set_published_utctime(to_datetime_utc(self.published))
.ok();
if let Some(updated) = self.updated {
person
.object_props
.set_updated_utctime(to_datetime_utc(updated))
.ok();
}
person
.ap_actor_props
.set_inbox_string(format!("{}/inbox", &base_url))
.ok();
person
.ap_actor_props
.set_outbox_string(format!("{}/outbox", &base_url))
.ok();
person
.ap_actor_props
.set_following_string(format!("{}/following", &base_url))
.ok();
person
.ap_actor_props
.set_liked_string(format!("{}/liked", &base_url))
.ok();
if let Some(i) = &self.preferred_username {
person
.ap_actor_props
.set_preferred_username_string(i.to_string())
.ok();
}
person
}
}
#[derive(Deserialize)]
pub struct UserQuery {
user_name: String,
}
pub async fn get_apub_user(info: Path<UserQuery>) -> HttpResponse<Body> {
let connection = establish_unpooled_connection();
if let Ok(user) = User_::find_by_email_or_username(&connection, &info.user_name) {
HttpResponse::Ok()
.content_type("application/activity+json")
.body(serde_json::to_string(&user.as_person()).unwrap())
} else {
HttpResponse::NotFound().finish()
}
}

View file

@ -1,18 +0,0 @@
use super::*;
use crate::apub;
pub fn config(cfg: &mut web::ServiceConfig) {
cfg
.route(
"/federation/c/{community_name}",
web::get().to(apub::community::get_apub_community),
)
.route(
"/federation/c/{community_name}/followers",
web::get().to(apub::community::get_apub_community_followers),
)
.route(
"/federation/u/{user_name}",
web::get().to(apub::user::get_apub_user),
);
}

View file

@ -1 +0,0 @@
pub const VERSION: &str = "v0.7.1";

16
server/utils/Cargo.toml vendored Normal file
View file

@ -0,0 +1,16 @@
[package]
name = "utils"
version = "0.1.0"
authors = ["Felix Ableitner <me@nutomic.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
lazy_static = "1.3.0"
regex = "1.3.5"
serde = { version = "1.0.105", features = ["derive"] }
failure = "0.1.8"
config = "0.10.1"
hjson = "0.8.2"
chrono = { version = "0.4.7", features = ["serde"] }

14
server/utils/src/lib.rs Normal file
View file

@ -0,0 +1,14 @@
#[macro_use]
pub extern crate lazy_static;
use regex::{Regex, RegexBuilder};
use chrono::{NaiveDateTime, DateTime, Utc};
pub mod settings;
pub fn is_email_regex(test: &str) -> bool {
EMAIL_REGEX.is_match(test)
}
lazy_static! {
static ref EMAIL_REGEX: Regex = Regex::new(r"^[a-zA-Z0-9.!#$%&*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$").unwrap();
}

View file

@ -37,7 +37,7 @@
}
.md-div img {
max-height: 40vh;
max-height: 90vh;
max-width: 100%;
height: auto;
}

View file

@ -1,30 +0,0 @@
$white: #ffffff;
$orange: #faa077;
$cyan: #02bdc2;
$green: #d4e9d7;
$secondary: $green;
$body-color: $gray-700;
$link-color: theme-color("danger");;
$primary: $orange;
$red: #d8486a;
$border-radius: 1.5rem;
$border-radius-lg: 1.5rem;
$border-radius-sm: 1rem;
$font-family-sans-serif: Guardian-EgypTT,serif,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
$headings-color: $gray-700;
$input-btn-focus-color: rgba($component-active-bg, .75);
$form-feedback-valid-color: theme-color("info");
$navbar-light-color: $gray-600;
$black: #222222;
$navbar-dark-toggler-border-color: rgba($black, .1);
$navbar-light-active-color: $gray-900;
$card-color: $gray-700;
$card-cap-color: $gray-700;
$info: darken($green, 25%);;
$body-bg: #f2f0f0;
$success: darken($green, 25%);;
$danger: darken($primary, 25%);
$navbar-light-hover-color: $gray-900;
$card-bg: $gray-100;
$border-color: $gray-700;

File diff suppressed because one or more lines are too long

View file

@ -18,7 +18,6 @@ import {
setupTribute,
wsJsonToRes,
emojiPicker,
pictrsDeleteToast,
} from '../utils';
import { WebSocketService, UserService } from '../services';
import autosize from 'autosize';
@ -61,7 +60,7 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
buttonTitle: !this.props.node
? capitalizeFirstLetter(i18n.t('post'))
: this.props.edit
? capitalizeFirstLetter(i18n.t('save'))
? capitalizeFirstLetter(i18n.t('edit'))
: capitalizeFirstLetter(i18n.t('reply')),
previewMode: false,
loading: false,
@ -138,7 +137,7 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
/>
{this.state.previewMode && (
<div
className="card card-body md-div"
className="md-div"
dangerouslySetInnerHTML={mdToHtml(
this.state.commentForm.content
)}
@ -151,7 +150,7 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
<button
type="submit"
class="btn btn-sm btn-secondary mr-2"
disabled={this.props.disabled || this.state.loading}
disabled={this.props.disabled}
>
{this.state.loading ? (
<svg class="icon icon-spinner spin">
@ -163,9 +162,8 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
</button>
{this.state.commentForm.content && (
<button
className={`btn btn-sm mr-2 btn-secondary ${
this.state.previewMode && 'active'
}`}
className={`btn btn-sm mr-2 btn-secondary ${this.state
.previewMode && 'active'}`}
onClick={linkEvent(this, this.handlePreviewToggle)}
>
{i18n.t('preview')}
@ -245,32 +243,18 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
});
}
handleFinished(data: CommentResponse) {
let isReply =
this.props.node !== undefined && data.comment.parent_id !== null;
let xor =
+!(data.comment.parent_id !== null) ^ +(this.props.node !== undefined);
if (
(data.comment.creator_id == UserService.Instance.user.id &&
// If its a reply, make sure parent child match
isReply &&
data.comment.parent_id == this.props.node.comment.id) ||
// Otherwise, check the XOR of the two
(!isReply && xor)
) {
this.state.previewMode = false;
this.state.loading = false;
this.state.commentForm.content = '';
this.setState(this.state);
let form: any = document.getElementById(this.formId);
form.reset();
if (this.props.node) {
this.props.onReplyCancel();
}
autosize.update(form);
this.setState(this.state);
handleFinished() {
this.state.previewMode = false;
this.state.loading = false;
this.state.commentForm.content = '';
this.setState(this.state);
let form: any = document.getElementById(this.formId);
form.reset();
if (this.props.node) {
this.props.onReplyCancel();
}
autosize.update(document.querySelector('textarea'));
this.setState(this.state);
}
handleCommentSubmit(i: CommentForm, event: any) {
@ -320,9 +304,9 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
file = event;
}
const imageUploadUrl = `/pictrs/image`;
const imageUploadUrl = `/pictshare/api/upload.php`;
const formData = new FormData();
formData.append('images[]', file);
formData.append('file', file);
i.state.imageLoading = true;
i.setState(i.state);
@ -333,31 +317,16 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
})
.then(res => res.json())
.then(res => {
console.log('pictrs upload:');
console.log(res);
if (res.msg == 'ok') {
let hash = res.files[0].file;
let url = `${window.location.origin}/pictrs/image/${hash}`;
let deleteToken = res.files[0].delete_token;
let deleteUrl = `${window.location.origin}/pictrs/image/delete/${deleteToken}/${hash}`;
let imageMarkdown = `![](${url})`;
let content = i.state.commentForm.content;
content = content ? `${content}\n${imageMarkdown}` : imageMarkdown;
i.state.commentForm.content = content;
i.state.imageLoading = false;
i.setState(i.state);
let textarea: any = document.getElementById(i.id);
autosize.update(textarea);
pictrsDeleteToast(
i18n.t('click_to_delete_picture'),
i18n.t('picture_deleted'),
deleteUrl
);
} else {
i.state.imageLoading = false;
i.setState(i.state);
toast(JSON.stringify(res), 'danger');
}
let url = `${window.location.origin}/pictshare/${res.url}`;
let imageMarkdown =
res.filetype == 'mp4' ? `[vid](${url}/raw)` : `![](${url})`;
let content = i.state.commentForm.content;
content = content ? `${content}\n${imageMarkdown}` : imageMarkdown;
i.state.commentForm.content = content;
i.state.imageLoading = false;
i.setState(i.state);
let textarea: any = document.getElementById(i.id);
autosize.update(textarea);
})
.catch(error => {
i.state.imageLoading = false;
@ -373,10 +342,14 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
if (UserService.Instance.user) {
if (res.op == UserOperation.CreateComment) {
let data = res.data as CommentResponse;
this.handleFinished(data);
if (data.comment.creator_id == UserService.Instance.user.id) {
this.handleFinished();
}
} else if (res.op == UserOperation.EditComment) {
let data = res.data as CommentResponse;
this.handleFinished(data);
if (data.comment.creator_id == UserService.Instance.user.id) {
this.handleFinished();
}
}
}
}

View file

@ -132,7 +132,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
>
<div
id={`comment-${node.comment.id}`}
className={`details comment-node border-top border-light py-2 ${
className={`details comment-node border-top border-light ${
this.isCommentNew ? 'mark' : ''
}`}
style={
@ -148,7 +148,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
'ml-2'
}`}
>
<div class="d-flex flex-wrap align-items-center text-muted small">
<div class="d-flex flex-wrap align-items-center mb-1 mt-1 text-muted small">
<span class="mr-2">
<UserListing
user={{
@ -294,6 +294,25 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
)}
</button>
)}
<button
class="btn btn-link btn-animate text-muted"
onClick={linkEvent(this, this.handleSaveCommentClick)}
data-tippy-content={
node.comment.saved ? i18n.t('unsave') : i18n.t('save')
}
>
{this.state.saveLoading ? (
this.loadingIcon
) : (
<svg
class={`icon icon-inline ${
node.comment.saved && 'text-warning'
}`}
>
<use xlinkHref="#icon-star"></use>
</svg>
)}
</button>
<button
class="btn btn-link btn-animate text-muted"
onClick={linkEvent(this, this.handleReplyClick)}
@ -329,30 +348,6 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
</button>
)}
{!this.props.showContext && this.linkBtn}
<button
class="btn btn-link btn-animate text-muted"
onClick={linkEvent(
this,
this.handleSaveCommentClick
)}
data-tippy-content={
node.comment.saved
? i18n.t('unsave')
: i18n.t('save')
}
>
{this.state.saveLoading ? (
this.loadingIcon
) : (
<svg
class={`icon icon-inline ${
node.comment.saved && 'text-warning'
}`}
>
<use xlinkHref="#icon-star"></use>
</svg>
)}
</button>
<button
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(this, this.handleViewSource)}

View file

@ -207,11 +207,7 @@ export class CommunityForm extends Component<
)}
<div class="form-group row">
<div class="col-12">
<button
type="submit"
class="btn btn-secondary mr-2"
disabled={this.state.loading}
>
<button type="submit" class="btn btn-secondary mr-2">
{this.state.loading ? (
<svg class="icon icon-spinner spin">
<use xlinkHref="#icon-spinner"></use>

View file

@ -123,10 +123,7 @@ export class Inbox extends Component<any, InboxState> {
this.state.unreadOrAll == UnreadOrAll.Unread && (
<ul class="list-inline mb-1 text-muted small font-weight-bold">
<li className="list-inline-item">
<span
class="pointer"
onClick={linkEvent(this, this.markAllAsRead)}
>
<span class="pointer" onClick={this.markAllAsRead}>
{i18n.t('mark_all_as_read')}
</span>
</li>
@ -395,14 +392,8 @@ export class Inbox extends Component<any, InboxState> {
this.refetch();
}
markAllAsRead(i: Inbox) {
markAllAsRead() {
WebSocketService.Instance.markAllAsRead();
i.state.replies = [];
i.state.mentions = [];
i.state.messages = [];
i.sendUnreadCount();
window.scrollTo(0, 0);
i.setState(i.state);
}
parseMessage(msg: WebSocketJsonResponse) {
@ -456,7 +447,12 @@ export class Inbox extends Component<any, InboxState> {
this.setState(this.state);
setupTippy();
} else if (res.op == UserOperation.MarkAllAsRead) {
// Moved to be instant
this.state.replies = [];
this.state.mentions = [];
this.state.messages = [];
this.sendUnreadCount();
window.scrollTo(0, 0);
this.setState(this.state);
} else if (res.op == UserOperation.EditComment) {
let data = res.data as CommentResponse;
editCommentRes(data, this.state.replies);

View file

@ -111,7 +111,6 @@ export class Login extends Component<any, State> {
required
/>
<button
type="button"
disabled={!validEmail(this.state.loginForm.username_or_email)}
onClick={linkEvent(this, this.handlePasswordReset)}
className="btn p-0 btn-link d-inline-block float-right text-muted small font-weight-bold"

View file

@ -22,7 +22,7 @@ import {
} from '../interfaces';
import {
wsJsonToRes,
pictrsAvatarThumbnail,
pictshareAvatarThumbnail,
showAvatars,
fetchLimit,
isCommentType,
@ -218,7 +218,7 @@ export class Navbar extends Component<any, NavbarState> {
<span>
{UserService.Instance.user.avatar && showAvatars() && (
<img
src={pictrsAvatarThumbnail(
src={pictshareAvatarThumbnail(
UserService.Instance.user.avatar
)}
height="32"
@ -381,7 +381,7 @@ export class Navbar extends Component<any, NavbarState> {
requestNotificationPermission() {
if (UserService.Instance.user) {
document.addEventListener('DOMContentLoaded', function () {
document.addEventListener('DOMContentLoaded', function() {
if (!Notification) {
toast(i18n.t('notifications_error'), 'danger');
return;

View file

@ -35,7 +35,6 @@ import {
setupTribute,
setupTippy,
emojiPicker,
pictrsDeleteToast,
} from '../utils';
import autosize from 'autosize';
import Tribute from 'tributejs/src/Tribute.js';
@ -284,7 +283,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
/>
{this.state.previewMode && (
<div
className="card card-body md-div"
className="md-div"
dangerouslySetInnerHTML={mdToHtml(this.state.postForm.body)}
/>
)}
@ -360,9 +359,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
<div class="form-group row">
<div class="col-sm-10">
<button
disabled={
!this.state.postForm.community_id || this.state.loading
}
disabled={!this.state.postForm.community_id}
type="submit"
class="btn btn-secondary mr-2"
>
@ -408,12 +405,6 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
handlePostSubmit(i: PostForm, event: any) {
event.preventDefault();
// Coerce empty url string to undefined
if (i.state.postForm.url && i.state.postForm.url === '') {
i.state.postForm.url = undefined;
}
if (i.props.post) {
WebSocketService.Instance.editPost(i.state.postForm);
} else {
@ -527,9 +518,9 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
file = event;
}
const imageUploadUrl = `/pictrs/image`;
const imageUploadUrl = `/pictshare/api/upload.php`;
const formData = new FormData();
formData.append('images[]', file);
formData.append('file', file);
i.state.imageLoading = true;
i.setState(i.state);
@ -540,26 +531,13 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
})
.then(res => res.json())
.then(res => {
console.log('pictrs upload:');
console.log(res);
if (res.msg == 'ok') {
let hash = res.files[0].file;
let url = `${window.location.origin}/pictrs/image/${hash}`;
let deleteToken = res.files[0].delete_token;
let deleteUrl = `${window.location.origin}/pictrs/image/delete/${deleteToken}/${hash}`;
i.state.postForm.url = url;
i.state.imageLoading = false;
i.setState(i.state);
pictrsDeleteToast(
i18n.t('click_to_delete_picture'),
i18n.t('picture_deleted'),
deleteUrl
);
} else {
i.state.imageLoading = false;
i.setState(i.state);
toast(JSON.stringify(res), 'danger');
let url = `${window.location.origin}/pictshare/${encodeURI(res.url)}`;
if (res.filetype == 'mp4') {
url += '/raw';
}
i.state.postForm.url = url;
i.state.imageLoading = false;
i.setState(i.state);
})
.catch(error => {
i.state.imageLoading = false;

View file

@ -28,7 +28,7 @@ import {
isImage,
isVideo,
getUnixTime,
pictrsImage,
pictshareImage,
setupTippy,
previewLines,
} from '../utils';
@ -161,15 +161,15 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
getImage(thumbnail: boolean = false) {
let post = this.props.post;
if (isImage(post.url)) {
if (post.url.includes('pictrs')) {
return pictrsImage(post.url, thumbnail);
if (post.url.includes('pictshare')) {
return pictshareImage(post.url, thumbnail);
} else if (post.thumbnail_url) {
return pictrsImage(post.thumbnail_url, thumbnail);
return pictshareImage(post.thumbnail_url, thumbnail);
} else {
return post.url;
}
} else if (post.thumbnail_url) {
return pictrsImage(post.thumbnail_url, thumbnail);
return pictshareImage(post.thumbnail_url, thumbnail);
}
}

View file

@ -154,7 +154,7 @@ export class PrivateMessageForm extends Component<
/>
{this.state.previewMode && (
<div
className="card card-body md-div"
className="md-div"
dangerouslySetInnerHTML={mdToHtml(
this.state.privateMessageForm.content
)}
@ -183,11 +183,7 @@ export class PrivateMessageForm extends Component<
)}
<div class="form-group row">
<div class="offset-sm-2 col-sm-10">
<button
type="submit"
class="btn btn-secondary mr-2"
disabled={this.state.loading}
>
<button type="submit" class="btn btn-secondary mr-2">
{this.state.loading ? (
<svg class="icon icon-spinner spin">
<use xlinkHref="#icon-spinner"></use>

View file

@ -5,7 +5,12 @@ import {
EditPrivateMessageForm,
} from '../interfaces';
import { WebSocketService, UserService } from '../services';
import { mdToHtml, pictrsAvatarThumbnail, showAvatars, toast } from '../utils';
import {
mdToHtml,
pictshareAvatarThumbnail,
showAvatars,
toast,
} from '../utils';
import { MomentTime } from './moment-time';
import { PrivateMessageForm } from './private-message-form';
import { i18n } from '../i18next';
@ -73,7 +78,7 @@ export class PrivateMessage extends Component<
<img
height="32"
width="32"
src={pictrsAvatarThumbnail(
src={pictshareAvatarThumbnail(
this.mine
? message.recipient_avatar
: message.creator_avatar
@ -139,9 +144,8 @@ export class PrivateMessage extends Component<
}
>
<svg
class={`icon icon-inline ${
message.read && 'text-success'
}`}
class={`icon icon-inline ${message.read &&
'text-success'}`}
>
<use xlinkHref="#icon-check"></use>
</svg>
@ -184,9 +188,8 @@ export class PrivateMessage extends Component<
}
>
<svg
class={`icon icon-inline ${
message.deleted && 'text-danger'
}`}
class={`icon icon-inline ${message.deleted &&
'text-danger'}`}
>
<use xlinkHref="#icon-trash"></use>
</svg>
@ -201,9 +204,8 @@ export class PrivateMessage extends Component<
data-tippy-content={i18n.t('view_source')}
>
<svg
class={`icon icon-inline ${
this.state.viewSource && 'text-success'
}`}
class={`icon icon-inline ${this.state.viewSource &&
'text-success'}`}
>
<use xlinkHref="#icon-file-text"></use>
</svg>

View file

@ -22,7 +22,7 @@ import {
fetchLimit,
routeSearchTypeToEnum,
routeSortTypeToEnum,
pictrsAvatarThumbnail,
pictshareAvatarThumbnail,
showAvatars,
toast,
createCommentLikeRes,

View file

@ -11,7 +11,7 @@ import { WebSocketService, UserService } from '../services';
import {
mdToHtml,
getUnixTime,
pictrsAvatarThumbnail,
pictshareAvatarThumbnail,
showAvatars,
} from '../utils';
import { CommunityForm } from './community-form';

View file

@ -78,7 +78,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
<form onSubmit={linkEvent(this, this.handleCreateSiteSubmit)}>
<h5>{`${
this.props.site
? capitalizeFirstLetter(i18n.t('save'))
? capitalizeFirstLetter(i18n.t('edit'))
: capitalizeFirstLetter(i18n.t('name'))
} ${i18n.t('your_site')}`}</h5>
<div class="form-group row">
@ -175,11 +175,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
</div>
<div class="form-group row">
<div class="col-12">
<button
type="submit"
class="btn btn-secondary mr-2"
disabled={this.state.loading}
>
<button type="submit" class="btn btn-secondary mr-2">
{this.state.loading ? (
<svg class="icon icon-spinner spin">
<use xlinkHref="#icon-spinner"></use>

View file

@ -1,7 +1,7 @@
import { Component } from 'inferno';
import { Link } from 'inferno-router';
import { UserView } from '../interfaces';
import { pictrsAvatarThumbnail, showAvatars } from '../utils';
import { pictshareAvatarThumbnail, showAvatars } from '../utils';
interface UserOther {
name: string;
@ -25,7 +25,7 @@ export class UserListing extends Component<UserListingProps, any> {
<img
height="32"
width="32"
src={pictrsAvatarThumbnail(user.avatar)}
src={pictshareAvatarThumbnail(user.avatar)}
class="rounded-circle mr-2"
/>
)}

View file

@ -922,7 +922,7 @@ export class User extends Component<any, UserState> {
handleUserSettingsThemeChange(i: User, event: any) {
i.state.userSettingsForm.theme = event.target.value;
setTheme(event.target.value, true);
setTheme(event.target.value);
i.setState(i.state);
}
@ -988,9 +988,9 @@ export class User extends Component<any, UserState> {
handleImageUpload(i: User, event: any) {
event.preventDefault();
let file = event.target.files[0];
const imageUploadUrl = `/pictrs/image`;
const imageUploadUrl = `/pictshare/api/upload.php`;
const formData = new FormData();
formData.append('images[]', file);
formData.append('file', file);
i.state.avatarLoading = true;
i.setState(i.state);
@ -1001,19 +1001,14 @@ export class User extends Component<any, UserState> {
})
.then(res => res.json())
.then(res => {
console.log('pictrs upload:');
console.log(res);
if (res.msg == 'ok') {
let hash = res.files[0].file;
let url = `${window.location.origin}/pictrs/image/${hash}`;
i.state.userSettingsForm.avatar = url;
i.state.avatarLoading = false;
i.setState(i.state);
} else {
i.state.avatarLoading = false;
i.setState(i.state);
toast(JSON.stringify(res), 'danger');
let url = `${window.location.origin}/pictshare/${res.url}`;
if (res.filetype == 'mp4') {
url += '/raw';
}
i.state.userSettingsForm.avatar = url;
console.log(url);
i.state.avatarLoading = false;
i.setState(i.state);
})
.catch(error => {
i.state.avatarLoading = false;

3
ui/src/index.html vendored
View file

@ -15,8 +15,7 @@
<link rel="stylesheet" type="text/css" href="/static/assets/css/toastify.css" />
<link rel="stylesheet" type="text/css" href="/static/assets/css/selectr.min.css" />
<link rel="stylesheet" type="text/css" href="/static/assets/css/tippy.css" />
<link rel="stylesheet" type="text/css" href="/static/assets/css/themes/litely.min.css" id="default-light" media="(prefers-color-scheme: light)" />
<link rel="stylesheet" type="text/css" href="/static/assets/css/themes/darkly.min.css" id="default-dark" media="(prefers-color-scheme: no-preference), (prefers-color-scheme: dark)" />
<link rel="stylesheet" type="text/css" href="/static/assets/css/themes/darkly.min.css" id="darkly" />
<link rel="stylesheet" type="text/css" href="/static/assets/css/main.css" />
<!-- Scripts -->

View file

@ -41,7 +41,9 @@ export class UserService {
private setUser(jwt: string) {
this.user = jwt_decode(jwt);
setTheme(this.user.theme, true);
if (this.user.theme != 'darkly') {
setTheme(this.user.theme);
}
this.sub.next({ user: this.user });
console.log(this.user);
}

102
ui/src/utils.ts vendored
View file

@ -103,7 +103,6 @@ export const themes = [
'vaporwave',
'vaporwave-dark',
'i386',
'litely',
];
export const emojiPicker = new EmojiButton({
@ -114,26 +113,11 @@ export const emojiPicker = new EmojiButton({
// TODO i18n
});
const DEFAULT_ALPHABET =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
function getRandomCharFromAlphabet(alphabet: string): string {
return alphabet.charAt(Math.floor(Math.random() * alphabet.length));
}
export function randomStr(
idDesiredLength: number = 20,
alphabet = DEFAULT_ALPHABET
): string {
/**
* Create n-long array and map it to random chars from given alphabet.
* Then join individual chars as string
*/
return Array.from({ length: idDesiredLength })
.map(() => {
return getRandomCharFromAlphabet(alphabet);
})
.join('');
export function randomStr() {
return Math.random()
.toString(36)
.replace(/[^a-z]+/g, '')
.substr(2, 10);
}
export function wsJsonToRes(msg: WebSocketJsonResponse): WebSocketResponse {
@ -420,7 +404,7 @@ export function getMomentLanguage(): string {
return lang;
}
export function setTheme(theme: string = 'darkly', loggedIn: boolean = false) {
export function setTheme(theme: string = 'darkly') {
// unload all the other themes
for (var i = 0; i < themes.length; i++) {
let styleSheet = document.getElementById(themes[i]);
@ -429,23 +413,10 @@ export function setTheme(theme: string = 'darkly', loggedIn: boolean = false) {
}
}
// if the user is not logged in, we load the default themes and let the browser decide
if (!loggedIn) {
document.getElementById('default-light').removeAttribute('disabled');
document.getElementById('default-dark').removeAttribute('disabled');
} else {
document
.getElementById('default-light')
.setAttribute('disabled', 'disabled');
document
.getElementById('default-dark')
.setAttribute('disabled', 'disabled');
// Load the theme dynamically
let cssLoc = `/static/assets/css/themes/${theme}.min.css`;
loadCss(theme, cssLoc);
document.getElementById(theme).removeAttribute('disabled');
}
// Load the theme dynamically
let cssLoc = `/static/assets/css/themes/${theme}.min.css`;
loadCss(theme, cssLoc);
document.getElementById(theme).removeAttribute('disabled');
}
export function loadCss(id: string, loc: string) {
@ -469,12 +440,10 @@ export function objectFlip(obj: any) {
return ret;
}
export function pictrsAvatarThumbnail(src: string): string {
// sample url: http://localhost:8535/pictrs/image/thumbnail256/gs7xuu.jpg
let split = src.split('/pictrs/image');
let out = `${split[0]}/pictrs/image/${
canUseWebP() ? 'webp/' : ''
}thumbnail96${split[1]}`;
export function pictshareAvatarThumbnail(src: string): string {
// sample url: http://localhost:8535/pictshare/gs7xuu.jpg
let split = src.split('pictshare');
let out = `${split[0]}pictshare/${canUseWebP() ? 'webp/' : ''}96${split[1]}`;
return out;
}
@ -486,18 +455,21 @@ export function showAvatars(): boolean {
}
// Converts to image thumbnail
export function pictrsImage(hash: string, thumbnail: boolean = false): string {
let root = `/pictrs/image`;
export function pictshareImage(
hash: string,
thumbnail: boolean = false
): string {
let root = `/pictshare`;
// Necessary for other servers / domains
if (hash.includes('pictrs')) {
let split = hash.split('/pictrs/image/');
root = `${split[0]}/pictrs/image`;
if (hash.includes('pictshare')) {
let split = hash.split('/pictshare/');
root = `${split[0]}/pictshare`;
hash = split[1];
}
let out = `${root}/${canUseWebP() ? 'webp/' : ''}${
thumbnail ? 'thumbnail256/' : ''
thumbnail ? '192/' : ''
}${hash}`;
return out;
}
@ -516,29 +488,6 @@ export function toast(text: string, background: string = 'success') {
}).showToast();
}
export function pictrsDeleteToast(
clickToDeleteText: string,
deletePictureText: string,
deleteUrl: string
) {
let backgroundColor = `var(--light)`;
let toast = Toastify({
text: clickToDeleteText,
backgroundColor: backgroundColor,
gravity: 'top',
position: 'right',
duration: 10000,
onClick: () => {
if (toast) {
window.location.replace(deleteUrl);
alert(deletePictureText);
toast.hideToast();
}
},
close: true,
}).showToast();
}
export function messageToastify(
creator: string,
avatar: string,
@ -552,11 +501,11 @@ export function messageToastify(
text: `${body}<br />${creator}`,
avatar: avatar,
backgroundColor: backgroundColor,
className: 'text-dark',
className: 'text-body',
close: true,
gravity: 'top',
position: 'right',
duration: 5000,
duration: 0,
onClick: () => {
if (toast) {
toast.hideToast();
@ -938,6 +887,7 @@ function canUseWebP() {
return false;
// var elem = document.createElement('canvas');
// if (!!(elem.getContext && elem.getContext('2d'))) {
// var testString = !(window.mozInnerScreenX == null) ? 'png' : 'webp';
// // was able or not to get WebP representation

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