mirror of
https://github.com/glitch-soc/mastodon.git
synced 2025-12-14 16:28:59 +00:00
Compare commits
42 Commits
fix-thread
...
for-upstre
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e168e8afe5 | ||
|
|
75c21adfbf | ||
|
|
685fafcc27 | ||
|
|
0e210b5c63 | ||
|
|
6b70c2ca12 | ||
|
|
8c6ecd5616 | ||
|
|
22cf9bcff6 | ||
|
|
21de45c7d2 | ||
|
|
88e52f3a2a | ||
|
|
d4bb04c45c | ||
|
|
33c56212b9 | ||
|
|
bcd4b72223 | ||
|
|
f39bba9a90 | ||
|
|
290c6b0f2e | ||
|
|
d5d1dcab77 | ||
|
|
ef5ebdd544 | ||
|
|
da85bfc252 | ||
|
|
d17255c0e0 | ||
|
|
74ce229101 | ||
|
|
fb8613d09b | ||
|
|
d73f437419 | ||
|
|
343c358bb2 | ||
|
|
8a6ad735f1 | ||
|
|
9fb8a6f231 | ||
|
|
f90ac53dc5 | ||
|
|
c814d19672 | ||
|
|
27eb75878e | ||
|
|
a81d3a2842 | ||
|
|
1fc0382d29 | ||
|
|
90db8b63b0 | ||
|
|
15a6cb5ca9 | ||
|
|
d5dc4696a7 | ||
|
|
eb6543b36b | ||
|
|
920c7cdaf3 | ||
|
|
f3aac23099 | ||
|
|
aded1acfda | ||
|
|
9855529a10 | ||
|
|
0ccfbe5747 | ||
|
|
921a1b7b2a | ||
|
|
aa7e541780 | ||
|
|
dac67960e0 | ||
|
|
90a0176b0b |
@@ -1,36 +1,21 @@
|
|||||||
version: "2"
|
engines:
|
||||||
checks:
|
|
||||||
argument-count:
|
|
||||||
enabled: false
|
|
||||||
complex-logic:
|
|
||||||
enabled: false
|
|
||||||
file-lines:
|
|
||||||
enabled: false
|
|
||||||
method-complexity:
|
|
||||||
enabled: false
|
|
||||||
method-count:
|
|
||||||
enabled: false
|
|
||||||
method-lines:
|
|
||||||
enabled: false
|
|
||||||
nested-control-flow:
|
|
||||||
enabled: false
|
|
||||||
return-statements:
|
|
||||||
enabled: false
|
|
||||||
similar-code:
|
|
||||||
enabled: false
|
|
||||||
identical-code:
|
|
||||||
enabled: false
|
|
||||||
plugins:
|
|
||||||
brakeman:
|
brakeman:
|
||||||
enabled: true
|
enabled: true
|
||||||
bundler-audit:
|
bundler-audit:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
duplication:
|
||||||
|
enabled: false
|
||||||
eslint:
|
eslint:
|
||||||
enabled: true
|
enabled: true
|
||||||
rubocop:
|
rubocop:
|
||||||
enabled: true
|
enabled: true
|
||||||
scss-lint:
|
scss-lint:
|
||||||
enabled: true
|
enabled: true
|
||||||
exclude_patterns:
|
ratings:
|
||||||
|
paths:
|
||||||
|
- "**.rb"
|
||||||
|
- "**.js"
|
||||||
|
- "**.scss"
|
||||||
|
exclude_paths:
|
||||||
- spec/
|
- spec/
|
||||||
- vendor/asset
|
- vendor/asset
|
||||||
|
|||||||
30
.env.nanobox
30
.env.nanobox
@@ -35,17 +35,6 @@ PAPERCLIP_SECRET=$PAPERCLIP_SECRET
|
|||||||
SECRET_KEY_BASE=$SECRET_KEY_BASE
|
SECRET_KEY_BASE=$SECRET_KEY_BASE
|
||||||
OTP_SECRET=$OTP_SECRET
|
OTP_SECRET=$OTP_SECRET
|
||||||
|
|
||||||
# VAPID keys (used for push notifications)
|
|
||||||
# You can generate the keys using the following command (first is the private key, second is the public one)
|
|
||||||
# You should only generate this once per instance. If you later decide to change it, all push subscription will
|
|
||||||
# be invalidated, requiring the users to access the website again to resubscribe.
|
|
||||||
#
|
|
||||||
# Generate with `rake mastodon:webpush:generate_vapid_key` task (`nanobox run bundle exec rake mastodon:webpush:generate_vapid_key`)
|
|
||||||
#
|
|
||||||
# For more information visit https://rossta.net/blog/using-the-web-push-api-with-vapid.html
|
|
||||||
VAPID_PRIVATE_KEY=$VAPID_PRIVATE_KEY
|
|
||||||
VAPID_PUBLIC_KEY=$VAPID_PUBLIC_KEY
|
|
||||||
|
|
||||||
# Registrations
|
# Registrations
|
||||||
# Single user mode will disable registrations and redirect frontpage to the first profile
|
# Single user mode will disable registrations and redirect frontpage to the first profile
|
||||||
# SINGLE_USER_MODE=true
|
# SINGLE_USER_MODE=true
|
||||||
@@ -73,7 +62,7 @@ SMTP_FROM_ADDRESS=notifications@${APP_NAME}.nanoapp.io
|
|||||||
#SMTP_CA_FILE=/etc/ssl/certs/ca-certificates.crt
|
#SMTP_CA_FILE=/etc/ssl/certs/ca-certificates.crt
|
||||||
#SMTP_OPENSSL_VERIFY_MODE=peer
|
#SMTP_OPENSSL_VERIFY_MODE=peer
|
||||||
#SMTP_ENABLE_STARTTLS_AUTO=true
|
#SMTP_ENABLE_STARTTLS_AUTO=true
|
||||||
#SMTP_TLS=true
|
|
||||||
|
|
||||||
# Optional user upload path and URL (images, avatars). Default is :rails_root/public/system. If you set this variable, you are responsible for making your HTTP server (eg. nginx) serve these files.
|
# Optional user upload path and URL (images, avatars). Default is :rails_root/public/system. If you set this variable, you are responsible for making your HTTP server (eg. nginx) serve these files.
|
||||||
# PAPERCLIP_ROOT_PATH=/var/lib/mastodon/public-system
|
# PAPERCLIP_ROOT_PATH=/var/lib/mastodon/public-system
|
||||||
@@ -102,23 +91,6 @@ SMTP_FROM_ADDRESS=notifications@${APP_NAME}.nanoapp.io
|
|||||||
# S3_ENDPOINT=
|
# S3_ENDPOINT=
|
||||||
# S3_SIGNATURE_VERSION=
|
# S3_SIGNATURE_VERSION=
|
||||||
|
|
||||||
# Swift (optional)
|
|
||||||
# SWIFT_ENABLED=true
|
|
||||||
# SWIFT_USERNAME=
|
|
||||||
# For Keystone V3, the value for SWIFT_TENANT should be the project name
|
|
||||||
# SWIFT_TENANT=
|
|
||||||
# SWIFT_PASSWORD=
|
|
||||||
# Keystone V2 and V3 URLs are supported. Use a V3 URL if possible to avoid
|
|
||||||
# issues with token rate-limiting during high load.
|
|
||||||
# SWIFT_AUTH_URL=
|
|
||||||
# SWIFT_CONTAINER=
|
|
||||||
# SWIFT_OBJECT_URL=
|
|
||||||
# SWIFT_REGION=
|
|
||||||
# Defaults to 'default'
|
|
||||||
# SWIFT_DOMAIN_NAME=
|
|
||||||
# Defaults to 60 seconds. Set to 0 to disable
|
|
||||||
# SWIFT_CACHE_TTL=
|
|
||||||
|
|
||||||
# Optional alias for S3 if you want to use Cloudfront or Cloudflare in front
|
# Optional alias for S3 if you want to use Cloudfront or Cloudflare in front
|
||||||
# S3_CLOUDFRONT_HOST=
|
# S3_CLOUDFRONT_HOST=
|
||||||
|
|
||||||
|
|||||||
@@ -11,11 +11,10 @@ DB_PASS=
|
|||||||
DB_PORT=5432
|
DB_PORT=5432
|
||||||
|
|
||||||
# Federation
|
# Federation
|
||||||
# Note: Changing LOCAL_DOMAIN at a later time will cause unwanted side effects, including breaking all existing federation.
|
# Note: Changing LOCAL_DOMAIN or LOCAL_HTTPS at a later time will cause unwanted side effects.
|
||||||
# LOCAL_DOMAIN should *NOT* contain the protocol part of the domain e.g https://example.com.
|
# LOCAL_DOMAIN should *NOT* contain the protocol part of the domain e.g https://example.com.
|
||||||
LOCAL_DOMAIN=example.com
|
LOCAL_DOMAIN=example.com
|
||||||
|
LOCAL_HTTPS=true
|
||||||
# Changing LOCAL_HTTPS in production is no longer supported. (Mastodon will always serve https:// links)
|
|
||||||
|
|
||||||
# Use this only if you need to run mastodon on a different domain than the one used for federation.
|
# Use this only if you need to run mastodon on a different domain than the one used for federation.
|
||||||
# You can read more about this option on https://github.com/tootsuite/documentation/blob/master/Running-Mastodon/Serving_a_different_domain.md
|
# You can read more about this option on https://github.com/tootsuite/documentation/blob/master/Running-Mastodon/Serving_a_different_domain.md
|
||||||
@@ -135,6 +134,3 @@ STREAMING_CLUSTER_NUM=1
|
|||||||
# If you use Docker, you may want to assign UID/GID manually.
|
# If you use Docker, you may want to assign UID/GID manually.
|
||||||
# UID=1000
|
# UID=1000
|
||||||
# GID=1000
|
# GID=1000
|
||||||
|
|
||||||
# Maximum allowed character count
|
|
||||||
# MAX_TOOT_CHARS=500
|
|
||||||
|
|||||||
@@ -29,11 +29,6 @@ settings:
|
|||||||
import/ignore:
|
import/ignore:
|
||||||
- node_modules
|
- node_modules
|
||||||
- \\.(css|scss|json)$
|
- \\.(css|scss|json)$
|
||||||
import/resolver:
|
|
||||||
node:
|
|
||||||
moduleDirectory:
|
|
||||||
- node_modules
|
|
||||||
- app/javascript
|
|
||||||
|
|
||||||
rules:
|
rules:
|
||||||
brace-style: warn
|
brace-style: warn
|
||||||
|
|||||||
0
.gitmodules
vendored
0
.gitmodules
vendored
@@ -27,14 +27,11 @@ addons:
|
|||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
- trusty-media
|
- trusty-media
|
||||||
- sourceline: deb https://dl.yarnpkg.com/debian/ stable main
|
|
||||||
key_url: https://dl.yarnpkg.com/debian/pubkey.gpg
|
|
||||||
packages:
|
packages:
|
||||||
- ffmpeg
|
- ffmpeg
|
||||||
- libicu-dev
|
|
||||||
- libprotobuf-dev
|
- libprotobuf-dev
|
||||||
- protobuf-compiler
|
- protobuf-compiler
|
||||||
- yarn
|
- libicu-dev
|
||||||
|
|
||||||
rvm:
|
rvm:
|
||||||
- 2.3.4
|
- 2.3.4
|
||||||
@@ -45,6 +42,7 @@ services:
|
|||||||
|
|
||||||
install:
|
install:
|
||||||
- nvm install
|
- nvm install
|
||||||
|
- npm install -g yarn
|
||||||
- bundle install --path=vendor/bundle --without development production --retry=3 --jobs=16
|
- bundle install --path=vendor/bundle --without development production --retry=3 --jobs=16
|
||||||
- yarn install
|
- yarn install
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ This Code of Conduct applies both within project spaces and in public spaces whe
|
|||||||
|
|
||||||
## Enforcement
|
## Enforcement
|
||||||
|
|
||||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at beatrix.bitrot@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at eugen@zeonfederated.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||||
|
|
||||||
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||||
|
|
||||||
|
|||||||
@@ -1,36 +1,3 @@
|
|||||||
# Contributing to Mastodon Glitch Edition #
|
|
||||||
|
|
||||||
Thank you for your interest in contributing to the `glitch-soc` project!
|
|
||||||
Here are some guidelines, and ways you can help.
|
|
||||||
|
|
||||||
> (This document is a bit of a work-in-progress, so please bear with us.
|
|
||||||
> If you don't see what you're looking for here, please don't hesitate to reach out!)
|
|
||||||
|
|
||||||
## Planning ##
|
|
||||||
|
|
||||||
Right now a lot of the planning for this project takes place in our development Discord, or through GitHub Issues and Projects.
|
|
||||||
We're working on ways to improve the planning structure and better solicit feedback, and if you feel like you can help in this respect, feel free to give us a holler.
|
|
||||||
|
|
||||||
## Documentation ##
|
|
||||||
|
|
||||||
The documentation for this repository is available at [`glitch-soc/docs`](https://github.com/glitch-soc/docs) (online at [glitch-soc.github.io/docs/](https://glitch-soc.github.io/docs/)).
|
|
||||||
Right now, we've mostly focused on the features that make this fork different from upstream in some manner.
|
|
||||||
Adding screenshots, improving descriptions, and so forth are all ways to help contribute to the project even if you don't know any code.
|
|
||||||
|
|
||||||
## Frontend Development ##
|
|
||||||
|
|
||||||
Check out [the documentation here](https://glitch-soc.github.io/docs/contributing/frontend/) for more information.
|
|
||||||
|
|
||||||
## Backend Development ##
|
|
||||||
|
|
||||||
See the guidelines below.
|
|
||||||
|
|
||||||
- - -
|
|
||||||
|
|
||||||
You should also try to follow the guidelines set out in the original `CONTRIBUTING.md` from `tootsuite/mastodon`, reproduced below.
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
|
|
||||||
CONTRIBUTING
|
CONTRIBUTING
|
||||||
============
|
============
|
||||||
|
|
||||||
@@ -82,5 +49,3 @@ It is expected that you have a working development environment set up (see back-
|
|||||||
* If you are introducing new strings, they must be using localization methods
|
* If you are introducing new strings, they must be using localization methods
|
||||||
|
|
||||||
If the JavaScript or CSS assets won't compile due to a syntax error, it's a good sign that the pull request isn't ready for submission yet.
|
If the JavaScript or CSS assets won't compile due to a syntax error, it's a good sign that the pull request isn't ready for submission yet.
|
||||||
|
|
||||||
</blockquote>
|
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ ENV UID=991 GID=991 \
|
|||||||
RAILS_SERVE_STATIC_FILES=true \
|
RAILS_SERVE_STATIC_FILES=true \
|
||||||
RAILS_ENV=production NODE_ENV=production
|
RAILS_ENV=production NODE_ENV=production
|
||||||
|
|
||||||
ARG YARN_VERSION=1.3.2
|
ARG YARN_VERSION=1.1.0
|
||||||
ARG YARN_DOWNLOAD_SHA256=6cfe82e530ef0837212f13e45c1565ba53f5199eec2527b85ecbcd88bf26821d
|
ARG YARN_DOWNLOAD_SHA256=171c1f9ee93c488c0d774ac6e9c72649047c3f896277d88d0f805266519430f3
|
||||||
ARG LIBICONV_VERSION=1.15
|
ARG LIBICONV_VERSION=1.15
|
||||||
ARG LIBICONV_DOWNLOAD_SHA256=ccf536620a45458d26ba83887a983b96827001e92a13847b45e4925cc8913178
|
ARG LIBICONV_DOWNLOAD_SHA256=ccf536620a45458d26ba83887a983b96827001e92a13847b45e4925cc8913178
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ RUN apk -U upgrade \
|
|||||||
&& rm yarn.tar.gz \
|
&& rm yarn.tar.gz \
|
||||||
&& mv /tmp/src/yarn-v$YARN_VERSION /opt/yarn \
|
&& mv /tmp/src/yarn-v$YARN_VERSION /opt/yarn \
|
||||||
&& ln -s /opt/yarn/bin/yarn /usr/local/bin/yarn \
|
&& ln -s /opt/yarn/bin/yarn /usr/local/bin/yarn \
|
||||||
&& wget -O libiconv.tar.gz "https://ftp.gnu.org/pub/gnu/libiconv/libiconv-$LIBICONV_VERSION.tar.gz" \
|
&& wget -O libiconv.tar.gz "http://ftp.gnu.org/pub/gnu/libiconv/libiconv-$LIBICONV_VERSION.tar.gz" \
|
||||||
&& echo "$LIBICONV_DOWNLOAD_SHA256 *libiconv.tar.gz" | sha256sum -c - \
|
&& echo "$LIBICONV_DOWNLOAD_SHA256 *libiconv.tar.gz" | sha256sum -c - \
|
||||||
&& tar -xzf libiconv.tar.gz -C /tmp/src \
|
&& tar -xzf libiconv.tar.gz -C /tmp/src \
|
||||||
&& rm libiconv.tar.gz \
|
&& rm libiconv.tar.gz \
|
||||||
|
|||||||
7
Gemfile
7
Gemfile
@@ -14,13 +14,12 @@ gem 'pg', '~> 0.20'
|
|||||||
gem 'pghero', '~> 1.7'
|
gem 'pghero', '~> 1.7'
|
||||||
gem 'dotenv-rails', '~> 2.2'
|
gem 'dotenv-rails', '~> 2.2'
|
||||||
|
|
||||||
gem 'aws-sdk', '~> 2.10', require: false
|
gem 'fog-aws', '~> 1.4', require: false
|
||||||
gem 'fog-core', '~> 1.45'
|
gem 'fog-core', '~> 1.45'
|
||||||
gem 'fog-local', '~> 0.4', require: false
|
gem 'fog-local', '~> 0.4', require: false
|
||||||
gem 'fog-openstack', '~> 0.1', require: false
|
gem 'fog-openstack', '~> 0.1', require: false
|
||||||
gem 'paperclip', '~> 5.1'
|
gem 'paperclip', '~> 5.1'
|
||||||
gem 'paperclip-av-transcoder', '~> 0.6'
|
gem 'paperclip-av-transcoder', '~> 0.6'
|
||||||
gem 'posix-spawn'
|
|
||||||
|
|
||||||
gem 'active_model_serializers', '~> 0.10'
|
gem 'active_model_serializers', '~> 0.10'
|
||||||
gem 'addressable', '~> 2.5'
|
gem 'addressable', '~> 2.5'
|
||||||
@@ -29,7 +28,7 @@ gem 'browser'
|
|||||||
gem 'charlock_holmes', '~> 0.7.5'
|
gem 'charlock_holmes', '~> 0.7.5'
|
||||||
gem 'iso-639'
|
gem 'iso-639'
|
||||||
gem 'cld3', '~> 3.2.0'
|
gem 'cld3', '~> 3.2.0'
|
||||||
gem 'devise', '~> 4.3'
|
gem 'devise', '~> 4.2'
|
||||||
gem 'devise-two-factor', '~> 3.0'
|
gem 'devise-two-factor', '~> 3.0'
|
||||||
gem 'doorkeeper', '~> 4.2'
|
gem 'doorkeeper', '~> 4.2'
|
||||||
gem 'fast_blank', '~> 1.0'
|
gem 'fast_blank', '~> 1.0'
|
||||||
@@ -50,6 +49,7 @@ gem 'oj', '~> 3.3'
|
|||||||
gem 'ostatus2', '~> 2.0'
|
gem 'ostatus2', '~> 2.0'
|
||||||
gem 'ox', '~> 2.8'
|
gem 'ox', '~> 2.8'
|
||||||
gem 'pundit', '~> 1.1'
|
gem 'pundit', '~> 1.1'
|
||||||
|
gem 'rabl', '~> 0.13'
|
||||||
gem 'rack-attack', '~> 5.0'
|
gem 'rack-attack', '~> 5.0'
|
||||||
gem 'rack-cors', '~> 0.4', require: 'rack/cors'
|
gem 'rack-cors', '~> 0.4', require: 'rack/cors'
|
||||||
gem 'rack-timeout', '~> 0.4'
|
gem 'rack-timeout', '~> 0.4'
|
||||||
@@ -59,7 +59,6 @@ gem 'redis', '~> 3.3', require: ['redis', 'redis/connection/hiredis']
|
|||||||
gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock'
|
gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock'
|
||||||
gem 'rqrcode', '~> 0.10'
|
gem 'rqrcode', '~> 0.10'
|
||||||
gem 'ruby-oembed', '~> 0.12', require: 'oembed'
|
gem 'ruby-oembed', '~> 0.12', require: 'oembed'
|
||||||
gem 'ruby-progressbar', '~> 1.4'
|
|
||||||
gem 'sanitize', '~> 4.4'
|
gem 'sanitize', '~> 4.4'
|
||||||
gem 'sidekiq', '~> 5.0'
|
gem 'sidekiq', '~> 5.0'
|
||||||
gem 'sidekiq-scheduler', '~> 2.1'
|
gem 'sidekiq-scheduler', '~> 2.1'
|
||||||
|
|||||||
118
Gemfile.lock
118
Gemfile.lock
@@ -24,11 +24,11 @@ GEM
|
|||||||
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.0, >= 1.0.3)
|
||||||
active_model_serializers (0.10.7)
|
active_model_serializers (0.10.6)
|
||||||
actionpack (>= 4.1, < 6)
|
actionpack (>= 4.1, < 6)
|
||||||
activemodel (>= 4.1, < 6)
|
activemodel (>= 4.1, < 6)
|
||||||
case_transform (>= 0.2)
|
case_transform (>= 0.2)
|
||||||
jsonapi-renderer (>= 0.1.1.beta1, < 0.3)
|
jsonapi-renderer (>= 0.1.1.beta1, < 0.2)
|
||||||
active_record_query_trace (1.5.4)
|
active_record_query_trace (1.5.4)
|
||||||
activejob (5.1.4)
|
activejob (5.1.4)
|
||||||
activesupport (= 5.1.4)
|
activesupport (= 5.1.4)
|
||||||
@@ -57,14 +57,6 @@ GEM
|
|||||||
encryptor (~> 3.0.0)
|
encryptor (~> 3.0.0)
|
||||||
av (0.9.0)
|
av (0.9.0)
|
||||||
cocaine (~> 0.5.3)
|
cocaine (~> 0.5.3)
|
||||||
aws-sdk (2.10.100)
|
|
||||||
aws-sdk-resources (= 2.10.100)
|
|
||||||
aws-sdk-core (2.10.100)
|
|
||||||
aws-sigv4 (~> 1.0)
|
|
||||||
jmespath (~> 1.0)
|
|
||||||
aws-sdk-resources (2.10.100)
|
|
||||||
aws-sdk-core (= 2.10.100)
|
|
||||||
aws-sigv4 (1.0.2)
|
|
||||||
bcrypt (3.1.11)
|
bcrypt (3.1.11)
|
||||||
better_errors (2.4.0)
|
better_errors (2.4.0)
|
||||||
coderay (>= 1.0.0)
|
coderay (>= 1.0.0)
|
||||||
@@ -91,15 +83,15 @@ GEM
|
|||||||
capistrano-bundler (1.3.0)
|
capistrano-bundler (1.3.0)
|
||||||
capistrano (~> 3.1)
|
capistrano (~> 3.1)
|
||||||
sshkit (~> 1.2)
|
sshkit (~> 1.2)
|
||||||
capistrano-rails (1.3.1)
|
capistrano-rails (1.3.0)
|
||||||
capistrano (~> 3.1)
|
capistrano (~> 3.1)
|
||||||
capistrano-bundler (~> 1.1)
|
capistrano-bundler (~> 1.1)
|
||||||
capistrano-rbenv (2.1.3)
|
capistrano-rbenv (2.1.2)
|
||||||
capistrano (~> 3.1)
|
capistrano (~> 3.1)
|
||||||
sshkit (~> 1.3)
|
sshkit (~> 1.3)
|
||||||
capistrano-yarn (2.0.2)
|
capistrano-yarn (2.0.2)
|
||||||
capistrano (~> 3.0)
|
capistrano (~> 3.0)
|
||||||
capybara (2.16.1)
|
capybara (2.15.4)
|
||||||
addressable
|
addressable
|
||||||
mini_mime (>= 0.1.3)
|
mini_mime (>= 0.1.3)
|
||||||
nokogiri (>= 1.3.3)
|
nokogiri (>= 1.3.3)
|
||||||
@@ -121,7 +113,7 @@ GEM
|
|||||||
connection_pool (2.2.1)
|
connection_pool (2.2.1)
|
||||||
crack (0.4.3)
|
crack (0.4.3)
|
||||||
safe_yaml (~> 1.0.0)
|
safe_yaml (~> 1.0.0)
|
||||||
crass (1.0.3)
|
crass (1.0.2)
|
||||||
debug_inspector (0.0.3)
|
debug_inspector (0.0.3)
|
||||||
devise (4.3.0)
|
devise (4.3.0)
|
||||||
bcrypt (~> 3.0)
|
bcrypt (~> 3.0)
|
||||||
@@ -129,11 +121,11 @@ GEM
|
|||||||
railties (>= 4.1.0, < 5.2)
|
railties (>= 4.1.0, < 5.2)
|
||||||
responders
|
responders
|
||||||
warden (~> 1.2.3)
|
warden (~> 1.2.3)
|
||||||
devise-two-factor (3.0.2)
|
devise-two-factor (3.0.0)
|
||||||
activesupport (< 5.2)
|
activesupport
|
||||||
attr_encrypted (>= 1.3, < 4, != 2)
|
attr_encrypted (>= 1.3, < 4, != 2)
|
||||||
devise (~> 4.0)
|
devise (~> 4.0)
|
||||||
railties (< 5.2)
|
railties
|
||||||
rotp (~> 2.0)
|
rotp (~> 2.0)
|
||||||
diff-lcs (1.3)
|
diff-lcs (1.3)
|
||||||
docile (1.1.5)
|
docile (1.1.5)
|
||||||
@@ -160,6 +152,11 @@ GEM
|
|||||||
i18n (~> 0.5)
|
i18n (~> 0.5)
|
||||||
fast_blank (1.0.0)
|
fast_blank (1.0.0)
|
||||||
ffi (1.9.18)
|
ffi (1.9.18)
|
||||||
|
fog-aws (1.4.1)
|
||||||
|
fog-core (~> 1.38)
|
||||||
|
fog-json (~> 1.0)
|
||||||
|
fog-xml (~> 0.1)
|
||||||
|
ipaddress (~> 0.8)
|
||||||
fog-core (1.45.0)
|
fog-core (1.45.0)
|
||||||
builder
|
builder
|
||||||
excon (~> 0.58)
|
excon (~> 0.58)
|
||||||
@@ -173,6 +170,9 @@ GEM
|
|||||||
fog-core (>= 1.40)
|
fog-core (>= 1.40)
|
||||||
fog-json (>= 1.0)
|
fog-json (>= 1.0)
|
||||||
ipaddress (>= 0.8)
|
ipaddress (>= 0.8)
|
||||||
|
fog-xml (0.1.3)
|
||||||
|
fog-core
|
||||||
|
nokogiri (>= 1.5.11, < 2.0.0)
|
||||||
formatador (0.2.5)
|
formatador (0.2.5)
|
||||||
fuubar (2.2.0)
|
fuubar (2.2.0)
|
||||||
rspec-core (~> 3.0)
|
rspec-core (~> 3.0)
|
||||||
@@ -184,7 +184,7 @@ GEM
|
|||||||
http (~> 2.2)
|
http (~> 2.2)
|
||||||
nokogiri (~> 1.8)
|
nokogiri (~> 1.8)
|
||||||
oj (~> 3.0)
|
oj (~> 3.0)
|
||||||
hamlit (2.8.5)
|
hamlit (2.8.4)
|
||||||
temple (>= 0.8.0)
|
temple (>= 0.8.0)
|
||||||
thor
|
thor
|
||||||
tilt
|
tilt
|
||||||
@@ -196,7 +196,7 @@ GEM
|
|||||||
hamster (3.0.0)
|
hamster (3.0.0)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
hashdiff (0.3.7)
|
hashdiff (0.3.7)
|
||||||
highline (1.7.10)
|
highline (1.7.8)
|
||||||
hiredis (0.6.1)
|
hiredis (0.6.1)
|
||||||
hkdf (0.3.0)
|
hkdf (0.3.0)
|
||||||
htmlentities (4.3.4)
|
htmlentities (4.3.4)
|
||||||
@@ -213,9 +213,9 @@ GEM
|
|||||||
httplog (0.99.7)
|
httplog (0.99.7)
|
||||||
colorize
|
colorize
|
||||||
rack
|
rack
|
||||||
i18n (0.9.1)
|
i18n (0.9.0)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
i18n-tasks (0.9.19)
|
i18n-tasks (0.9.18)
|
||||||
activesupport (>= 4.0.2)
|
activesupport (>= 4.0.2)
|
||||||
ast (>= 2.1.0)
|
ast (>= 2.1.0)
|
||||||
easy_translate (>= 0.5.0)
|
easy_translate (>= 0.5.0)
|
||||||
@@ -228,7 +228,6 @@ GEM
|
|||||||
idn-ruby (0.1.0)
|
idn-ruby (0.1.0)
|
||||||
ipaddress (0.8.3)
|
ipaddress (0.8.3)
|
||||||
iso-639 (0.2.8)
|
iso-639 (0.2.8)
|
||||||
jmespath (1.3.1)
|
|
||||||
json (2.1.0)
|
json (2.1.0)
|
||||||
json-ld (2.1.7)
|
json-ld (2.1.7)
|
||||||
multi_json (~> 1.12)
|
multi_json (~> 1.12)
|
||||||
@@ -237,8 +236,8 @@ GEM
|
|||||||
json-ld (~> 2.1, >= 2.1.5)
|
json-ld (~> 2.1, >= 2.1.5)
|
||||||
multi_json (~> 1.11)
|
multi_json (~> 1.11)
|
||||||
rdf (~> 2.2)
|
rdf (~> 2.2)
|
||||||
jsonapi-renderer (0.2.0)
|
jsonapi-renderer (0.1.3)
|
||||||
jwt (2.1.0)
|
jwt (1.5.6)
|
||||||
kaminari (1.1.1)
|
kaminari (1.1.1)
|
||||||
activesupport (>= 4.1.0)
|
activesupport (>= 4.1.0)
|
||||||
kaminari-actionview (= 1.1.1)
|
kaminari-actionview (= 1.1.1)
|
||||||
@@ -268,8 +267,8 @@ GEM
|
|||||||
loofah (2.1.1)
|
loofah (2.1.1)
|
||||||
crass (~> 1.0.2)
|
crass (~> 1.0.2)
|
||||||
nokogiri (>= 1.5.9)
|
nokogiri (>= 1.5.9)
|
||||||
mail (2.7.0)
|
mail (2.6.6)
|
||||||
mini_mime (>= 0.1.1)
|
mime-types (>= 1.16, < 4)
|
||||||
mario-redis-lock (1.2.0)
|
mario-redis-lock (1.2.0)
|
||||||
redis (~> 3, >= 3.0.5)
|
redis (~> 3, >= 3.0.5)
|
||||||
method_source (0.9.0)
|
method_source (0.9.0)
|
||||||
@@ -280,7 +279,7 @@ GEM
|
|||||||
mime-types-data (~> 3.2015)
|
mime-types-data (~> 3.2015)
|
||||||
mime-types-data (3.2016.0521)
|
mime-types-data (3.2016.0521)
|
||||||
mimemagic (0.3.2)
|
mimemagic (0.3.2)
|
||||||
mini_mime (1.0.0)
|
mini_mime (0.1.4)
|
||||||
mini_portile2 (2.3.0)
|
mini_portile2 (2.3.0)
|
||||||
minitest (5.10.3)
|
minitest (5.10.3)
|
||||||
msgpack (1.1.0)
|
msgpack (1.1.0)
|
||||||
@@ -299,12 +298,14 @@ GEM
|
|||||||
sidekiq (>= 3.5.0)
|
sidekiq (>= 3.5.0)
|
||||||
statsd-ruby (~> 1.2.0)
|
statsd-ruby (~> 1.2.0)
|
||||||
oj (3.3.9)
|
oj (3.3.9)
|
||||||
|
openssl (2.0.6)
|
||||||
orm_adapter (0.5.0)
|
orm_adapter (0.5.0)
|
||||||
ostatus2 (2.0.2)
|
ostatus2 (2.0.1)
|
||||||
addressable (~> 2.4)
|
addressable (~> 2.4)
|
||||||
http (~> 2.0)
|
http (~> 2.0)
|
||||||
nokogiri (~> 1.6)
|
nokogiri (~> 1.6)
|
||||||
ox (2.8.2)
|
openssl (~> 2.0)
|
||||||
|
ox (2.8.1)
|
||||||
paperclip (5.1.0)
|
paperclip (5.1.0)
|
||||||
activemodel (>= 4.2.0)
|
activemodel (>= 4.2.0)
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 4.2.0)
|
||||||
@@ -315,25 +316,26 @@ GEM
|
|||||||
av (~> 0.9.0)
|
av (~> 0.9.0)
|
||||||
paperclip (>= 2.5.2)
|
paperclip (>= 2.5.2)
|
||||||
parallel (1.12.0)
|
parallel (1.12.0)
|
||||||
parallel_tests (2.19.0)
|
parallel_tests (2.17.0)
|
||||||
parallel
|
parallel
|
||||||
parser (2.4.0.2)
|
parser (2.4.0.0)
|
||||||
ast (~> 2.3)
|
ast (~> 2.2)
|
||||||
pg (0.21.0)
|
pg (0.21.0)
|
||||||
pghero (1.7.0)
|
pghero (1.7.0)
|
||||||
activerecord
|
activerecord
|
||||||
pkg-config (1.2.8)
|
pkg-config (1.2.8)
|
||||||
posix-spawn (0.3.13)
|
|
||||||
powerpack (0.1.1)
|
powerpack (0.1.1)
|
||||||
pry (0.11.3)
|
pry (0.11.2)
|
||||||
coderay (~> 1.1.0)
|
coderay (~> 1.1.0)
|
||||||
method_source (~> 0.9.0)
|
method_source (~> 0.9.0)
|
||||||
pry-rails (0.3.6)
|
pry-rails (0.3.6)
|
||||||
pry (>= 0.10.4)
|
pry (>= 0.10.4)
|
||||||
public_suffix (3.0.1)
|
public_suffix (3.0.0)
|
||||||
puma (3.11.0)
|
puma (3.10.0)
|
||||||
pundit (1.1.0)
|
pundit (1.1.0)
|
||||||
activesupport (>= 3.0.0)
|
activesupport (>= 3.0.0)
|
||||||
|
rabl (0.13.1)
|
||||||
|
activesupport (>= 2.3.14)
|
||||||
rack (2.0.3)
|
rack (2.0.3)
|
||||||
rack-attack (5.0.1)
|
rack-attack (5.0.1)
|
||||||
rack
|
rack
|
||||||
@@ -342,7 +344,7 @@ GEM
|
|||||||
rack
|
rack
|
||||||
rack-proxy (0.6.2)
|
rack-proxy (0.6.2)
|
||||||
rack
|
rack
|
||||||
rack-test (0.8.2)
|
rack-test (0.7.0)
|
||||||
rack (>= 1.0, < 3)
|
rack (>= 1.0, < 3)
|
||||||
rack-timeout (0.4.2)
|
rack-timeout (0.4.2)
|
||||||
rails (5.1.4)
|
rails (5.1.4)
|
||||||
@@ -379,11 +381,8 @@ GEM
|
|||||||
thor (>= 0.18.1, < 2.0)
|
thor (>= 0.18.1, < 2.0)
|
||||||
rainbow (2.2.2)
|
rainbow (2.2.2)
|
||||||
rake
|
rake
|
||||||
rake (12.3.0)
|
rake (12.2.1)
|
||||||
rb-fsevent (0.10.2)
|
rdf (2.2.11)
|
||||||
rb-inotify (0.9.10)
|
|
||||||
ffi (>= 0.5.0, < 2)
|
|
||||||
rdf (2.2.12)
|
|
||||||
hamster (~> 3.0)
|
hamster (~> 3.0)
|
||||||
link_header (~> 0.0, >= 0.0.8)
|
link_header (~> 0.0, >= 0.0.8)
|
||||||
rdf-normalize (0.3.2)
|
rdf-normalize (0.3.2)
|
||||||
@@ -396,8 +395,8 @@ GEM
|
|||||||
redis-activesupport (5.0.4)
|
redis-activesupport (5.0.4)
|
||||||
activesupport (>= 3, < 6)
|
activesupport (>= 3, < 6)
|
||||||
redis-store (>= 1.3, < 2)
|
redis-store (>= 1.3, < 2)
|
||||||
redis-namespace (1.6.0)
|
redis-namespace (1.5.3)
|
||||||
redis (>= 3.0.4)
|
redis (~> 3.0, >= 3.0.4)
|
||||||
redis-rack (2.0.3)
|
redis-rack (2.0.3)
|
||||||
rack (>= 1.5, < 3)
|
rack (>= 1.5, < 3)
|
||||||
redis-store (>= 1.2, < 2)
|
redis-store (>= 1.2, < 2)
|
||||||
@@ -422,7 +421,7 @@ GEM
|
|||||||
rspec-mocks (3.7.0)
|
rspec-mocks (3.7.0)
|
||||||
diff-lcs (>= 1.2.0, < 2.0)
|
diff-lcs (>= 1.2.0, < 2.0)
|
||||||
rspec-support (~> 3.7.0)
|
rspec-support (~> 3.7.0)
|
||||||
rspec-rails (3.7.2)
|
rspec-rails (3.7.1)
|
||||||
actionpack (>= 3.0)
|
actionpack (>= 3.0)
|
||||||
activesupport (>= 3.0)
|
activesupport (>= 3.0)
|
||||||
railties (>= 3.0)
|
railties (>= 3.0)
|
||||||
@@ -450,14 +449,10 @@ GEM
|
|||||||
crass (~> 1.0.2)
|
crass (~> 1.0.2)
|
||||||
nokogiri (>= 1.4.4)
|
nokogiri (>= 1.4.4)
|
||||||
nokogumbo (~> 1.4.1)
|
nokogumbo (~> 1.4.1)
|
||||||
sass (3.5.3)
|
sass (3.4.25)
|
||||||
sass-listen (~> 4.0.0)
|
scss_lint (0.55.0)
|
||||||
sass-listen (4.0.0)
|
|
||||||
rb-fsevent (~> 0.9, >= 0.9.4)
|
|
||||||
rb-inotify (~> 0.9, >= 0.9.7)
|
|
||||||
scss_lint (0.56.0)
|
|
||||||
rake (>= 0.9, < 13)
|
rake (>= 0.9, < 13)
|
||||||
sass (~> 3.5.3)
|
sass (~> 3.4.20)
|
||||||
sidekiq (5.0.5)
|
sidekiq (5.0.5)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
connection_pool (~> 2.2, >= 2.2.0)
|
connection_pool (~> 2.2, >= 2.2.0)
|
||||||
@@ -491,7 +486,7 @@ GEM
|
|||||||
actionpack (>= 4.0)
|
actionpack (>= 4.0)
|
||||||
activesupport (>= 4.0)
|
activesupport (>= 4.0)
|
||||||
sprockets (>= 3.0.0)
|
sprockets (>= 3.0.0)
|
||||||
sshkit (1.15.1)
|
sshkit (1.14.0)
|
||||||
net-scp (>= 1.1.2)
|
net-scp (>= 1.1.2)
|
||||||
net-ssh (>= 2.8.0)
|
net-ssh (>= 2.8.0)
|
||||||
statsd-ruby (1.2.1)
|
statsd-ruby (1.2.1)
|
||||||
@@ -519,7 +514,7 @@ GEM
|
|||||||
uniform_notifier (1.10.0)
|
uniform_notifier (1.10.0)
|
||||||
warden (1.2.7)
|
warden (1.2.7)
|
||||||
rack (>= 1.0)
|
rack (>= 1.0)
|
||||||
webmock (3.1.1)
|
webmock (3.1.0)
|
||||||
addressable (>= 2.3.6)
|
addressable (>= 2.3.6)
|
||||||
crack (>= 0.3.2)
|
crack (>= 0.3.2)
|
||||||
hashdiff
|
hashdiff
|
||||||
@@ -527,12 +522,12 @@ GEM
|
|||||||
activesupport (>= 4.2)
|
activesupport (>= 4.2)
|
||||||
rack-proxy (>= 0.6.1)
|
rack-proxy (>= 0.6.1)
|
||||||
railties (>= 4.2)
|
railties (>= 4.2)
|
||||||
webpush (0.3.3)
|
webpush (0.3.2)
|
||||||
hkdf (~> 0.2)
|
hkdf (~> 0.2)
|
||||||
jwt (~> 2.0)
|
jwt
|
||||||
websocket-driver (0.6.5)
|
websocket-driver (0.6.5)
|
||||||
websocket-extensions (>= 0.1.0)
|
websocket-extensions (>= 0.1.0)
|
||||||
websocket-extensions (0.1.3)
|
websocket-extensions (0.1.2)
|
||||||
xpath (2.1.0)
|
xpath (2.1.0)
|
||||||
nokogiri (~> 1.3)
|
nokogiri (~> 1.3)
|
||||||
|
|
||||||
@@ -544,7 +539,6 @@ DEPENDENCIES
|
|||||||
active_record_query_trace (~> 1.5)
|
active_record_query_trace (~> 1.5)
|
||||||
addressable (~> 2.5)
|
addressable (~> 2.5)
|
||||||
annotate (~> 2.7)
|
annotate (~> 2.7)
|
||||||
aws-sdk (~> 2.10)
|
|
||||||
better_errors (~> 2.4)
|
better_errors (~> 2.4)
|
||||||
binding_of_caller (~> 0.7)
|
binding_of_caller (~> 0.7)
|
||||||
bootsnap
|
bootsnap
|
||||||
@@ -560,13 +554,14 @@ DEPENDENCIES
|
|||||||
charlock_holmes (~> 0.7.5)
|
charlock_holmes (~> 0.7.5)
|
||||||
cld3 (~> 3.2.0)
|
cld3 (~> 3.2.0)
|
||||||
climate_control (~> 0.2)
|
climate_control (~> 0.2)
|
||||||
devise (~> 4.3)
|
devise (~> 4.2)
|
||||||
devise-two-factor (~> 3.0)
|
devise-two-factor (~> 3.0)
|
||||||
doorkeeper (~> 4.2)
|
doorkeeper (~> 4.2)
|
||||||
dotenv-rails (~> 2.2)
|
dotenv-rails (~> 2.2)
|
||||||
fabrication (~> 2.18)
|
fabrication (~> 2.18)
|
||||||
faker (~> 1.7)
|
faker (~> 1.7)
|
||||||
fast_blank (~> 1.0)
|
fast_blank (~> 1.0)
|
||||||
|
fog-aws (~> 1.4)
|
||||||
fog-core (~> 1.45)
|
fog-core (~> 1.45)
|
||||||
fog-local (~> 0.4)
|
fog-local (~> 0.4)
|
||||||
fog-openstack (~> 0.1)
|
fog-openstack (~> 0.1)
|
||||||
@@ -601,10 +596,10 @@ DEPENDENCIES
|
|||||||
pg (~> 0.20)
|
pg (~> 0.20)
|
||||||
pghero (~> 1.7)
|
pghero (~> 1.7)
|
||||||
pkg-config (~> 1.2)
|
pkg-config (~> 1.2)
|
||||||
posix-spawn
|
|
||||||
pry-rails (~> 0.3)
|
pry-rails (~> 0.3)
|
||||||
puma (~> 3.10)
|
puma (~> 3.10)
|
||||||
pundit (~> 1.1)
|
pundit (~> 1.1)
|
||||||
|
rabl (~> 0.13)
|
||||||
rack-attack (~> 5.0)
|
rack-attack (~> 5.0)
|
||||||
rack-cors (~> 0.4)
|
rack-cors (~> 0.4)
|
||||||
rack-timeout (~> 0.4)
|
rack-timeout (~> 0.4)
|
||||||
@@ -621,7 +616,6 @@ DEPENDENCIES
|
|||||||
rspec-sidekiq (~> 3.0)
|
rspec-sidekiq (~> 3.0)
|
||||||
rubocop
|
rubocop
|
||||||
ruby-oembed (~> 0.12)
|
ruby-oembed (~> 0.12)
|
||||||
ruby-progressbar (~> 1.4)
|
|
||||||
sanitize (~> 4.4)
|
sanitize (~> 4.4)
|
||||||
scss_lint (~> 0.55)
|
scss_lint (~> 0.55)
|
||||||
sidekiq (~> 5.0)
|
sidekiq (~> 5.0)
|
||||||
@@ -644,4 +638,4 @@ RUBY VERSION
|
|||||||
ruby 2.4.2p198
|
ruby 2.4.2p198
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
1.16.1
|
1.15.4
|
||||||
|
|||||||
87
README.md
87
README.md
@@ -1,10 +1,85 @@
|
|||||||
# Mastodon Glitch Edition #
|

|
||||||
|
========
|
||||||
|
|
||||||
> Now with automated deploys!
|
[][travis]
|
||||||
|
[][code_climate]
|
||||||
|
|
||||||
[](https://travis-ci.org/glitch-soc/mastodon)
|
[travis]: https://travis-ci.org/tootsuite/mastodon
|
||||||
|
[code_climate]: https://codeclimate.com/github/tootsuite/mastodon
|
||||||
|
|
||||||
So here's the deal: we all work on this code, and then it runs on dev.glitch.social and anyone who uses that does so absolutely at their own risk. can you dig it?
|
Mastodon is a **free, open-source social network server** based on **open web protocols** like ActivityPub and OStatus. The social focus of the project is a viable decentralized alternative to commercial social media silos that returns the control of the content distribution channels to the people. The technical focus of the project is a good user interface, a clean REST API for 3rd party apps and robust anti-abuse tools.
|
||||||
|
|
||||||
- You can view documentation for this project at [glitch-soc.github.io/docs/](https://glitch-soc.github.io/docs/).
|
Click on the screenshot below to watch a demo of the UI:
|
||||||
- And contributing guidelines are available [here](CONTRIBUTING.md) and [here](https://glitch-soc.github.io/docs/contributing/).
|
|
||||||
|
[][youtube_demo]
|
||||||
|
|
||||||
|
[youtube_demo]: https://www.youtube.com/watch?v=YO1jQ8_rAMU
|
||||||
|
|
||||||
|
**Ruby on Rails** is used for the back-end, while **React.js** and Redux are used for the dynamic front-end. A static front-end for public resources (profiles and statuses) is also provided.
|
||||||
|
|
||||||
|
If you would like, you can [support the development of this project on Patreon][patreon]. Alternatively, you can donate to this BTC address: `17j2g7vpgHhLuXhN4bueZFCvdxxieyRVWd`
|
||||||
|
|
||||||
|
[patreon]: https://www.patreon.com/user?u=619786
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
- [Frequently Asked Questions](https://github.com/tootsuite/documentation/blob/master/Using-Mastodon/FAQ.md)
|
||||||
|
- [Use this tool to find Twitter friends on Mastodon](https://bridge.joinmastodon.org)
|
||||||
|
- [API overview](https://github.com/tootsuite/documentation/blob/master/Using-the-API/API.md)
|
||||||
|
- [List of Mastodon instances](https://github.com/tootsuite/documentation/blob/master/Using-Mastodon/List-of-Mastodon-instances.md)
|
||||||
|
- [List of apps](https://github.com/tootsuite/documentation/blob/master/Using-Mastodon/Apps.md)
|
||||||
|
- [List of sponsors](https://joinmastodon.org/sponsors)
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
**No vendor lock-in: Fully interoperable with any conforming platform**
|
||||||
|
|
||||||
|
It doesn't have to be Mastodon, whatever implements ActivityPub or OStatus is part of the social network!
|
||||||
|
|
||||||
|
**Real-time timeline updates**
|
||||||
|
|
||||||
|
See the updates of people you're following appear in real-time in the UI via WebSockets. There's a firehose view as well!
|
||||||
|
|
||||||
|
**Federated thread resolving**
|
||||||
|
|
||||||
|
If someone you follow replies to a user unknown to the server, the server fetches the full thread so you can view it without leaving the UI
|
||||||
|
|
||||||
|
**Media attachments like images and short videos**
|
||||||
|
|
||||||
|
Upload and view images and WebM/MP4 videos attached to the updates. Videos with no audio track are treated like GIFs; normal videos are looped - like vines!
|
||||||
|
|
||||||
|
**OAuth2 and a straightforward REST API**
|
||||||
|
|
||||||
|
Mastodon acts as an OAuth2 provider so 3rd party apps can use the API
|
||||||
|
|
||||||
|
**Fast response times**
|
||||||
|
|
||||||
|
Mastodon tries to be as fast and responsive as possible, so all long-running tasks are delegated to background processing
|
||||||
|
|
||||||
|
**Deployable via Docker**
|
||||||
|
|
||||||
|
You don't need to mess with dependencies and configuration if you want to try Mastodon, if you have Docker and Docker Compose the deployment is extremely easy
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
Please follow the [development guide](https://github.com/tootsuite/documentation/blob/master/Running-Mastodon/Development-guide.md) from the documentation repository.
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
There are guides in the documentation repository for [deploying on various platforms](https://github.com/tootsuite/documentation#running-mastodon).
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
You can open issues for bugs you've found or features you think are missing. You can also submit pull requests to this repository. [Here are the guidelines for code contributions](CONTRIBUTING.md)
|
||||||
|
|
||||||
|
**IRC channel**: #mastodon on irc.freenode.net
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Extra credits
|
||||||
|
|
||||||
|
The elephant friend illustrations are created by [Dopatwo](https://mastodon.social/@dopatwo)
|
||||||
|
|||||||
2
Vagrantfile
vendored
2
Vagrantfile
vendored
@@ -83,7 +83,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
|||||||
|
|
||||||
config.vm.provider :virtualbox do |vb|
|
config.vm.provider :virtualbox do |vb|
|
||||||
vb.name = "mastodon"
|
vb.name = "mastodon"
|
||||||
vb.customize ["modifyvm", :id, "--memory", "4096"]
|
vb.customize ["modifyvm", :id, "--memory", "2048"]
|
||||||
|
|
||||||
# Disable VirtualBox DNS proxy to skip long-delay IPv6 resolutions.
|
# Disable VirtualBox DNS proxy to skip long-delay IPv6 resolutions.
|
||||||
# https://github.com/mitchellh/vagrant/issues/1172
|
# https://github.com/mitchellh/vagrant/issues/1172
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class AboutController < ApplicationController
|
class AboutController < ApplicationController
|
||||||
before_action :set_pack
|
|
||||||
before_action :set_body_classes
|
before_action :set_body_classes
|
||||||
before_action :set_instance_presenter, only: [:show, :more, :terms]
|
before_action :set_instance_presenter, only: [:show, :more, :terms]
|
||||||
|
|
||||||
@@ -22,10 +21,6 @@ class AboutController < ApplicationController
|
|||||||
|
|
||||||
helper_method :new_user
|
helper_method :new_user
|
||||||
|
|
||||||
def set_pack
|
|
||||||
use_pack action_name == 'show' ? 'about' : 'common'
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_instance_presenter
|
def set_instance_presenter
|
||||||
@instance_presenter = InstancePresenter.new
|
@instance_presenter = InstancePresenter.new
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2,13 +2,11 @@
|
|||||||
|
|
||||||
class AccountsController < ApplicationController
|
class AccountsController < ApplicationController
|
||||||
include AccountControllerConcern
|
include AccountControllerConcern
|
||||||
|
include SignatureVerification
|
||||||
before_action :set_cache_headers
|
|
||||||
|
|
||||||
def show
|
def show
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html do
|
format.html do
|
||||||
use_pack 'public'
|
|
||||||
@pinned_statuses = []
|
@pinned_statuses = []
|
||||||
|
|
||||||
if current_account && @account.blocking?(current_account)
|
if current_account && @account.blocking?(current_account)
|
||||||
@@ -28,11 +26,10 @@ class AccountsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
format.json do
|
format.json do
|
||||||
skip_session!
|
render json: @account,
|
||||||
|
serializer: ActivityPub::ActorSerializer,
|
||||||
render_cached_json(['activitypub', 'actor', @account.cache_key], content_type: 'application/activity+json') do
|
adapter: ActivityPub::Adapter,
|
||||||
ActiveModelSerializers::SerializableResource.new(@account, serializer: ActivityPub::ActorSerializer, adapter: ActivityPub::Adapter)
|
content_type: 'application/activity+json'
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -51,7 +48,7 @@ class AccountsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def default_statuses
|
def default_statuses
|
||||||
@account.statuses.not_local_only.where(visibility: [:public, :unlisted])
|
@account.statuses.where(visibility: [:public, :unlisted])
|
||||||
end
|
end
|
||||||
|
|
||||||
def only_media_scope
|
def only_media_scope
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ module Admin
|
|||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
authorize @account_moderation_note, :destroy?
|
authorize @account_moderation_note, :destroy?
|
||||||
@account_moderation_note.destroy!
|
@account_moderation_note.destroy
|
||||||
redirect_to admin_account_path(@account_moderation_note.target_account_id), notice: I18n.t('admin.account_moderation_notes.destroyed_msg')
|
redirect_to admin_account_path(@account_moderation_note.target_account_id), notice: I18n.t('admin.account_moderation_notes.destroyed_msg')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -32,21 +32,18 @@ module Admin
|
|||||||
def memorialize
|
def memorialize
|
||||||
authorize @account, :memorialize?
|
authorize @account, :memorialize?
|
||||||
@account.memorialize!
|
@account.memorialize!
|
||||||
log_action :memorialize, @account
|
|
||||||
redirect_to admin_account_path(@account.id)
|
redirect_to admin_account_path(@account.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def enable
|
def enable
|
||||||
authorize @account.user, :enable?
|
authorize @account.user, :enable?
|
||||||
@account.user.enable!
|
@account.user.enable!
|
||||||
log_action :enable, @account.user
|
|
||||||
redirect_to admin_account_path(@account.id)
|
redirect_to admin_account_path(@account.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def disable
|
def disable
|
||||||
authorize @account.user, :disable?
|
authorize @account.user, :disable?
|
||||||
@account.user.disable!
|
@account.user.disable!
|
||||||
log_action :disable, @account.user
|
|
||||||
redirect_to admin_account_path(@account.id)
|
redirect_to admin_account_path(@account.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -89,8 +86,7 @@ module Admin
|
|||||||
:username,
|
:username,
|
||||||
:display_name,
|
:display_name,
|
||||||
:email,
|
:email,
|
||||||
:ip,
|
:ip
|
||||||
:staff
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module Admin
|
|
||||||
class ActionLogsController < BaseController
|
|
||||||
def index
|
|
||||||
@action_logs = Admin::ActionLog.page(params[:page])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -3,15 +3,9 @@
|
|||||||
module Admin
|
module Admin
|
||||||
class BaseController < ApplicationController
|
class BaseController < ApplicationController
|
||||||
include Authorization
|
include Authorization
|
||||||
include AccountableConcern
|
|
||||||
|
|
||||||
layout 'admin'
|
|
||||||
|
|
||||||
before_action :require_staff!
|
before_action :require_staff!
|
||||||
before_action :set_pack
|
|
||||||
|
|
||||||
def set_pack
|
layout 'admin'
|
||||||
use_pack 'admin'
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ module Admin
|
|||||||
def create
|
def create
|
||||||
authorize @user, :confirm?
|
authorize @user, :confirm?
|
||||||
@user.confirm!
|
@user.confirm!
|
||||||
log_action :confirm, @user
|
|
||||||
redirect_to admin_accounts_path
|
redirect_to admin_accounts_path
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
module Admin
|
module Admin
|
||||||
class CustomEmojisController < BaseController
|
class CustomEmojisController < BaseController
|
||||||
before_action :set_custom_emoji, except: [:index, :new, :create]
|
before_action :set_custom_emoji, except: [:index, :new, :create]
|
||||||
before_action :set_filter_params
|
|
||||||
|
|
||||||
def index
|
def index
|
||||||
authorize :custom_emoji, :index?
|
authorize :custom_emoji, :index?
|
||||||
@@ -21,7 +20,6 @@ module Admin
|
|||||||
@custom_emoji = CustomEmoji.new(resource_params)
|
@custom_emoji = CustomEmoji.new(resource_params)
|
||||||
|
|
||||||
if @custom_emoji.save
|
if @custom_emoji.save
|
||||||
log_action :create, @custom_emoji
|
|
||||||
redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.created_msg')
|
redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.created_msg')
|
||||||
else
|
else
|
||||||
render :new
|
render :new
|
||||||
@@ -32,53 +30,42 @@ module Admin
|
|||||||
authorize @custom_emoji, :update?
|
authorize @custom_emoji, :update?
|
||||||
|
|
||||||
if @custom_emoji.update(resource_params)
|
if @custom_emoji.update(resource_params)
|
||||||
log_action :update, @custom_emoji
|
redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.updated_msg')
|
||||||
flash[:notice] = I18n.t('admin.custom_emojis.updated_msg')
|
|
||||||
else
|
else
|
||||||
flash[:alert] = I18n.t('admin.custom_emojis.update_failed_msg')
|
redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.update_failed_msg')
|
||||||
end
|
end
|
||||||
redirect_to admin_custom_emojis_path(page: params[:page], **@filter_params)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
authorize @custom_emoji, :destroy?
|
authorize @custom_emoji, :destroy?
|
||||||
@custom_emoji.destroy!
|
@custom_emoji.destroy
|
||||||
log_action :destroy, @custom_emoji
|
redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.destroyed_msg')
|
||||||
flash[:notice] = I18n.t('admin.custom_emojis.destroyed_msg')
|
|
||||||
redirect_to admin_custom_emojis_path(page: params[:page], **@filter_params)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def copy
|
def copy
|
||||||
authorize @custom_emoji, :copy?
|
authorize @custom_emoji, :copy?
|
||||||
|
|
||||||
emoji = CustomEmoji.find_or_initialize_by(domain: nil,
|
emoji = CustomEmoji.find_or_create_by(domain: nil, shortcode: @custom_emoji.shortcode)
|
||||||
shortcode: @custom_emoji.shortcode)
|
|
||||||
emoji.image = @custom_emoji.image
|
|
||||||
|
|
||||||
if emoji.save
|
if emoji.update(image: @custom_emoji.image)
|
||||||
log_action :create, emoji
|
|
||||||
flash[:notice] = I18n.t('admin.custom_emojis.copied_msg')
|
flash[:notice] = I18n.t('admin.custom_emojis.copied_msg')
|
||||||
else
|
else
|
||||||
flash[:alert] = I18n.t('admin.custom_emojis.copy_failed_msg')
|
flash[:alert] = I18n.t('admin.custom_emojis.copy_failed_msg')
|
||||||
end
|
end
|
||||||
|
|
||||||
redirect_to admin_custom_emojis_path(page: params[:page], **@filter_params)
|
redirect_to admin_custom_emojis_path(page: params[:page])
|
||||||
end
|
end
|
||||||
|
|
||||||
def enable
|
def enable
|
||||||
authorize @custom_emoji, :enable?
|
authorize @custom_emoji, :enable?
|
||||||
@custom_emoji.update!(disabled: false)
|
@custom_emoji.update!(disabled: false)
|
||||||
log_action :enable, @custom_emoji
|
redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.enabled_msg')
|
||||||
flash[:notice] = I18n.t('admin.custom_emojis.enabled_msg')
|
|
||||||
redirect_to admin_custom_emojis_path(page: params[:page], **@filter_params)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def disable
|
def disable
|
||||||
authorize @custom_emoji, :disable?
|
authorize @custom_emoji, :disable?
|
||||||
@custom_emoji.update!(disabled: true)
|
@custom_emoji.update!(disabled: true)
|
||||||
log_action :disable, @custom_emoji
|
redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.disabled_msg')
|
||||||
flash[:notice] = I18n.t('admin.custom_emojis.disabled_msg')
|
|
||||||
redirect_to admin_custom_emojis_path(page: params[:page], **@filter_params)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
@@ -87,10 +74,6 @@ module Admin
|
|||||||
@custom_emoji = CustomEmoji.find(params[:id])
|
@custom_emoji = CustomEmoji.find(params[:id])
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_filter_params
|
|
||||||
@filter_params = filter_params.to_hash.symbolize_keys
|
|
||||||
end
|
|
||||||
|
|
||||||
def resource_params
|
def resource_params
|
||||||
params.require(:custom_emoji).permit(:shortcode, :image, :visible_in_picker)
|
params.require(:custom_emoji).permit(:shortcode, :image, :visible_in_picker)
|
||||||
end
|
end
|
||||||
@@ -102,9 +85,7 @@ module Admin
|
|||||||
def filter_params
|
def filter_params
|
||||||
params.permit(
|
params.permit(
|
||||||
:local,
|
:local,
|
||||||
:remote,
|
:remote
|
||||||
:by_domain,
|
|
||||||
:shortcode
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ module Admin
|
|||||||
|
|
||||||
if @domain_block.save
|
if @domain_block.save
|
||||||
DomainBlockWorker.perform_async(@domain_block.id)
|
DomainBlockWorker.perform_async(@domain_block.id)
|
||||||
log_action :create, @domain_block
|
|
||||||
redirect_to admin_domain_blocks_path, notice: I18n.t('admin.domain_blocks.created_msg')
|
redirect_to admin_domain_blocks_path, notice: I18n.t('admin.domain_blocks.created_msg')
|
||||||
else
|
else
|
||||||
render :new
|
render :new
|
||||||
@@ -35,7 +34,6 @@ module Admin
|
|||||||
def destroy
|
def destroy
|
||||||
authorize @domain_block, :destroy?
|
authorize @domain_block, :destroy?
|
||||||
UnblockDomainService.new.call(@domain_block, retroactive_unblock?)
|
UnblockDomainService.new.call(@domain_block, retroactive_unblock?)
|
||||||
log_action :destroy, @domain_block
|
|
||||||
redirect_to admin_domain_blocks_path, notice: I18n.t('admin.domain_blocks.destroyed_msg')
|
redirect_to admin_domain_blocks_path, notice: I18n.t('admin.domain_blocks.destroyed_msg')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ module Admin
|
|||||||
@email_domain_block = EmailDomainBlock.new(resource_params)
|
@email_domain_block = EmailDomainBlock.new(resource_params)
|
||||||
|
|
||||||
if @email_domain_block.save
|
if @email_domain_block.save
|
||||||
log_action :create, @email_domain_block
|
|
||||||
redirect_to admin_email_domain_blocks_path, notice: I18n.t('admin.email_domain_blocks.created_msg')
|
redirect_to admin_email_domain_blocks_path, notice: I18n.t('admin.email_domain_blocks.created_msg')
|
||||||
else
|
else
|
||||||
render :new
|
render :new
|
||||||
@@ -29,8 +28,7 @@ module Admin
|
|||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
authorize @email_domain_block, :destroy?
|
authorize @email_domain_block, :destroy?
|
||||||
@email_domain_block.destroy!
|
@email_domain_block.destroy
|
||||||
log_action :destroy, @email_domain_block
|
|
||||||
redirect_to admin_email_domain_blocks_path, notice: I18n.t('admin.email_domain_blocks.destroyed_msg')
|
redirect_to admin_email_domain_blocks_path, notice: I18n.t('admin.email_domain_blocks.destroyed_msg')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module Admin
|
|
||||||
class InvitesController < BaseController
|
|
||||||
def index
|
|
||||||
authorize :invite, :index?
|
|
||||||
|
|
||||||
@invites = filtered_invites.includes(user: :account).page(params[:page])
|
|
||||||
@invite = Invite.new
|
|
||||||
end
|
|
||||||
|
|
||||||
def create
|
|
||||||
authorize :invite, :create?
|
|
||||||
|
|
||||||
@invite = Invite.new(resource_params)
|
|
||||||
@invite.user = current_user
|
|
||||||
|
|
||||||
if @invite.save
|
|
||||||
redirect_to admin_invites_path
|
|
||||||
else
|
|
||||||
@invites = Invite.page(params[:page])
|
|
||||||
render :index
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def destroy
|
|
||||||
@invite = Invite.find(params[:id])
|
|
||||||
authorize @invite, :destroy?
|
|
||||||
@invite.expire!
|
|
||||||
redirect_to admin_invites_path
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def resource_params
|
|
||||||
params.require(:invite).permit(:max_uses, :expires_in)
|
|
||||||
end
|
|
||||||
|
|
||||||
def filtered_invites
|
|
||||||
InviteFilter.new(filter_params).results
|
|
||||||
end
|
|
||||||
|
|
||||||
def filter_params
|
|
||||||
params.permit(:available, :expired)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -8,7 +8,7 @@ module Admin
|
|||||||
def create
|
def create
|
||||||
authorize :status, :update?
|
authorize :status, :update?
|
||||||
|
|
||||||
@form = Form::StatusBatch.new(form_status_batch_params.merge(current_account: current_account))
|
@form = Form::StatusBatch.new(form_status_batch_params)
|
||||||
flash[:alert] = I18n.t('admin.statuses.failed_to_execute') unless @form.save
|
flash[:alert] = I18n.t('admin.statuses.failed_to_execute') unless @form.save
|
||||||
|
|
||||||
redirect_to admin_report_path(@report)
|
redirect_to admin_report_path(@report)
|
||||||
@@ -16,15 +16,13 @@ module Admin
|
|||||||
|
|
||||||
def update
|
def update
|
||||||
authorize @status, :update?
|
authorize @status, :update?
|
||||||
@status.update!(status_params)
|
@status.update(status_params)
|
||||||
log_action :update, @status
|
|
||||||
redirect_to admin_report_path(@report)
|
redirect_to admin_report_path(@report)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
authorize @status, :destroy?
|
authorize @status, :destroy?
|
||||||
RemovalWorker.perform_async(@status.id)
|
RemovalWorker.perform_async(@status.id)
|
||||||
log_action :destroy, @status
|
|
||||||
render json: @status
|
render json: @status
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -25,17 +25,12 @@ module Admin
|
|||||||
def process_report
|
def process_report
|
||||||
case params[:outcome].to_s
|
case params[:outcome].to_s
|
||||||
when 'resolve'
|
when 'resolve'
|
||||||
@report.update!(action_taken_by_current_attributes)
|
@report.update(action_taken_by_current_attributes)
|
||||||
log_action :resolve, @report
|
|
||||||
when 'suspend'
|
when 'suspend'
|
||||||
Admin::SuspensionWorker.perform_async(@report.target_account.id)
|
Admin::SuspensionWorker.perform_async(@report.target_account.id)
|
||||||
log_action :resolve, @report
|
|
||||||
log_action :suspend, @report.target_account
|
|
||||||
resolve_all_target_account_reports
|
resolve_all_target_account_reports
|
||||||
when 'silence'
|
when 'silence'
|
||||||
@report.target_account.update!(silenced: true)
|
@report.target_account.update(silenced: true)
|
||||||
log_action :resolve, @report
|
|
||||||
log_action :silence, @report.target_account
|
|
||||||
resolve_all_target_account_reports
|
resolve_all_target_account_reports
|
||||||
else
|
else
|
||||||
raise ActiveRecord::RecordNotFound
|
raise ActiveRecord::RecordNotFound
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ module Admin
|
|||||||
def create
|
def create
|
||||||
authorize @user, :reset_password?
|
authorize @user, :reset_password?
|
||||||
@user.send_reset_password_instructions
|
@user.send_reset_password_instructions
|
||||||
log_action :reset_password, @user
|
|
||||||
redirect_to admin_accounts_path
|
redirect_to admin_accounts_path
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -7,14 +7,12 @@ module Admin
|
|||||||
def promote
|
def promote
|
||||||
authorize @user, :promote?
|
authorize @user, :promote?
|
||||||
@user.promote!
|
@user.promote!
|
||||||
log_action :promote, @user
|
|
||||||
redirect_to admin_account_path(@user.account_id)
|
redirect_to admin_account_path(@user.account_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def demote
|
def demote
|
||||||
authorize @user, :demote?
|
authorize @user, :demote?
|
||||||
@user.demote!
|
@user.demote!
|
||||||
log_action :demote, @user
|
|
||||||
redirect_to admin_account_path(@user.account_id)
|
redirect_to admin_account_path(@user.account_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -13,21 +13,14 @@ module Admin
|
|||||||
closed_registrations_message
|
closed_registrations_message
|
||||||
open_deletion
|
open_deletion
|
||||||
timeline_preview
|
timeline_preview
|
||||||
show_staff_badge
|
|
||||||
bootstrap_timeline_accounts
|
bootstrap_timeline_accounts
|
||||||
thumbnail
|
thumbnail
|
||||||
min_invite_role
|
|
||||||
activity_api_enabled
|
|
||||||
peers_api_enabled
|
|
||||||
).freeze
|
).freeze
|
||||||
|
|
||||||
BOOLEAN_SETTINGS = %w(
|
BOOLEAN_SETTINGS = %w(
|
||||||
open_registrations
|
open_registrations
|
||||||
open_deletion
|
open_deletion
|
||||||
timeline_preview
|
timeline_preview
|
||||||
show_staff_badge
|
|
||||||
activity_api_enabled
|
|
||||||
peers_api_enabled
|
|
||||||
).freeze
|
).freeze
|
||||||
|
|
||||||
UPLOAD_SETTINGS = %w(
|
UPLOAD_SETTINGS = %w(
|
||||||
|
|||||||
@@ -6,15 +6,13 @@ module Admin
|
|||||||
|
|
||||||
def create
|
def create
|
||||||
authorize @account, :silence?
|
authorize @account, :silence?
|
||||||
@account.update!(silenced: true)
|
@account.update(silenced: true)
|
||||||
log_action :silence, @account
|
|
||||||
redirect_to admin_accounts_path
|
redirect_to admin_accounts_path
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
authorize @account, :unsilence?
|
authorize @account, :unsilence?
|
||||||
@account.update!(silenced: false)
|
@account.update(silenced: false)
|
||||||
log_action :unsilence, @account
|
|
||||||
redirect_to admin_accounts_path
|
redirect_to admin_accounts_path
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ module Admin
|
|||||||
def create
|
def create
|
||||||
authorize :status, :update?
|
authorize :status, :update?
|
||||||
|
|
||||||
@form = Form::StatusBatch.new(form_status_batch_params.merge(current_account: current_account))
|
@form = Form::StatusBatch.new(form_status_batch_params)
|
||||||
flash[:alert] = I18n.t('admin.statuses.failed_to_execute') unless @form.save
|
flash[:alert] = I18n.t('admin.statuses.failed_to_execute') unless @form.save
|
||||||
|
|
||||||
redirect_to admin_account_statuses_path(@account.id, current_params)
|
redirect_to admin_account_statuses_path(@account.id, current_params)
|
||||||
@@ -34,15 +34,13 @@ module Admin
|
|||||||
|
|
||||||
def update
|
def update
|
||||||
authorize @status, :update?
|
authorize @status, :update?
|
||||||
@status.update!(status_params)
|
@status.update(status_params)
|
||||||
log_action :update, @status
|
|
||||||
redirect_to admin_account_statuses_path(@account.id, current_params)
|
redirect_to admin_account_statuses_path(@account.id, current_params)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
authorize @status, :destroy?
|
authorize @status, :destroy?
|
||||||
RemovalWorker.perform_async(@status.id)
|
RemovalWorker.perform_async(@status.id)
|
||||||
log_action :destroy, @status
|
|
||||||
render json: @status
|
render json: @status
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -7,14 +7,12 @@ module Admin
|
|||||||
def create
|
def create
|
||||||
authorize @account, :suspend?
|
authorize @account, :suspend?
|
||||||
Admin::SuspensionWorker.perform_async(@account.id)
|
Admin::SuspensionWorker.perform_async(@account.id)
|
||||||
log_action :suspend, @account
|
|
||||||
redirect_to admin_accounts_path
|
redirect_to admin_accounts_path
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
authorize @account, :unsuspend?
|
authorize @account, :unsuspend?
|
||||||
@account.unsuspend!
|
@account.unsuspend!
|
||||||
log_action :unsuspend, @account
|
|
||||||
redirect_to admin_accounts_path
|
redirect_to admin_accounts_path
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ module Admin
|
|||||||
def destroy
|
def destroy
|
||||||
authorize @user, :disable_2fa?
|
authorize @user, :disable_2fa?
|
||||||
@user.disable_two_factor!
|
@user.disable_two_factor!
|
||||||
log_action :disable_2fa, @user
|
|
||||||
redirect_to admin_accounts_path
|
redirect_to admin_accounts_path
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -72,4 +72,19 @@ class Api::BaseController < ApplicationController
|
|||||||
def render_empty
|
def render_empty
|
||||||
render json: {}, status: 200
|
render json: {}, status: 200
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_maps(statuses) # rubocop:disable Style/AccessorMethodName
|
||||||
|
if current_account.nil?
|
||||||
|
@reblogs_map = {}
|
||||||
|
@favourites_map = {}
|
||||||
|
@mutes_map = {}
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
status_ids = statuses.compact.flat_map { |s| [s.id, s.reblog_of_id] }.uniq
|
||||||
|
conversation_ids = statuses.compact.map(&:conversation_id).compact.uniq
|
||||||
|
@reblogs_map = Status.reblogs_map(status_ids, current_account)
|
||||||
|
@favourites_map = Status.favourites_map(status_ids, current_account)
|
||||||
|
@mutes_map = Status.mutes_map(conversation_ids, current_account)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Api::V1::Accounts::ListsController < Api::BaseController
|
|
||||||
before_action -> { doorkeeper_authorize! :read }
|
|
||||||
before_action :require_user!
|
|
||||||
before_action :set_account
|
|
||||||
|
|
||||||
respond_to :json
|
|
||||||
|
|
||||||
def index
|
|
||||||
@lists = @account.lists.where(account: current_account)
|
|
||||||
render json: @lists, each_serializer: REST::ListSerializer
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def set_account
|
|
||||||
@account = Account.find(params[:account_id])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -17,13 +17,12 @@ class Api::V1::Accounts::SearchController < Api::BaseController
|
|||||||
AccountSearchService.new.call(
|
AccountSearchService.new.call(
|
||||||
params[:q],
|
params[:q],
|
||||||
limit_param(DEFAULT_ACCOUNTS_LIMIT),
|
limit_param(DEFAULT_ACCOUNTS_LIMIT),
|
||||||
current_account,
|
resolving_search?,
|
||||||
resolve: truthy_param?(:resolve),
|
current_account
|
||||||
following: truthy_param?(:following)
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def truthy_param?(key)
|
def resolving_search?
|
||||||
params[key] == 'true'
|
params[:resolve] == 'true'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ class Api::V1::AccountsController < Api::BaseController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def follow
|
def follow
|
||||||
FollowService.new.call(current_user.account, @account.acct, reblogs: params[:reblogs])
|
FollowService.new.call(current_user.account, @account.acct)
|
||||||
|
|
||||||
options = @account.locked? ? {} : { following_map: { @account.id => { reblogs: params[:reblogs] } }, requested_map: { @account.id => false } }
|
options = @account.locked? ? {} : { following_map: { @account.id => true }, requested_map: { @account.id => false } }
|
||||||
|
|
||||||
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships(options)
|
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships(options)
|
||||||
end
|
end
|
||||||
@@ -51,7 +51,7 @@ class Api::V1::AccountsController < Api::BaseController
|
|||||||
@account = Account.find(params[:id])
|
@account = Account.find(params[:id])
|
||||||
end
|
end
|
||||||
|
|
||||||
def relationships(**options)
|
def relationships(options = {})
|
||||||
AccountRelationshipsPresenter.new([@account.id], current_user.account_id, options)
|
AccountRelationshipsPresenter.new([@account.id], current_user.account_id, options)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Api::V1::Instances::ActivityController < Api::BaseController
|
|
||||||
before_action :require_enabled_api!
|
|
||||||
|
|
||||||
respond_to :json
|
|
||||||
|
|
||||||
def show
|
|
||||||
render_cached_json('api:v1:instances:activity:show', expires_in: 1.day) { activity }
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def activity
|
|
||||||
weeks = []
|
|
||||||
|
|
||||||
12.times do |i|
|
|
||||||
day = i.weeks.ago.to_date
|
|
||||||
week_id = day.cweek
|
|
||||||
week = Date.commercial(day.cwyear, week_id)
|
|
||||||
|
|
||||||
weeks << {
|
|
||||||
week: week.to_time.to_i.to_s,
|
|
||||||
statuses: Redis.current.get("activity:statuses:local:#{week_id}") || '0',
|
|
||||||
logins: Redis.current.pfcount("activity:logins:#{week_id}").to_s,
|
|
||||||
registrations: Redis.current.get("activity:accounts:local:#{week_id}") || '0',
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
weeks
|
|
||||||
end
|
|
||||||
|
|
||||||
def require_enabled_api!
|
|
||||||
head 404 unless Setting.activity_api_enabled
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Api::V1::Instances::PeersController < Api::BaseController
|
|
||||||
before_action :require_enabled_api!
|
|
||||||
|
|
||||||
respond_to :json
|
|
||||||
|
|
||||||
def index
|
|
||||||
render_cached_json('api:v1:instances:peers:index', expires_in: 1.day) { Account.remote.domains }
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def require_enabled_api!
|
|
||||||
head 404 unless Setting.peers_api_enabled
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Api::V1::Lists::AccountsController < Api::BaseController
|
|
||||||
before_action -> { doorkeeper_authorize! :read }, only: [:show]
|
|
||||||
before_action -> { doorkeeper_authorize! :write }, except: [:show]
|
|
||||||
|
|
||||||
before_action :require_user!
|
|
||||||
before_action :set_list
|
|
||||||
|
|
||||||
after_action :insert_pagination_headers, only: :show
|
|
||||||
|
|
||||||
def show
|
|
||||||
@accounts = load_accounts
|
|
||||||
render json: @accounts, each_serializer: REST::AccountSerializer
|
|
||||||
end
|
|
||||||
|
|
||||||
def create
|
|
||||||
ApplicationRecord.transaction do
|
|
||||||
list_accounts.each do |account|
|
|
||||||
@list.accounts << account
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
render_empty
|
|
||||||
end
|
|
||||||
|
|
||||||
def destroy
|
|
||||||
ListAccount.where(list: @list, account_id: account_ids).destroy_all
|
|
||||||
render_empty
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def set_list
|
|
||||||
@list = List.where(account: current_account).find(params[:list_id])
|
|
||||||
end
|
|
||||||
|
|
||||||
def load_accounts
|
|
||||||
if unlimited?
|
|
||||||
@list.accounts.all
|
|
||||||
else
|
|
||||||
@list.accounts.paginate_by_max_id(limit_param(DEFAULT_ACCOUNTS_LIMIT), params[:max_id], params[:since_id])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def list_accounts
|
|
||||||
Account.find(account_ids)
|
|
||||||
end
|
|
||||||
|
|
||||||
def account_ids
|
|
||||||
Array(resource_params[:account_ids])
|
|
||||||
end
|
|
||||||
|
|
||||||
def resource_params
|
|
||||||
params.permit(account_ids: [])
|
|
||||||
end
|
|
||||||
|
|
||||||
def insert_pagination_headers
|
|
||||||
set_pagination_headers(next_path, prev_path)
|
|
||||||
end
|
|
||||||
|
|
||||||
def next_path
|
|
||||||
return if unlimited?
|
|
||||||
|
|
||||||
if records_continue?
|
|
||||||
api_v1_list_accounts_url pagination_params(max_id: pagination_max_id)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def prev_path
|
|
||||||
return if unlimited?
|
|
||||||
|
|
||||||
unless @accounts.empty?
|
|
||||||
api_v1_list_accounts_url pagination_params(since_id: pagination_since_id)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def pagination_max_id
|
|
||||||
@accounts.last.id
|
|
||||||
end
|
|
||||||
|
|
||||||
def pagination_since_id
|
|
||||||
@accounts.first.id
|
|
||||||
end
|
|
||||||
|
|
||||||
def records_continue?
|
|
||||||
@accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
|
|
||||||
end
|
|
||||||
|
|
||||||
def pagination_params(core_params)
|
|
||||||
params.permit(:limit).merge(core_params)
|
|
||||||
end
|
|
||||||
|
|
||||||
def unlimited?
|
|
||||||
params[:limit] == '0'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Api::V1::ListsController < Api::BaseController
|
|
||||||
before_action -> { doorkeeper_authorize! :read }, only: [:index, :show]
|
|
||||||
before_action -> { doorkeeper_authorize! :write }, except: [:index, :show]
|
|
||||||
|
|
||||||
before_action :require_user!
|
|
||||||
before_action :set_list, except: [:index, :create]
|
|
||||||
|
|
||||||
def index
|
|
||||||
@lists = List.where(account: current_account).all
|
|
||||||
render json: @lists, each_serializer: REST::ListSerializer
|
|
||||||
end
|
|
||||||
|
|
||||||
def show
|
|
||||||
render json: @list, serializer: REST::ListSerializer
|
|
||||||
end
|
|
||||||
|
|
||||||
def create
|
|
||||||
@list = List.create!(list_params.merge(account: current_account))
|
|
||||||
render json: @list, serializer: REST::ListSerializer
|
|
||||||
end
|
|
||||||
|
|
||||||
def update
|
|
||||||
@list.update!(list_params)
|
|
||||||
render json: @list, serializer: REST::ListSerializer
|
|
||||||
end
|
|
||||||
|
|
||||||
def destroy
|
|
||||||
@list.destroy!
|
|
||||||
render_empty
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def set_list
|
|
||||||
@list = List.where(account: current_account).find(params[:id])
|
|
||||||
end
|
|
||||||
|
|
||||||
def list_params
|
|
||||||
params.permit(:title)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -8,15 +8,10 @@ class Api::V1::MutesController < Api::BaseController
|
|||||||
respond_to :json
|
respond_to :json
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@data = @accounts = load_accounts
|
@accounts = load_accounts
|
||||||
render json: @accounts, each_serializer: REST::AccountSerializer
|
render json: @accounts, each_serializer: REST::AccountSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
def details
|
|
||||||
@data = @mutes = load_mutes
|
|
||||||
render json: @mutes, each_serializer: REST::MuteSerializer
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def load_accounts
|
def load_accounts
|
||||||
@@ -27,10 +22,6 @@ class Api::V1::MutesController < Api::BaseController
|
|||||||
Account.includes(:muted_by).references(:muted_by)
|
Account.includes(:muted_by).references(:muted_by)
|
||||||
end
|
end
|
||||||
|
|
||||||
def load_mutes
|
|
||||||
paginated_mutes.includes(:account, :target_account).to_a
|
|
||||||
end
|
|
||||||
|
|
||||||
def paginated_mutes
|
def paginated_mutes
|
||||||
Mute.where(account: current_account).paginate_by_max_id(
|
Mute.where(account: current_account).paginate_by_max_id(
|
||||||
limit_param(DEFAULT_ACCOUNTS_LIMIT),
|
limit_param(DEFAULT_ACCOUNTS_LIMIT),
|
||||||
@@ -45,34 +36,26 @@ class Api::V1::MutesController < Api::BaseController
|
|||||||
|
|
||||||
def next_path
|
def next_path
|
||||||
if records_continue?
|
if records_continue?
|
||||||
url_for pagination_params(max_id: pagination_max_id)
|
api_v1_mutes_url pagination_params(max_id: pagination_max_id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def prev_path
|
def prev_path
|
||||||
unless@data.empty?
|
unless @accounts.empty?
|
||||||
url_for pagination_params(since_id: pagination_since_id)
|
api_v1_mutes_url pagination_params(since_id: pagination_since_id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def pagination_max_id
|
def pagination_max_id
|
||||||
if params[:action] == "details"
|
@accounts.last.muted_by_ids.last
|
||||||
@mutes.last.id
|
|
||||||
else
|
|
||||||
@accounts.last.muted_by_ids.last
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def pagination_since_id
|
def pagination_since_id
|
||||||
if params[:action] == "details"
|
@accounts.first.muted_by_ids.first
|
||||||
@mutes.first.id
|
|
||||||
else
|
|
||||||
@accounts.first.muted_by_ids.first
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def records_continue?
|
def records_continue?
|
||||||
@data.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
|
@accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
|
||||||
end
|
end
|
||||||
|
|
||||||
def pagination_params(core_params)
|
def pagination_params(core_params)
|
||||||
|
|||||||
@@ -24,20 +24,11 @@ class Api::V1::NotificationsController < Api::BaseController
|
|||||||
render_empty
|
render_empty
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
|
||||||
dismiss
|
|
||||||
end
|
|
||||||
|
|
||||||
def dismiss
|
def dismiss
|
||||||
current_account.notifications.find_by!(id: params[:id]).destroy!
|
current_account.notifications.find_by!(id: params[:id]).destroy!
|
||||||
render_empty
|
render_empty
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy_multiple
|
|
||||||
current_account.notifications.where(id: params[:ids]).destroy_all
|
|
||||||
render_empty
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def load_notifications
|
def load_notifications
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
class Api::V1::SearchController < Api::BaseController
|
class Api::V1::SearchController < Api::BaseController
|
||||||
include Authorization
|
include Authorization
|
||||||
|
|
||||||
RESULTS_LIMIT = 10
|
RESULTS_LIMIT = 5
|
||||||
|
|
||||||
before_action -> { doorkeeper_authorize! :read }
|
before_action -> { doorkeeper_authorize! :read }
|
||||||
before_action :require_user!
|
before_action :require_user!
|
||||||
|
|||||||
@@ -1,60 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Api::V1::Timelines::DirectController < Api::BaseController
|
|
||||||
before_action -> { doorkeeper_authorize! :read }, only: [:show]
|
|
||||||
before_action :require_user!, only: [:show]
|
|
||||||
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
|
|
||||||
|
|
||||||
respond_to :json
|
|
||||||
|
|
||||||
def show
|
|
||||||
@statuses = load_statuses
|
|
||||||
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def load_statuses
|
|
||||||
cached_direct_statuses
|
|
||||||
end
|
|
||||||
|
|
||||||
def cached_direct_statuses
|
|
||||||
cache_collection direct_statuses, Status
|
|
||||||
end
|
|
||||||
|
|
||||||
def direct_statuses
|
|
||||||
direct_timeline_statuses.paginate_by_max_id(
|
|
||||||
limit_param(DEFAULT_STATUSES_LIMIT),
|
|
||||||
params[:max_id],
|
|
||||||
params[:since_id]
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def direct_timeline_statuses
|
|
||||||
Status.as_direct_timeline(current_account)
|
|
||||||
end
|
|
||||||
|
|
||||||
def insert_pagination_headers
|
|
||||||
set_pagination_headers(next_path, prev_path)
|
|
||||||
end
|
|
||||||
|
|
||||||
def pagination_params(core_params)
|
|
||||||
params.permit(:local, :limit).merge(core_params)
|
|
||||||
end
|
|
||||||
|
|
||||||
def next_path
|
|
||||||
api_v1_timelines_direct_url pagination_params(max_id: pagination_max_id)
|
|
||||||
end
|
|
||||||
|
|
||||||
def prev_path
|
|
||||||
api_v1_timelines_direct_url pagination_params(since_id: pagination_since_id)
|
|
||||||
end
|
|
||||||
|
|
||||||
def pagination_max_id
|
|
||||||
@statuses.last.id
|
|
||||||
end
|
|
||||||
|
|
||||||
def pagination_since_id
|
|
||||||
@statuses.first.id
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -31,7 +31,7 @@ class Api::V1::Timelines::HomeController < Api::BaseController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def account_home_feed
|
def account_home_feed
|
||||||
HomeFeed.new(current_account)
|
Feed.new(:home, current_account)
|
||||||
end
|
end
|
||||||
|
|
||||||
def insert_pagination_headers
|
def insert_pagination_headers
|
||||||
|
|||||||
@@ -1,66 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Api::V1::Timelines::ListController < Api::BaseController
|
|
||||||
before_action -> { doorkeeper_authorize! :read }
|
|
||||||
before_action :require_user!
|
|
||||||
before_action :set_list
|
|
||||||
before_action :set_statuses
|
|
||||||
|
|
||||||
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
|
|
||||||
|
|
||||||
def show
|
|
||||||
render json: @statuses,
|
|
||||||
each_serializer: REST::StatusSerializer,
|
|
||||||
relationships: StatusRelationshipsPresenter.new(@statuses, current_user.account_id)
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def set_list
|
|
||||||
@list = List.where(account: current_account).find(params[:id])
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_statuses
|
|
||||||
@statuses = cached_list_statuses
|
|
||||||
end
|
|
||||||
|
|
||||||
def cached_list_statuses
|
|
||||||
cache_collection list_statuses, Status
|
|
||||||
end
|
|
||||||
|
|
||||||
def list_statuses
|
|
||||||
list_feed.get(
|
|
||||||
limit_param(DEFAULT_STATUSES_LIMIT),
|
|
||||||
params[:max_id],
|
|
||||||
params[:since_id]
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def list_feed
|
|
||||||
ListFeed.new(@list)
|
|
||||||
end
|
|
||||||
|
|
||||||
def insert_pagination_headers
|
|
||||||
set_pagination_headers(next_path, prev_path)
|
|
||||||
end
|
|
||||||
|
|
||||||
def pagination_params(core_params)
|
|
||||||
params.permit(:limit).merge(core_params)
|
|
||||||
end
|
|
||||||
|
|
||||||
def next_path
|
|
||||||
api_v1_timelines_list_url params[:id], pagination_params(max_id: pagination_max_id)
|
|
||||||
end
|
|
||||||
|
|
||||||
def prev_path
|
|
||||||
api_v1_timelines_list_url params[:id], pagination_params(since_id: pagination_since_id)
|
|
||||||
end
|
|
||||||
|
|
||||||
def pagination_max_id
|
|
||||||
@statuses.last.id
|
|
||||||
end
|
|
||||||
|
|
||||||
def pagination_since_id
|
|
||||||
@statuses.first.id
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -28,8 +28,6 @@ class Api::Web::PushSubscriptionsController < Api::BaseController
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
data.deep_merge!(params[:data]) if params[:data]
|
|
||||||
|
|
||||||
web_subscription = ::Web::PushSubscription.create!(
|
web_subscription = ::Web::PushSubscription.create!(
|
||||||
endpoint: params[:subscription][:endpoint],
|
endpoint: params[:subscription][:endpoint],
|
||||||
key_p256dh: params[:subscription][:keys][:p256dh],
|
key_p256dh: params[:subscription][:keys][:p256dh],
|
||||||
|
|||||||
@@ -12,8 +12,7 @@ class ApplicationController < ActionController::Base
|
|||||||
|
|
||||||
helper_method :current_account
|
helper_method :current_account
|
||||||
helper_method :current_session
|
helper_method :current_session
|
||||||
helper_method :current_flavour
|
helper_method :current_theme
|
||||||
helper_method :current_skin
|
|
||||||
helper_method :single_user_mode?
|
helper_method :single_user_mode?
|
||||||
|
|
||||||
rescue_from ActionController::RoutingError, with: :not_found
|
rescue_from ActionController::RoutingError, with: :not_found
|
||||||
@@ -31,7 +30,7 @@ class ApplicationController < ActionController::Base
|
|||||||
private
|
private
|
||||||
|
|
||||||
def https_enabled?
|
def https_enabled?
|
||||||
Rails.env.production?
|
Rails.env.production? && ENV['LOCAL_HTTPS'] == 'true'
|
||||||
end
|
end
|
||||||
|
|
||||||
def store_current_location
|
def store_current_location
|
||||||
@@ -54,75 +53,6 @@ class ApplicationController < ActionController::Base
|
|||||||
new_user_session_path
|
new_user_session_path
|
||||||
end
|
end
|
||||||
|
|
||||||
def pack(data, pack_name, skin = 'default')
|
|
||||||
return nil unless pack?(data, pack_name)
|
|
||||||
pack_data = {
|
|
||||||
common: pack_name == 'common' ? nil : resolve_pack(data['name'] ? Themes.instance.flavour(current_flavour) : Themes.instance.core, 'common', skin),
|
|
||||||
flavour: data['name'],
|
|
||||||
pack: pack_name,
|
|
||||||
preload: nil,
|
|
||||||
skin: nil,
|
|
||||||
supported_locales: data['locales'],
|
|
||||||
}
|
|
||||||
if data['pack'][pack_name].is_a?(Hash)
|
|
||||||
pack_data[:common] = nil if data['pack'][pack_name]['use_common'] == false
|
|
||||||
pack_data[:pack] = nil unless data['pack'][pack_name]['filename']
|
|
||||||
if data['pack'][pack_name]['preload']
|
|
||||||
pack_data[:preload] = [data['pack'][pack_name]['preload']] if data['pack'][pack_name]['preload'].is_a?(String)
|
|
||||||
pack_data[:preload] = data['pack'][pack_name]['preload'] if data['pack'][pack_name]['preload'].is_a?(Array)
|
|
||||||
end
|
|
||||||
if skin != 'default' && data['skin'][skin]
|
|
||||||
pack_data[:skin] = skin if data['skin'][skin].include?(pack_name)
|
|
||||||
else # default skin
|
|
||||||
pack_data[:skin] = 'default' if data['pack'][pack_name]['stylesheet']
|
|
||||||
end
|
|
||||||
end
|
|
||||||
pack_data
|
|
||||||
end
|
|
||||||
|
|
||||||
def pack?(data, pack_name)
|
|
||||||
if data['pack'].is_a?(Hash) && data['pack'].key?(pack_name)
|
|
||||||
return true if data['pack'][pack_name].is_a?(String) || data['pack'][pack_name].is_a?(Hash)
|
|
||||||
end
|
|
||||||
false
|
|
||||||
end
|
|
||||||
|
|
||||||
def nil_pack(data, pack_name, skin = 'default')
|
|
||||||
{
|
|
||||||
common: pack_name == 'common' ? nil : resolve_pack(data['name'] ? Themes.instance.flavour(current_flavour) : Themes.instance.core, 'common', skin),
|
|
||||||
flavour: data['name'],
|
|
||||||
pack: nil,
|
|
||||||
preload: nil,
|
|
||||||
skin: nil,
|
|
||||||
supported_locales: data['locales'],
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
def resolve_pack(data, pack_name, skin = 'default')
|
|
||||||
result = pack(data, pack_name, skin)
|
|
||||||
unless result
|
|
||||||
if data['name'] && data.key?('fallback')
|
|
||||||
if data['fallback'].nil?
|
|
||||||
return nil_pack(data, pack_name, skin)
|
|
||||||
elsif data['fallback'].is_a?(String) && Themes.instance.flavour(data['fallback'])
|
|
||||||
return resolve_pack(Themes.instance.flavour(data['fallback']), pack_name)
|
|
||||||
elsif data['fallback'].is_a?(Array)
|
|
||||||
data['fallback'].each do |fallback|
|
|
||||||
return resolve_pack(Themes.instance.flavour(fallback), pack_name) if Themes.instance.flavour(fallback)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return nil_pack(data, pack_name, skin)
|
|
||||||
end
|
|
||||||
return data.key?('name') && data['name'] != Setting.default_settings['flavour'] ? resolve_pack(Themes.instance.flavour(Setting.default_settings['flavour']), pack_name) : nil_pack(data, pack_name, skin)
|
|
||||||
end
|
|
||||||
result
|
|
||||||
end
|
|
||||||
|
|
||||||
def use_pack(pack_name)
|
|
||||||
@core = resolve_pack(Themes.instance.core, pack_name)
|
|
||||||
@theme = resolve_pack(Themes.instance.flavour(current_flavour), pack_name, current_skin)
|
|
||||||
end
|
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def forbidden
|
def forbidden
|
||||||
@@ -153,14 +83,9 @@ class ApplicationController < ActionController::Base
|
|||||||
@current_session ||= SessionActivation.find_by(session_id: cookies.signed['_session_id'])
|
@current_session ||= SessionActivation.find_by(session_id: cookies.signed['_session_id'])
|
||||||
end
|
end
|
||||||
|
|
||||||
def current_flavour
|
def current_theme
|
||||||
return Setting.default_settings['flavour'] unless Themes.instance.flavours.include? current_user&.setting_flavour
|
return Setting.default_settings['theme'] unless Themes.instance.names.include? current_user&.setting_theme
|
||||||
current_user.setting_flavour
|
current_user.setting_theme
|
||||||
end
|
|
||||||
|
|
||||||
def current_skin
|
|
||||||
return 'default' unless Themes.instance.skins_for(current_flavour).include? current_user&.setting_skin
|
|
||||||
current_user.setting_skin
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def cache_collection(raw, klass)
|
def cache_collection(raw, klass)
|
||||||
@@ -179,7 +104,7 @@ class ApplicationController < ActionController::Base
|
|||||||
unless uncached_ids.empty?
|
unless uncached_ids.empty?
|
||||||
uncached = klass.where(id: uncached_ids).with_includes.map { |item| [item.id, item] }.to_h
|
uncached = klass.where(id: uncached_ids).with_includes.map { |item| [item.id, item] }.to_h
|
||||||
|
|
||||||
uncached.each_value do |item|
|
uncached.values.each do |item|
|
||||||
Rails.cache.write(item.cache_key, item)
|
Rails.cache.write(item.cache_key, item)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -192,31 +117,8 @@ class ApplicationController < ActionController::Base
|
|||||||
format.any { head code }
|
format.any { head code }
|
||||||
format.html do
|
format.html do
|
||||||
set_locale
|
set_locale
|
||||||
use_pack 'error'
|
|
||||||
render "errors/#{code}", layout: 'error', status: code
|
render "errors/#{code}", layout: 'error', status: code
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_cached_json(cache_key, **options)
|
|
||||||
options[:expires_in] ||= 3.minutes
|
|
||||||
cache_key = cache_key.join(':') if cache_key.is_a?(Enumerable)
|
|
||||||
cache_public = options.key?(:public) ? options.delete(:public) : true
|
|
||||||
content_type = options.delete(:content_type) || 'application/json'
|
|
||||||
|
|
||||||
data = Rails.cache.fetch(cache_key, { raw: true }.merge(options)) do
|
|
||||||
yield.to_json
|
|
||||||
end
|
|
||||||
|
|
||||||
expires_in options[:expires_in], public: cache_public
|
|
||||||
render json: data, content_type: content_type
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_cache_headers
|
|
||||||
response.headers['Vary'] = 'Accept'
|
|
||||||
end
|
|
||||||
|
|
||||||
def skip_session!
|
|
||||||
request.session_options[:skip] = true
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -3,11 +3,9 @@
|
|||||||
class Auth::ConfirmationsController < Devise::ConfirmationsController
|
class Auth::ConfirmationsController < Devise::ConfirmationsController
|
||||||
layout 'auth'
|
layout 'auth'
|
||||||
|
|
||||||
before_action :set_pack
|
def show
|
||||||
|
super do |user|
|
||||||
private
|
BootstrapTimelineWorker.perform_async(user.account_id) if user.errors.empty?
|
||||||
|
end
|
||||||
def set_pack
|
|
||||||
use_pack 'auth'
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
class Auth::PasswordsController < Devise::PasswordsController
|
class Auth::PasswordsController < Devise::PasswordsController
|
||||||
before_action :check_validity_of_reset_password_token, only: :edit
|
before_action :check_validity_of_reset_password_token, only: :edit
|
||||||
before_action :set_pack
|
|
||||||
|
|
||||||
layout 'auth'
|
layout 'auth'
|
||||||
|
|
||||||
@@ -18,8 +17,4 @@ class Auth::PasswordsController < Devise::PasswordsController
|
|||||||
def reset_password_token_is_valid?
|
def reset_password_token_is_valid?
|
||||||
resource_class.with_reset_password_token(params[:reset_password_token]).present?
|
resource_class.with_reset_password_token(params[:reset_password_token]).present?
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_pack
|
|
||||||
use_pack 'auth'
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ class Auth::RegistrationsController < Devise::RegistrationsController
|
|||||||
|
|
||||||
before_action :check_enabled_registrations, only: [:new, :create]
|
before_action :check_enabled_registrations, only: [:new, :create]
|
||||||
before_action :configure_sign_up_params, only: [:create]
|
before_action :configure_sign_up_params, only: [:create]
|
||||||
before_action :set_pack
|
|
||||||
before_action :set_sessions, only: [:edit, :update]
|
before_action :set_sessions, only: [:edit, :update]
|
||||||
before_action :set_instance_presenter, only: [:new, :create, :update]
|
before_action :set_instance_presenter, only: [:new, :create, :update]
|
||||||
|
|
||||||
@@ -17,16 +16,13 @@ class Auth::RegistrationsController < Devise::RegistrationsController
|
|||||||
|
|
||||||
def build_resource(hash = nil)
|
def build_resource(hash = nil)
|
||||||
super(hash)
|
super(hash)
|
||||||
|
resource.locale = I18n.locale
|
||||||
resource.locale = I18n.locale
|
|
||||||
resource.invite_code = params[:invite_code] if resource.invite_code.blank?
|
|
||||||
|
|
||||||
resource.build_account if resource.account.nil?
|
resource.build_account if resource.account.nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
def configure_sign_up_params
|
def configure_sign_up_params
|
||||||
devise_parameter_sanitizer.permit(:sign_up) do |u|
|
devise_parameter_sanitizer.permit(:sign_up) do |u|
|
||||||
u.permit({ account_attributes: [:username] }, :email, :password, :password_confirmation, :invite_code)
|
u.permit({ account_attributes: [:username] }, :email, :password, :password_confirmation)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -38,32 +34,12 @@ class Auth::RegistrationsController < Devise::RegistrationsController
|
|||||||
new_user_session_path
|
new_user_session_path
|
||||||
end
|
end
|
||||||
|
|
||||||
def after_update_path_for(_resource)
|
|
||||||
edit_user_registration_path
|
|
||||||
end
|
|
||||||
|
|
||||||
def check_enabled_registrations
|
def check_enabled_registrations
|
||||||
redirect_to root_path if single_user_mode? || !allowed_registrations?
|
redirect_to root_path if single_user_mode? || !Setting.open_registrations
|
||||||
end
|
|
||||||
|
|
||||||
def allowed_registrations?
|
|
||||||
Setting.open_registrations || (invite_code.present? && Invite.find_by(code: invite_code)&.valid_for_use?)
|
|
||||||
end
|
|
||||||
|
|
||||||
def invite_code
|
|
||||||
if params[:user]
|
|
||||||
params[:user][:invite_code]
|
|
||||||
else
|
|
||||||
params[:invite_code]
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_pack
|
|
||||||
use_pack %w(edit update).include?(action_name) ? 'admin' : 'auth'
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_instance_presenter
|
def set_instance_presenter
|
||||||
@instance_presenter = InstancePresenter.new
|
@instance_presenter = InstancePresenter.new
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ class Auth::SessionsController < Devise::SessionsController
|
|||||||
skip_before_action :require_no_authentication, only: [:create]
|
skip_before_action :require_no_authentication, only: [:create]
|
||||||
skip_before_action :check_suspension, only: [:destroy]
|
skip_before_action :check_suspension, only: [:destroy]
|
||||||
prepend_before_action :authenticate_with_two_factor, if: :two_factor_enabled?, only: [:create]
|
prepend_before_action :authenticate_with_two_factor, if: :two_factor_enabled?, only: [:create]
|
||||||
prepend_before_action :set_pack
|
|
||||||
before_action :set_instance_presenter, only: [:new]
|
before_action :set_instance_presenter, only: [:new]
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@@ -63,7 +62,7 @@ class Auth::SessionsController < Devise::SessionsController
|
|||||||
|
|
||||||
if user_params[:otp_attempt].present? && session[:otp_user_id]
|
if user_params[:otp_attempt].present? && session[:otp_user_id]
|
||||||
authenticate_with_two_factor_via_otp(user)
|
authenticate_with_two_factor_via_otp(user)
|
||||||
elsif user&.valid_password?(user_params[:password])
|
elsif user && user.valid_password?(user_params[:password])
|
||||||
prompt_for_two_factor(user)
|
prompt_for_two_factor(user)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -86,10 +85,6 @@ class Auth::SessionsController < Devise::SessionsController
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_pack
|
|
||||||
use_pack 'auth'
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_instance_presenter
|
def set_instance_presenter
|
||||||
@instance_presenter = InstancePresenter.new
|
@instance_presenter = InstancePresenter.new
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ class AuthorizeFollowsController < ApplicationController
|
|||||||
layout 'modal'
|
layout 'modal'
|
||||||
|
|
||||||
before_action :authenticate_user!
|
before_action :authenticate_user!
|
||||||
before_action :set_pack
|
|
||||||
before_action :set_body_classes
|
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@account = located_account || render(:error)
|
@account = located_account || render(:error)
|
||||||
@@ -25,10 +23,6 @@ class AuthorizeFollowsController < ApplicationController
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_pack
|
|
||||||
use_pack 'modal'
|
|
||||||
end
|
|
||||||
|
|
||||||
def follow_attempt
|
def follow_attempt
|
||||||
FollowService.new.call(current_account, acct_without_prefix)
|
FollowService.new.call(current_account, acct_without_prefix)
|
||||||
end
|
end
|
||||||
@@ -64,8 +58,4 @@ class AuthorizeFollowsController < ApplicationController
|
|||||||
def acct_params
|
def acct_params
|
||||||
params.fetch(:acct, '')
|
params.fetch(:acct, '')
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_body_classes
|
|
||||||
@body_classes = 'modal-layout'
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module AccountableConcern
|
|
||||||
extend ActiveSupport::Concern
|
|
||||||
|
|
||||||
def log_action(action, target)
|
|
||||||
Admin::ActionLog.create(account: current_account, action: action, target: target)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -44,8 +44,7 @@ module RateLimitHeaders
|
|||||||
end
|
end
|
||||||
|
|
||||||
def api_throttle_data
|
def api_throttle_data
|
||||||
most_limited_type, = request.env['rack.attack.throttle_data'].min_by { |_, v| v[:limit] }
|
request.env['rack.attack.throttle_data']['api']
|
||||||
request.env['rack.attack.throttle_data'][most_limited_type]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def request_time
|
def request_time
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ module UserTrackingConcern
|
|||||||
|
|
||||||
# Mark as signed-in today
|
# Mark as signed-in today
|
||||||
current_user.update_tracked_fields!(request)
|
current_user.update_tracked_fields!(request)
|
||||||
ActivityTracker.record('activity:logins', current_user.id)
|
|
||||||
|
|
||||||
# Regenerate feed if needed
|
# Regenerate feed if needed
|
||||||
regenerate_feed! if user_needs_feed_update?
|
regenerate_feed! if user_needs_feed_update?
|
||||||
|
|||||||
@@ -2,16 +2,14 @@
|
|||||||
|
|
||||||
class EmojisController < ApplicationController
|
class EmojisController < ApplicationController
|
||||||
before_action :set_emoji
|
before_action :set_emoji
|
||||||
before_action :set_cache_headers
|
|
||||||
|
|
||||||
def show
|
def show
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.json do
|
format.json do
|
||||||
skip_session!
|
render json: @emoji,
|
||||||
|
serializer: ActivityPub::EmojiSerializer,
|
||||||
render_cached_json(['activitypub', 'emoji', @emoji.cache_key], content_type: 'application/activity+json') do
|
adapter: ActivityPub::Adapter,
|
||||||
ActiveModelSerializers::SerializableResource.new(@emoji, serializer: ActivityPub::EmojiSerializer, adapter: ActivityPub::Adapter)
|
content_type: 'application/activity+json'
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -7,9 +7,7 @@ class FollowerAccountsController < ApplicationController
|
|||||||
@follows = Follow.where(target_account: @account).recent.page(params[:page]).per(FOLLOW_PER_PAGE).preload(:account)
|
@follows = Follow.where(target_account: @account).recent.page(params[:page]).per(FOLLOW_PER_PAGE).preload(:account)
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html do
|
format.html
|
||||||
use_pack 'public'
|
|
||||||
end
|
|
||||||
|
|
||||||
format.json do
|
format.json do
|
||||||
render json: collection_presenter,
|
render json: collection_presenter,
|
||||||
|
|||||||
@@ -7,9 +7,7 @@ class FollowingAccountsController < ApplicationController
|
|||||||
@follows = Follow.where(account: @account).recent.page(params[:page]).per(FOLLOW_PER_PAGE).preload(:target_account)
|
@follows = Follow.where(account: @account).recent.page(params[:page]).per(FOLLOW_PER_PAGE).preload(:target_account)
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html do
|
format.html
|
||||||
use_pack 'public'
|
|
||||||
end
|
|
||||||
|
|
||||||
format.json do
|
format.json do
|
||||||
render json: collection_presenter,
|
render json: collection_presenter,
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
class HomeController < ApplicationController
|
class HomeController < ApplicationController
|
||||||
before_action :authenticate_user!
|
before_action :authenticate_user!
|
||||||
before_action :set_pack
|
|
||||||
before_action :set_initial_state_json
|
before_action :set_initial_state_json
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@@ -38,10 +37,6 @@ class HomeController < ApplicationController
|
|||||||
redirect_to(default_redirect_path)
|
redirect_to(default_redirect_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_pack
|
|
||||||
use_pack 'home'
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_initial_state_json
|
def set_initial_state_json
|
||||||
serializable_resource = ActiveModelSerializers::SerializableResource.new(InitialStatePresenter.new(initial_state_params), serializer: InitialStateSerializer)
|
serializable_resource = ActiveModelSerializers::SerializableResource.new(InitialStatePresenter.new(initial_state_params), serializer: InitialStateSerializer)
|
||||||
@initial_state_json = serializable_resource.to_json
|
@initial_state_json = serializable_resource.to_json
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class InvitesController < ApplicationController
|
|
||||||
include Authorization
|
|
||||||
|
|
||||||
layout 'admin'
|
|
||||||
|
|
||||||
before_action :authenticate_user!
|
|
||||||
before_action :set_pack
|
|
||||||
|
|
||||||
def index
|
|
||||||
authorize :invite, :create?
|
|
||||||
|
|
||||||
@invites = Invite.where(user: current_user)
|
|
||||||
@invite = Invite.new(expires_in: 1.day.to_i)
|
|
||||||
end
|
|
||||||
|
|
||||||
def create
|
|
||||||
authorize :invite, :create?
|
|
||||||
|
|
||||||
@invite = Invite.new(resource_params)
|
|
||||||
@invite.user = current_user
|
|
||||||
|
|
||||||
if @invite.save
|
|
||||||
redirect_to invites_path
|
|
||||||
else
|
|
||||||
@invites = Invite.where(user: current_user)
|
|
||||||
render :index
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def destroy
|
|
||||||
@invite = Invite.where(user: current_user).find(params[:id])
|
|
||||||
authorize @invite, :destroy?
|
|
||||||
@invite.expire!
|
|
||||||
redirect_to invites_path
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def set_pack
|
|
||||||
use_pack 'settings'
|
|
||||||
end
|
|
||||||
|
|
||||||
def resource_params
|
|
||||||
params.require(:invite).permit(:max_uses, :expires_in)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -5,7 +5,6 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
|
|||||||
|
|
||||||
before_action :store_current_location
|
before_action :store_current_location
|
||||||
before_action :authenticate_resource_owner!
|
before_action :authenticate_resource_owner!
|
||||||
before_action :set_pack
|
|
||||||
|
|
||||||
include Localized
|
include Localized
|
||||||
|
|
||||||
@@ -14,8 +13,4 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
|
|||||||
def store_current_location
|
def store_current_location
|
||||||
store_location_for(:user, request.url)
|
store_location_for(:user, request.url)
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_pack
|
|
||||||
use_pack 'auth'
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio
|
|||||||
|
|
||||||
before_action :store_current_location
|
before_action :store_current_location
|
||||||
before_action :authenticate_resource_owner!
|
before_action :authenticate_resource_owner!
|
||||||
before_action :set_pack
|
|
||||||
|
|
||||||
include Localized
|
include Localized
|
||||||
|
|
||||||
@@ -14,8 +13,4 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio
|
|||||||
def store_current_location
|
def store_current_location
|
||||||
store_location_for(:user, request.url)
|
store_location_for(:user, request.url)
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_pack
|
|
||||||
use_pack 'settings'
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ class RemoteFollowController < ApplicationController
|
|||||||
layout 'modal'
|
layout 'modal'
|
||||||
|
|
||||||
before_action :set_account
|
before_action :set_account
|
||||||
before_action :set_pack
|
|
||||||
before_action :gone, if: :suspended_account?
|
before_action :gone, if: :suspended_account?
|
||||||
|
|
||||||
def new
|
def new
|
||||||
@@ -32,10 +31,6 @@ class RemoteFollowController < ApplicationController
|
|||||||
{ acct: session[:remote_follow] }
|
{ acct: session[:remote_follow] }
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_pack
|
|
||||||
use_pack 'modal'
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_account
|
def set_account
|
||||||
@account = Account.find_local!(params[:account_username])
|
@account = Account.find_local!(params[:account_username])
|
||||||
end
|
end
|
||||||
@@ -43,8 +38,4 @@ class RemoteFollowController < ApplicationController
|
|||||||
def suspended_account?
|
def suspended_account?
|
||||||
@account.suspended?
|
@account.suspended?
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_body_classes
|
|
||||||
@body_classes = 'modal-layout'
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Settings::ApplicationsController < Settings::BaseController
|
class Settings::ApplicationsController < ApplicationController
|
||||||
|
layout 'admin'
|
||||||
|
|
||||||
|
before_action :authenticate_user!
|
||||||
before_action :set_application, only: [:show, :update, :destroy, :regenerate]
|
before_action :set_application, only: [:show, :update, :destroy, :regenerate]
|
||||||
before_action :prepare_scopes, only: [:create, :update]
|
before_action :prepare_scopes, only: [:create, :update]
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Settings::BaseController < ApplicationController
|
|
||||||
layout 'admin'
|
|
||||||
|
|
||||||
before_action :authenticate_user!
|
|
||||||
before_action :set_pack
|
|
||||||
|
|
||||||
def set_pack
|
|
||||||
use_pack 'settings'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Settings::DeletesController < Settings::BaseController
|
class Settings::DeletesController < ApplicationController
|
||||||
|
layout 'admin'
|
||||||
|
|
||||||
prepend_before_action :check_enabled_deletion
|
before_action :check_enabled_deletion
|
||||||
|
before_action :authenticate_user!
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@confirmation = Form::DeleteConfirmation.new
|
@confirmation = Form::DeleteConfirmation.new
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Settings::ExportsController < Settings::BaseController
|
class Settings::ExportsController < ApplicationController
|
||||||
|
layout 'admin'
|
||||||
|
|
||||||
|
before_action :authenticate_user!
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@export = Export.new(current_account)
|
@export = Export.new(current_account)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Settings::FlavoursController < Settings::BaseController
|
|
||||||
|
|
||||||
def index
|
|
||||||
redirect_to action: 'show', flavour: current_flavour
|
|
||||||
end
|
|
||||||
|
|
||||||
def show
|
|
||||||
unless Themes.instance.flavours.include?(params[:flavour]) or params[:flavour] == current_flavour
|
|
||||||
redirect_to action: 'show', flavour: current_flavour
|
|
||||||
end
|
|
||||||
|
|
||||||
@listing = Themes.instance.flavours
|
|
||||||
@selected = params[:flavour]
|
|
||||||
end
|
|
||||||
|
|
||||||
def update
|
|
||||||
user_settings.update(user_settings_params(params[:flavour]).to_h)
|
|
||||||
redirect_to action: 'show', flavour: params[:flavour]
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def user_settings
|
|
||||||
UserSettingsDecorator.new(current_user)
|
|
||||||
end
|
|
||||||
|
|
||||||
def user_settings_params(flavour)
|
|
||||||
params.require(:user).merge({ setting_flavour: flavour }).permit(
|
|
||||||
:setting_flavour,
|
|
||||||
:setting_skin
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -2,7 +2,11 @@
|
|||||||
|
|
||||||
require 'sidekiq-bulk'
|
require 'sidekiq-bulk'
|
||||||
|
|
||||||
class Settings::FollowerDomainsController < Settings::BaseController
|
class Settings::FollowerDomainsController < ApplicationController
|
||||||
|
layout 'admin'
|
||||||
|
|
||||||
|
before_action :authenticate_user!
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@account = current_account
|
@account = current_account
|
||||||
@domains = current_account.followers.reorder('MIN(follows.id) DESC').group('accounts.domain').select('accounts.domain, count(accounts.id) as accounts_from_domain').page(params[:page]).per(10)
|
@domains = current_account.followers.reorder('MIN(follows.id) DESC').group('accounts.domain').select('accounts.domain, count(accounts.id) as accounts_from_domain').page(params[:page]).per(10)
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Settings::ImportsController < Settings::BaseController
|
class Settings::ImportsController < ApplicationController
|
||||||
|
layout 'admin'
|
||||||
|
|
||||||
|
before_action :authenticate_user!
|
||||||
before_action :set_account
|
before_action :set_account
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Settings::KeywordMutesController < Settings::BaseController
|
|
||||||
before_action :load_keyword_mute, only: [:edit, :update, :destroy]
|
|
||||||
|
|
||||||
def index
|
|
||||||
@keyword_mutes = paginated_keyword_mutes_for_account
|
|
||||||
end
|
|
||||||
|
|
||||||
def new
|
|
||||||
@keyword_mute = keyword_mutes_for_account.build
|
|
||||||
end
|
|
||||||
|
|
||||||
def create
|
|
||||||
@keyword_mute = keyword_mutes_for_account.create(keyword_mute_params)
|
|
||||||
|
|
||||||
if @keyword_mute.persisted?
|
|
||||||
redirect_to settings_keyword_mutes_path, notice: I18n.t('generic.changes_saved_msg')
|
|
||||||
else
|
|
||||||
render :new
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def update
|
|
||||||
if @keyword_mute.update(keyword_mute_params)
|
|
||||||
redirect_to settings_keyword_mutes_path, notice: I18n.t('generic.changes_saved_msg')
|
|
||||||
else
|
|
||||||
render :edit
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def destroy
|
|
||||||
@keyword_mute.destroy!
|
|
||||||
|
|
||||||
redirect_to settings_keyword_mutes_path, notice: I18n.t('generic.changes_saved_msg')
|
|
||||||
end
|
|
||||||
|
|
||||||
def destroy_all
|
|
||||||
keyword_mutes_for_account.delete_all
|
|
||||||
|
|
||||||
redirect_to settings_keyword_mutes_path, notice: I18n.t('generic.changes_saved_msg')
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def keyword_mutes_for_account
|
|
||||||
Glitch::KeywordMute.where(account: current_account)
|
|
||||||
end
|
|
||||||
|
|
||||||
def load_keyword_mute
|
|
||||||
@keyword_mute = keyword_mutes_for_account.find(params[:id])
|
|
||||||
end
|
|
||||||
|
|
||||||
def keyword_mute_params
|
|
||||||
params.require(:keyword_mute).permit(:keyword, :whole_word)
|
|
||||||
end
|
|
||||||
|
|
||||||
def paginated_keyword_mutes_for_account
|
|
||||||
keyword_mutes_for_account.order(:keyword).page params[:page]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Settings::MigrationsController < ApplicationController
|
|
||||||
layout 'admin'
|
|
||||||
|
|
||||||
before_action :authenticate_user!
|
|
||||||
|
|
||||||
def show
|
|
||||||
@migration = Form::Migration.new(account: current_account.moved_to_account)
|
|
||||||
end
|
|
||||||
|
|
||||||
def update
|
|
||||||
@migration = Form::Migration.new(resource_params)
|
|
||||||
|
|
||||||
if @migration.valid? && migration_account_changed?
|
|
||||||
current_account.update!(moved_to_account: @migration.account)
|
|
||||||
ActivityPub::UpdateDistributionWorker.perform_async(current_account.id)
|
|
||||||
redirect_to settings_migration_path, notice: I18n.t('migrations.updated_msg')
|
|
||||||
else
|
|
||||||
render :show
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def resource_params
|
|
||||||
params.require(:migration).permit(:acct)
|
|
||||||
end
|
|
||||||
|
|
||||||
def migration_account_changed?
|
|
||||||
current_account.moved_to_account_id != @migration.account&.id &&
|
|
||||||
current_account.id != @migration.account&.id
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Settings::NotificationsController < Settings::BaseController
|
class Settings::NotificationsController < ApplicationController
|
||||||
|
layout 'admin'
|
||||||
|
|
||||||
|
before_action :authenticate_user!
|
||||||
|
|
||||||
def show; end
|
def show; end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Settings::PreferencesController < Settings::BaseController
|
class Settings::PreferencesController < ApplicationController
|
||||||
|
layout 'admin'
|
||||||
|
|
||||||
|
before_action :authenticate_user!
|
||||||
|
|
||||||
def show; end
|
def show; end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
@@ -33,12 +37,12 @@ class Settings::PreferencesController < Settings::BaseController
|
|||||||
:setting_default_sensitive,
|
:setting_default_sensitive,
|
||||||
:setting_unfollow_modal,
|
:setting_unfollow_modal,
|
||||||
:setting_boost_modal,
|
:setting_boost_modal,
|
||||||
:setting_favourite_modal,
|
|
||||||
:setting_delete_modal,
|
:setting_delete_modal,
|
||||||
:setting_auto_play_gif,
|
:setting_auto_play_gif,
|
||||||
:setting_reduce_motion,
|
:setting_reduce_motion,
|
||||||
:setting_system_font_ui,
|
:setting_system_font_ui,
|
||||||
:setting_noindex,
|
:setting_noindex,
|
||||||
|
:setting_theme,
|
||||||
notification_emails: %i(follow follow_request reblog favourite mention digest),
|
notification_emails: %i(follow follow_request reblog favourite mention digest),
|
||||||
interactions: %i(must_be_follower must_be_following)
|
interactions: %i(must_be_follower must_be_following)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Settings::ProfilesController < Settings::BaseController
|
class Settings::ProfilesController < ApplicationController
|
||||||
include ObfuscateFilename
|
include ObfuscateFilename
|
||||||
|
|
||||||
|
layout 'admin'
|
||||||
|
|
||||||
|
before_action :authenticate_user!
|
||||||
before_action :set_account
|
before_action :set_account
|
||||||
|
|
||||||
obfuscate_filename [:account, :avatar]
|
obfuscate_filename [:account, :avatar]
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
# Intentionally does not inherit from BaseController
|
|
||||||
class Settings::SessionsController < ApplicationController
|
class Settings::SessionsController < ApplicationController
|
||||||
before_action :set_session, only: :destroy
|
before_action :set_session, only: :destroy
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,11 @@
|
|||||||
|
|
||||||
module Settings
|
module Settings
|
||||||
module TwoFactorAuthentication
|
module TwoFactorAuthentication
|
||||||
class ConfirmationsController < BaseController
|
class ConfirmationsController < ApplicationController
|
||||||
|
layout 'admin'
|
||||||
|
|
||||||
|
before_action :authenticate_user!
|
||||||
|
|
||||||
def new
|
def new
|
||||||
prepare_two_factor_form
|
prepare_two_factor_form
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2,7 +2,11 @@
|
|||||||
|
|
||||||
module Settings
|
module Settings
|
||||||
module TwoFactorAuthentication
|
module TwoFactorAuthentication
|
||||||
class RecoveryCodesController < BaseController
|
class RecoveryCodesController < ApplicationController
|
||||||
|
layout 'admin'
|
||||||
|
|
||||||
|
before_action :authenticate_user!
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@recovery_codes = current_user.generate_otp_backup_codes!
|
@recovery_codes = current_user.generate_otp_backup_codes!
|
||||||
current_user.save!
|
current_user.save!
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Settings
|
module Settings
|
||||||
class TwoFactorAuthenticationsController < BaseController
|
class TwoFactorAuthenticationsController < ApplicationController
|
||||||
|
layout 'admin'
|
||||||
|
|
||||||
|
before_action :authenticate_user!
|
||||||
before_action :verify_otp_required, only: [:create]
|
before_action :verify_otp_required, only: [:create]
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ class SharesController < ApplicationController
|
|||||||
layout 'modal'
|
layout 'modal'
|
||||||
|
|
||||||
before_action :authenticate_user!
|
before_action :authenticate_user!
|
||||||
before_action :set_pack
|
|
||||||
before_action :set_body_classes
|
before_action :set_body_classes
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@@ -25,11 +24,7 @@ class SharesController < ApplicationController
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_pack
|
|
||||||
use_pack 'share'
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_body_classes
|
def set_body_classes
|
||||||
@body_classes = 'modal-layout compose-standalone'
|
@body_classes = 'compose-standalone'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -10,12 +10,10 @@ class StatusesController < ApplicationController
|
|||||||
before_action :set_link_headers
|
before_action :set_link_headers
|
||||||
before_action :check_account_suspension
|
before_action :check_account_suspension
|
||||||
before_action :redirect_to_original, only: [:show]
|
before_action :redirect_to_original, only: [:show]
|
||||||
before_action :set_cache_headers
|
|
||||||
|
|
||||||
def show
|
def show
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html do
|
format.html do
|
||||||
use_pack 'public'
|
|
||||||
@ancestors = @status.reply? ? cache_collection(@status.ancestors(current_account), Status) : []
|
@ancestors = @status.reply? ? cache_collection(@status.ancestors(current_account), Status) : []
|
||||||
@descendants = cache_collection(@status.descendants(current_account), Status)
|
@descendants = cache_collection(@status.descendants(current_account), Status)
|
||||||
|
|
||||||
@@ -23,25 +21,22 @@ class StatusesController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
format.json do
|
format.json do
|
||||||
skip_session! unless @stream_entry.hidden?
|
render json: @status,
|
||||||
|
serializer: ActivityPub::NoteSerializer,
|
||||||
render_cached_json(['activitypub', 'note', @status.cache_key], content_type: 'application/activity+json', public: !@stream_entry.hidden?) do
|
adapter: ActivityPub::Adapter,
|
||||||
ActiveModelSerializers::SerializableResource.new(@status, serializer: ActivityPub::NoteSerializer, adapter: ActivityPub::Adapter)
|
content_type: 'application/activity+json'
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def activity
|
def activity
|
||||||
skip_session!
|
render json: @status,
|
||||||
|
serializer: ActivityPub::ActivitySerializer,
|
||||||
render_cached_json(['activitypub', 'activity', @status.cache_key], content_type: 'application/activity+json', public: !@stream_entry.hidden?) do
|
adapter: ActivityPub::Adapter,
|
||||||
ActiveModelSerializers::SerializableResource.new(@status, serializer: ActivityPub::ActivitySerializer, adapter: ActivityPub::Adapter)
|
content_type: 'application/activity+json'
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def embed
|
def embed
|
||||||
use_pack 'embed'
|
|
||||||
response.headers['X-Frame-Options'] = 'ALLOWALL'
|
response.headers['X-Frame-Options'] = 'ALLOWALL'
|
||||||
render 'stream_entries/embed', layout: 'embedded'
|
render 'stream_entries/embed', layout: 'embedded'
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ class StreamEntriesController < ApplicationController
|
|||||||
def show
|
def show
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html do
|
format.html do
|
||||||
use_pack 'public'
|
|
||||||
@ancestors = @stream_entry.activity.reply? ? cache_collection(@stream_entry.activity.ancestors(current_account), Status) : []
|
@ancestors = @stream_entry.activity.reply? ? cache_collection(@stream_entry.activity.ancestors(current_account), Status) : []
|
||||||
@descendants = cache_collection(@stream_entry.activity.descendants(current_account), Status)
|
@descendants = cache_collection(@stream_entry.activity.descendants(current_account), Status)
|
||||||
end
|
end
|
||||||
@@ -49,7 +48,7 @@ class StreamEntriesController < ApplicationController
|
|||||||
@type = @stream_entry.activity_type.downcase
|
@type = @stream_entry.activity_type.downcase
|
||||||
|
|
||||||
raise ActiveRecord::RecordNotFound if @stream_entry.activity.nil?
|
raise ActiveRecord::RecordNotFound if @stream_entry.activity.nil?
|
||||||
authorize @stream_entry.activity, :show? if @stream_entry.hidden? || @stream_entry.local_only?
|
authorize @stream_entry.activity, :show? if @stream_entry.hidden?
|
||||||
rescue Mastodon::NotPermittedError
|
rescue Mastodon::NotPermittedError
|
||||||
# Reraise in order to get a 404
|
# Reraise in order to get a 404
|
||||||
raise ActiveRecord::RecordNotFound
|
raise ActiveRecord::RecordNotFound
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ class TagsController < ApplicationController
|
|||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html do
|
format.html do
|
||||||
use_pack 'about'
|
|
||||||
serializable_resource = ActiveModelSerializers::SerializableResource.new(InitialStatePresenter.new(initial_state_params), serializer: InitialStateSerializer)
|
serializable_resource = ActiveModelSerializers::SerializableResource.new(InitialStatePresenter.new(initial_state_params), serializer: InitialStateSerializer)
|
||||||
@initial_state_json = serializable_resource.to_json
|
@initial_state_json = serializable_resource.to_json
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,19 +1,15 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module WellKnown
|
module WellKnown
|
||||||
class HostMetaController < ActionController::Base
|
class HostMetaController < ApplicationController
|
||||||
include RoutingHelper
|
include RoutingHelper
|
||||||
|
|
||||||
before_action { response.headers['Vary'] = 'Accept' }
|
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@webfinger_template = "#{webfinger_url}?resource={uri}"
|
@webfinger_template = "#{webfinger_url}?resource={uri}"
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.xml { render content_type: 'application/xrd+xml' }
|
format.xml { render content_type: 'application/xrd+xml' }
|
||||||
end
|
end
|
||||||
|
|
||||||
expires_in(3.days, public: true)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,25 +1,23 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module WellKnown
|
module WellKnown
|
||||||
class WebfingerController < ActionController::Base
|
class WebfingerController < ApplicationController
|
||||||
include RoutingHelper
|
include RoutingHelper
|
||||||
|
|
||||||
before_action { response.headers['Vary'] = 'Accept' }
|
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@account = Account.find_local!(username_from_resource)
|
@account = Account.find_local!(username_from_resource)
|
||||||
|
@canonical_account_uri = @account.to_webfinger_s
|
||||||
|
@magic_key = pem_to_magic_key(@account.keypair.public_key)
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.any(:json, :html) do
|
format.any(:json, :html) do
|
||||||
render json: @account, serializer: WebfingerSerializer, content_type: 'application/jrd+json'
|
render formats: :json, content_type: 'application/jrd+json'
|
||||||
end
|
end
|
||||||
|
|
||||||
format.xml do
|
format.xml do
|
||||||
render content_type: 'application/xrd+xml'
|
render content_type: 'application/xrd+xml'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
expires_in(3.days, public: true)
|
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue ActiveRecord::RecordNotFound
|
||||||
head 404
|
head 404
|
||||||
end
|
end
|
||||||
@@ -37,6 +35,21 @@ module WellKnown
|
|||||||
WebfingerResource.new(resource_user).username
|
WebfingerResource.new(resource_user).username
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def pem_to_magic_key(public_key)
|
||||||
|
modulus, exponent = [public_key.n, public_key.e].map do |component|
|
||||||
|
result = []
|
||||||
|
|
||||||
|
until component.zero?
|
||||||
|
result << [component % 256].pack('C')
|
||||||
|
component >>= 8
|
||||||
|
end
|
||||||
|
|
||||||
|
result.reverse.join
|
||||||
|
end
|
||||||
|
|
||||||
|
(['RSA'] + [modulus, exponent].map { |n| Base64.urlsafe_encode64(n) }).join('.')
|
||||||
|
end
|
||||||
|
|
||||||
def resource_param
|
def resource_param
|
||||||
params.require(:resource)
|
params.require(:resource)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,103 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module Admin::ActionLogsHelper
|
|
||||||
def log_target(log)
|
|
||||||
if log.target
|
|
||||||
linkable_log_target(log.target)
|
|
||||||
else
|
|
||||||
log_target_from_history(log.target_type, log.recorded_changes)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def linkable_log_target(record)
|
|
||||||
case record.class.name
|
|
||||||
when 'Account'
|
|
||||||
link_to record.acct, admin_account_path(record.id)
|
|
||||||
when 'User'
|
|
||||||
link_to record.account.acct, admin_account_path(record.account_id)
|
|
||||||
when 'CustomEmoji'
|
|
||||||
record.shortcode
|
|
||||||
when 'Report'
|
|
||||||
link_to "##{record.id}", admin_report_path(record)
|
|
||||||
when 'DomainBlock', 'EmailDomainBlock'
|
|
||||||
link_to record.domain, "https://#{record.domain}"
|
|
||||||
when 'Status'
|
|
||||||
link_to record.account.acct, TagManager.instance.url_for(record)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def log_target_from_history(type, attributes)
|
|
||||||
case type
|
|
||||||
when 'CustomEmoji'
|
|
||||||
attributes['shortcode']
|
|
||||||
when 'DomainBlock', 'EmailDomainBlock'
|
|
||||||
link_to attributes['domain'], "https://#{attributes['domain']}"
|
|
||||||
when 'Status'
|
|
||||||
tmp_status = Status.new(attributes)
|
|
||||||
link_to tmp_status.account&.acct || "##{tmp_status.account_id}", TagManager.instance.url_for(tmp_status)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def relevant_log_changes(log)
|
|
||||||
if log.target_type == 'CustomEmoji' && [:enable, :disable, :destroy].include?(log.action)
|
|
||||||
log.recorded_changes.slice('domain')
|
|
||||||
elsif log.target_type == 'CustomEmoji' && log.action == :update
|
|
||||||
log.recorded_changes.slice('domain', 'visible_in_picker')
|
|
||||||
elsif log.target_type == 'User' && [:promote, :demote].include?(log.action)
|
|
||||||
log.recorded_changes.slice('moderator', 'admin')
|
|
||||||
elsif log.target_type == 'DomainBlock'
|
|
||||||
log.recorded_changes.slice('severity', 'reject_media')
|
|
||||||
elsif log.target_type == 'Status' && log.action == :update
|
|
||||||
log.recorded_changes.slice('sensitive')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def log_extra_attributes(hash)
|
|
||||||
safe_join(hash.to_a.map { |key, value| safe_join([content_tag(:span, key, class: 'diff-key'), '=', log_change(value)]) }, ' ')
|
|
||||||
end
|
|
||||||
|
|
||||||
def log_change(val)
|
|
||||||
return content_tag(:span, val, class: 'diff-neutral') unless val.is_a?(Array)
|
|
||||||
safe_join([content_tag(:span, val.first, class: 'diff-old'), content_tag(:span, val.last, class: 'diff-new')], '→')
|
|
||||||
end
|
|
||||||
|
|
||||||
def icon_for_log(log)
|
|
||||||
case log.target_type
|
|
||||||
when 'Account', 'User'
|
|
||||||
'user'
|
|
||||||
when 'CustomEmoji'
|
|
||||||
'file'
|
|
||||||
when 'Report'
|
|
||||||
'flag'
|
|
||||||
when 'DomainBlock'
|
|
||||||
'lock'
|
|
||||||
when 'EmailDomainBlock'
|
|
||||||
'envelope'
|
|
||||||
when 'Status'
|
|
||||||
'pencil'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def class_for_log_icon(log)
|
|
||||||
case log.action
|
|
||||||
when :enable, :unsuspend, :unsilence, :confirm, :promote, :resolve
|
|
||||||
'positive'
|
|
||||||
when :create
|
|
||||||
opposite_verbs?(log) ? 'negative' : 'positive'
|
|
||||||
when :update, :reset_password, :disable_2fa, :memorialize
|
|
||||||
'neutral'
|
|
||||||
when :demote, :silence, :disable, :suspend
|
|
||||||
'negative'
|
|
||||||
when :destroy
|
|
||||||
opposite_verbs?(log) ? 'positive' : 'negative'
|
|
||||||
else
|
|
||||||
''
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def opposite_verbs?(log)
|
|
||||||
%w(DomainBlock EmailDomainBlock).include?(log.target_type)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,12 +1,10 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Admin::FilterHelper
|
module Admin::FilterHelper
|
||||||
ACCOUNT_FILTERS = %i(local remote by_domain silenced suspended recent username display_name email ip staff).freeze
|
ACCOUNT_FILTERS = %i(local remote by_domain silenced suspended recent username display_name email ip).freeze
|
||||||
REPORT_FILTERS = %i(resolved account_id target_account_id).freeze
|
REPORT_FILTERS = %i(resolved account_id target_account_id).freeze
|
||||||
INVITE_FILTER = %i(available expired).freeze
|
|
||||||
CUSTOM_EMOJI_FILTERS = %i(local remote by_domain shortcode).freeze
|
|
||||||
|
|
||||||
FILTERS = ACCOUNT_FILTERS + REPORT_FILTERS + INVITE_FILTER + CUSTOM_EMOJI_FILTERS
|
FILTERS = ACCOUNT_FILTERS + REPORT_FILTERS
|
||||||
|
|
||||||
def filter_link_to(text, link_to_params, link_class_params = link_to_params)
|
def filter_link_to(text, link_to_params, link_class_params = link_to_params)
|
||||||
new_url = filtered_url_for(link_to_params)
|
new_url = filtered_url_for(link_to_params)
|
||||||
@@ -14,13 +12,13 @@ module Admin::FilterHelper
|
|||||||
link_to text, new_url, class: filter_link_class(new_class)
|
link_to text, new_url, class: filter_link_class(new_class)
|
||||||
end
|
end
|
||||||
|
|
||||||
def table_link_to(icon, text, path, **options)
|
def table_link_to(icon, text, path, options = {})
|
||||||
link_to safe_join([fa_icon(icon), text]), path, options.merge(class: 'table-action-link')
|
link_to safe_join([fa_icon(icon), text]), path, options.merge(class: 'table-action-link')
|
||||||
end
|
end
|
||||||
|
|
||||||
def selected?(more_params)
|
def selected?(more_params)
|
||||||
new_url = filtered_url_for(more_params)
|
new_url = filtered_url_for(more_params)
|
||||||
filter_link_class(new_url) == 'selected'
|
filter_link_class(new_url) == 'selected' ? true : false
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ module ApplicationHelper
|
|||||||
current_page?(path) ? 'active' : ''
|
current_page?(path) ? 'active' : ''
|
||||||
end
|
end
|
||||||
|
|
||||||
def active_link_to(label, path, **options)
|
def active_link_to(label, path, options = {})
|
||||||
link_to label, path, options.merge(class: active_nav_class(path))
|
link_to label, path, options.merge(class: active_nav_class(path))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -9,24 +9,6 @@ module JsonLdHelper
|
|||||||
value.is_a?(Array) ? value.first : value
|
value.is_a?(Array) ? value.first : value
|
||||||
end
|
end
|
||||||
|
|
||||||
# The url attribute can be a string, an array of strings, or an array of objects.
|
|
||||||
# The objects could include a mimeType. Not-included mimeType means it's text/html.
|
|
||||||
def url_to_href(value, preferred_type = nil)
|
|
||||||
single_value = if value.is_a?(Array) && !value.first.is_a?(String)
|
|
||||||
value.find { |link| preferred_type.nil? || ((link['mimeType'].presence || 'text/html') == preferred_type) }
|
|
||||||
elsif value.is_a?(Array)
|
|
||||||
value.first
|
|
||||||
else
|
|
||||||
value
|
|
||||||
end
|
|
||||||
|
|
||||||
if single_value.nil? || single_value.is_a?(String)
|
|
||||||
single_value
|
|
||||||
else
|
|
||||||
single_value['href']
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def as_array(value)
|
def as_array(value)
|
||||||
value.is_a?(Array) ? value : [value]
|
value.is_a?(Array) ? value : [value]
|
||||||
end
|
end
|
||||||
@@ -39,10 +21,6 @@ module JsonLdHelper
|
|||||||
!json.nil? && equals_or_includes?(json['@context'], ActivityPub::TagManager::CONTEXT)
|
!json.nil? && equals_or_includes?(json['@context'], ActivityPub::TagManager::CONTEXT)
|
||||||
end
|
end
|
||||||
|
|
||||||
def unsupported_uri_scheme?(uri)
|
|
||||||
!uri.start_with?('http://', 'https://')
|
|
||||||
end
|
|
||||||
|
|
||||||
def canonicalize(json)
|
def canonicalize(json)
|
||||||
graph = RDF::Graph.new << JSON::LD::API.toRdf(json)
|
graph = RDF::Graph.new << JSON::LD::API.toRdf(json)
|
||||||
graph.dump(:normalize)
|
graph.dump(:normalize)
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ module RoutingHelper
|
|||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
include Rails.application.routes.url_helpers
|
include Rails.application.routes.url_helpers
|
||||||
include ActionView::Helpers::AssetTagHelper
|
include ActionView::Helpers::AssetTagHelper
|
||||||
include Webpacker::Helper
|
|
||||||
|
|
||||||
included do
|
included do
|
||||||
def default_url_options
|
def default_url_options
|
||||||
@@ -12,16 +11,12 @@ module RoutingHelper
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def full_asset_url(source, **options)
|
def full_asset_url(source, options = {})
|
||||||
source = ActionController::Base.helpers.asset_url(source, options) unless use_storage?
|
source = ActionController::Base.helpers.asset_url(source, options) unless use_storage?
|
||||||
|
|
||||||
URI.join(root_url, source).to_s
|
URI.join(root_url, source).to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
def full_pack_url(source, **options)
|
|
||||||
full_asset_url(asset_pack_path(source, options))
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def use_storage?
|
def use_storage?
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
module Settings::KeywordMutesHelper
|
|
||||||
end
|
|
||||||
@@ -10,7 +10,6 @@ module SettingsHelper
|
|||||||
eo: 'Esperanto',
|
eo: 'Esperanto',
|
||||||
es: 'Español',
|
es: 'Español',
|
||||||
fa: 'فارسی',
|
fa: 'فارسی',
|
||||||
gl: 'Galego',
|
|
||||||
fi: 'Suomi',
|
fi: 'Suomi',
|
||||||
fr: 'Français',
|
fr: 'Français',
|
||||||
he: 'עברית',
|
he: 'עברית',
|
||||||
@@ -28,9 +27,6 @@ module SettingsHelper
|
|||||||
pt: 'Português',
|
pt: 'Português',
|
||||||
'pt-BR': 'Português do Brasil',
|
'pt-BR': 'Português do Brasil',
|
||||||
ru: 'Русский',
|
ru: 'Русский',
|
||||||
sk: 'Slovensky',
|
|
||||||
sr: 'Српски',
|
|
||||||
'sr-Latn': 'Srpski (latinica)',
|
|
||||||
sv: 'Svenska',
|
sv: 'Svenska',
|
||||||
th: 'ภาษาไทย',
|
th: 'ภาษาไทย',
|
||||||
tr: 'Türkçe',
|
tr: 'Türkçe',
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
// This file will be loaded on all pages, regardless of theme.
|
|
||||||
|
|
||||||
import { start } from 'rails-ujs';
|
|
||||||
import 'font-awesome/css/font-awesome.css';
|
|
||||||
|
|
||||||
require.context('../images/', true);
|
|
||||||
|
|
||||||
start();
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
// This file will be loaded on embed pages, regardless of theme.
|
|
||||||
|
|
||||||
window.addEventListener('message', e => {
|
|
||||||
const data = e.data || {};
|
|
||||||
|
|
||||||
if (!window.parent || data.type !== 'setHeight') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
function setEmbedHeight () {
|
|
||||||
window.parent.postMessage({
|
|
||||||
type: 'setHeight',
|
|
||||||
id: data.id,
|
|
||||||
height: document.getElementsByTagName('html')[0].scrollHeight,
|
|
||||||
}, '*');
|
|
||||||
};
|
|
||||||
|
|
||||||
if (['interactive', 'complete'].includes(document.readyState)) {
|
|
||||||
setEmbedHeight();
|
|
||||||
} else {
|
|
||||||
document.addEventListener('DOMContentLoaded', setEmbedHeight);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
// This file will be loaded on public pages, regardless of theme.
|
|
||||||
|
|
||||||
const { delegate } = require('rails-ujs');
|
|
||||||
|
|
||||||
delegate(document, '.webapp-btn', 'click', ({ target, button }) => {
|
|
||||||
if (button !== 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
window.location.href = target.href;
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
delegate(document, '.status__content__spoiler-link', 'click', ({ target }) => {
|
|
||||||
const contentEl = target.parentNode.parentNode.querySelector('.e-content');
|
|
||||||
|
|
||||||
if (contentEl.style.display === 'block') {
|
|
||||||
contentEl.style.display = 'none';
|
|
||||||
target.parentNode.style.marginBottom = 0;
|
|
||||||
} else {
|
|
||||||
contentEl.style.display = 'block';
|
|
||||||
target.parentNode.style.marginBottom = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
// This file will be loaded on settings pages, regardless of theme.
|
|
||||||
|
|
||||||
const { length } = require('stringz');
|
|
||||||
const { delegate } = require('rails-ujs');
|
|
||||||
|
|
||||||
import { processBio } from 'flavours/glitch/util/bio_metadata';
|
|
||||||
|
|
||||||
delegate(document, '.account_display_name', 'input', ({ target }) => {
|
|
||||||
const nameCounter = document.querySelector('.name-counter');
|
|
||||||
|
|
||||||
if (nameCounter) {
|
|
||||||
nameCounter.textContent = 30 - length(target.value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
delegate(document, '.account_note', 'input', ({ target }) => {
|
|
||||||
const noteCounter = document.querySelector('.note-counter');
|
|
||||||
|
|
||||||
if (noteCounter) {
|
|
||||||
const noteWithoutMetadata = processBio(target.value).text;
|
|
||||||
noteCounter.textContent = 500 - length(noteWithoutMetadata);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
delegate(document, '#account_avatar', 'change', ({ target }) => {
|
|
||||||
const avatar = document.querySelector('.card.compact .avatar img');
|
|
||||||
const [file] = target.files || [];
|
|
||||||
const url = file ? URL.createObjectURL(file) : avatar.dataset.originalSrc;
|
|
||||||
|
|
||||||
avatar.src = url;
|
|
||||||
});
|
|
||||||
|
|
||||||
delegate(document, '#account_header', 'change', ({ target }) => {
|
|
||||||
const header = document.querySelector('.card.compact');
|
|
||||||
const [file] = target.files || [];
|
|
||||||
const url = file ? URL.createObjectURL(file) : header.dataset.originalSrc;
|
|
||||||
|
|
||||||
header.style.backgroundImage = `url(${url})`;
|
|
||||||
});
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user