Merge pull request #1516 from ClearlyClaire/glitch-soc/merge-upstream
Merge upstream changespull/1517/head
commit
a2a85d5ae0
71
Dockerfile
71
Dockerfile
|
@ -1,7 +1,7 @@
|
||||||
FROM ubuntu:20.04 as build-dep
|
FROM ubuntu:20.04 as build-dep
|
||||||
|
|
||||||
# Use bash for the shell
|
# Use bash for the shell
|
||||||
SHELL ["/usr/bin/bash", "-c"]
|
SHELL ["/bin/bash", "-c"]
|
||||||
|
|
||||||
# Install Node v12 (LTS)
|
# Install Node v12 (LTS)
|
||||||
ENV NODE_VER="12.21.0"
|
ENV NODE_VER="12.21.0"
|
||||||
|
@ -17,35 +17,19 @@ RUN ARCH= && \
|
||||||
*) echo "unsupported architecture"; exit 1 ;; \
|
*) echo "unsupported architecture"; exit 1 ;; \
|
||||||
esac && \
|
esac && \
|
||||||
echo "Etc/UTC" > /etc/localtime && \
|
echo "Etc/UTC" > /etc/localtime && \
|
||||||
apt update && \
|
apt-get update && \
|
||||||
apt -y install wget python && \
|
apt-get install -y --no-install-recommends ca-certificates wget python && \
|
||||||
cd ~ && \
|
cd ~ && \
|
||||||
wget https://nodejs.org/download/release/v$NODE_VER/node-v$NODE_VER-linux-$ARCH.tar.gz && \
|
wget -q https://nodejs.org/download/release/v$NODE_VER/node-v$NODE_VER-linux-$ARCH.tar.gz && \
|
||||||
tar xf node-v$NODE_VER-linux-$ARCH.tar.gz && \
|
tar xf node-v$NODE_VER-linux-$ARCH.tar.gz && \
|
||||||
rm node-v$NODE_VER-linux-$ARCH.tar.gz && \
|
rm node-v$NODE_VER-linux-$ARCH.tar.gz && \
|
||||||
mv node-v$NODE_VER-linux-$ARCH /opt/node
|
mv node-v$NODE_VER-linux-$ARCH /opt/node
|
||||||
|
|
||||||
# Install jemalloc
|
|
||||||
ENV JE_VER="5.2.1"
|
|
||||||
RUN apt update && \
|
|
||||||
apt -y install make autoconf gcc g++ && \
|
|
||||||
cd ~ && \
|
|
||||||
wget https://github.com/jemalloc/jemalloc/archive/$JE_VER.tar.gz && \
|
|
||||||
tar xf $JE_VER.tar.gz && \
|
|
||||||
cd jemalloc-$JE_VER && \
|
|
||||||
./autogen.sh && \
|
|
||||||
./configure --prefix=/opt/jemalloc && \
|
|
||||||
make -j$(nproc) > /dev/null && \
|
|
||||||
make install_bin install_include install_lib && \
|
|
||||||
cd .. && rm -rf jemalloc-$JE_VER $JE_VER.tar.gz
|
|
||||||
|
|
||||||
# Install Ruby
|
# Install Ruby
|
||||||
ENV RUBY_VER="2.7.2"
|
ENV RUBY_VER="2.7.2"
|
||||||
ENV CPPFLAGS="-I/opt/jemalloc/include"
|
RUN apt-get update && \
|
||||||
ENV LDFLAGS="-L/opt/jemalloc/lib/"
|
apt-get install -y --no-install-recommends build-essential \
|
||||||
RUN apt update && \
|
bison libyaml-dev libgdbm-dev libreadline-dev libjemalloc-dev \
|
||||||
apt -y install build-essential \
|
|
||||||
bison libyaml-dev libgdbm-dev libreadline-dev \
|
|
||||||
libncurses5-dev libffi-dev zlib1g-dev libssl-dev && \
|
libncurses5-dev libffi-dev zlib1g-dev libssl-dev && \
|
||||||
cd ~ && \
|
cd ~ && \
|
||||||
wget https://cache.ruby-lang.org/pub/ruby/${RUBY_VER%.*}/ruby-$RUBY_VER.tar.gz && \
|
wget https://cache.ruby-lang.org/pub/ruby/${RUBY_VER%.*}/ruby-$RUBY_VER.tar.gz && \
|
||||||
|
@ -55,17 +39,16 @@ RUN apt update && \
|
||||||
--with-jemalloc \
|
--with-jemalloc \
|
||||||
--with-shared \
|
--with-shared \
|
||||||
--disable-install-doc && \
|
--disable-install-doc && \
|
||||||
ln -s /opt/jemalloc/lib/* /usr/lib/ && \
|
make -j"$(nproc)" > /dev/null && \
|
||||||
make -j$(nproc) > /dev/null && \
|
|
||||||
make install && \
|
make install && \
|
||||||
cd .. && rm -rf ruby-$RUBY_VER.tar.gz ruby-$RUBY_VER
|
rm -rf ../ruby-$RUBY_VER.tar.gz ../ruby-$RUBY_VER
|
||||||
|
|
||||||
ENV PATH="${PATH}:/opt/ruby/bin:/opt/node/bin"
|
ENV PATH="${PATH}:/opt/ruby/bin:/opt/node/bin"
|
||||||
|
|
||||||
RUN npm install -g yarn && \
|
RUN npm install -g yarn && \
|
||||||
gem install bundler && \
|
gem install bundler && \
|
||||||
apt update && \
|
apt-get update && \
|
||||||
apt -y install git libicu-dev libidn11-dev \
|
apt-get install -y --no-install-recommends git libicu-dev libidn11-dev \
|
||||||
libpq-dev libprotobuf-dev protobuf-compiler
|
libpq-dev libprotobuf-dev protobuf-compiler
|
||||||
|
|
||||||
COPY Gemfile* package.json yarn.lock /opt/mastodon/
|
COPY Gemfile* package.json yarn.lock /opt/mastodon/
|
||||||
|
@ -73,7 +56,7 @@ COPY Gemfile* package.json yarn.lock /opt/mastodon/
|
||||||
RUN cd /opt/mastodon && \
|
RUN cd /opt/mastodon && \
|
||||||
bundle config set deployment 'true' && \
|
bundle config set deployment 'true' && \
|
||||||
bundle config set without 'development test' && \
|
bundle config set without 'development test' && \
|
||||||
bundle install -j$(nproc) && \
|
bundle install -j"$(nproc)" && \
|
||||||
yarn install --pure-lockfile
|
yarn install --pure-lockfile
|
||||||
|
|
||||||
FROM ubuntu:20.04
|
FROM ubuntu:20.04
|
||||||
|
@ -81,7 +64,6 @@ FROM ubuntu:20.04
|
||||||
# Copy over all the langs needed for runtime
|
# Copy over all the langs needed for runtime
|
||||||
COPY --from=build-dep /opt/node /opt/node
|
COPY --from=build-dep /opt/node /opt/node
|
||||||
COPY --from=build-dep /opt/ruby /opt/ruby
|
COPY --from=build-dep /opt/ruby /opt/ruby
|
||||||
COPY --from=build-dep /opt/jemalloc /opt/jemalloc
|
|
||||||
|
|
||||||
# Add more PATHs to the PATH
|
# Add more PATHs to the PATH
|
||||||
ENV PATH="${PATH}:/opt/ruby/bin:/opt/node/bin:/opt/mastodon/bin"
|
ENV PATH="${PATH}:/opt/ruby/bin:/opt/node/bin:/opt/mastodon/bin"
|
||||||
|
@ -89,35 +71,26 @@ ENV PATH="${PATH}:/opt/ruby/bin:/opt/node/bin:/opt/mastodon/bin"
|
||||||
# Create the mastodon user
|
# Create the mastodon user
|
||||||
ARG UID=991
|
ARG UID=991
|
||||||
ARG GID=991
|
ARG GID=991
|
||||||
RUN apt update && \
|
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||||
|
RUN apt-get update && \
|
||||||
echo "Etc/UTC" > /etc/localtime && \
|
echo "Etc/UTC" > /etc/localtime && \
|
||||||
ln -s /opt/jemalloc/lib/* /usr/lib/ && \
|
apt-get install -y --no-install-recommends whois wget && \
|
||||||
apt install -y whois wget && \
|
|
||||||
addgroup --gid $GID mastodon && \
|
addgroup --gid $GID mastodon && \
|
||||||
useradd -m -u $UID -g $GID -d /opt/mastodon mastodon && \
|
useradd -m -u $UID -g $GID -d /opt/mastodon mastodon && \
|
||||||
echo "mastodon:`head /dev/urandom | tr -dc A-Za-z0-9 | head -c 24 | mkpasswd -s -m sha-256`" | chpasswd
|
echo "mastodon:$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 24 | mkpasswd -s -m sha-256)" | chpasswd && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# Install mastodon runtime deps
|
# Install mastodon runtime deps
|
||||||
RUN apt -y --no-install-recommends install \
|
RUN apt-get update && \
|
||||||
libssl1.1 libpq5 imagemagick ffmpeg \
|
apt-get -y --no-install-recommends install \
|
||||||
|
libssl1.1 libpq5 imagemagick ffmpeg libjemalloc2 \
|
||||||
libicu66 libprotobuf17 libidn11 libyaml-0-2 \
|
libicu66 libprotobuf17 libidn11 libyaml-0-2 \
|
||||||
file ca-certificates tzdata libreadline8 && \
|
file ca-certificates tzdata libreadline8 gcc tini && \
|
||||||
apt -y install gcc && \
|
|
||||||
ln -s /opt/mastodon /mastodon && \
|
ln -s /opt/mastodon /mastodon && \
|
||||||
gem install bundler && \
|
gem install bundler && \
|
||||||
rm -rf /var/cache && \
|
rm -rf /var/cache && \
|
||||||
rm -rf /var/lib/apt/lists/*
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# Add tini
|
|
||||||
ENV TINI_VERSION="0.19.0"
|
|
||||||
RUN dpkgArch="$(dpkg --print-architecture)" && \
|
|
||||||
ARCH=$dpkgArch && \
|
|
||||||
wget https://github.com/krallin/tini/releases/download/v${TINI_VERSION}/tini-$ARCH \
|
|
||||||
https://github.com/krallin/tini/releases/download/v${TINI_VERSION}/tini-$ARCH.sha256sum && \
|
|
||||||
cat tini-$ARCH.sha256sum | sha256sum -c - && \
|
|
||||||
mv tini-$ARCH /tini && rm tini-$ARCH.sha256sum && \
|
|
||||||
chmod +x /tini
|
|
||||||
|
|
||||||
# Copy over mastodon source, and dependencies from building, and set permissions
|
# Copy over mastodon source, and dependencies from building, and set permissions
|
||||||
COPY --chown=mastodon:mastodon . /opt/mastodon
|
COPY --chown=mastodon:mastodon . /opt/mastodon
|
||||||
COPY --from=build-dep --chown=mastodon:mastodon /opt/mastodon /opt/mastodon
|
COPY --from=build-dep --chown=mastodon:mastodon /opt/mastodon /opt/mastodon
|
||||||
|
@ -140,5 +113,5 @@ RUN cd ~ && \
|
||||||
|
|
||||||
# Set the work dir and the container entry point
|
# Set the work dir and the container entry point
|
||||||
WORKDIR /opt/mastodon
|
WORKDIR /opt/mastodon
|
||||||
ENTRYPOINT ["/tini", "--"]
|
ENTRYPOINT ["/usr/bin/tini", "--"]
|
||||||
EXPOSE 3000 4000
|
EXPOSE 3000 4000
|
||||||
|
|
16
Gemfile
16
Gemfile
|
@ -6,7 +6,7 @@ ruby '>= 2.5.0', '< 3.0.0'
|
||||||
gem 'pkg-config', '~> 1.4'
|
gem 'pkg-config', '~> 1.4'
|
||||||
|
|
||||||
gem 'puma', '~> 5.2'
|
gem 'puma', '~> 5.2'
|
||||||
gem 'rails', '~> 5.2.4.5'
|
gem 'rails', '~> 6.1.3'
|
||||||
gem 'sprockets', '~> 3.7.2'
|
gem 'sprockets', '~> 3.7.2'
|
||||||
gem 'thor', '~> 1.1'
|
gem 'thor', '~> 1.1'
|
||||||
gem 'rack', '~> 2.2.3'
|
gem 'rack', '~> 2.2.3'
|
||||||
|
@ -17,7 +17,7 @@ gem 'makara', '~> 0.5'
|
||||||
gem 'pghero', '~> 2.8'
|
gem 'pghero', '~> 2.8'
|
||||||
gem 'dotenv-rails', '~> 2.7'
|
gem 'dotenv-rails', '~> 2.7'
|
||||||
|
|
||||||
gem 'aws-sdk-s3', '~> 1.91', require: false
|
gem 'aws-sdk-s3', '~> 1.92', require: false
|
||||||
gem 'fog-core', '<= 2.1.0'
|
gem 'fog-core', '<= 2.1.0'
|
||||||
gem 'fog-openstack', '~> 0.3', require: false
|
gem 'fog-openstack', '~> 0.3', require: false
|
||||||
gem 'paperclip', '~> 6.0'
|
gem 'paperclip', '~> 6.0'
|
||||||
|
@ -34,7 +34,7 @@ gem 'iso-639'
|
||||||
gem 'chewy', '~> 5.2'
|
gem 'chewy', '~> 5.2'
|
||||||
gem 'cld3', '~> 3.4.1'
|
gem 'cld3', '~> 3.4.1'
|
||||||
gem 'devise', '~> 4.7'
|
gem 'devise', '~> 4.7'
|
||||||
gem 'devise-two-factor', '~> 3.1'
|
gem 'devise-two-factor', git: 'https://github.com/ClearlyClaire/devise-two-factor', ref: '594bb8a32e6f94df7e5ba7c9399eaf9ff25bac0d'
|
||||||
|
|
||||||
group :pam_authentication, optional: true do
|
group :pam_authentication, optional: true do
|
||||||
gem 'devise_pam_authenticatable2', '~> 9.2'
|
gem 'devise_pam_authenticatable2', '~> 9.2'
|
||||||
|
@ -65,7 +65,7 @@ gem 'link_header', '~> 0.0'
|
||||||
gem 'mime-types', '~> 3.3.1', require: 'mime/types/columnar'
|
gem 'mime-types', '~> 3.3.1', require: 'mime/types/columnar'
|
||||||
gem 'nilsimsa', git: 'https://github.com/witgo/nilsimsa', ref: 'fd184883048b922b176939f851338d0a4971a532'
|
gem 'nilsimsa', git: 'https://github.com/witgo/nilsimsa', ref: 'fd184883048b922b176939f851338d0a4971a532'
|
||||||
gem 'nokogiri', '~> 1.11'
|
gem 'nokogiri', '~> 1.11'
|
||||||
gem 'nsa', '~> 0.2'
|
gem 'nsa', git: 'https://github.com/Gargron/nsa', ref: 'd1079e0cdafdfed7f9f35478d13b9bdaa65965c0'
|
||||||
gem 'oj', '~> 3.11'
|
gem 'oj', '~> 3.11'
|
||||||
gem 'ox', '~> 2.14'
|
gem 'ox', '~> 2.14'
|
||||||
gem 'parslet'
|
gem 'parslet'
|
||||||
|
@ -75,7 +75,7 @@ gem 'pundit', '~> 2.1'
|
||||||
gem 'premailer-rails'
|
gem 'premailer-rails'
|
||||||
gem 'rack-attack', '~> 6.5'
|
gem 'rack-attack', '~> 6.5'
|
||||||
gem 'rack-cors', '~> 1.1', require: 'rack/cors'
|
gem 'rack-cors', '~> 1.1', require: 'rack/cors'
|
||||||
gem 'rails-i18n', '~> 5.1'
|
gem 'rails-i18n', '~> 6.0'
|
||||||
gem 'rails-settings-cached', '~> 0.6'
|
gem 'rails-settings-cached', '~> 0.6'
|
||||||
gem 'redis', '~> 4.2', require: ['redis', 'redis/connection/hiredis']
|
gem 'redis', '~> 4.2', require: ['redis', 'redis/connection/hiredis']
|
||||||
gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock'
|
gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock'
|
||||||
|
@ -83,7 +83,7 @@ gem 'rqrcode', '~> 1.2'
|
||||||
gem 'ruby-progressbar', '~> 1.11'
|
gem 'ruby-progressbar', '~> 1.11'
|
||||||
gem 'sanitize', '~> 5.2'
|
gem 'sanitize', '~> 5.2'
|
||||||
gem 'scenic', '~> 1.5'
|
gem 'scenic', '~> 1.5'
|
||||||
gem 'sidekiq', '~> 6.1'
|
gem 'sidekiq', '~> 6.2'
|
||||||
gem 'sidekiq-scheduler', '~> 3.0'
|
gem 'sidekiq-scheduler', '~> 3.0'
|
||||||
gem 'sidekiq-unique-jobs', '~> 7.0'
|
gem 'sidekiq-unique-jobs', '~> 7.0'
|
||||||
gem 'sidekiq-bulk', '~>0.2.0'
|
gem 'sidekiq-bulk', '~>0.2.0'
|
||||||
|
@ -142,7 +142,7 @@ group :development do
|
||||||
gem 'memory_profiler'
|
gem 'memory_profiler'
|
||||||
gem 'rubocop', '~> 1.11', require: false
|
gem 'rubocop', '~> 1.11', require: false
|
||||||
gem 'rubocop-rails', '~> 2.9', require: false
|
gem 'rubocop-rails', '~> 2.9', require: false
|
||||||
gem 'brakeman', '~> 4.10', require: false
|
gem 'brakeman', '~> 5.0', require: false
|
||||||
gem 'bundler-audit', '~> 0.8', require: false
|
gem 'bundler-audit', '~> 0.8', require: false
|
||||||
|
|
||||||
gem 'capistrano', '~> 3.16'
|
gem 'capistrano', '~> 3.16'
|
||||||
|
@ -161,4 +161,4 @@ gem 'concurrent-ruby', require: false
|
||||||
gem 'connection_pool', require: false
|
gem 'connection_pool', require: false
|
||||||
|
|
||||||
gem 'xorcist', '~> 1.1'
|
gem 'xorcist', '~> 1.1'
|
||||||
gem 'pluck_each', '~> 0.1.3'
|
gem 'pluck_each', git: 'https://github.com/nsommer/pluck_each', ref: '73be0947c52fc54bf6d7085378db008358aac5eb'
|
||||||
|
|
211
Gemfile.lock
211
Gemfile.lock
|
@ -1,3 +1,26 @@
|
||||||
|
GIT
|
||||||
|
remote: https://github.com/ClearlyClaire/devise-two-factor
|
||||||
|
revision: 594bb8a32e6f94df7e5ba7c9399eaf9ff25bac0d
|
||||||
|
ref: 594bb8a32e6f94df7e5ba7c9399eaf9ff25bac0d
|
||||||
|
specs:
|
||||||
|
devise-two-factor (3.1.0)
|
||||||
|
activesupport (< 7.0)
|
||||||
|
attr_encrypted (>= 1.3, < 4, != 2)
|
||||||
|
devise
|
||||||
|
railties (< 7.0)
|
||||||
|
rotp (~> 6)
|
||||||
|
|
||||||
|
GIT
|
||||||
|
remote: https://github.com/Gargron/nsa
|
||||||
|
revision: d1079e0cdafdfed7f9f35478d13b9bdaa65965c0
|
||||||
|
ref: d1079e0cdafdfed7f9f35478d13b9bdaa65965c0
|
||||||
|
specs:
|
||||||
|
nsa (0.2.8)
|
||||||
|
activesupport (>= 4.2, < 7)
|
||||||
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||||
|
sidekiq (>= 3.5)
|
||||||
|
statsd-ruby (~> 1.4, >= 1.4.0)
|
||||||
|
|
||||||
GIT
|
GIT
|
||||||
remote: https://github.com/ianheggie/health_check
|
remote: https://github.com/ianheggie/health_check
|
||||||
revision: 0b799ead604f900ed50685e9b2d469cd2befba5b
|
revision: 0b799ead604f900ed50685e9b2d469cd2befba5b
|
||||||
|
@ -6,6 +29,15 @@ GIT
|
||||||
health_check (4.0.0.pre)
|
health_check (4.0.0.pre)
|
||||||
rails (>= 4.0)
|
rails (>= 4.0)
|
||||||
|
|
||||||
|
GIT
|
||||||
|
remote: https://github.com/nsommer/pluck_each
|
||||||
|
revision: 73be0947c52fc54bf6d7085378db008358aac5eb
|
||||||
|
ref: 73be0947c52fc54bf6d7085378db008358aac5eb
|
||||||
|
specs:
|
||||||
|
pluck_each (0.1.3)
|
||||||
|
activerecord (>= 6.1.0)
|
||||||
|
activesupport (>= 6.1.0)
|
||||||
|
|
||||||
GIT
|
GIT
|
||||||
remote: https://github.com/witgo/nilsimsa
|
remote: https://github.com/witgo/nilsimsa
|
||||||
revision: fd184883048b922b176939f851338d0a4971a532
|
revision: fd184883048b922b176939f851338d0a4971a532
|
||||||
|
@ -16,53 +48,71 @@ GIT
|
||||||
GEM
|
GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
actioncable (5.2.4.5)
|
actioncable (6.1.3)
|
||||||
actionpack (= 5.2.4.5)
|
actionpack (= 6.1.3)
|
||||||
|
activesupport (= 6.1.3)
|
||||||
nio4r (~> 2.0)
|
nio4r (~> 2.0)
|
||||||
websocket-driver (>= 0.6.1)
|
websocket-driver (>= 0.6.1)
|
||||||
actionmailer (5.2.4.5)
|
actionmailbox (6.1.3)
|
||||||
actionpack (= 5.2.4.5)
|
actionpack (= 6.1.3)
|
||||||
actionview (= 5.2.4.5)
|
activejob (= 6.1.3)
|
||||||
activejob (= 5.2.4.5)
|
activerecord (= 6.1.3)
|
||||||
|
activestorage (= 6.1.3)
|
||||||
|
activesupport (= 6.1.3)
|
||||||
|
mail (>= 2.7.1)
|
||||||
|
actionmailer (6.1.3)
|
||||||
|
actionpack (= 6.1.3)
|
||||||
|
actionview (= 6.1.3)
|
||||||
|
activejob (= 6.1.3)
|
||||||
|
activesupport (= 6.1.3)
|
||||||
mail (~> 2.5, >= 2.5.4)
|
mail (~> 2.5, >= 2.5.4)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
actionpack (5.2.4.5)
|
actionpack (6.1.3)
|
||||||
actionview (= 5.2.4.5)
|
actionview (= 6.1.3)
|
||||||
activesupport (= 5.2.4.5)
|
activesupport (= 6.1.3)
|
||||||
rack (~> 2.0, >= 2.0.8)
|
rack (~> 2.0, >= 2.0.9)
|
||||||
rack-test (>= 0.6.3)
|
rack-test (>= 0.6.3)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
||||||
actionview (5.2.4.5)
|
actiontext (6.1.3)
|
||||||
activesupport (= 5.2.4.5)
|
actionpack (= 6.1.3)
|
||||||
|
activerecord (= 6.1.3)
|
||||||
|
activestorage (= 6.1.3)
|
||||||
|
activesupport (= 6.1.3)
|
||||||
|
nokogiri (>= 1.8.5)
|
||||||
|
actionview (6.1.3)
|
||||||
|
activesupport (= 6.1.3)
|
||||||
builder (~> 3.1)
|
builder (~> 3.1)
|
||||||
erubi (~> 1.4)
|
erubi (~> 1.4)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
||||||
active_model_serializers (0.10.12)
|
active_model_serializers (0.10.12)
|
||||||
actionpack (>= 4.1, < 6.2)
|
actionpack (>= 4.1, < 6.2)
|
||||||
activemodel (>= 4.1, < 6.2)
|
activemodel (>= 4.1, < 6.2)
|
||||||
case_transform (>= 0.2)
|
case_transform (>= 0.2)
|
||||||
jsonapi-renderer (>= 0.1.1.beta1, < 0.3)
|
jsonapi-renderer (>= 0.1.1.beta1, < 0.3)
|
||||||
active_record_query_trace (1.8)
|
active_record_query_trace (1.8)
|
||||||
activejob (5.2.4.5)
|
activejob (6.1.3)
|
||||||
activesupport (= 5.2.4.5)
|
activesupport (= 6.1.3)
|
||||||
globalid (>= 0.3.6)
|
globalid (>= 0.3.6)
|
||||||
activemodel (5.2.4.5)
|
activemodel (6.1.3)
|
||||||
activesupport (= 5.2.4.5)
|
activesupport (= 6.1.3)
|
||||||
activerecord (5.2.4.5)
|
activerecord (6.1.3)
|
||||||
activemodel (= 5.2.4.5)
|
activemodel (= 6.1.3)
|
||||||
activesupport (= 5.2.4.5)
|
activesupport (= 6.1.3)
|
||||||
arel (>= 9.0)
|
activestorage (6.1.3)
|
||||||
activestorage (5.2.4.5)
|
actionpack (= 6.1.3)
|
||||||
actionpack (= 5.2.4.5)
|
activejob (= 6.1.3)
|
||||||
activerecord (= 5.2.4.5)
|
activerecord (= 6.1.3)
|
||||||
|
activesupport (= 6.1.3)
|
||||||
marcel (~> 0.3.1)
|
marcel (~> 0.3.1)
|
||||||
activesupport (5.2.4.5)
|
mimemagic (~> 0.3.2)
|
||||||
|
activesupport (6.1.3)
|
||||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||||
i18n (>= 0.7, < 2)
|
i18n (>= 1.6, < 2)
|
||||||
minitest (~> 5.1)
|
minitest (>= 5.1)
|
||||||
tzinfo (~> 1.1)
|
tzinfo (~> 2.0)
|
||||||
|
zeitwerk (~> 2.3)
|
||||||
addressable (2.7.0)
|
addressable (2.7.0)
|
||||||
public_suffix (>= 2.0.2, < 5.0)
|
public_suffix (>= 2.0.2, < 5.0)
|
||||||
airbrussh (1.4.0)
|
airbrussh (1.4.0)
|
||||||
|
@ -71,7 +121,6 @@ GEM
|
||||||
annotate (3.1.1)
|
annotate (3.1.1)
|
||||||
activerecord (>= 3.2, < 7.0)
|
activerecord (>= 3.2, < 7.0)
|
||||||
rake (>= 10.4, < 14.0)
|
rake (>= 10.4, < 14.0)
|
||||||
arel (9.0.0)
|
|
||||||
ast (2.4.2)
|
ast (2.4.2)
|
||||||
attr_encrypted (3.1.0)
|
attr_encrypted (3.1.0)
|
||||||
encryptor (~> 3.0.0)
|
encryptor (~> 3.0.0)
|
||||||
|
@ -79,7 +128,7 @@ GEM
|
||||||
cocaine (~> 0.5.3)
|
cocaine (~> 0.5.3)
|
||||||
awrence (1.1.1)
|
awrence (1.1.1)
|
||||||
aws-eventstream (1.1.1)
|
aws-eventstream (1.1.1)
|
||||||
aws-partitions (1.432.0)
|
aws-partitions (1.434.0)
|
||||||
aws-sdk-core (3.113.0)
|
aws-sdk-core (3.113.0)
|
||||||
aws-eventstream (~> 1, >= 1.0.2)
|
aws-eventstream (~> 1, >= 1.0.2)
|
||||||
aws-partitions (~> 1, >= 1.239.0)
|
aws-partitions (~> 1, >= 1.239.0)
|
||||||
|
@ -88,7 +137,7 @@ GEM
|
||||||
aws-sdk-kms (1.43.0)
|
aws-sdk-kms (1.43.0)
|
||||||
aws-sdk-core (~> 3, >= 3.112.0)
|
aws-sdk-core (~> 3, >= 3.112.0)
|
||||||
aws-sigv4 (~> 1.1)
|
aws-sigv4 (~> 1.1)
|
||||||
aws-sdk-s3 (1.91.0)
|
aws-sdk-s3 (1.92.0)
|
||||||
aws-sdk-core (~> 3, >= 3.112.0)
|
aws-sdk-core (~> 3, >= 3.112.0)
|
||||||
aws-sdk-kms (~> 1)
|
aws-sdk-kms (~> 1)
|
||||||
aws-sigv4 (~> 1.1)
|
aws-sigv4 (~> 1.1)
|
||||||
|
@ -102,13 +151,13 @@ GEM
|
||||||
bindata (2.4.8)
|
bindata (2.4.8)
|
||||||
binding_of_caller (1.0.0)
|
binding_of_caller (1.0.0)
|
||||||
debug_inspector (>= 0.0.1)
|
debug_inspector (>= 0.0.1)
|
||||||
blurhash (0.1.4)
|
blurhash (0.1.5)
|
||||||
ffi (~> 1.10.0)
|
ffi (~> 1.14)
|
||||||
bootsnap (1.6.0)
|
bootsnap (1.6.0)
|
||||||
msgpack (~> 1.0)
|
msgpack (~> 1.0)
|
||||||
brakeman (4.10.1)
|
brakeman (5.0.0)
|
||||||
browser (4.2.0)
|
browser (4.2.0)
|
||||||
brpoplpush-redis_script (0.1.1)
|
brpoplpush-redis_script (0.1.2)
|
||||||
concurrent-ruby (~> 1.0, >= 1.0.5)
|
concurrent-ruby (~> 1.0, >= 1.0.5)
|
||||||
redis (>= 1.0, <= 5.0)
|
redis (>= 1.0, <= 5.0)
|
||||||
builder (3.2.4)
|
builder (3.2.4)
|
||||||
|
@ -175,12 +224,6 @@ GEM
|
||||||
railties (>= 4.1.0)
|
railties (>= 4.1.0)
|
||||||
responders
|
responders
|
||||||
warden (~> 1.2.3)
|
warden (~> 1.2.3)
|
||||||
devise-two-factor (3.1.0)
|
|
||||||
activesupport (< 6.1)
|
|
||||||
attr_encrypted (>= 1.3, < 4, != 2)
|
|
||||||
devise (~> 4.0)
|
|
||||||
railties (< 6.1)
|
|
||||||
rotp (~> 2.0)
|
|
||||||
devise_pam_authenticatable2 (9.2.0)
|
devise_pam_authenticatable2 (9.2.0)
|
||||||
devise (>= 4.0.0)
|
devise (>= 4.0.0)
|
||||||
rpam2 (~> 4.0)
|
rpam2 (~> 4.0)
|
||||||
|
@ -222,7 +265,7 @@ GEM
|
||||||
faraday-net_http (1.0.1)
|
faraday-net_http (1.0.1)
|
||||||
fast_blank (1.0.0)
|
fast_blank (1.0.0)
|
||||||
fastimage (2.2.3)
|
fastimage (2.2.3)
|
||||||
ffi (1.10.0)
|
ffi (1.14.2)
|
||||||
ffi-compiler (1.0.1)
|
ffi-compiler (1.0.1)
|
||||||
ffi (>= 1.0.0)
|
ffi (>= 1.0.0)
|
||||||
rake
|
rake
|
||||||
|
@ -370,11 +413,6 @@ GEM
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
nokogumbo (2.0.4)
|
nokogumbo (2.0.4)
|
||||||
nokogiri (~> 1.8, >= 1.8.4)
|
nokogiri (~> 1.8, >= 1.8.4)
|
||||||
nsa (0.2.7)
|
|
||||||
activesupport (>= 4.2, < 6)
|
|
||||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
||||||
sidekiq (>= 3.5)
|
|
||||||
statsd-ruby (~> 1.4, >= 1.4.0)
|
|
||||||
oj (3.11.3)
|
oj (3.11.3)
|
||||||
omniauth (1.9.1)
|
omniauth (1.9.1)
|
||||||
hashie (>= 3.4.6)
|
hashie (>= 3.4.6)
|
||||||
|
@ -392,7 +430,7 @@ GEM
|
||||||
openssl (2.2.0)
|
openssl (2.2.0)
|
||||||
openssl-signature_algorithm (0.4.0)
|
openssl-signature_algorithm (0.4.0)
|
||||||
orm_adapter (0.5.0)
|
orm_adapter (0.5.0)
|
||||||
ox (2.14.3)
|
ox (2.14.4)
|
||||||
paperclip (6.0.0)
|
paperclip (6.0.0)
|
||||||
activemodel (>= 4.2.0)
|
activemodel (>= 4.2.0)
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 4.2.0)
|
||||||
|
@ -414,9 +452,6 @@ GEM
|
||||||
pghero (2.8.0)
|
pghero (2.8.0)
|
||||||
activerecord (>= 5)
|
activerecord (>= 5)
|
||||||
pkg-config (1.4.5)
|
pkg-config (1.4.5)
|
||||||
pluck_each (0.1.3)
|
|
||||||
activerecord (> 3.2.0)
|
|
||||||
activesupport (> 3.0.0)
|
|
||||||
posix-spawn (0.3.15)
|
posix-spawn (0.3.15)
|
||||||
premailer (1.14.2)
|
premailer (1.14.2)
|
||||||
addressable
|
addressable
|
||||||
|
@ -450,18 +485,20 @@ GEM
|
||||||
rack
|
rack
|
||||||
rack-test (1.1.0)
|
rack-test (1.1.0)
|
||||||
rack (>= 1.0, < 3)
|
rack (>= 1.0, < 3)
|
||||||
rails (5.2.4.5)
|
rails (6.1.3)
|
||||||
actioncable (= 5.2.4.5)
|
actioncable (= 6.1.3)
|
||||||
actionmailer (= 5.2.4.5)
|
actionmailbox (= 6.1.3)
|
||||||
actionpack (= 5.2.4.5)
|
actionmailer (= 6.1.3)
|
||||||
actionview (= 5.2.4.5)
|
actionpack (= 6.1.3)
|
||||||
activejob (= 5.2.4.5)
|
actiontext (= 6.1.3)
|
||||||
activemodel (= 5.2.4.5)
|
actionview (= 6.1.3)
|
||||||
activerecord (= 5.2.4.5)
|
activejob (= 6.1.3)
|
||||||
activestorage (= 5.2.4.5)
|
activemodel (= 6.1.3)
|
||||||
activesupport (= 5.2.4.5)
|
activerecord (= 6.1.3)
|
||||||
bundler (>= 1.3.0)
|
activestorage (= 6.1.3)
|
||||||
railties (= 5.2.4.5)
|
activesupport (= 6.1.3)
|
||||||
|
bundler (>= 1.15.0)
|
||||||
|
railties (= 6.1.3)
|
||||||
sprockets-rails (>= 2.0.0)
|
sprockets-rails (>= 2.0.0)
|
||||||
rails-controller-testing (1.0.5)
|
rails-controller-testing (1.0.5)
|
||||||
actionpack (>= 5.0.1.rc1)
|
actionpack (>= 5.0.1.rc1)
|
||||||
|
@ -472,17 +509,17 @@ GEM
|
||||||
nokogiri (>= 1.6)
|
nokogiri (>= 1.6)
|
||||||
rails-html-sanitizer (1.3.0)
|
rails-html-sanitizer (1.3.0)
|
||||||
loofah (~> 2.3)
|
loofah (~> 2.3)
|
||||||
rails-i18n (5.1.3)
|
rails-i18n (6.0.0)
|
||||||
i18n (>= 0.7, < 2)
|
i18n (>= 0.7, < 2)
|
||||||
railties (>= 5.0, < 6)
|
railties (>= 6.0.0, < 7)
|
||||||
rails-settings-cached (0.6.6)
|
rails-settings-cached (0.6.6)
|
||||||
rails (>= 4.2.0)
|
rails (>= 4.2.0)
|
||||||
railties (5.2.4.5)
|
railties (6.1.3)
|
||||||
actionpack (= 5.2.4.5)
|
actionpack (= 6.1.3)
|
||||||
activesupport (= 5.2.4.5)
|
activesupport (= 6.1.3)
|
||||||
method_source
|
method_source
|
||||||
rake (>= 0.8.7)
|
rake (>= 0.8.7)
|
||||||
thor (>= 0.19.0, < 2.0)
|
thor (~> 1.0)
|
||||||
rainbow (3.0.0)
|
rainbow (3.0.0)
|
||||||
rake (13.0.3)
|
rake (13.0.3)
|
||||||
rdf (3.1.13)
|
rdf (3.1.13)
|
||||||
|
@ -501,7 +538,7 @@ GEM
|
||||||
actionpack (>= 5.0)
|
actionpack (>= 5.0)
|
||||||
railties (>= 5.0)
|
railties (>= 5.0)
|
||||||
rexml (3.2.4)
|
rexml (3.2.4)
|
||||||
rotp (2.1.2)
|
rotp (6.2.0)
|
||||||
rpam2 (4.0.2)
|
rpam2 (4.0.2)
|
||||||
rqrcode (1.2.0)
|
rqrcode (1.2.0)
|
||||||
chunky_png (~> 1.0)
|
chunky_png (~> 1.0)
|
||||||
|
@ -515,7 +552,7 @@ GEM
|
||||||
rspec-mocks (3.10.2)
|
rspec-mocks (3.10.2)
|
||||||
diff-lcs (>= 1.2.0, < 2.0)
|
diff-lcs (>= 1.2.0, < 2.0)
|
||||||
rspec-support (~> 3.10.0)
|
rspec-support (~> 3.10.0)
|
||||||
rspec-rails (5.0.0)
|
rspec-rails (5.0.1)
|
||||||
actionpack (>= 5.2)
|
actionpack (>= 5.2)
|
||||||
activesupport (>= 5.2)
|
activesupport (>= 5.2)
|
||||||
railties (>= 5.2)
|
railties (>= 5.2)
|
||||||
|
@ -561,7 +598,7 @@ GEM
|
||||||
railties (>= 4.0.0)
|
railties (>= 4.0.0)
|
||||||
securecompare (1.0.0)
|
securecompare (1.0.0)
|
||||||
semantic_range (2.3.0)
|
semantic_range (2.3.0)
|
||||||
sidekiq (6.1.3)
|
sidekiq (6.2.0)
|
||||||
connection_pool (>= 2.2.2)
|
connection_pool (>= 2.2.2)
|
||||||
rack (~> 2.0)
|
rack (~> 2.0)
|
||||||
redis (>= 4.2.0)
|
redis (>= 4.2.0)
|
||||||
|
@ -574,8 +611,8 @@ GEM
|
||||||
sidekiq (>= 3)
|
sidekiq (>= 3)
|
||||||
thwait
|
thwait
|
||||||
tilt (>= 1.4.0)
|
tilt (>= 1.4.0)
|
||||||
sidekiq-unique-jobs (7.0.4)
|
sidekiq-unique-jobs (7.0.7)
|
||||||
brpoplpush-redis_script (> 0.0.0, <= 2.0.0)
|
brpoplpush-redis_script (> 0.1.1, <= 2.0.0)
|
||||||
concurrent-ruby (~> 1.0, >= 1.0.5)
|
concurrent-ruby (~> 1.0, >= 1.0.5)
|
||||||
sidekiq (>= 5.0, < 7.0)
|
sidekiq (>= 5.0, < 7.0)
|
||||||
thor (>= 0.20, < 2.0)
|
thor (>= 0.20, < 2.0)
|
||||||
|
@ -601,7 +638,7 @@ GEM
|
||||||
net-scp (>= 1.1.2)
|
net-scp (>= 1.1.2)
|
||||||
net-ssh (>= 2.8.0)
|
net-ssh (>= 2.8.0)
|
||||||
stackprof (0.2.16)
|
stackprof (0.2.16)
|
||||||
statsd-ruby (1.4.0)
|
statsd-ruby (1.5.0)
|
||||||
stoplight (2.2.1)
|
stoplight (2.2.1)
|
||||||
streamio-ffmpeg (3.0.2)
|
streamio-ffmpeg (3.0.2)
|
||||||
multi_json (~> 1.8)
|
multi_json (~> 1.8)
|
||||||
|
@ -613,7 +650,6 @@ GEM
|
||||||
terrapin (0.6.0)
|
terrapin (0.6.0)
|
||||||
climate_control (>= 0.0.3, < 1.0)
|
climate_control (>= 0.0.3, < 1.0)
|
||||||
thor (1.1.0)
|
thor (1.1.0)
|
||||||
thread_safe (0.3.6)
|
|
||||||
thwait (0.2.0)
|
thwait (0.2.0)
|
||||||
e2mmap
|
e2mmap
|
||||||
tilt (2.0.10)
|
tilt (2.0.10)
|
||||||
|
@ -633,8 +669,8 @@ GEM
|
||||||
twitter-text (3.1.0)
|
twitter-text (3.1.0)
|
||||||
idn-ruby
|
idn-ruby
|
||||||
unf (~> 0.1.0)
|
unf (~> 0.1.0)
|
||||||
tzinfo (1.2.9)
|
tzinfo (2.0.4)
|
||||||
thread_safe (~> 0.1)
|
concurrent-ruby (~> 1.0)
|
||||||
tzinfo-data (1.2021.1)
|
tzinfo-data (1.2021.1)
|
||||||
tzinfo (>= 1.0.0)
|
tzinfo (>= 1.0.0)
|
||||||
unf (0.1.4)
|
unf (0.1.4)
|
||||||
|
@ -673,6 +709,7 @@ GEM
|
||||||
xorcist (1.1.2)
|
xorcist (1.1.2)
|
||||||
xpath (3.2.0)
|
xpath (3.2.0)
|
||||||
nokogiri (~> 1.8)
|
nokogiri (~> 1.8)
|
||||||
|
zeitwerk (2.4.2)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
|
@ -682,12 +719,12 @@ DEPENDENCIES
|
||||||
active_record_query_trace (~> 1.8)
|
active_record_query_trace (~> 1.8)
|
||||||
addressable (~> 2.7)
|
addressable (~> 2.7)
|
||||||
annotate (~> 3.1)
|
annotate (~> 3.1)
|
||||||
aws-sdk-s3 (~> 1.91)
|
aws-sdk-s3 (~> 1.92)
|
||||||
better_errors (~> 2.9)
|
better_errors (~> 2.9)
|
||||||
binding_of_caller (~> 1.0)
|
binding_of_caller (~> 1.0)
|
||||||
blurhash (~> 0.1)
|
blurhash (~> 0.1)
|
||||||
bootsnap (~> 1.6.0)
|
bootsnap (~> 1.6.0)
|
||||||
brakeman (~> 4.10)
|
brakeman (~> 5.0)
|
||||||
browser
|
browser
|
||||||
bullet (~> 6.1)
|
bullet (~> 6.1)
|
||||||
bundler-audit (~> 0.8)
|
bundler-audit (~> 0.8)
|
||||||
|
@ -704,7 +741,7 @@ DEPENDENCIES
|
||||||
concurrent-ruby
|
concurrent-ruby
|
||||||
connection_pool
|
connection_pool
|
||||||
devise (~> 4.7)
|
devise (~> 4.7)
|
||||||
devise-two-factor (~> 3.1)
|
devise-two-factor!
|
||||||
devise_pam_authenticatable2 (~> 9.2)
|
devise_pam_authenticatable2 (~> 9.2)
|
||||||
discard (~> 1.2)
|
discard (~> 1.2)
|
||||||
doorkeeper (~> 5.5)
|
doorkeeper (~> 5.5)
|
||||||
|
@ -742,7 +779,7 @@ DEPENDENCIES
|
||||||
net-ldap (~> 0.17)
|
net-ldap (~> 0.17)
|
||||||
nilsimsa!
|
nilsimsa!
|
||||||
nokogiri (~> 1.11)
|
nokogiri (~> 1.11)
|
||||||
nsa (~> 0.2)
|
nsa!
|
||||||
oj (~> 3.11)
|
oj (~> 3.11)
|
||||||
omniauth (~> 1.9)
|
omniauth (~> 1.9)
|
||||||
omniauth-cas (~> 2.0)
|
omniauth-cas (~> 2.0)
|
||||||
|
@ -757,7 +794,7 @@ DEPENDENCIES
|
||||||
pg (~> 1.2)
|
pg (~> 1.2)
|
||||||
pghero (~> 2.8)
|
pghero (~> 2.8)
|
||||||
pkg-config (~> 1.4)
|
pkg-config (~> 1.4)
|
||||||
pluck_each (~> 0.1.3)
|
pluck_each!
|
||||||
posix-spawn
|
posix-spawn
|
||||||
premailer-rails
|
premailer-rails
|
||||||
private_address_check (~> 0.5)
|
private_address_check (~> 0.5)
|
||||||
|
@ -768,9 +805,9 @@ DEPENDENCIES
|
||||||
rack (~> 2.2.3)
|
rack (~> 2.2.3)
|
||||||
rack-attack (~> 6.5)
|
rack-attack (~> 6.5)
|
||||||
rack-cors (~> 1.1)
|
rack-cors (~> 1.1)
|
||||||
rails (~> 5.2.4.5)
|
rails (~> 6.1.3)
|
||||||
rails-controller-testing (~> 1.0)
|
rails-controller-testing (~> 1.0)
|
||||||
rails-i18n (~> 5.1)
|
rails-i18n (~> 6.0)
|
||||||
rails-settings-cached (~> 0.6)
|
rails-settings-cached (~> 0.6)
|
||||||
rdf-normalize (~> 0.4)
|
rdf-normalize (~> 0.4)
|
||||||
redcarpet (~> 3.5)
|
redcarpet (~> 3.5)
|
||||||
|
@ -785,7 +822,7 @@ DEPENDENCIES
|
||||||
ruby-progressbar (~> 1.11)
|
ruby-progressbar (~> 1.11)
|
||||||
sanitize (~> 5.2)
|
sanitize (~> 5.2)
|
||||||
scenic (~> 1.5)
|
scenic (~> 1.5)
|
||||||
sidekiq (~> 6.1)
|
sidekiq (~> 6.2)
|
||||||
sidekiq-bulk (~> 0.2.0)
|
sidekiq-bulk (~> 0.2.0)
|
||||||
sidekiq-scheduler (~> 3.0)
|
sidekiq-scheduler (~> 3.0)
|
||||||
sidekiq-unique-jobs (~> 7.0)
|
sidekiq-unique-jobs (~> 7.0)
|
||||||
|
|
|
@ -5,8 +5,6 @@ class ApplicationController < ActionController::Base
|
||||||
# For APIs, you may want to use :null_session instead.
|
# For APIs, you may want to use :null_session instead.
|
||||||
protect_from_forgery with: :exception
|
protect_from_forgery with: :exception
|
||||||
|
|
||||||
force_ssl if: :https_enabled?
|
|
||||||
|
|
||||||
include Localized
|
include Localized
|
||||||
include UserTrackingConcern
|
include UserTrackingConcern
|
||||||
include SessionTrackingConcern
|
include SessionTrackingConcern
|
||||||
|
@ -43,10 +41,6 @@ class ApplicationController < ActionController::Base
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def https_enabled?
|
|
||||||
Rails.env.production? && !request.path.start_with?('/health') && !request.headers["Host"].end_with?(".onion")
|
|
||||||
end
|
|
||||||
|
|
||||||
def authorized_fetch_mode?
|
def authorized_fetch_mode?
|
||||||
ENV['AUTHORIZED_FETCH'] == 'true' || Rails.configuration.x.whitelist_mode
|
ENV['AUTHORIZED_FETCH'] == 'true' || Rails.configuration.x.whitelist_mode
|
||||||
end
|
end
|
||||||
|
|
|
@ -199,6 +199,14 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidMount () {
|
||||||
|
this._updateFocusAndSelection({ });
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate (prevProps) {
|
||||||
|
this._updateFocusAndSelection(prevProps);
|
||||||
|
}
|
||||||
|
|
||||||
// This statement does several things:
|
// This statement does several things:
|
||||||
// - If we're beginning a reply, and,
|
// - If we're beginning a reply, and,
|
||||||
// - Replying to zero or one users, places the cursor at the end
|
// - Replying to zero or one users, places the cursor at the end
|
||||||
|
@ -206,7 +214,7 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
// - Replying to more than one user, selects any usernames past
|
// - Replying to more than one user, selects any usernames past
|
||||||
// the first; this provides a convenient shortcut to drop
|
// the first; this provides a convenient shortcut to drop
|
||||||
// everyone else from the conversation.
|
// everyone else from the conversation.
|
||||||
componentDidUpdate (prevProps) {
|
_updateFocusAndSelection = (prevProps) => {
|
||||||
const {
|
const {
|
||||||
textarea,
|
textarea,
|
||||||
spoilerText,
|
spoilerText,
|
||||||
|
|
|
@ -59,7 +59,7 @@ class ColumnSettings extends React.PureComponent {
|
||||||
{this.modeLabel(mode)}
|
{this.modeLabel(mode)}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<NonceProvider nonce={document.querySelector('meta[name=style-nonce]').content}>
|
<NonceProvider nonce={document.querySelector('meta[name=style-nonce]').content} cacheKey='tags'>
|
||||||
<AsyncSelect
|
<AsyncSelect
|
||||||
isMulti
|
isMulti
|
||||||
autoFocus
|
autoFocus
|
||||||
|
|
|
@ -70,8 +70,12 @@ class ColumnsArea extends ImmutablePureComponent {
|
||||||
openSettings: PropTypes.func,
|
openSettings: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Corresponds to (max-width: 600px + (285px * 1) + (10px * 1)) in SCSS
|
||||||
|
mediaQuery = 'matchMedia' in window && window.matchMedia('(max-width: 895px)');
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
shouldAnimate: false,
|
shouldAnimate: false,
|
||||||
|
renderComposePanel: !(this.mediaQuery && this.mediaQuery.matches),
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps() {
|
componentWillReceiveProps() {
|
||||||
|
@ -85,6 +89,11 @@ class ColumnsArea extends ImmutablePureComponent {
|
||||||
this.node.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : false);
|
this.node.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.mediaQuery) {
|
||||||
|
this.mediaQuery.addEventListener('change', this.handleLayoutChange);
|
||||||
|
this.setState({ renderComposePanel: !this.mediaQuery.matches });
|
||||||
|
}
|
||||||
|
|
||||||
this.lastIndex = getIndex(this.context.router.history.location.pathname);
|
this.lastIndex = getIndex(this.context.router.history.location.pathname);
|
||||||
this.isRtlLayout = document.getElementsByTagName('body')[0].classList.contains('rtl');
|
this.isRtlLayout = document.getElementsByTagName('body')[0].classList.contains('rtl');
|
||||||
|
|
||||||
|
@ -114,6 +123,10 @@ class ColumnsArea extends ImmutablePureComponent {
|
||||||
if (!this.props.singleColumn) {
|
if (!this.props.singleColumn) {
|
||||||
this.node.removeEventListener('wheel', this.handleWheel);
|
this.node.removeEventListener('wheel', this.handleWheel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.mediaQuery) {
|
||||||
|
this.mediaQuery.removeEventListener('change', this.handleLayoutChange);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleChildrenContentChange() {
|
handleChildrenContentChange() {
|
||||||
|
@ -123,6 +136,10 @@ class ColumnsArea extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleLayoutChange = (e) => {
|
||||||
|
this.setState({ renderComposePanel: !e.matches });
|
||||||
|
}
|
||||||
|
|
||||||
handleSwipe = (index) => {
|
handleSwipe = (index) => {
|
||||||
this.pendingIndex = index;
|
this.pendingIndex = index;
|
||||||
|
|
||||||
|
@ -186,7 +203,7 @@ class ColumnsArea extends ImmutablePureComponent {
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { columns, children, singleColumn, swipeToChangeColumns, intl, navbarUnder, openSettings } = this.props;
|
const { columns, children, singleColumn, swipeToChangeColumns, intl, navbarUnder, openSettings } = this.props;
|
||||||
const { shouldAnimate } = this.state;
|
const { shouldAnimate, renderComposePanel } = this.state;
|
||||||
|
|
||||||
const columnIndex = getIndex(this.context.router.history.location.pathname);
|
const columnIndex = getIndex(this.context.router.history.location.pathname);
|
||||||
|
|
||||||
|
@ -205,7 +222,7 @@ class ColumnsArea extends ImmutablePureComponent {
|
||||||
<div className='columns-area__panels'>
|
<div className='columns-area__panels'>
|
||||||
<div className='columns-area__panels__pane columns-area__panels__pane--compositional'>
|
<div className='columns-area__panels__pane columns-area__panels__pane--compositional'>
|
||||||
<div className='columns-area__panels__pane__inner'>
|
<div className='columns-area__panels__pane__inner'>
|
||||||
<ComposePanel />
|
{renderComposePanel && <ComposePanel />}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -133,7 +133,15 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidMount () {
|
||||||
|
this._updateFocusAndSelection({ });
|
||||||
|
}
|
||||||
|
|
||||||
componentDidUpdate (prevProps) {
|
componentDidUpdate (prevProps) {
|
||||||
|
this._updateFocusAndSelection(prevProps);
|
||||||
|
}
|
||||||
|
|
||||||
|
_updateFocusAndSelection = (prevProps) => {
|
||||||
// This statement does several things:
|
// This statement does several things:
|
||||||
// - If we're beginning a reply, and,
|
// - If we're beginning a reply, and,
|
||||||
// - Replying to zero or one users, places the cursor at the end of the textbox.
|
// - Replying to zero or one users, places the cursor at the end of the textbox.
|
||||||
|
|
|
@ -59,7 +59,7 @@ class ColumnSettings extends React.PureComponent {
|
||||||
{this.modeLabel(mode)}
|
{this.modeLabel(mode)}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<NonceProvider nonce={document.querySelector('meta[name=style-nonce]').content}>
|
<NonceProvider nonce={document.querySelector('meta[name=style-nonce]').content} cacheKey='tags'>
|
||||||
<AsyncSelect
|
<AsyncSelect
|
||||||
isMulti
|
isMulti
|
||||||
autoFocus
|
autoFocus
|
||||||
|
|
|
@ -70,8 +70,12 @@ class ColumnsArea extends ImmutablePureComponent {
|
||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Corresponds to (max-width: 600px + (285px * 1) + (10px * 1)) in SCSS
|
||||||
|
mediaQuery = 'matchMedia' in window && window.matchMedia('(max-width: 895px)');
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
shouldAnimate: false,
|
shouldAnimate: false,
|
||||||
|
renderComposePanel: !(this.mediaQuery && this.mediaQuery.matches),
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps() {
|
componentWillReceiveProps() {
|
||||||
|
@ -85,6 +89,11 @@ class ColumnsArea extends ImmutablePureComponent {
|
||||||
this.node.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : false);
|
this.node.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.mediaQuery) {
|
||||||
|
this.mediaQuery.addEventListener('change', this.handleLayoutChange);
|
||||||
|
this.setState({ renderComposePanel: !this.mediaQuery.matches });
|
||||||
|
}
|
||||||
|
|
||||||
this.lastIndex = getIndex(this.context.router.history.location.pathname);
|
this.lastIndex = getIndex(this.context.router.history.location.pathname);
|
||||||
this.isRtlLayout = document.getElementsByTagName('body')[0].classList.contains('rtl');
|
this.isRtlLayout = document.getElementsByTagName('body')[0].classList.contains('rtl');
|
||||||
|
|
||||||
|
@ -114,6 +123,10 @@ class ColumnsArea extends ImmutablePureComponent {
|
||||||
if (!this.props.singleColumn) {
|
if (!this.props.singleColumn) {
|
||||||
this.node.removeEventListener('wheel', this.handleWheel);
|
this.node.removeEventListener('wheel', this.handleWheel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.mediaQuery) {
|
||||||
|
this.mediaQuery.removeEventListener('change', this.handleLayoutChange);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleChildrenContentChange() {
|
handleChildrenContentChange() {
|
||||||
|
@ -123,6 +136,10 @@ class ColumnsArea extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleLayoutChange = (e) => {
|
||||||
|
this.setState({ renderComposePanel: !e.matches });
|
||||||
|
}
|
||||||
|
|
||||||
handleSwipe = (index) => {
|
handleSwipe = (index) => {
|
||||||
this.pendingIndex = index;
|
this.pendingIndex = index;
|
||||||
|
|
||||||
|
@ -186,7 +203,7 @@ class ColumnsArea extends ImmutablePureComponent {
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { columns, children, singleColumn, isModalOpen, intl } = this.props;
|
const { columns, children, singleColumn, isModalOpen, intl } = this.props;
|
||||||
const { shouldAnimate } = this.state;
|
const { shouldAnimate, renderComposePanel } = this.state;
|
||||||
|
|
||||||
const columnIndex = getIndex(this.context.router.history.location.pathname);
|
const columnIndex = getIndex(this.context.router.history.location.pathname);
|
||||||
|
|
||||||
|
@ -205,7 +222,7 @@ class ColumnsArea extends ImmutablePureComponent {
|
||||||
<div className='columns-area__panels'>
|
<div className='columns-area__panels'>
|
||||||
<div className='columns-area__panels__pane columns-area__panels__pane--compositional'>
|
<div className='columns-area__panels__pane columns-area__panels__pane--compositional'>
|
||||||
<div className='columns-area__panels__pane__inner'>
|
<div className='columns-area__panels__pane__inner'>
|
||||||
<ComposePanel />
|
{renderComposePanel && <ComposePanel />}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -707,7 +707,6 @@ html {
|
||||||
.public-account-bio,
|
.public-account-bio,
|
||||||
.hero-widget__text {
|
.hero-widget__text {
|
||||||
background: $account-background-color;
|
background: $account-background-color;
|
||||||
border: 1px solid lighten($ui-base-color, 8%);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
|
|
|
@ -43,9 +43,9 @@ class ActivityPub::Activity::Announce < ActivityPub::Activity
|
||||||
end
|
end
|
||||||
|
|
||||||
def visibility_from_audience
|
def visibility_from_audience
|
||||||
if audience_to.include?(ActivityPub::TagManager::COLLECTIONS[:public])
|
if audience_to.any? { |to| ActivityPub::TagManager.instance.public_collection?(to) }
|
||||||
:public
|
:public
|
||||||
elsif audience_cc.include?(ActivityPub::TagManager::COLLECTIONS[:public])
|
elsif audience_cc.any? { |cc| ActivityPub::TagManager.instance.public_collection?(cc) }
|
||||||
:unlisted
|
:unlisted
|
||||||
elsif audience_to.include?(@account.followers_url)
|
elsif audience_to.include?(@account.followers_url)
|
||||||
:private
|
:private
|
||||||
|
|
|
@ -123,7 +123,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
|
||||||
|
|
||||||
def process_audience
|
def process_audience
|
||||||
(audience_to + audience_cc).uniq.each do |audience|
|
(audience_to + audience_cc).uniq.each do |audience|
|
||||||
next if audience == ActivityPub::TagManager::COLLECTIONS[:public]
|
next if ActivityPub::TagManager.instance.public_collection?(audience)
|
||||||
|
|
||||||
# Unlike with tags, there is no point in resolving accounts we don't already
|
# Unlike with tags, there is no point in resolving accounts we don't already
|
||||||
# know here, because silent mentions would only be used for local access
|
# know here, because silent mentions would only be used for local access
|
||||||
|
@ -356,9 +356,9 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
|
||||||
end
|
end
|
||||||
|
|
||||||
def visibility_from_audience
|
def visibility_from_audience
|
||||||
if audience_to.include?(ActivityPub::TagManager::COLLECTIONS[:public])
|
if audience_to.any? { |to| ActivityPub::TagManager.instance.public_collection?(to) }
|
||||||
:public
|
:public
|
||||||
elsif audience_cc.include?(ActivityPub::TagManager::COLLECTIONS[:public])
|
elsif audience_cc.any? { |cc| ActivityPub::TagManager.instance.public_collection?(cc) }
|
||||||
:unlisted
|
:unlisted
|
||||||
elsif audience_to.include?(@account.followers_url)
|
elsif audience_to.include?(@account.followers_url)
|
||||||
:private
|
:private
|
||||||
|
|
|
@ -12,6 +12,10 @@ class ActivityPub::TagManager
|
||||||
public: 'https://www.w3.org/ns/activitystreams#Public',
|
public: 'https://www.w3.org/ns/activitystreams#Public',
|
||||||
}.freeze
|
}.freeze
|
||||||
|
|
||||||
|
def public_collection?(uri)
|
||||||
|
uri == COLLECTIONS[:public] || uri == 'as:Public' || uri == 'Public'
|
||||||
|
end
|
||||||
|
|
||||||
def url_for(target)
|
def url_for(target)
|
||||||
return target.url if target.respond_to?(:local?) && !target.local?
|
return target.url if target.respond_to?(:local?) && !target.local?
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ class DeliveryFailureTracker
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
def without_unavailable(urls)
|
def without_unavailable(urls)
|
||||||
unavailable_domains_map = Rails.cache.fetch('unavailable_domains') { UnavailableDomain.pluck(:domain).each_with_object({}) { |domain, hash| hash[domain] = true } }
|
unavailable_domains_map = Rails.cache.fetch('unavailable_domains') { UnavailableDomain.pluck(:domain).index_with(true) }
|
||||||
|
|
||||||
urls.reject do |url|
|
urls.reject do |url|
|
||||||
host = Addressable::URI.parse(url).normalized_host
|
host = Addressable::URI.parse(url).normalized_host
|
||||||
|
|
|
@ -591,12 +591,12 @@ class FeedManager
|
||||||
arr
|
arr
|
||||||
end
|
end
|
||||||
|
|
||||||
crutches[:following] = Follow.where(account_id: receiver_id, target_account_id: statuses.map(&:in_reply_to_account_id).compact).pluck(:target_account_id).each_with_object({}) { |id, mapping| mapping[id] = true }
|
crutches[:following] = Follow.where(account_id: receiver_id, target_account_id: statuses.map(&:in_reply_to_account_id).compact).pluck(:target_account_id).index_with(true)
|
||||||
crutches[:hiding_reblogs] = Follow.where(account_id: receiver_id, target_account_id: statuses.map { |s| s.account_id if s.reblog? }.compact, show_reblogs: false).pluck(:target_account_id).each_with_object({}) { |id, mapping| mapping[id] = true }
|
crutches[:hiding_reblogs] = Follow.where(account_id: receiver_id, target_account_id: statuses.map { |s| s.account_id if s.reblog? }.compact, show_reblogs: false).pluck(:target_account_id).index_with(true)
|
||||||
crutches[:blocking] = Block.where(account_id: receiver_id, target_account_id: check_for_blocks).pluck(:target_account_id).each_with_object({}) { |id, mapping| mapping[id] = true }
|
crutches[:blocking] = Block.where(account_id: receiver_id, target_account_id: check_for_blocks).pluck(:target_account_id).index_with(true)
|
||||||
crutches[:muting] = Mute.where(account_id: receiver_id, target_account_id: check_for_blocks).pluck(:target_account_id).each_with_object({}) { |id, mapping| mapping[id] = true }
|
crutches[:muting] = Mute.where(account_id: receiver_id, target_account_id: check_for_blocks).pluck(:target_account_id).index_with(true)
|
||||||
crutches[:domain_blocking] = AccountDomainBlock.where(account_id: receiver_id, domain: statuses.map { |s| s.reblog&.account&.domain }.compact).pluck(:domain).each_with_object({}) { |domain, mapping| mapping[domain] = true }
|
crutches[:domain_blocking] = AccountDomainBlock.where(account_id: receiver_id, domain: statuses.map { |s| s.reblog&.account&.domain }.compact).pluck(:domain).index_with(true)
|
||||||
crutches[:blocked_by] = Block.where(target_account_id: receiver_id, account_id: statuses.map { |s| s.reblog&.account_id }.compact).pluck(:account_id).each_with_object({}) { |id, mapping| mapping[id] = true }
|
crutches[:blocked_by] = Block.where(target_account_id: receiver_id, account_id: statuses.map { |s| s.reblog&.account_id }.compact).pluck(:account_id).index_with(true)
|
||||||
|
|
||||||
crutches
|
crutches
|
||||||
end
|
end
|
||||||
|
|
|
@ -64,7 +64,7 @@ module Settings
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
def default_settings
|
def default_settings
|
||||||
defaulting = DEFAULTING_TO_UNSCOPED.each_with_object({}) { |k, h| h[k] = Setting[k] }
|
defaulting = DEFAULTING_TO_UNSCOPED.index_with { |k| Setting[k] }
|
||||||
Setting.default_settings.merge!(defaulting)
|
Setting.default_settings.merge!(defaulting)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -67,7 +67,7 @@ module AccountInteractions
|
||||||
private
|
private
|
||||||
|
|
||||||
def follow_mapping(query, field)
|
def follow_mapping(query, field)
|
||||||
query.pluck(field).each_with_object({}) { |id, mapping| mapping[id] = true }
|
query.pluck(field).index_with(true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,6 @@ module Omniauthable
|
||||||
def user_params_from_auth(email, auth)
|
def user_params_from_auth(email, auth)
|
||||||
{
|
{
|
||||||
email: email || "#{TEMP_EMAIL_PREFIX}-#{auth.uid}-#{auth.provider}.com",
|
email: email || "#{TEMP_EMAIL_PREFIX}-#{auth.uid}-#{auth.provider}.com",
|
||||||
password: Devise.friendly_token[0, 20],
|
|
||||||
agreement: true,
|
agreement: true,
|
||||||
external: true,
|
external: true,
|
||||||
account_attributes: {
|
account_attributes: {
|
||||||
|
|
|
@ -32,7 +32,7 @@ class Report < ApplicationRecord
|
||||||
|
|
||||||
scope :unresolved, -> { where(action_taken: false) }
|
scope :unresolved, -> { where(action_taken: false) }
|
||||||
scope :resolved, -> { where(action_taken: true) }
|
scope :resolved, -> { where(action_taken: true) }
|
||||||
scope :with_accounts, -> { includes([:account, :target_account, :action_taken_by_account, :assigned_account].each_with_object({}) { |k, h| h[k] = { user: [:invite_request, :invite] } }) }
|
scope :with_accounts, -> { includes([:account, :target_account, :action_taken_by_account, :assigned_account].index_with({ user: [:invite_request, :invite] })) }
|
||||||
|
|
||||||
validates :comment, length: { maximum: 1000 }
|
validates :comment, length: { maximum: 1000 }
|
||||||
|
|
||||||
|
|
|
@ -468,7 +468,7 @@ class User < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_email_dns?
|
def validate_email_dns?
|
||||||
email_changed? && !(Rails.env.test? || Rails.env.development?)
|
email_changed? && !external? && !(Rails.env.test? || Rails.env.development?)
|
||||||
end
|
end
|
||||||
|
|
||||||
def invite_text_required?
|
def invite_text_required?
|
||||||
|
|
|
@ -188,8 +188,7 @@ class DeleteAccountService < BaseService
|
||||||
ids = favourites.pluck(:status_id)
|
ids = favourites.pluck(:status_id)
|
||||||
StatusStat.where(status_id: ids).update_all('favourites_count = GREATEST(0, favourites_count - 1)')
|
StatusStat.where(status_id: ids).update_all('favourites_count = GREATEST(0, favourites_count - 1)')
|
||||||
Chewy.strategy.current.update(StatusesIndex::Status, ids) if Chewy.enabled?
|
Chewy.strategy.current.update(StatusesIndex::Status, ids) if Chewy.enabled?
|
||||||
# Rails.cache.delete_multi would be better, but we don't have it yet
|
Rails.cache.delete_multi(ids.map { |id| "statuses/#{id}" })
|
||||||
ids.each { |id| Rails.cache.delete("statuses/#{id}") }
|
|
||||||
favourites.delete_all
|
favourites.delete_all
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -45,7 +45,7 @@ class ImportService < BaseService
|
||||||
items = @data.take(ROWS_PROCESSING_LIMIT).map { |row| row['#domain'].strip }
|
items = @data.take(ROWS_PROCESSING_LIMIT).map { |row| row['#domain'].strip }
|
||||||
|
|
||||||
if @import.overwrite?
|
if @import.overwrite?
|
||||||
presence_hash = items.each_with_object({}) { |id, mapping| mapping[id] = true }
|
presence_hash = items.index_with(true)
|
||||||
|
|
||||||
@account.domain_blocks.find_each do |domain_block|
|
@account.domain_blocks.find_each do |domain_block|
|
||||||
if presence_hash[domain_block.domain]
|
if presence_hash[domain_block.domain]
|
||||||
|
@ -96,7 +96,7 @@ class ImportService < BaseService
|
||||||
items = @data.take(ROWS_PROCESSING_LIMIT).map { |row| row['#uri'].strip }
|
items = @data.take(ROWS_PROCESSING_LIMIT).map { |row| row['#uri'].strip }
|
||||||
|
|
||||||
if @import.overwrite?
|
if @import.overwrite?
|
||||||
presence_hash = items.each_with_object({}) { |id, mapping| mapping[id] = true }
|
presence_hash = items.index_with(true)
|
||||||
|
|
||||||
@account.bookmarks.find_each do |bookmark|
|
@account.bookmarks.find_each do |bookmark|
|
||||||
if presence_hash[bookmark.status.uri]
|
if presence_hash[bookmark.status.uri]
|
||||||
|
|
|
@ -10,7 +10,7 @@ class EmailMxValidator < ActiveModel::Validator
|
||||||
|
|
||||||
if domain.blank?
|
if domain.blank?
|
||||||
user.errors.add(:email, :invalid)
|
user.errors.add(:email, :invalid)
|
||||||
else
|
elsif !on_allowlist?(domain)
|
||||||
ips, hostnames = resolve_mx(domain)
|
ips, hostnames = resolve_mx(domain)
|
||||||
|
|
||||||
if ips.empty?
|
if ips.empty?
|
||||||
|
@ -33,6 +33,12 @@ class EmailMxValidator < ActiveModel::Validator
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def on_allowlist?(domain)
|
||||||
|
return false if Rails.configuration.x.email_domains_whitelist.blank?
|
||||||
|
|
||||||
|
Rails.configuration.x.email_domains_whitelist.include?(domain)
|
||||||
|
end
|
||||||
|
|
||||||
def resolve_mx(domain)
|
def resolve_mx(domain)
|
||||||
hostnames = []
|
hostnames = []
|
||||||
ips = []
|
ips = []
|
||||||
|
|
|
@ -4,6 +4,6 @@
|
||||||
= image_tag action_log.account.avatar.url(:original), alt: '', width: 40, height: 40, class: 'avatar'
|
= image_tag action_log.account.avatar.url(:original), alt: '', width: 40, height: 40, class: 'avatar'
|
||||||
.log-entry__content
|
.log-entry__content
|
||||||
.log-entry__title
|
.log-entry__title
|
||||||
= t("admin.action_logs.actions.#{action_log.action}_#{action_log.target_type.underscore}", name: content_tag(:span, action_log.account.username, class: 'username'), target: content_tag(:span, log_target(action_log), class: 'target')).html_safe
|
= t("admin.action_logs.actions.#{action_log.action}_#{action_log.target_type.underscore}_html", name: content_tag(:span, action_log.account.username, class: 'username'), target: content_tag(:span, log_target(action_log), class: 'target'))
|
||||||
.log-entry__timestamp
|
.log-entry__timestamp
|
||||||
%time.formatted{ datetime: action_log.created_at.iso8601 }
|
%time.formatted{ datetime: action_log.created_at.iso8601 }
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
.speech-bubble.positive
|
.speech-bubble.positive
|
||||||
.speech-bubble__bubble
|
.speech-bubble__bubble
|
||||||
= t("admin.action_logs.actions.#{action_log.action}_#{action_log.target_type.underscore}", name: content_tag(:span, action_log.account.username, class: 'username'), target: content_tag(:span, log_target(action_log), class: 'target')).html_safe
|
= t("admin.action_logs.actions.#{action_log.action}_#{action_log.target_type.underscore}_html", name: content_tag(:span, action_log.account.username, class: 'username'), target: content_tag(:span, log_target(action_log), class: 'target'))
|
||||||
.speech-bubble__owner
|
.speech-bubble__owner
|
||||||
= admin_account_link_to(action_log.account)
|
= admin_account_link_to(action_log.account)
|
||||||
%time.formatted{ datetime: action_log.created_at.iso8601 }= l action_log.created_at
|
%time.formatted{ datetime: action_log.created_at.iso8601 }= l action_log.created_at
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
= render partial: 'layouts/theme', object: @theme
|
= render partial: 'layouts/theme', object: @theme
|
||||||
|
|
||||||
- if Setting.custom_css.present?
|
- if Setting.custom_css.present?
|
||||||
= stylesheet_link_tag custom_css_path, media: 'all'
|
= stylesheet_link_tag custom_css_path, host: request.host, media: 'all'
|
||||||
|
|
||||||
%body{ class: body_classes }
|
%body{ class: body_classes }
|
||||||
= content_for?(:content) ? yield(:content) : yield
|
= content_for?(:content) ? yield(:content) : yield
|
||||||
|
|
16
bin/setup
16
bin/setup
|
@ -1,6 +1,5 @@
|
||||||
#!/usr/bin/env ruby
|
#!/usr/bin/env ruby
|
||||||
require 'fileutils'
|
require "fileutils"
|
||||||
include FileUtils
|
|
||||||
|
|
||||||
# path to your application root.
|
# path to your application root.
|
||||||
APP_ROOT = File.expand_path('..', __dir__)
|
APP_ROOT = File.expand_path('..', __dir__)
|
||||||
|
@ -9,22 +8,25 @@ def system!(*args)
|
||||||
system(*args) || abort("\n== Command #{args} failed ==")
|
system(*args) || abort("\n== Command #{args} failed ==")
|
||||||
end
|
end
|
||||||
|
|
||||||
chdir APP_ROOT do
|
FileUtils.chdir APP_ROOT do
|
||||||
# This script is a starting point to setup your application.
|
# This script is a way to set up or update your development environment automatically.
|
||||||
|
# This script is idempotent, so that you can run it at any time and get an expectable outcome.
|
||||||
# Add necessary setup steps to this file.
|
# Add necessary setup steps to this file.
|
||||||
|
|
||||||
puts '== Installing dependencies =='
|
puts '== Installing dependencies =='
|
||||||
system! 'gem install bundler --conservative'
|
system! 'gem install bundler --conservative'
|
||||||
system('bundle check') || system!('bundle install')
|
system('bundle check') || system!('bundle install')
|
||||||
system!('yarn install')
|
|
||||||
|
# Install JavaScript dependencies
|
||||||
|
system! 'bin/yarn'
|
||||||
|
|
||||||
# puts "\n== Copying sample files =="
|
# puts "\n== Copying sample files =="
|
||||||
# unless File.exist?('config/database.yml')
|
# unless File.exist?('config/database.yml')
|
||||||
# cp 'config/database.yml.sample', 'config/database.yml'
|
# FileUtils.cp 'config/database.yml.sample', 'config/database.yml'
|
||||||
# end
|
# end
|
||||||
|
|
||||||
puts "\n== Preparing database =="
|
puts "\n== Preparing database =="
|
||||||
system! 'bin/rails db:setup'
|
system! 'bin/rails db:prepare'
|
||||||
|
|
||||||
puts "\n== Removing old logs and tempfiles =="
|
puts "\n== Removing old logs and tempfiles =="
|
||||||
system! 'bin/rails log:clear tmp:clear'
|
system! 'bin/rails log:clear tmp:clear'
|
||||||
|
|
12
bin/yarn
12
bin/yarn
|
@ -1,9 +1,15 @@
|
||||||
#!/usr/bin/env ruby
|
#!/usr/bin/env ruby
|
||||||
APP_ROOT = File.expand_path('..', __dir__)
|
APP_ROOT = File.expand_path('..', __dir__)
|
||||||
Dir.chdir(APP_ROOT) do
|
Dir.chdir(APP_ROOT) do
|
||||||
begin
|
yarn = ENV["PATH"].split(File::PATH_SEPARATOR).
|
||||||
exec "yarnpkg", *ARGV
|
select { |dir| File.expand_path(dir) != __dir__ }.
|
||||||
rescue Errno::ENOENT
|
product(["yarn", "yarn.cmd", "yarn.ps1"]).
|
||||||
|
map { |dir, file| File.expand_path(file, dir) }.
|
||||||
|
find { |file| File.executable?(file) }
|
||||||
|
|
||||||
|
if yarn
|
||||||
|
exec yarn, *ARGV
|
||||||
|
else
|
||||||
$stderr.puts "Yarn executable was not detected in the system."
|
$stderr.puts "Yarn executable was not detected in the system."
|
||||||
$stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install"
|
$stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install"
|
||||||
exit 1
|
exit 1
|
||||||
|
|
|
@ -39,7 +39,8 @@ require_relative '../lib/mastodon/redis_config'
|
||||||
module Mastodon
|
module Mastodon
|
||||||
class Application < Rails::Application
|
class Application < Rails::Application
|
||||||
# Initialize configuration defaults for originally generated Rails version.
|
# Initialize configuration defaults for originally generated Rails version.
|
||||||
config.load_defaults 5.2
|
config.load_defaults 6.1
|
||||||
|
config.add_autoload_paths_to_load_path = false
|
||||||
|
|
||||||
# Settings in config/environments/* take precedence over those specified here.
|
# Settings in config/environments/* take precedence over those specified here.
|
||||||
# Application configuration should go into files in config/initializers
|
# Application configuration should go into files in config/initializers
|
||||||
|
|
|
@ -44,6 +44,13 @@ Rails.application.configure do
|
||||||
# Allow to specify public IP of reverse proxy if it's needed
|
# Allow to specify public IP of reverse proxy if it's needed
|
||||||
config.action_dispatch.trusted_proxies = ENV['TRUSTED_PROXY_IP'].split.map { |item| IPAddr.new(item) } if ENV['TRUSTED_PROXY_IP'].present?
|
config.action_dispatch.trusted_proxies = ENV['TRUSTED_PROXY_IP'].split.map { |item| IPAddr.new(item) } if ENV['TRUSTED_PROXY_IP'].present?
|
||||||
|
|
||||||
|
config.force_ssl = true
|
||||||
|
config.ssl_options = {
|
||||||
|
redirect: {
|
||||||
|
exclude: -> request { request.path.start_with?('/health') || request.headers["Host"].end_with?('.onion') }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# Use the lowest log level to ensure availability of diagnostic information
|
# Use the lowest log level to ensure availability of diagnostic information
|
||||||
# when problems arise.
|
# when problems arise.
|
||||||
config.log_level = ENV.fetch('RAILS_LOG_LEVEL', 'info').to_sym
|
config.log_level = ENV.fetch('RAILS_LOG_LEVEL', 'info').to_sym
|
||||||
|
|
|
@ -16,7 +16,7 @@ ALLOWED_DUPLICATES = [20180410220657, 20180831171112].freeze
|
||||||
|
|
||||||
module ActiveRecord
|
module ActiveRecord
|
||||||
class Migrator
|
class Migrator
|
||||||
def self.new(direction, migrations, target_version = nil)
|
def self.new(direction, migrations, schema_migration, target_version = nil)
|
||||||
migrated = Set.new(Base.connection.migration_context.get_all_versions)
|
migrated = Set.new(Base.connection.migration_context.get_all_versions)
|
||||||
|
|
||||||
migrations.group_by(&:name).each do |name, duplicates|
|
migrations.group_by(&:name).each do |name, duplicates|
|
||||||
|
@ -34,7 +34,7 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
super(direction, migrations, target_version)
|
super(direction, migrations, schema_migration, target_version)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
# Be sure to restart your server when you modify this file.
|
# Be sure to restart your server when you modify this file.
|
||||||
|
|
||||||
# ApplicationController.renderer.defaults.merge!(
|
# ActiveSupport::Reloader.to_prepare do
|
||||||
# http_host: 'example.org',
|
# ApplicationController.renderer.defaults.merge!(
|
||||||
# https: false
|
# http_host: 'example.org',
|
||||||
# )
|
# https: false
|
||||||
|
# )
|
||||||
|
# end
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
# Be sure to restart your server when you modify this file.
|
# Be sure to restart your server when you modify this file.
|
||||||
|
|
||||||
# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
|
# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
|
||||||
# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
|
# Rails.backtrace_cleaner.add_silencer { |line| /my_noisy_library/.match?(line) }
|
||||||
|
|
||||||
# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
|
# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code
|
||||||
# Rails.backtrace_cleaner.remove_silencers!
|
# by setting BACKTRACE=1 before calling your invocation, like "BACKTRACE=1 ./bin/rails runner 'MyClass.perform'".
|
||||||
|
Rails.backtrace_cleaner.remove_silencers! if ENV["BACKTRACE"]
|
||||||
|
|
|
@ -51,17 +51,7 @@ end
|
||||||
|
|
||||||
Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) }
|
Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) }
|
||||||
|
|
||||||
# Monkey-patching Rails 5
|
Rails.application.config.content_security_policy_nonce_directives = %w(style-src)
|
||||||
module ActionDispatch
|
|
||||||
class ContentSecurityPolicy
|
|
||||||
def nonce_directive?(directive)
|
|
||||||
directive == 'style-src'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Rails 6 would require the following instead:
|
|
||||||
# Rails.application.config.content_security_policy_nonce_directives = %w(style-src)
|
|
||||||
|
|
||||||
PgHero::HomeController.content_security_policy do |p|
|
PgHero::HomeController.content_security_policy do |p|
|
||||||
p.script_src :self, :unsafe_inline, assets_host
|
p.script_src :self, :unsafe_inline, assets_host
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
# Define an application-wide HTTP permissions policy. For further
|
||||||
|
# information see https://developers.google.com/web/updates/2018/06/feature-policy
|
||||||
|
#
|
||||||
|
# Rails.application.config.permissions_policy do |f|
|
||||||
|
# f.camera :none
|
||||||
|
# f.gyroscope :none
|
||||||
|
# f.microphone :none
|
||||||
|
# f.usb :none
|
||||||
|
# f.fullscreen :self
|
||||||
|
# f.payment :self, "https://secure.example.com"
|
||||||
|
# end
|
|
@ -0,0 +1,8 @@
|
||||||
|
# Since Rails 6.1, ActionView adds preload links for javascript files
|
||||||
|
# in the Links header per default.
|
||||||
|
|
||||||
|
# In our case, that will bloat headers too much and potentially cause
|
||||||
|
# issues with reverse proxies. Furhermore, we don't need those links,
|
||||||
|
# as we already output them as HTML link tags.
|
||||||
|
|
||||||
|
Rails.application.config.action_view.preload_links_header = false
|
|
@ -261,46 +261,46 @@ en:
|
||||||
update_domain_block: Update Domain Block
|
update_domain_block: Update Domain Block
|
||||||
update_status: Update Status
|
update_status: Update Status
|
||||||
actions:
|
actions:
|
||||||
assigned_to_self_report: "%{name} assigned report %{target} to themselves"
|
assigned_to_self_report_html: "%{name} assigned report %{target} to themselves"
|
||||||
change_email_user: "%{name} changed the e-mail address of user %{target}"
|
change_email_user_html: "%{name} changed the e-mail address of user %{target}"
|
||||||
confirm_user: "%{name} confirmed e-mail address of user %{target}"
|
confirm_user_html: "%{name} confirmed e-mail address of user %{target}"
|
||||||
create_account_warning: "%{name} sent a warning to %{target}"
|
create_account_warning_html: "%{name} sent a warning to %{target}"
|
||||||
create_announcement: "%{name} created new announcement %{target}"
|
create_announcement_html: "%{name} created new announcement %{target}"
|
||||||
create_custom_emoji: "%{name} uploaded new emoji %{target}"
|
create_custom_emoji_html: "%{name} uploaded new emoji %{target}"
|
||||||
create_domain_allow: "%{name} allowed federation with domain %{target}"
|
create_domain_allow_html: "%{name} allowed federation with domain %{target}"
|
||||||
create_domain_block: "%{name} blocked domain %{target}"
|
create_domain_block_html: "%{name} blocked domain %{target}"
|
||||||
create_email_domain_block: "%{name} blocked e-mail domain %{target}"
|
create_email_domain_block_html: "%{name} blocked e-mail domain %{target}"
|
||||||
create_ip_block: "%{name} created rule for IP %{target}"
|
create_ip_block_html: "%{name} created rule for IP %{target}"
|
||||||
demote_user: "%{name} demoted user %{target}"
|
demote_user_html: "%{name} demoted user %{target}"
|
||||||
destroy_announcement: "%{name} deleted announcement %{target}"
|
destroy_announcement_html: "%{name} deleted announcement %{target}"
|
||||||
destroy_custom_emoji: "%{name} destroyed emoji %{target}"
|
destroy_custom_emoji_html: "%{name} destroyed emoji %{target}"
|
||||||
destroy_domain_allow: "%{name} disallowed federation with domain %{target}"
|
destroy_domain_allow_html: "%{name} disallowed federation with domain %{target}"
|
||||||
destroy_domain_block: "%{name} unblocked domain %{target}"
|
destroy_domain_block_html: "%{name} unblocked domain %{target}"
|
||||||
destroy_email_domain_block: "%{name} unblocked e-mail domain %{target}"
|
destroy_email_domain_block_html: "%{name} unblocked e-mail domain %{target}"
|
||||||
destroy_ip_block: "%{name} deleted rule for IP %{target}"
|
destroy_ip_block_html: "%{name} deleted rule for IP %{target}"
|
||||||
destroy_status: "%{name} removed status by %{target}"
|
destroy_status_html: "%{name} removed status by %{target}"
|
||||||
disable_2fa_user: "%{name} disabled two factor requirement for user %{target}"
|
disable_2fa_user_html: "%{name} disabled two factor requirement for user %{target}"
|
||||||
disable_custom_emoji: "%{name} disabled emoji %{target}"
|
disable_custom_emoji_html: "%{name} disabled emoji %{target}"
|
||||||
disable_user: "%{name} disabled login for user %{target}"
|
disable_user_html: "%{name} disabled login for user %{target}"
|
||||||
enable_custom_emoji: "%{name} enabled emoji %{target}"
|
enable_custom_emoji_html: "%{name} enabled emoji %{target}"
|
||||||
enable_user: "%{name} enabled login for user %{target}"
|
enable_user_html: "%{name} enabled login for user %{target}"
|
||||||
memorialize_account: "%{name} turned %{target}'s account into a memoriam page"
|
memorialize_account_html: "%{name} turned %{target}'s account into a memoriam page"
|
||||||
promote_user: "%{name} promoted user %{target}"
|
promote_user_html: "%{name} promoted user %{target}"
|
||||||
remove_avatar_user: "%{name} removed %{target}'s avatar"
|
remove_avatar_user_html: "%{name} removed %{target}'s avatar"
|
||||||
reopen_report: "%{name} reopened report %{target}"
|
reopen_report_html: "%{name} reopened report %{target}"
|
||||||
reset_password_user: "%{name} reset password of user %{target}"
|
reset_password_user_html: "%{name} reset password of user %{target}"
|
||||||
resolve_report: "%{name} resolved report %{target}"
|
resolve_report_html: "%{name} resolved report %{target}"
|
||||||
sensitive_account: "%{name} marked %{target}'s media as sensitive"
|
sensitive_account_html: "%{name} marked %{target}'s media as sensitive"
|
||||||
silence_account: "%{name} silenced %{target}'s account"
|
silence_account_html: "%{name} silenced %{target}'s account"
|
||||||
suspend_account: "%{name} suspended %{target}'s account"
|
suspend_account_html: "%{name} suspended %{target}'s account"
|
||||||
unassigned_report: "%{name} unassigned report %{target}"
|
unassigned_report_html: "%{name} unassigned report %{target}"
|
||||||
unsensitive_account: "%{name} unmarked %{target}'s media as sensitive"
|
unsensitive_account_html: "%{name} unmarked %{target}'s media as sensitive"
|
||||||
unsilence_account: "%{name} unsilenced %{target}'s account"
|
unsilence_account_html: "%{name} unsilenced %{target}'s account"
|
||||||
unsuspend_account: "%{name} unsuspended %{target}'s account"
|
unsuspend_account_html: "%{name} unsuspended %{target}'s account"
|
||||||
update_announcement: "%{name} updated announcement %{target}"
|
update_announcement_html: "%{name} updated announcement %{target}"
|
||||||
update_custom_emoji: "%{name} updated emoji %{target}"
|
update_custom_emoji_html: "%{name} updated emoji %{target}"
|
||||||
update_domain_block: "%{name} updated domain block for %{target}"
|
update_domain_block_html: "%{name} updated domain block for %{target}"
|
||||||
update_status: "%{name} updated status by %{target}"
|
update_status_html: "%{name} updated status by %{target}"
|
||||||
deleted_status: "(deleted status)"
|
deleted_status: "(deleted status)"
|
||||||
empty: No logs found.
|
empty: No logs found.
|
||||||
filter_by_action: Filter by action
|
filter_by_action: Filter by action
|
||||||
|
@ -1044,10 +1044,14 @@ en:
|
||||||
body: 'You were mentioned by %{name} in:'
|
body: 'You were mentioned by %{name} in:'
|
||||||
subject: You were mentioned by %{name}
|
subject: You were mentioned by %{name}
|
||||||
title: New mention
|
title: New mention
|
||||||
|
poll:
|
||||||
|
subject: A poll by %{name} has ended
|
||||||
reblog:
|
reblog:
|
||||||
body: 'Your status was boosted by %{name}:'
|
body: 'Your status was boosted by %{name}:'
|
||||||
subject: "%{name} boosted your status"
|
subject: "%{name} boosted your status"
|
||||||
title: New boost
|
title: New boost
|
||||||
|
status:
|
||||||
|
subject: "%{name} just posted"
|
||||||
notifications:
|
notifications:
|
||||||
email_events: Events for e-mail notifications
|
email_events: Events for e-mail notifications
|
||||||
email_events_hint: 'Select events that you want to receive notifications for:'
|
email_events_hint: 'Select events that you want to receive notifications for:'
|
||||||
|
|
|
@ -12,6 +12,33 @@ Environment="MALLOC_ARENA_MAX=2"
|
||||||
ExecStart=/home/mastodon/.rbenv/shims/bundle exec sidekiq -c 25
|
ExecStart=/home/mastodon/.rbenv/shims/bundle exec sidekiq -c 25
|
||||||
TimeoutSec=15
|
TimeoutSec=15
|
||||||
Restart=always
|
Restart=always
|
||||||
|
# Capabilities
|
||||||
|
CapabilityBoundingSet=
|
||||||
|
# Security
|
||||||
|
NoNewPrivileges=true
|
||||||
|
# Sandboxing
|
||||||
|
ProtectSystem=strict
|
||||||
|
PrivateTmp=true
|
||||||
|
PrivateDevices=true
|
||||||
|
PrivateUsers=true
|
||||||
|
ProtectHostname=true
|
||||||
|
ProtectKernelLogs=true
|
||||||
|
ProtectKernelModules=true
|
||||||
|
ProtectKernelTunables=true
|
||||||
|
ProtectControlGroups=true
|
||||||
|
RestrictAddressFamilies=AF_INET
|
||||||
|
RestrictAddressFamilies=AF_INET6
|
||||||
|
RestrictAddressFamilies=AF_NETLINK
|
||||||
|
RestrictAddressFamilies=AF_UNIX
|
||||||
|
RestrictNamespaces=true
|
||||||
|
LockPersonality=true
|
||||||
|
RestrictRealtime=true
|
||||||
|
RestrictSUIDSGID=true
|
||||||
|
PrivateMounts=true
|
||||||
|
ProtectClock=true
|
||||||
|
# System Call Filtering
|
||||||
|
SystemCallArchitectures=native
|
||||||
|
SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @reboot @resources @setuid @swap
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
|
|
|
@ -12,6 +12,33 @@ Environment="STREAMING_CLUSTER_NUM=1"
|
||||||
ExecStart=/usr/bin/node ./streaming
|
ExecStart=/usr/bin/node ./streaming
|
||||||
TimeoutSec=15
|
TimeoutSec=15
|
||||||
Restart=always
|
Restart=always
|
||||||
|
# Capabilities
|
||||||
|
CapabilityBoundingSet=
|
||||||
|
# Security
|
||||||
|
NoNewPrivileges=true
|
||||||
|
# Sandboxing
|
||||||
|
ProtectSystem=strict
|
||||||
|
PrivateTmp=true
|
||||||
|
PrivateDevices=true
|
||||||
|
PrivateUsers=true
|
||||||
|
ProtectHostname=true
|
||||||
|
ProtectKernelLogs=true
|
||||||
|
ProtectKernelModules=true
|
||||||
|
ProtectKernelTunables=true
|
||||||
|
ProtectControlGroups=true
|
||||||
|
RestrictAddressFamilies=AF_INET
|
||||||
|
RestrictAddressFamilies=AF_INET6
|
||||||
|
RestrictAddressFamilies=AF_NETLINK
|
||||||
|
RestrictAddressFamilies=AF_UNIX
|
||||||
|
RestrictNamespaces=true
|
||||||
|
LockPersonality=true
|
||||||
|
RestrictRealtime=true
|
||||||
|
RestrictSUIDSGID=true
|
||||||
|
PrivateMounts=true
|
||||||
|
ProtectClock=true
|
||||||
|
# System Call Filtering
|
||||||
|
SystemCallArchitectures=native
|
||||||
|
SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @reboot @resources @setuid @swap
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
|
|
|
@ -12,6 +12,33 @@ ExecStart=/home/mastodon/.rbenv/shims/bundle exec puma -C config/puma.rb
|
||||||
ExecReload=/bin/kill -SIGUSR1 $MAINPID
|
ExecReload=/bin/kill -SIGUSR1 $MAINPID
|
||||||
TimeoutSec=15
|
TimeoutSec=15
|
||||||
Restart=always
|
Restart=always
|
||||||
|
# Capabilities
|
||||||
|
CapabilityBoundingSet=
|
||||||
|
# Security
|
||||||
|
NoNewPrivileges=true
|
||||||
|
# Sandboxing
|
||||||
|
ProtectSystem=strict
|
||||||
|
PrivateTmp=true
|
||||||
|
PrivateDevices=true
|
||||||
|
PrivateUsers=true
|
||||||
|
ProtectHostname=true
|
||||||
|
ProtectKernelLogs=true
|
||||||
|
ProtectKernelModules=true
|
||||||
|
ProtectKernelTunables=true
|
||||||
|
ProtectControlGroups=true
|
||||||
|
RestrictAddressFamilies=AF_INET
|
||||||
|
RestrictAddressFamilies=AF_INET6
|
||||||
|
RestrictAddressFamilies=AF_NETLINK
|
||||||
|
RestrictAddressFamilies=AF_UNIX
|
||||||
|
RestrictNamespaces=true
|
||||||
|
LockPersonality=true
|
||||||
|
RestrictRealtime=true
|
||||||
|
RestrictSUIDSGID=true
|
||||||
|
PrivateMounts=true
|
||||||
|
ProtectClock=true
|
||||||
|
# System Call Filtering
|
||||||
|
SystemCallArchitectures=native
|
||||||
|
SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @reboot @resources @setuid @swap
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
|
|
|
@ -69,7 +69,7 @@ namespace :emojis do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
existence_maps = grouped_codes.map { |c| c.map { |cc| [cc, File.exist?(Rails.root.join('public', 'emoji', codepoints_to_filename(cc) + '.svg'))] }.to_h }
|
existence_maps = grouped_codes.map { |c| c.index_with { |cc| File.exist?(Rails.root.join('public', 'emoji', codepoints_to_filename(cc) + '.svg')) } }
|
||||||
map = {}
|
map = {}
|
||||||
|
|
||||||
existence_maps.each do |group|
|
existence_maps.each do |group|
|
||||||
|
|
|
@ -371,18 +371,20 @@ namespace :mastodon do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
prompt.say "\n"
|
unless using_docker
|
||||||
prompt.say 'The final step is compiling CSS/JS assets.'
|
prompt.say "\n"
|
||||||
prompt.say 'This may take a while and consume a lot of RAM.'
|
prompt.say 'The final step is compiling CSS/JS assets.'
|
||||||
|
prompt.say 'This may take a while and consume a lot of RAM.'
|
||||||
|
|
||||||
if prompt.yes?('Compile the assets now?')
|
if prompt.yes?('Compile the assets now?')
|
||||||
prompt.say 'Running `RAILS_ENV=production rails assets:precompile` ...'
|
prompt.say 'Running `RAILS_ENV=production rails assets:precompile` ...'
|
||||||
prompt.say "\n\n"
|
prompt.say "\n\n"
|
||||||
|
|
||||||
if !system(env.transform_values(&:to_s).merge({ 'RAILS_ENV' => 'production' }), 'rails assets:precompile')
|
if !system(env.transform_values(&:to_s).merge({ 'RAILS_ENV' => 'production' }), 'rails assets:precompile')
|
||||||
prompt.error 'That failed! Maybe you need swap space?'
|
prompt.error 'That failed! Maybe you need swap space?'
|
||||||
else
|
else
|
||||||
prompt.say 'Done!'
|
prompt.say 'Done!'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
12
package.json
12
package.json
|
@ -68,7 +68,6 @@
|
||||||
"@babel/preset-env": "^7.13.10",
|
"@babel/preset-env": "^7.13.10",
|
||||||
"@babel/preset-react": "^7.12.13",
|
"@babel/preset-react": "^7.12.13",
|
||||||
"@babel/runtime": "^7.13.10",
|
"@babel/runtime": "^7.13.10",
|
||||||
"@clusterws/cws": "^3.0.0",
|
|
||||||
"@gamestdio/websocket": "^0.3.2",
|
"@gamestdio/websocket": "^0.3.2",
|
||||||
"@github/webauthn-json": "^0.5.7",
|
"@github/webauthn-json": "^0.5.7",
|
||||||
"@rails/ujs": "^6.1.3",
|
"@rails/ujs": "^6.1.3",
|
||||||
|
@ -88,7 +87,7 @@
|
||||||
"color-blend": "^3.0.1",
|
"color-blend": "^3.0.1",
|
||||||
"compression-webpack-plugin": "^6.1.1",
|
"compression-webpack-plugin": "^6.1.1",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"css-loader": "^5.1.2",
|
"css-loader": "^5.1.3",
|
||||||
"cssnano": "^4.1.10",
|
"cssnano": "^4.1.10",
|
||||||
"detect-passive-events": "^2.0.3",
|
"detect-passive-events": "^2.0.3",
|
||||||
"dotenv": "^8.2.0",
|
"dotenv": "^8.2.0",
|
||||||
|
@ -142,7 +141,7 @@
|
||||||
"react-redux-loading-bar": "^4.0.8",
|
"react-redux-loading-bar": "^4.0.8",
|
||||||
"react-router-dom": "^4.1.1",
|
"react-router-dom": "^4.1.1",
|
||||||
"react-router-scroll-4": "^1.0.0-beta.1",
|
"react-router-scroll-4": "^1.0.0-beta.1",
|
||||||
"react-select": "^3.2.0",
|
"react-select": "^4.0.2",
|
||||||
"react-sparklines": "^1.7.0",
|
"react-sparklines": "^1.7.0",
|
||||||
"react-swipeable-views": "^0.13.9",
|
"react-swipeable-views": "^0.13.9",
|
||||||
"react-textarea-autosize": "^8.3.2",
|
"react-textarea-autosize": "^8.3.2",
|
||||||
|
@ -172,7 +171,8 @@
|
||||||
"webpack-bundle-analyzer": "^4.4.0",
|
"webpack-bundle-analyzer": "^4.4.0",
|
||||||
"webpack-cli": "^3.3.12",
|
"webpack-cli": "^3.3.12",
|
||||||
"webpack-merge": "^5.7.3",
|
"webpack-merge": "^5.7.3",
|
||||||
"wicg-inert": "^3.1.1"
|
"wicg-inert": "^3.1.1",
|
||||||
|
"ws": "^7.4.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@testing-library/jest-dom": "^5.11.9",
|
"@testing-library/jest-dom": "^5.11.9",
|
||||||
|
@ -194,5 +194,9 @@
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"kind-of": "^6.0.3"
|
"kind-of": "^6.0.3"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"bufferutil": "^4.0.3",
|
||||||
|
"utf-8-validate": "^5.0.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,8 +30,8 @@ describe Api::V1::Accounts::CredentialsController do
|
||||||
patch :update, params: {
|
patch :update, params: {
|
||||||
display_name: "Alice Isn't Dead",
|
display_name: "Alice Isn't Dead",
|
||||||
note: "Hi!\n\nToot toot!",
|
note: "Hi!\n\nToot toot!",
|
||||||
avatar: fixture_file_upload('files/avatar.gif', 'image/gif'),
|
avatar: fixture_file_upload('avatar.gif', 'image/gif'),
|
||||||
header: fixture_file_upload('files/attachment.jpg', 'image/jpeg'),
|
header: fixture_file_upload('attachment.jpg', 'image/jpeg'),
|
||||||
source: {
|
source: {
|
||||||
privacy: 'unlisted',
|
privacy: 'unlisted',
|
||||||
sensitive: true,
|
sensitive: true,
|
||||||
|
|
|
@ -15,7 +15,7 @@ RSpec.describe Api::V1::MediaController, type: :controller do
|
||||||
context 'when imagemagick cant identify the file type' do
|
context 'when imagemagick cant identify the file type' do
|
||||||
before do
|
before do
|
||||||
expect_any_instance_of(Account).to receive_message_chain(:media_attachments, :create!).and_raise(Paperclip::Errors::NotIdentifiedByImageMagickError)
|
expect_any_instance_of(Account).to receive_message_chain(:media_attachments, :create!).and_raise(Paperclip::Errors::NotIdentifiedByImageMagickError)
|
||||||
post :create, params: { file: fixture_file_upload('files/attachment.jpg', 'image/jpeg') }
|
post :create, params: { file: fixture_file_upload('attachment.jpg', 'image/jpeg') }
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns http 422' do
|
it 'returns http 422' do
|
||||||
|
@ -26,7 +26,7 @@ RSpec.describe Api::V1::MediaController, type: :controller do
|
||||||
context 'when there is a generic error' do
|
context 'when there is a generic error' do
|
||||||
before do
|
before do
|
||||||
expect_any_instance_of(Account).to receive_message_chain(:media_attachments, :create!).and_raise(Paperclip::Error)
|
expect_any_instance_of(Account).to receive_message_chain(:media_attachments, :create!).and_raise(Paperclip::Error)
|
||||||
post :create, params: { file: fixture_file_upload('files/attachment.jpg', 'image/jpeg') }
|
post :create, params: { file: fixture_file_upload('attachment.jpg', 'image/jpeg') }
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns http 422' do
|
it 'returns http 422' do
|
||||||
|
@ -37,7 +37,7 @@ RSpec.describe Api::V1::MediaController, type: :controller do
|
||||||
|
|
||||||
context 'image/jpeg' do
|
context 'image/jpeg' do
|
||||||
before do
|
before do
|
||||||
post :create, params: { file: fixture_file_upload('files/attachment.jpg', 'image/jpeg') }
|
post :create, params: { file: fixture_file_upload('attachment.jpg', 'image/jpeg') }
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns http success' do
|
it 'returns http success' do
|
||||||
|
@ -59,7 +59,7 @@ RSpec.describe Api::V1::MediaController, type: :controller do
|
||||||
|
|
||||||
context 'image/gif' do
|
context 'image/gif' do
|
||||||
before do
|
before do
|
||||||
post :create, params: { file: fixture_file_upload('files/attachment.gif', 'image/gif') }
|
post :create, params: { file: fixture_file_upload('attachment.gif', 'image/gif') }
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns http success' do
|
it 'returns http success' do
|
||||||
|
@ -81,7 +81,7 @@ RSpec.describe Api::V1::MediaController, type: :controller do
|
||||||
|
|
||||||
context 'video/webm' do
|
context 'video/webm' do
|
||||||
before do
|
before do
|
||||||
post :create, params: { file: fixture_file_upload('files/attachment.webm', 'video/webm') }
|
post :create, params: { file: fixture_file_upload('attachment.webm', 'video/webm') }
|
||||||
end
|
end
|
||||||
|
|
||||||
it do
|
it do
|
||||||
|
|
|
@ -42,20 +42,6 @@ describe ApplicationController, type: :controller do
|
||||||
include_examples 'respond_with_error', 422
|
include_examples 'respond_with_error', 422
|
||||||
end
|
end
|
||||||
|
|
||||||
it "does not force ssl if Rails.env.production? is not 'true'" do
|
|
||||||
routes.draw { get 'success' => 'anonymous#success' }
|
|
||||||
allow(Rails.env).to receive(:production?).and_return(false)
|
|
||||||
get 'success'
|
|
||||||
expect(response).to have_http_status(200)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "forces ssl if Rails.env.production? is 'true'" do
|
|
||||||
routes.draw { get 'success' => 'anonymous#success' }
|
|
||||||
allow(Rails.env).to receive(:production?).and_return(true)
|
|
||||||
get 'success'
|
|
||||||
expect(response).to redirect_to('https://test.host/success')
|
|
||||||
end
|
|
||||||
|
|
||||||
describe 'helper_method :current_account' do
|
describe 'helper_method :current_account' do
|
||||||
it 'returns nil if not signed in' do
|
it 'returns nil if not signed in' do
|
||||||
expect(controller.view_context.current_account).to be_nil
|
expect(controller.view_context.current_account).to be_nil
|
||||||
|
|
|
@ -21,7 +21,7 @@ RSpec.describe Settings::ImportsController, type: :controller do
|
||||||
post :create, params: {
|
post :create, params: {
|
||||||
import: {
|
import: {
|
||||||
type: 'following',
|
type: 'following',
|
||||||
data: fixture_file_upload('files/imports.txt')
|
data: fixture_file_upload('imports.txt')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ RSpec.describe Settings::ImportsController, type: :controller do
|
||||||
post :create, params: {
|
post :create, params: {
|
||||||
import: {
|
import: {
|
||||||
type: 'blocking',
|
type: 'blocking',
|
||||||
data: fixture_file_upload('files/imports.txt')
|
data: fixture_file_upload('imports.txt')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ RSpec.describe Settings::ProfilesController, type: :controller do
|
||||||
account = Fabricate(:account, user: @user, display_name: 'AvatarTest')
|
account = Fabricate(:account, user: @user, display_name: 'AvatarTest')
|
||||||
expect(account.avatar.instance.avatar_file_name).to be_nil
|
expect(account.avatar.instance.avatar_file_name).to be_nil
|
||||||
|
|
||||||
put :update, params: { account: { avatar: fixture_file_upload('files/avatar.gif', 'image/gif') } }
|
put :update, params: { account: { avatar: fixture_file_upload('avatar.gif', 'image/gif') } }
|
||||||
expect(response).to redirect_to(settings_profile_path)
|
expect(response).to redirect_to(settings_profile_path)
|
||||||
expect(account.reload.avatar.instance.avatar_file_name).not_to be_nil
|
expect(account.reload.avatar.instance.avatar_file_name).not_to be_nil
|
||||||
expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_async).with(account.id)
|
expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_async).with(account.id)
|
||||||
|
@ -44,7 +44,7 @@ RSpec.describe Settings::ProfilesController, type: :controller do
|
||||||
it 'gives the user an error message' do
|
it 'gives the user an error message' do
|
||||||
allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_async)
|
allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_async)
|
||||||
account = Fabricate(:account, user: @user, display_name: 'AvatarTest')
|
account = Fabricate(:account, user: @user, display_name: 'AvatarTest')
|
||||||
put :update, params: { account: { avatar: fixture_file_upload('files/4096x4097.png', 'image/png') } }
|
put :update, params: { account: { avatar: fixture_file_upload('4096x4097.png', 'image/png') } }
|
||||||
expect(response.body).to include('images are not supported')
|
expect(response.body).to include('images are not supported')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,7 +11,7 @@ describe Settings::TwoFactorAuthentication::ConfirmationsController do
|
||||||
subject
|
subject
|
||||||
|
|
||||||
expect(assigns(:confirmation)).to be_instance_of Form::TwoFactorConfirmation
|
expect(assigns(:confirmation)).to be_instance_of Form::TwoFactorConfirmation
|
||||||
expect(assigns(:provision_url)).to eq 'otpauth://totp/local-part@domain?secret=thisisasecretforthespecofnewview&issuer=cb6e6126.ngrok.io'
|
expect(assigns(:provision_url)).to eq 'otpauth://totp/cb6e6126.ngrok.io:local-part%40domain?secret=thisisasecretforthespecofnewview&issuer=cb6e6126.ngrok.io'
|
||||||
expect(assigns(:qrcode)).to be_instance_of RQRCode::QRCode
|
expect(assigns(:qrcode)).to be_instance_of RQRCode::QRCode
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
expect(response).to render_template(:new)
|
expect(response).to render_template(:new)
|
||||||
|
|
|
@ -67,7 +67,7 @@ RSpec.describe ActivityPub::Activity::Create do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'public' do
|
context 'public with explicit public address' do
|
||||||
let(:object_json) do
|
let(:object_json) do
|
||||||
{
|
{
|
||||||
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
|
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
|
||||||
|
@ -85,7 +85,43 @@ RSpec.describe ActivityPub::Activity::Create do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'unlisted' do
|
context 'public with as:Public' do
|
||||||
|
let(:object_json) do
|
||||||
|
{
|
||||||
|
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
|
||||||
|
type: 'Note',
|
||||||
|
content: 'Lorem ipsum',
|
||||||
|
to: 'as:Public',
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'creates status' do
|
||||||
|
status = sender.statuses.first
|
||||||
|
|
||||||
|
expect(status).to_not be_nil
|
||||||
|
expect(status.visibility).to eq 'public'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'public with Public' do
|
||||||
|
let(:object_json) do
|
||||||
|
{
|
||||||
|
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
|
||||||
|
type: 'Note',
|
||||||
|
content: 'Lorem ipsum',
|
||||||
|
to: 'Public',
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'creates status' do
|
||||||
|
status = sender.statuses.first
|
||||||
|
|
||||||
|
expect(status).to_not be_nil
|
||||||
|
expect(status.visibility).to eq 'public'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'unlisted with explicit public address' do
|
||||||
let(:object_json) do
|
let(:object_json) do
|
||||||
{
|
{
|
||||||
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
|
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
|
||||||
|
@ -103,6 +139,42 @@ RSpec.describe ActivityPub::Activity::Create do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'unlisted with as:Public' do
|
||||||
|
let(:object_json) do
|
||||||
|
{
|
||||||
|
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
|
||||||
|
type: 'Note',
|
||||||
|
content: 'Lorem ipsum',
|
||||||
|
cc: 'as:Public',
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'creates status' do
|
||||||
|
status = sender.statuses.first
|
||||||
|
|
||||||
|
expect(status).to_not be_nil
|
||||||
|
expect(status.visibility).to eq 'unlisted'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'unlisted with Public' do
|
||||||
|
let(:object_json) do
|
||||||
|
{
|
||||||
|
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
|
||||||
|
type: 'Note',
|
||||||
|
content: 'Lorem ipsum',
|
||||||
|
cc: 'Public',
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'creates status' do
|
||||||
|
status = sender.statuses.first
|
||||||
|
|
||||||
|
expect(status).to_not be_nil
|
||||||
|
expect(status.visibility).to eq 'unlisted'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'private' do
|
context 'private' do
|
||||||
let(:object_json) do
|
let(:object_json) do
|
||||||
{
|
{
|
||||||
|
|
|
@ -99,11 +99,12 @@ RSpec.describe Setting, type: :model do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'does not query the database' do
|
it 'does not query the database' do
|
||||||
expect do |callback|
|
callback = double
|
||||||
ActiveSupport::Notifications.subscribed callback, 'sql.active_record' do
|
allow(callback).to receive(:call)
|
||||||
described_class[key]
|
ActiveSupport::Notifications.subscribed callback, 'sql.active_record' do
|
||||||
end
|
described_class[key]
|
||||||
end.not_to yield_control
|
end
|
||||||
|
expect(callback).not_to have_received(:call)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns the cached value' do
|
it 'returns the cached value' do
|
||||||
|
|
|
@ -175,7 +175,7 @@ RSpec.describe User, type: :model do
|
||||||
user = Fabricate(:user)
|
user = Fabricate(:user)
|
||||||
ActiveJob::Base.queue_adapter = :test
|
ActiveJob::Base.queue_adapter = :test
|
||||||
|
|
||||||
expect { user.send_confirmation_instructions }.to have_enqueued_job(ActionMailer::DeliveryJob)
|
expect { user.send_confirmation_instructions }.to have_enqueued_job(ActionMailer::MailDeliveryJob)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -206,7 +206,7 @@ RSpec.describe User, type: :model do
|
||||||
|
|
||||||
describe 'whitelist' do
|
describe 'whitelist' do
|
||||||
around(:each) do |example|
|
around(:each) do |example|
|
||||||
old_whitelist = Rails.configuration.x.email_whitelist
|
old_whitelist = Rails.configuration.x.email_domains_whitelist
|
||||||
|
|
||||||
Rails.configuration.x.email_domains_whitelist = 'mastodon.space'
|
Rails.configuration.x.email_domains_whitelist = 'mastodon.space'
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,24 @@ describe EmailMxValidator do
|
||||||
describe '#validate' do
|
describe '#validate' do
|
||||||
let(:user) { double(email: 'foo@example.com', errors: double(add: nil)) }
|
let(:user) { double(email: 'foo@example.com', errors: double(add: nil)) }
|
||||||
|
|
||||||
|
it 'does not add errors if there are no DNS records for an e-mail domain that is explicitly allowed' do
|
||||||
|
old_whitelist = Rails.configuration.x.email_domains_whitelist
|
||||||
|
Rails.configuration.x.email_domains_whitelist = 'example.com'
|
||||||
|
|
||||||
|
resolver = double
|
||||||
|
|
||||||
|
allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::MX).and_return([])
|
||||||
|
allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::A).and_return([])
|
||||||
|
allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::AAAA).and_return([])
|
||||||
|
allow(resolver).to receive(:timeouts=).and_return(nil)
|
||||||
|
allow(Resolv::DNS).to receive(:open).and_yield(resolver)
|
||||||
|
|
||||||
|
subject.validate(user)
|
||||||
|
expect(user.errors).to_not have_received(:add)
|
||||||
|
|
||||||
|
Rails.configuration.x.email_domains_whitelist = old_whitelist
|
||||||
|
end
|
||||||
|
|
||||||
it 'adds an error if there are no DNS records for the e-mail domain' do
|
it 'adds an error if there are no DNS records for the e-mail domain' do
|
||||||
resolver = double
|
resolver = double
|
||||||
|
|
||||||
|
|
|
@ -9,9 +9,9 @@ const redis = require('redis');
|
||||||
const pg = require('pg');
|
const pg = require('pg');
|
||||||
const log = require('npmlog');
|
const log = require('npmlog');
|
||||||
const url = require('url');
|
const url = require('url');
|
||||||
const { WebSocketServer } = require('@clusterws/cws');
|
|
||||||
const uuid = require('uuid');
|
const uuid = require('uuid');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
const WebSocket = require('ws');
|
||||||
|
|
||||||
const env = process.env.NODE_ENV || 'development';
|
const env = process.env.NODE_ENV || 'development';
|
||||||
const alwaysRequireAuth = process.env.LIMITED_FEDERATION_MODE === 'true' || process.env.WHITELIST_MODE === 'true' || process.env.AUTHORIZED_FETCH === 'true';
|
const alwaysRequireAuth = process.env.LIMITED_FEDERATION_MODE === 'true' || process.env.WHITELIST_MODE === 'true' || process.env.AUTHORIZED_FETCH === 'true';
|
||||||
|
@ -774,7 +774,7 @@ const startWorker = (workerId) => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const wss = new WebSocketServer({ server, verifyClient: wsVerifyClient });
|
const wss = new WebSocket.Server({ server, verifyClient: wsVerifyClient });
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef StreamParams
|
* @typedef StreamParams
|
||||||
|
@ -1021,6 +1021,12 @@ const startWorker = (workerId) => {
|
||||||
req.requestId = uuid.v4();
|
req.requestId = uuid.v4();
|
||||||
req.remoteAddress = ws._socket.remoteAddress;
|
req.remoteAddress = ws._socket.remoteAddress;
|
||||||
|
|
||||||
|
ws.isAlive = true;
|
||||||
|
|
||||||
|
ws.on('pong', () => {
|
||||||
|
ws.isAlive = true;
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {WebSocketSession}
|
* @type {WebSocketSession}
|
||||||
*/
|
*/
|
||||||
|
@ -1070,7 +1076,17 @@ const startWorker = (workerId) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
wss.startAutoPing(30000);
|
setInterval(() => {
|
||||||
|
wss.clients.forEach(ws => {
|
||||||
|
if (ws.isAlive === false) {
|
||||||
|
ws.terminate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ws.isAlive = false;
|
||||||
|
ws.ping('', false, true);
|
||||||
|
});
|
||||||
|
}, 30000);
|
||||||
|
|
||||||
attachServerWithConfig(server, address => {
|
attachServerWithConfig(server, address => {
|
||||||
log.info(`Worker ${workerId} now listening on ${address}`);
|
log.info(`Worker ${workerId} now listening on ${address}`);
|
||||||
|
|
238
yarn.lock
238
yarn.lock
|
@ -170,7 +170,14 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/types" "^7.13.0"
|
"@babel/types" "^7.13.0"
|
||||||
|
|
||||||
"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.0.0-beta.49", "@babel/helper-module-imports@^7.12.13":
|
"@babel/helper-module-imports@^7.0.0-beta.49", "@babel/helper-module-imports@^7.7.0":
|
||||||
|
version "7.12.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz#1bfc0229f794988f76ed0a4d4e90860850b54dfb"
|
||||||
|
integrity sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/types" "^7.12.5"
|
||||||
|
|
||||||
|
"@babel/helper-module-imports@^7.12.13":
|
||||||
version "7.12.13"
|
version "7.12.13"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.13.tgz#ec67e4404f41750463e455cc3203f6a32e93fcb0"
|
resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.13.tgz#ec67e4404f41750463e455cc3203f6a32e93fcb0"
|
||||||
integrity sha512-NGmfvRp9Rqxy0uHSSVP+SRIW1q31a7Ji10cLBcqSDUngGentY4FRiHOFZFE1CLU5eiL0oE8reH7Tg1y99TDM/g==
|
integrity sha512-NGmfvRp9Rqxy0uHSSVP+SRIW1q31a7Ji10cLBcqSDUngGentY4FRiHOFZFE1CLU5eiL0oE8reH7Tg1y99TDM/g==
|
||||||
|
@ -471,7 +478,7 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-plugin-utils" "^7.8.0"
|
"@babel/helper-plugin-utils" "^7.8.0"
|
||||||
|
|
||||||
"@babel/plugin-syntax-jsx@^7.12.13":
|
"@babel/plugin-syntax-jsx@^7.12.1", "@babel/plugin-syntax-jsx@^7.12.13":
|
||||||
version "7.12.13"
|
version "7.12.13"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.13.tgz#044fb81ebad6698fe62c478875575bcbb9b70f15"
|
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.13.tgz#044fb81ebad6698fe62c478875575bcbb9b70f15"
|
||||||
integrity sha512-d4HM23Q1K7oq/SLNmG6mRt85l2csmQ0cHRaxRXjKW0YFdEXqlZ5kzFQKH5Uc3rDJECgu+yCRgPkG04Mm98R/1g==
|
integrity sha512-d4HM23Q1K7oq/SLNmG6mRt85l2csmQ0cHRaxRXjKW0YFdEXqlZ5kzFQKH5Uc3rDJECgu+yCRgPkG04Mm98R/1g==
|
||||||
|
@ -984,11 +991,6 @@
|
||||||
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
||||||
|
|
||||||
"@clusterws/cws@^3.0.0":
|
|
||||||
version "3.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@clusterws/cws/-/cws-3.0.0.tgz#518fc8e7d9066e220f6f6aef3158cc14d5a1e98e"
|
|
||||||
integrity sha512-6RO7IUbSlTO3l8XPN/9g21YGPF4HjfkidDzchkP0h6iwq5jYtji+KUCgyxcSYiuN7aWu8nGJDjBer7XJilPnOg==
|
|
||||||
|
|
||||||
"@cnakazawa/watch@^1.0.3":
|
"@cnakazawa/watch@^1.0.3":
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a"
|
resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a"
|
||||||
|
@ -997,87 +999,99 @@
|
||||||
exec-sh "^0.3.2"
|
exec-sh "^0.3.2"
|
||||||
minimist "^1.2.0"
|
minimist "^1.2.0"
|
||||||
|
|
||||||
"@emotion/cache@^10.0.17", "@emotion/cache@^10.0.9":
|
"@emotion/babel-plugin@^11.0.0":
|
||||||
version "10.0.19"
|
version "11.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-10.0.19.tgz#d258d94d9c707dcadaf1558def968b86bb87ad71"
|
resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.1.2.tgz#68fe1aa3130099161036858c64ee92056c6730b7"
|
||||||
integrity sha512-BoiLlk4vEsGBg2dAqGSJu0vJl/PgVtCYLBFJaEO8RmQzPugXewQCXZJNXTDFaRlfCs0W+quesayav4fvaif5WQ==
|
integrity sha512-Nz1k7b11dWw8Nw4Z1R99A9mlB6C6rRsCtZnwNUOj4NsoZdrO2f2A/83ST7htJORD5zpOiLKY59aJN23092949w==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@emotion/sheet" "0.9.3"
|
"@babel/helper-module-imports" "^7.7.0"
|
||||||
"@emotion/stylis" "0.8.4"
|
"@babel/plugin-syntax-jsx" "^7.12.1"
|
||||||
"@emotion/utils" "0.11.2"
|
"@babel/runtime" "^7.7.2"
|
||||||
"@emotion/weak-memoize" "0.2.4"
|
"@emotion/hash" "^0.8.0"
|
||||||
|
"@emotion/memoize" "^0.7.5"
|
||||||
|
"@emotion/serialize" "^1.0.0"
|
||||||
|
babel-plugin-macros "^2.6.1"
|
||||||
|
convert-source-map "^1.5.0"
|
||||||
|
escape-string-regexp "^4.0.0"
|
||||||
|
find-root "^1.1.0"
|
||||||
|
source-map "^0.5.7"
|
||||||
|
stylis "^4.0.3"
|
||||||
|
|
||||||
"@emotion/core@^10.0.9":
|
"@emotion/cache@^11.0.0", "@emotion/cache@^11.1.3":
|
||||||
version "10.0.17"
|
version "11.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/@emotion/core/-/core-10.0.17.tgz#3367376709721f4ee2068cff54ba581d362789d8"
|
resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.1.3.tgz#c7683a9484bcd38d5562f2b9947873cf66829afd"
|
||||||
integrity sha512-gykyjjr0sxzVuZBVTVK4dUmYsorc2qLhdYgSiOVK+m7WXgcYTKZevGWZ7TLAgTZvMelCTvhNq8xnf8FR1IdTbg==
|
integrity sha512-n4OWinUPJVaP6fXxWZD9OUeQ0lY7DvtmtSuqtRWT0Ofo/sBLCVSgb4/Oa0Q5eFxcwablRKjUXqXtNZVyEwCAuA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.5.5"
|
"@emotion/memoize" "^0.7.4"
|
||||||
"@emotion/cache" "^10.0.17"
|
"@emotion/sheet" "^1.0.0"
|
||||||
"@emotion/css" "^10.0.14"
|
"@emotion/utils" "^1.0.0"
|
||||||
"@emotion/serialize" "^0.11.10"
|
"@emotion/weak-memoize" "^0.2.5"
|
||||||
"@emotion/sheet" "0.9.3"
|
stylis "^4.0.3"
|
||||||
"@emotion/utils" "0.11.2"
|
|
||||||
|
|
||||||
"@emotion/css@^10.0.14", "@emotion/css@^10.0.9":
|
"@emotion/css@^11.0.0":
|
||||||
version "10.0.14"
|
version "11.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/@emotion/css/-/css-10.0.14.tgz#95dacabdd0e22845d1a1b0b5968d9afa34011139"
|
resolved "https://registry.yarnpkg.com/@emotion/css/-/css-11.1.3.tgz#9ed44478b19e5d281ccbbd46d74d123d59be793f"
|
||||||
integrity sha512-MozgPkBEWvorcdpqHZE5x1D/PLEHUitALQCQYt2wayf4UNhpgQs2tN0UwHYS4FMy5ROBH+0ALyCFVYJ/ywmwlg==
|
integrity sha512-RSQP59qtCNTf5NWD6xM08xsQdCZmVYnX/panPYvB6LQAPKQB6GL49Njf0EMbS3CyDtrlWsBcmqBtysFvfWT3rA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@emotion/serialize" "^0.11.8"
|
"@emotion/babel-plugin" "^11.0.0"
|
||||||
"@emotion/utils" "0.11.2"
|
"@emotion/cache" "^11.1.3"
|
||||||
babel-plugin-emotion "^10.0.14"
|
"@emotion/serialize" "^1.0.0"
|
||||||
|
"@emotion/sheet" "^1.0.0"
|
||||||
|
"@emotion/utils" "^1.0.0"
|
||||||
|
|
||||||
"@emotion/hash@0.8.0":
|
"@emotion/hash@^0.8.0":
|
||||||
version "0.8.0"
|
version "0.8.0"
|
||||||
resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413"
|
resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413"
|
||||||
integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==
|
integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==
|
||||||
|
|
||||||
"@emotion/memoize@0.7.4":
|
"@emotion/memoize@^0.7.4", "@emotion/memoize@^0.7.5":
|
||||||
version "0.7.4"
|
version "0.7.5"
|
||||||
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb"
|
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.5.tgz#2c40f81449a4e554e9fc6396910ed4843ec2be50"
|
||||||
integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==
|
integrity sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ==
|
||||||
|
|
||||||
"@emotion/serialize@^0.11.10", "@emotion/serialize@^0.11.16", "@emotion/serialize@^0.11.8":
|
"@emotion/react@^11.1.1":
|
||||||
version "0.11.16"
|
version "11.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-0.11.16.tgz#dee05f9e96ad2fb25a5206b6d759b2d1ed3379ad"
|
resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.1.4.tgz#ddee4247627ff7dd7d0c6ae52f1cfd6b420357d2"
|
||||||
integrity sha512-G3J4o8by0VRrO+PFeSc3js2myYNOXVJ3Ya+RGVxnshRYgsvErfAOglKAiy1Eo1vhzxqtUvjCyS5gtewzkmvSSg==
|
integrity sha512-9gkhrW8UjV4IGRnEe4/aGPkUxoGS23aD9Vu6JCGfEDyBYL+nGkkRBoMFGAzCT9qFdyUvQp4UUtErbKWxq/JS4A==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@emotion/hash" "0.8.0"
|
"@babel/runtime" "^7.7.2"
|
||||||
"@emotion/memoize" "0.7.4"
|
"@emotion/cache" "^11.1.3"
|
||||||
"@emotion/unitless" "0.7.5"
|
"@emotion/serialize" "^1.0.0"
|
||||||
"@emotion/utils" "0.11.3"
|
"@emotion/sheet" "^1.0.1"
|
||||||
csstype "^2.5.7"
|
"@emotion/utils" "^1.0.0"
|
||||||
|
"@emotion/weak-memoize" "^0.2.5"
|
||||||
|
hoist-non-react-statics "^3.3.1"
|
||||||
|
|
||||||
"@emotion/sheet@0.9.3":
|
"@emotion/serialize@^1.0.0":
|
||||||
version "0.9.3"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-0.9.3.tgz#689f135ecf87d3c650ed0c4f5ddcbe579883564a"
|
resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.0.0.tgz#1a61f4f037cf39995c97fc80ebe99abc7b191ca9"
|
||||||
integrity sha512-c3Q6V7Df7jfwSq5AzQWbXHa5soeE4F5cbqi40xn0CzXxWW9/6Mxq48WJEtqfWzbZtW9odZdnRAkwCQwN12ob4A==
|
integrity sha512-zt1gm4rhdo5Sry8QpCOpopIUIKU+mUSpV9WNmFILUraatm5dttNEaYzUWWSboSMUE6PtN2j1cAsuvcugfdI3mw==
|
||||||
|
dependencies:
|
||||||
|
"@emotion/hash" "^0.8.0"
|
||||||
|
"@emotion/memoize" "^0.7.4"
|
||||||
|
"@emotion/unitless" "^0.7.5"
|
||||||
|
"@emotion/utils" "^1.0.0"
|
||||||
|
csstype "^3.0.2"
|
||||||
|
|
||||||
"@emotion/stylis@0.8.4":
|
"@emotion/sheet@^1.0.0", "@emotion/sheet@^1.0.1":
|
||||||
version "0.8.4"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.4.tgz#6c51afdf1dd0d73666ba09d2eb6c25c220d6fe4c"
|
resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.0.1.tgz#245f54abb02dfd82326e28689f34c27aa9b2a698"
|
||||||
integrity sha512-TLmkCVm8f8gH0oLv+HWKiu7e8xmBIaokhxcEKPh1m8pXiV/akCiq50FvYgOwY42rjejck8nsdQxZlXZ7pmyBUQ==
|
integrity sha512-GbIvVMe4U+Zc+929N1V7nW6YYJtidj31lidSmdYcWozwoBIObXBnaJkKNDjZrLm9Nc0BR+ZyHNaRZxqNZbof5g==
|
||||||
|
|
||||||
"@emotion/unitless@0.7.5":
|
"@emotion/unitless@^0.7.5":
|
||||||
version "0.7.5"
|
version "0.7.5"
|
||||||
resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed"
|
resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed"
|
||||||
integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==
|
integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==
|
||||||
|
|
||||||
"@emotion/utils@0.11.2":
|
"@emotion/utils@^1.0.0":
|
||||||
version "0.11.2"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.11.2.tgz#713056bfdffb396b0a14f1c8f18e7b4d0d200183"
|
resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.0.0.tgz#abe06a83160b10570816c913990245813a2fd6af"
|
||||||
integrity sha512-UHX2XklLl3sIaP6oiMmlVzT0J+2ATTVpf0dHQVyPJHTkOITvXfaSqnRk6mdDhV9pR8T/tHc3cex78IKXssmzrA==
|
integrity sha512-mQC2b3XLDs6QCW+pDQDiyO/EdGZYOygE8s5N5rrzjSI4M3IejPE/JPndCBwRT9z982aqQNi6beWs1UeayrQxxA==
|
||||||
|
|
||||||
"@emotion/utils@0.11.3":
|
"@emotion/weak-memoize@^0.2.5":
|
||||||
version "0.11.3"
|
version "0.2.5"
|
||||||
resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.11.3.tgz#a759863867befa7e583400d322652a3f44820924"
|
resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46"
|
||||||
integrity sha512-0o4l6pZC+hI88+bzuaX/6BgOvQVhbt2PfmxauVaYOGgbsAw14wdKyvMCZXnsnsHys94iadcF+RG/wZyx6+ZZBw==
|
integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==
|
||||||
|
|
||||||
"@emotion/weak-memoize@0.2.4":
|
|
||||||
version "0.2.4"
|
|
||||||
resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.4.tgz#622a72bebd1e3f48d921563b4b60a762295a81fc"
|
|
||||||
integrity sha512-6PYY5DVdAY1ifaQW6XYTnOMihmBVT27elqSjEoodchsGjzYlEsTQMcEhSud99kVawatyTZRTiVkJ/c6lwbQ7nA==
|
|
||||||
|
|
||||||
"@eslint/eslintrc@^0.4.0":
|
"@eslint/eslintrc@^0.4.0":
|
||||||
version "0.4.0"
|
version "0.4.0"
|
||||||
|
@ -2186,22 +2200,6 @@ babel-plugin-dynamic-import-node@^2.3.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
object.assign "^4.1.0"
|
object.assign "^4.1.0"
|
||||||
|
|
||||||
babel-plugin-emotion@^10.0.14:
|
|
||||||
version "10.0.33"
|
|
||||||
resolved "https://registry.yarnpkg.com/babel-plugin-emotion/-/babel-plugin-emotion-10.0.33.tgz#ce1155dcd1783bbb9286051efee53f4e2be63e03"
|
|
||||||
integrity sha512-bxZbTTGz0AJQDHm8k6Rf3RQJ8tX2scsfsRyKVgAbiUPUNIRtlK+7JxP+TAd1kRLABFxe0CFm2VdK4ePkoA9FxQ==
|
|
||||||
dependencies:
|
|
||||||
"@babel/helper-module-imports" "^7.0.0"
|
|
||||||
"@emotion/hash" "0.8.0"
|
|
||||||
"@emotion/memoize" "0.7.4"
|
|
||||||
"@emotion/serialize" "^0.11.16"
|
|
||||||
babel-plugin-macros "^2.0.0"
|
|
||||||
babel-plugin-syntax-jsx "^6.18.0"
|
|
||||||
convert-source-map "^1.5.0"
|
|
||||||
escape-string-regexp "^1.0.5"
|
|
||||||
find-root "^1.1.0"
|
|
||||||
source-map "^0.5.7"
|
|
||||||
|
|
||||||
babel-plugin-istanbul@^6.0.0:
|
babel-plugin-istanbul@^6.0.0:
|
||||||
version "6.0.0"
|
version "6.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz#e159ccdc9af95e0b570c75b4573b7c34d671d765"
|
resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz#e159ccdc9af95e0b570c75b4573b7c34d671d765"
|
||||||
|
@ -2234,7 +2232,7 @@ babel-plugin-lodash@^3.3.4:
|
||||||
lodash "^4.17.10"
|
lodash "^4.17.10"
|
||||||
require-package-name "^2.0.1"
|
require-package-name "^2.0.1"
|
||||||
|
|
||||||
babel-plugin-macros@^2.0.0, babel-plugin-macros@^2.8.0:
|
babel-plugin-macros@^2.6.1, babel-plugin-macros@^2.8.0:
|
||||||
version "2.8.0"
|
version "2.8.0"
|
||||||
resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz#0f958a7cc6556b1e65344465d99111a1e5e10138"
|
resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz#0f958a7cc6556b1e65344465d99111a1e5e10138"
|
||||||
integrity sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==
|
integrity sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==
|
||||||
|
@ -2289,11 +2287,6 @@ babel-plugin-react-intl@^6.2.0:
|
||||||
intl-messageformat-parser "^4.1.1"
|
intl-messageformat-parser "^4.1.1"
|
||||||
schema-utils "^2.2.0"
|
schema-utils "^2.2.0"
|
||||||
|
|
||||||
babel-plugin-syntax-jsx@^6.18.0:
|
|
||||||
version "6.18.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946"
|
|
||||||
integrity sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=
|
|
||||||
|
|
||||||
babel-plugin-transform-react-remove-prop-types@^0.4.24:
|
babel-plugin-transform-react-remove-prop-types@^0.4.24:
|
||||||
version "0.4.24"
|
version "0.4.24"
|
||||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz#f2edaf9b4c6a5fbe5c1d678bfb531078c1555f3a"
|
resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz#f2edaf9b4c6a5fbe5c1d678bfb531078c1555f3a"
|
||||||
|
@ -2630,6 +2623,13 @@ buffer@^4.3.0:
|
||||||
ieee754 "^1.1.4"
|
ieee754 "^1.1.4"
|
||||||
isarray "^1.0.0"
|
isarray "^1.0.0"
|
||||||
|
|
||||||
|
bufferutil@^4.0.3:
|
||||||
|
version "4.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.3.tgz#66724b756bed23cd7c28c4d306d7994f9943cc6b"
|
||||||
|
integrity sha512-yEYTwGndELGvfXsImMBLop58eaGW+YdONi1fNjTINSY98tmMmFijBG6WXgdkfuLNt4imzQNtIE+eBp1PVpMCSw==
|
||||||
|
dependencies:
|
||||||
|
node-gyp-build "^4.2.0"
|
||||||
|
|
||||||
builtin-status-codes@^3.0.0:
|
builtin-status-codes@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
|
resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
|
||||||
|
@ -3378,10 +3378,10 @@ css-list-helpers@^1.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
tcomb "^2.5.0"
|
tcomb "^2.5.0"
|
||||||
|
|
||||||
css-loader@^5.1.2:
|
css-loader@^5.1.3:
|
||||||
version "5.1.2"
|
version "5.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-5.1.2.tgz#b93dba498ec948b543b49d4fab5017205d4f5c3e"
|
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-5.1.3.tgz#87f6fc96816b20debe3cf682f85c7e56a963d0d1"
|
||||||
integrity sha512-T7vTXHSx0KrVEg/xjcl7G01RcVXpcw4OELwDPvkr7izQNny85A84dK3dqrczuEfBcu7Yg7mdTjJLSTibRUoRZg==
|
integrity sha512-CoPZvyh8sLiGARK3gqczpfdedbM74klGWurF2CsNZ2lhNaXdLIUks+3Mfax3WBeRuHoglU+m7KG/+7gY6G4aag==
|
||||||
dependencies:
|
dependencies:
|
||||||
camelcase "^6.2.0"
|
camelcase "^6.2.0"
|
||||||
cssesc "^3.0.0"
|
cssesc "^3.0.0"
|
||||||
|
@ -3548,11 +3548,16 @@ cssstyle@^2.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
cssom "~0.3.6"
|
cssom "~0.3.6"
|
||||||
|
|
||||||
csstype@^2.5.7, csstype@^2.6.7:
|
csstype@^2.6.7:
|
||||||
version "2.6.13"
|
version "2.6.13"
|
||||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.13.tgz#a6893015b90e84dd6e85d0e3b442a1e84f2dbe0f"
|
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.13.tgz#a6893015b90e84dd6e85d0e3b442a1e84f2dbe0f"
|
||||||
integrity sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A==
|
integrity sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A==
|
||||||
|
|
||||||
|
csstype@^3.0.2:
|
||||||
|
version "3.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.6.tgz#865d0b5833d7d8d40f4e5b8a6d76aea3de4725ef"
|
||||||
|
integrity sha512-+ZAmfyWMT7TiIlzdqJgjMb7S4f1beorDbWbsocyK4RaiqA5RTX3K14bnBWmmA9QEM0gRdsjyyrEmcyga8Zsxmw==
|
||||||
|
|
||||||
cyclist@^1.0.1:
|
cyclist@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
|
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
|
||||||
|
@ -4173,6 +4178,11 @@ escape-string-regexp@^2.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344"
|
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344"
|
||||||
integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==
|
integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==
|
||||||
|
|
||||||
|
escape-string-regexp@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
|
||||||
|
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
|
||||||
|
|
||||||
escodegen@^1.14.1:
|
escodegen@^1.14.1:
|
||||||
version "1.14.3"
|
version "1.14.3"
|
||||||
resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503"
|
resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503"
|
||||||
|
@ -5325,7 +5335,7 @@ hoist-non-react-statics@^2.5.0:
|
||||||
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47"
|
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47"
|
||||||
integrity sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==
|
integrity sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==
|
||||||
|
|
||||||
hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2:
|
hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2:
|
||||||
version "3.3.2"
|
version "3.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
|
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
|
||||||
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
|
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
|
||||||
|
@ -7372,6 +7382,11 @@ node-forge@^0.10.0:
|
||||||
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3"
|
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3"
|
||||||
integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==
|
integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==
|
||||||
|
|
||||||
|
node-gyp-build@^4.2.0:
|
||||||
|
version "4.2.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.2.3.tgz#ce6277f853835f718829efb47db20f3e4d9c4739"
|
||||||
|
integrity sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==
|
||||||
|
|
||||||
node-int64@^0.4.0:
|
node-int64@^0.4.0:
|
||||||
version "0.4.0"
|
version "0.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
|
resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
|
||||||
|
@ -8939,15 +8954,15 @@ react-router@^4.3.1:
|
||||||
prop-types "^15.6.1"
|
prop-types "^15.6.1"
|
||||||
warning "^4.0.1"
|
warning "^4.0.1"
|
||||||
|
|
||||||
react-select@^3.2.0:
|
react-select@^4.0.2:
|
||||||
version "3.2.0"
|
version "4.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/react-select/-/react-select-3.2.0.tgz#de9284700196f5f9b5277c5d850a9ce85f5c72fe"
|
resolved "https://registry.yarnpkg.com/react-select/-/react-select-4.0.2.tgz#4dcca9f38d6a41e01f2dc7673e244a325e3b4e0e"
|
||||||
integrity sha512-B/q3TnCZXEKItO0fFN/I0tWOX3WJvi/X2wtdffmwSQVRwg5BpValScTO1vdic9AxlUgmeSzib2hAZAwIUQUZGQ==
|
integrity sha512-BiihrRpRIBBvNqofNZIBpo08Kw8DBHb/kgpIDW4bxgkttk50Sxf0alEIKobns3U7UJXk/CA4rsFUueQEg9Pm5A==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.4.4"
|
"@babel/runtime" "^7.4.4"
|
||||||
"@emotion/cache" "^10.0.9"
|
"@emotion/cache" "^11.0.0"
|
||||||
"@emotion/core" "^10.0.9"
|
"@emotion/css" "^11.0.0"
|
||||||
"@emotion/css" "^10.0.9"
|
"@emotion/react" "^11.1.1"
|
||||||
memoize-one "^5.0.0"
|
memoize-one "^5.0.0"
|
||||||
prop-types "^15.6.0"
|
prop-types "^15.6.0"
|
||||||
react-input-autosize "^3.0.0"
|
react-input-autosize "^3.0.0"
|
||||||
|
@ -10363,6 +10378,11 @@ stylehacks@^4.0.0:
|
||||||
postcss "^7.0.0"
|
postcss "^7.0.0"
|
||||||
postcss-selector-parser "^3.0.0"
|
postcss-selector-parser "^3.0.0"
|
||||||
|
|
||||||
|
stylis@^4.0.3:
|
||||||
|
version "4.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.0.6.tgz#0d8b97b6bc4748bea46f68602b6df27641b3c548"
|
||||||
|
integrity sha512-1igcUEmYFBEO14uQHAJhCUelTR5jPztfdVKrYxRnDa5D5Dn3w0NxXupJNPr/VV/yRfZYEAco8sTIRZzH3sRYKg==
|
||||||
|
|
||||||
substring-trie@^1.0.2:
|
substring-trie@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/substring-trie/-/substring-trie-1.0.2.tgz#7b42592391628b4f2cb17365c6cce4257c7b7af5"
|
resolved "https://registry.yarnpkg.com/substring-trie/-/substring-trie-1.0.2.tgz#7b42592391628b4f2cb17365c6cce4257c7b7af5"
|
||||||
|
@ -10977,6 +10997,13 @@ user-home@^2.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
os-homedir "^1.0.0"
|
os-homedir "^1.0.0"
|
||||||
|
|
||||||
|
utf-8-validate@^5.0.4:
|
||||||
|
version "5.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.4.tgz#72a1735983ddf7a05a43a9c6b67c5ce1c910f9b8"
|
||||||
|
integrity sha512-MEF05cPSq3AwJ2C7B7sHAA6i53vONoZbMGX8My5auEVm6W+dJ2Jd/TZPyGJ5CH42V2XtbI5FD28HeHeqlPzZ3Q==
|
||||||
|
dependencies:
|
||||||
|
node-gyp-build "^4.2.0"
|
||||||
|
|
||||||
util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
|
util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||||
|
@ -11458,6 +11485,11 @@ ws@^7.2.3, ws@^7.3.1:
|
||||||
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.0.tgz#a5dd76a24197940d4a8bb9e0e152bb4503764da7"
|
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.0.tgz#a5dd76a24197940d4a8bb9e0e152bb4503764da7"
|
||||||
integrity sha512-kyFwXuV/5ymf+IXhS6f0+eAFvydbaBW3zjpT6hUdAh/hbVjTIB5EHBGi0bPoCLSK2wcuz3BrEkB9LrYv1Nm4NQ==
|
integrity sha512-kyFwXuV/5ymf+IXhS6f0+eAFvydbaBW3zjpT6hUdAh/hbVjTIB5EHBGi0bPoCLSK2wcuz3BrEkB9LrYv1Nm4NQ==
|
||||||
|
|
||||||
|
ws@^7.4.4:
|
||||||
|
version "7.4.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.4.tgz#383bc9742cb202292c9077ceab6f6047b17f2d59"
|
||||||
|
integrity sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw==
|
||||||
|
|
||||||
xml-name-validator@^3.0.0:
|
xml-name-validator@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
|
resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
|
||||||
|
|
Loading…
Reference in New Issue