Compare commits
No commits in common. "2fab999373bdaf4d430499bc30c09fa4fd87be8f" and "adaca2c33d7b2414d9c9e46322be5d962f636809" have entirely different histories.
2fab999373
...
adaca2c33d
|
@ -1,7 +0,0 @@
|
|||
[production]
|
||||
defaults
|
||||
not IE 11
|
||||
not dead
|
||||
|
||||
[development]
|
||||
supports es6-module
|
|
@ -1,209 +1,255 @@
|
|||
version: 2.1
|
||||
version: 2
|
||||
|
||||
orbs:
|
||||
ruby: circleci/ruby@1.4.1
|
||||
node: circleci/node@5.0.1
|
||||
|
||||
executors:
|
||||
default:
|
||||
parameters:
|
||||
ruby-version:
|
||||
type: string
|
||||
aliases:
|
||||
- &defaults
|
||||
docker:
|
||||
- image: cimg/ruby:<< parameters.ruby-version >>
|
||||
environment:
|
||||
- image: circleci/ruby:2.7-buster-node
|
||||
environment: &ruby_environment
|
||||
BUNDLE_JOBS: 3
|
||||
BUNDLE_RETRY: 3
|
||||
CONTINUOUS_INTEGRATION: true
|
||||
BUNDLE_APP_CONFIG: ./.bundle/
|
||||
BUNDLE_PATH: ./vendor/bundle/
|
||||
DB_HOST: localhost
|
||||
DB_USER: root
|
||||
DISABLE_SIMPLECOV: true
|
||||
RAILS_ENV: test
|
||||
- image: cimg/postgres:14.0
|
||||
ALLOW_NOPAM: true
|
||||
CONTINUOUS_INTEGRATION: true
|
||||
DISABLE_SIMPLECOV: true
|
||||
PAM_ENABLED: true
|
||||
PAM_DEFAULT_SERVICE: pam_test
|
||||
PAM_CONTROLLED_SERVICE: pam_test_controlled
|
||||
working_directory: ~/projects/mastodon/
|
||||
|
||||
- &attach_workspace
|
||||
attach_workspace:
|
||||
at: ~/projects/
|
||||
|
||||
- &persist_to_workspace
|
||||
persist_to_workspace:
|
||||
root: ~/projects/
|
||||
paths:
|
||||
- ./mastodon/
|
||||
|
||||
- &restore_ruby_dependencies
|
||||
restore_cache:
|
||||
keys:
|
||||
- v3-ruby-dependencies-{{ checksum "/tmp/.ruby-version" }}-{{ checksum "Gemfile.lock" }}
|
||||
- v3-ruby-dependencies-{{ checksum "/tmp/.ruby-version" }}-
|
||||
- v3-ruby-dependencies-
|
||||
|
||||
- &install_steps
|
||||
steps:
|
||||
- checkout
|
||||
- *attach_workspace
|
||||
- restore_cache:
|
||||
keys:
|
||||
- v2-node-dependencies-{{ checksum "yarn.lock" }}
|
||||
- v2-node-dependencies-
|
||||
- run:
|
||||
name: Install yarn dependencies
|
||||
command: yarn install --frozen-lockfile
|
||||
- save_cache:
|
||||
key: v2-node-dependencies-{{ checksum "yarn.lock" }}
|
||||
paths:
|
||||
- ./node_modules/
|
||||
- *persist_to_workspace
|
||||
|
||||
- &install_system_dependencies
|
||||
run:
|
||||
name: Install system dependencies
|
||||
command: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libicu-dev libidn11-dev libprotobuf-dev protobuf-compiler
|
||||
|
||||
- &install_ruby_dependencies
|
||||
steps:
|
||||
- *attach_workspace
|
||||
- *install_system_dependencies
|
||||
- run:
|
||||
name: Set Ruby version
|
||||
command: ruby -e 'puts RUBY_VERSION' | tee /tmp/.ruby-version
|
||||
- *restore_ruby_dependencies
|
||||
- run:
|
||||
name: Set bundler settings
|
||||
command: |
|
||||
bundle config --local clean 'true'
|
||||
bundle config --local deployment 'true'
|
||||
bundle config --local with 'pam_authentication'
|
||||
bundle config --local without 'development production'
|
||||
bundle config --local frozen 'true'
|
||||
bundle config --local path $BUNDLE_PATH
|
||||
- run:
|
||||
name: Install bundler dependencies
|
||||
command: bundle check || (bundle install && bundle clean)
|
||||
- save_cache:
|
||||
key: v3-ruby-dependencies-{{ checksum "/tmp/.ruby-version" }}-{{ checksum "Gemfile.lock" }}
|
||||
paths:
|
||||
- ./.bundle/
|
||||
- ./vendor/bundle/
|
||||
- persist_to_workspace:
|
||||
root: ~/projects/
|
||||
paths:
|
||||
- ./mastodon/.bundle/
|
||||
- ./mastodon/vendor/bundle/
|
||||
|
||||
- &test_steps
|
||||
parallelism: 4
|
||||
steps:
|
||||
- *attach_workspace
|
||||
- *install_system_dependencies
|
||||
- run:
|
||||
name: Install FFMPEG
|
||||
command: sudo apt-get install -y ffmpeg
|
||||
- run:
|
||||
name: Load database schema
|
||||
command: ./bin/rails db:create db:schema:load db:seed
|
||||
- run:
|
||||
name: Run rspec in parallel
|
||||
command: |
|
||||
bundle exec rspec --profile 10 \
|
||||
--format RspecJunitFormatter \
|
||||
--out test_results/rspec.xml \
|
||||
--format progress \
|
||||
$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)
|
||||
- store_test_results:
|
||||
path: test_results
|
||||
jobs:
|
||||
install:
|
||||
<<: *defaults
|
||||
<<: *install_steps
|
||||
|
||||
install-ruby2.7:
|
||||
<<: *defaults
|
||||
<<: *install_ruby_dependencies
|
||||
|
||||
install-ruby2.6:
|
||||
<<: *defaults
|
||||
docker:
|
||||
- image: circleci/ruby:2.6-buster-node
|
||||
environment: *ruby_environment
|
||||
<<: *install_ruby_dependencies
|
||||
|
||||
install-ruby3.0:
|
||||
<<: *defaults
|
||||
docker:
|
||||
- image: circleci/ruby:3.0-buster-node
|
||||
environment: *ruby_environment
|
||||
<<: *install_ruby_dependencies
|
||||
|
||||
build:
|
||||
<<: *defaults
|
||||
steps:
|
||||
- *attach_workspace
|
||||
- *install_system_dependencies
|
||||
- run:
|
||||
name: Precompile assets
|
||||
command: ./bin/rails assets:precompile
|
||||
- persist_to_workspace:
|
||||
root: ~/projects/
|
||||
paths:
|
||||
- ./mastodon/public/assets
|
||||
- ./mastodon/public/packs-test/
|
||||
|
||||
test-migrations:
|
||||
<<: *defaults
|
||||
docker:
|
||||
- image: circleci/ruby:2.7-buster-node
|
||||
environment: *ruby_environment
|
||||
- image: circleci/postgres:12.2
|
||||
environment:
|
||||
POSTGRES_USER: root
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
- image: cimg/redis:6.2
|
||||
- image: circleci/redis:5-alpine
|
||||
steps:
|
||||
- *attach_workspace
|
||||
- *install_system_dependencies
|
||||
- run:
|
||||
name: Create database
|
||||
command: ./bin/rails db:create
|
||||
- run:
|
||||
name: Run migrations
|
||||
command: ./bin/rails db:migrate
|
||||
|
||||
commands:
|
||||
install-system-dependencies:
|
||||
steps:
|
||||
- run:
|
||||
name: Install system dependencies
|
||||
command: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libicu-dev libidn11-dev
|
||||
install-ruby-dependencies:
|
||||
parameters:
|
||||
ruby-version:
|
||||
type: string
|
||||
steps:
|
||||
- run:
|
||||
command: |
|
||||
bundle config clean 'true'
|
||||
bundle config frozen 'true'
|
||||
bundle config without 'development production'
|
||||
name: Set bundler settings
|
||||
- ruby/install-deps:
|
||||
bundler-version: '2.3.8'
|
||||
key: ruby<< parameters.ruby-version >>-gems-v1
|
||||
wait-db:
|
||||
steps:
|
||||
- run:
|
||||
command: dockerize -wait tcp://localhost:5432 -wait tcp://localhost:6379 -timeout 1m
|
||||
name: Wait for PostgreSQL and Redis
|
||||
|
||||
jobs:
|
||||
build:
|
||||
test-ruby2.7:
|
||||
<<: *defaults
|
||||
docker:
|
||||
- image: cimg/ruby:3.0-node
|
||||
- image: circleci/ruby:2.7-buster-node
|
||||
environment: *ruby_environment
|
||||
- image: circleci/postgres:12.2
|
||||
environment:
|
||||
RAILS_ENV: test
|
||||
steps:
|
||||
- checkout
|
||||
- install-system-dependencies
|
||||
- install-ruby-dependencies:
|
||||
ruby-version: '3.0'
|
||||
- node/install-packages:
|
||||
cache-version: v1
|
||||
pkg-manager: yarn
|
||||
- run:
|
||||
command: ./bin/rails assets:precompile
|
||||
name: Precompile assets
|
||||
- persist_to_workspace:
|
||||
paths:
|
||||
- public/assets
|
||||
- public/packs-test
|
||||
root: .
|
||||
POSTGRES_USER: root
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
- image: circleci/redis:5-alpine
|
||||
<<: *test_steps
|
||||
|
||||
test:
|
||||
parameters:
|
||||
ruby-version:
|
||||
type: string
|
||||
executor:
|
||||
name: default
|
||||
ruby-version: << parameters.ruby-version >>
|
||||
environment:
|
||||
ALLOW_NOPAM: true
|
||||
PAM_ENABLED: true
|
||||
PAM_DEFAULT_SERVICE: pam_test
|
||||
PAM_CONTROLLED_SERVICE: pam_test_controlled
|
||||
parallelism: 4
|
||||
steps:
|
||||
- checkout
|
||||
- install-system-dependencies
|
||||
- run:
|
||||
command: sudo apt-get install -y ffmpeg imagemagick libpam-dev
|
||||
name: Install additional system dependencies
|
||||
- run:
|
||||
command: bundle config with 'pam_authentication'
|
||||
name: Enable PAM authentication
|
||||
- install-ruby-dependencies:
|
||||
ruby-version: << parameters.ruby-version >>
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- wait-db
|
||||
- run:
|
||||
command: ./bin/rails db:create db:schema:load db:seed
|
||||
name: Load database schema
|
||||
- ruby/rspec-test
|
||||
test-ruby2.6:
|
||||
<<: *defaults
|
||||
docker:
|
||||
- image: circleci/ruby:2.6-buster-node
|
||||
environment: *ruby_environment
|
||||
- image: circleci/postgres:12.2
|
||||
environment:
|
||||
POSTGRES_USER: root
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
- image: circleci/redis:5-alpine
|
||||
<<: *test_steps
|
||||
|
||||
test-migrations:
|
||||
executor:
|
||||
name: default
|
||||
ruby-version: '3.0'
|
||||
steps:
|
||||
- checkout
|
||||
- install-system-dependencies
|
||||
- install-ruby-dependencies:
|
||||
ruby-version: '3.0'
|
||||
- wait-db
|
||||
- run:
|
||||
command: ./bin/rails db:create
|
||||
name: Create database
|
||||
- run:
|
||||
command: ./bin/rails db:migrate VERSION=20171010025614
|
||||
name: Run migrations up to v2.0.0
|
||||
- run:
|
||||
command: ./bin/rails tests:migrations:populate_v2
|
||||
name: Populate database with test data
|
||||
- run:
|
||||
command: ./bin/rails db:migrate VERSION=20180514140000
|
||||
name: Run migrations up to v2.4.0
|
||||
- run:
|
||||
command: ./bin/rails tests:migrations:populate_v2_4
|
||||
name: Populate database with test data
|
||||
- run:
|
||||
command: ./bin/rails db:migrate
|
||||
name: Run all remaining migrations
|
||||
- run:
|
||||
command: ./bin/rails tests:migrations:check_database
|
||||
name: Check migration result
|
||||
test-ruby3.0:
|
||||
<<: *defaults
|
||||
docker:
|
||||
- image: circleci/ruby:3.0-buster-node
|
||||
environment: *ruby_environment
|
||||
- image: circleci/postgres:12.2
|
||||
environment:
|
||||
POSTGRES_USER: root
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
- image: circleci/redis:5-alpine
|
||||
<<: *test_steps
|
||||
|
||||
test-two-step-migrations:
|
||||
executor:
|
||||
name: default
|
||||
ruby-version: '3.0'
|
||||
test-webui:
|
||||
<<: *defaults
|
||||
docker:
|
||||
- image: circleci/node:14-buster
|
||||
steps:
|
||||
- checkout
|
||||
- install-system-dependencies
|
||||
- install-ruby-dependencies:
|
||||
ruby-version: '3.0'
|
||||
- wait-db
|
||||
- *attach_workspace
|
||||
- run:
|
||||
command: ./bin/rails db:create
|
||||
name: Create database
|
||||
- run:
|
||||
command: ./bin/rails db:migrate VERSION=20171010025614
|
||||
name: Run migrations up to v2.0.0
|
||||
- run:
|
||||
command: ./bin/rails tests:migrations:populate_v2
|
||||
name: Populate database with test data
|
||||
- run:
|
||||
command: ./bin/rails db:migrate VERSION=20180514140000
|
||||
name: Run pre-deployment migrations up to v2.4.0
|
||||
environment:
|
||||
SKIP_POST_DEPLOYMENT_MIGRATIONS: true
|
||||
- run:
|
||||
command: ./bin/rails tests:migrations:populate_v2_4
|
||||
name: Populate database with test data
|
||||
- run:
|
||||
command: ./bin/rails db:migrate
|
||||
name: Run all pre-deployment migrations
|
||||
environment:
|
||||
SKIP_POST_DEPLOYMENT_MIGRATIONS: true
|
||||
- run:
|
||||
command: ./bin/rails db:migrate
|
||||
name: Run all post-deployment remaining migrations
|
||||
- run:
|
||||
command: ./bin/rails tests:migrations:check_database
|
||||
name: Check migration result
|
||||
name: Run jest
|
||||
command: yarn test:jest
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
build-and-test:
|
||||
jobs:
|
||||
- build
|
||||
- test:
|
||||
matrix:
|
||||
parameters:
|
||||
ruby-version:
|
||||
- '2.7'
|
||||
- '3.0'
|
||||
name: test-ruby<< matrix.ruby-version >>
|
||||
- install
|
||||
- install-ruby2.7:
|
||||
requires:
|
||||
- build
|
||||
- install
|
||||
- install-ruby2.6:
|
||||
requires:
|
||||
- install
|
||||
- install-ruby2.7
|
||||
- install-ruby3.0:
|
||||
requires:
|
||||
- install
|
||||
- install-ruby2.7
|
||||
- build:
|
||||
requires:
|
||||
- install-ruby2.7
|
||||
- test-migrations:
|
||||
requires:
|
||||
- build
|
||||
- test-two-step-migrations:
|
||||
- install-ruby2.7
|
||||
- test-ruby2.7:
|
||||
requires:
|
||||
- install-ruby2.7
|
||||
- build
|
||||
- node/run:
|
||||
cache-version: v1
|
||||
name: test-webui
|
||||
pkg-manager: yarn
|
||||
- test-ruby2.6:
|
||||
requires:
|
||||
- install-ruby2.6
|
||||
- build
|
||||
version: lts
|
||||
yarn-run: test:jest
|
||||
- test-ruby3.0:
|
||||
requires:
|
||||
- install-ruby3.0
|
||||
- build
|
||||
- test-webui:
|
||||
requires:
|
||||
- install
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
version: '2'
|
||||
version: "2"
|
||||
checks:
|
||||
argument-count:
|
||||
enabled: false
|
||||
|
@ -34,8 +34,5 @@ plugins:
|
|||
sass-lint:
|
||||
enabled: true
|
||||
exclude_patterns:
|
||||
- spec/
|
||||
- vendor/asset/
|
||||
|
||||
- app/javascript/mastodon/locales/**/*.json
|
||||
- config/locales/**/*.yml
|
||||
- spec/
|
||||
- vendor/asset
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
# [Choice] Ruby version (use -bullseye variants on local arm64/Apple Silicon): 3, 3.1, 3.0, 2, 2.7, 2.6, 3-bullseye, 3.1-bullseye, 3.0-bullseye, 2-bullseye, 2.7-bullseye, 2.6-bullseye, 3-buster, 3.1-buster, 3.0-buster, 2-buster, 2.7-buster, 2.6-buster
|
||||
ARG VARIANT=3.1-bullseye
|
||||
FROM mcr.microsoft.com/vscode/devcontainers/ruby:${VARIANT}
|
||||
|
||||
# Install Rails
|
||||
# RUN gem install rails webdrivers
|
||||
|
||||
# Default value to allow debug server to serve content over GitHub Codespace's port forwarding service
|
||||
# The value is a comma-separated list of allowed domains
|
||||
ENV RAILS_DEVELOPMENT_HOSTS=".githubpreview.dev"
|
||||
|
||||
# [Choice] Node.js version: lts/*, 16, 14, 12, 10
|
||||
ARG NODE_VERSION="lts/*"
|
||||
RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"
|
||||
|
||||
# [Optional] Uncomment this section to install additional OS packages.
|
||||
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
||||
&& apt-get -y install --no-install-recommends libicu-dev libidn11-dev ffmpeg imagemagick libpam-dev
|
||||
|
||||
# [Optional] Uncomment this line to install additional gems.
|
||||
RUN gem install foreman
|
||||
|
||||
# [Optional] Uncomment this line to install global node packages.
|
||||
RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g yarn" 2>&1
|
|
@ -1,27 +0,0 @@
|
|||
{
|
||||
"name": "Mastodon",
|
||||
"dockerComposeFile": "docker-compose.yml",
|
||||
"service": "app",
|
||||
"workspaceFolder": "/workspaces/mastodon",
|
||||
|
||||
// Set *default* container specific settings.json values on container create.
|
||||
"settings": {},
|
||||
|
||||
// Add the IDs of extensions you want installed when the container is created.
|
||||
"extensions": [
|
||||
"EditorConfig.EditorConfig",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"rebornix.Ruby",
|
||||
"webben.browserslist"
|
||||
],
|
||||
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
// This can be used to network with other containers or the host.
|
||||
"forwardPorts": [3000, 4000],
|
||||
|
||||
// Use 'postCreateCommand' to run commands after the container is created.
|
||||
"postCreateCommand": "bundle install --path vendor/bundle && yarn install && ./bin/rails db:setup",
|
||||
|
||||
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
|
||||
"remoteUser": "vscode"
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
version: '3'
|
||||
|
||||
services:
|
||||
app:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
# Update 'VARIANT' to pick a version of Ruby: 3, 3.1, 3.0, 2, 2.7, 2.6
|
||||
# Append -bullseye or -buster to pin to an OS version.
|
||||
# Use -bullseye variants on local arm64/Apple Silicon.
|
||||
VARIANT: '3.0-bullseye'
|
||||
# Optional Node.js version to install
|
||||
NODE_VERSION: '14'
|
||||
volumes:
|
||||
- ..:/workspaces/mastodon:cached
|
||||
environment:
|
||||
RAILS_ENV: development
|
||||
NODE_ENV: development
|
||||
|
||||
REDIS_HOST: redis
|
||||
REDIS_PORT: '6379'
|
||||
DB_HOST: db
|
||||
DB_USER: postgres
|
||||
DB_PASS: postgres
|
||||
DB_PORT: '5432'
|
||||
ES_ENABLED: 'true'
|
||||
ES_HOST: es
|
||||
ES_PORT: '9200'
|
||||
# Overrides default command so things don't shut down after the process ends.
|
||||
command: sleep infinity
|
||||
networks:
|
||||
- external_network
|
||||
- internal_network
|
||||
user: vscode
|
||||
|
||||
db:
|
||||
image: postgres:14-alpine
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_DB: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
networks:
|
||||
- internal_network
|
||||
|
||||
redis:
|
||||
image: redis:6-alpine
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- redis-data:/data
|
||||
networks:
|
||||
- internal_network
|
||||
|
||||
es:
|
||||
image: docker.elastic.co/elasticsearch/elasticsearch-oss:7.10.2
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
ES_JAVA_OPTS: -Xms512m -Xmx512m
|
||||
cluster.name: es-mastodon
|
||||
discovery.type: single-node
|
||||
bootstrap.memory_lock: 'true'
|
||||
volumes:
|
||||
- es-data:/usr/share/elasticsearch/data
|
||||
networks:
|
||||
- internal_network
|
||||
ulimits:
|
||||
memlock:
|
||||
soft: -1
|
||||
hard: -1
|
||||
|
||||
volumes:
|
||||
postgres-data:
|
||||
redis-data:
|
||||
es-data:
|
||||
|
||||
networks:
|
||||
external_network:
|
||||
internal_network:
|
||||
internal: true
|
|
@ -15,7 +15,6 @@ vendor/bundle
|
|||
*.swp
|
||||
*~
|
||||
postgres
|
||||
postgres14
|
||||
redis
|
||||
elasticsearch
|
||||
chart
|
||||
|
|
|
@ -13,7 +13,7 @@ DB_PORT=5432
|
|||
|
||||
# DATABASE_URL=postgresql://$DATA_DB_USER:$DATA_DB_PASS@$DATA_DB_HOST/gonano
|
||||
|
||||
# Optional Elasticsearch configuration
|
||||
# Optional ElasticSearch configuration
|
||||
ES_ENABLED=true
|
||||
ES_HOST=$DATA_ELASTIC_HOST
|
||||
ES_PORT=9200
|
||||
|
@ -202,6 +202,10 @@ SMTP_FROM_ADDRESS=notifications@${APP_NAME}.nanoapp.io
|
|||
# Name of the pam service used for checking if an user can register (pam "account" section is evaluated) (nil (disabled) by default)
|
||||
# PAM_CONTROLLED_SERVICE=rpam
|
||||
|
||||
# Global OAuth settings (optional) :
|
||||
# If you have only one strategy, you may want to enable this
|
||||
# OAUTH_REDIRECT_AT_SIGN_IN=true
|
||||
|
||||
# Optional CAS authentication (cf. omniauth-cas) :
|
||||
# CAS_ENABLED=true
|
||||
# CAS_URL=https://sso.myserver.com/
|
||||
|
|
|
@ -4,12 +4,6 @@
|
|||
# not demonstrate all available configuration options. Please look at
|
||||
# https://docs.joinmastodon.org/admin/config/ for the full documentation.
|
||||
|
||||
# Note that this file accepts slightly different syntax depending on whether
|
||||
# you are using `docker-compose` or not. In particular, if you use
|
||||
# `docker-compose`, the value of each declared variable will be taken verbatim,
|
||||
# including surrounding quotes.
|
||||
# See: https://github.com/mastodon/mastodon/issues/16895
|
||||
|
||||
# Federation
|
||||
# ----------
|
||||
# This identifies your server and cannot be changed safely later
|
||||
|
@ -56,14 +50,11 @@ DB_PASS=
|
|||
DB_PORT=5432
|
||||
|
||||
|
||||
# Elasticsearch (optional)
|
||||
# ElasticSearch (optional)
|
||||
# ------------------------
|
||||
#ES_ENABLED=true
|
||||
#ES_HOST=localhost
|
||||
#ES_PORT=9200
|
||||
# Authentication for ES (optional)
|
||||
#ES_USER=elastic
|
||||
#ES_PASS=password
|
||||
|
||||
|
||||
# Secrets
|
||||
|
@ -107,7 +98,7 @@ SMTP_SERVER=smtp.mailgun.org
|
|||
SMTP_PORT=587
|
||||
SMTP_LOGIN=
|
||||
SMTP_PASSWORD=
|
||||
SMTP_FROM_ADDRESS=notifications@example.com
|
||||
SMTP_FROM_ADDRESS=notificatons@example.com
|
||||
|
||||
|
||||
# File storage (optional)
|
||||
|
@ -285,7 +276,3 @@ MAX_POLL_OPTION_CHARS=100
|
|||
# Units are in bytes
|
||||
MAX_EMOJI_SIZE=51200
|
||||
MAX_REMOTE_EMOJI_SIZE=204800
|
||||
|
||||
# Optional hCaptcha support
|
||||
# HCAPTCHA_SECRET_KEY=
|
||||
# HCAPTCHA_SITE_KEY=
|
||||
|
|
|
@ -79,11 +79,6 @@ module.exports = {
|
|||
'no-irregular-whitespace': 'error',
|
||||
'no-mixed-spaces-and-tabs': 'warn',
|
||||
'no-nested-ternary': 'warn',
|
||||
'no-restricted-properties': [
|
||||
'error',
|
||||
{ property: 'substring', message: 'Use .slice instead of .substring.' },
|
||||
{ property: 'substr', message: 'Use .slice instead of .substr.' },
|
||||
],
|
||||
'no-trailing-spaces': 'warn',
|
||||
'no-undef': 'error',
|
||||
'no-unreachable': 'error',
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
# CODEOWNERS for mastodon/mastodon
|
||||
|
||||
# Translators
|
||||
# To add translator, copy these lines, replace `fr` with appropriate language code and replace `@żelipapą` with user's GitHub nickname preceded by `@` sign or e-mail address.
|
||||
# /app/javascript/mastodon/locales/fr.json @żelipapą
|
||||
# /app/views/user_mailer/*.fr.html.erb @żelipapą
|
||||
# /app/views/user_mailer/*.fr.text.erb @żelipapą
|
||||
# /config/locales/*.fr.yml @żelipapą
|
||||
# /config/locales/fr.yml @żelipapą
|
||||
|
||||
# Polish
|
||||
/app/javascript/mastodon/locales/pl.json @m4sk1n
|
||||
/app/views/user_mailer/*.pl.html.erb @m4sk1n
|
||||
/app/views/user_mailer/*.pl.text.erb @m4sk1n
|
||||
/config/locales/*.pl.yml @m4sk1n
|
||||
/config/locales/pl.yml @m4sk1n
|
||||
|
||||
# French
|
||||
/app/javascript/mastodon/locales/fr.json @aldarone
|
||||
/app/javascript/mastodon/locales/whitelist_fr.json @aldarone
|
||||
/app/views/user_mailer/*.fr.html.erb @aldarone
|
||||
/app/views/user_mailer/*.fr.text.erb @aldarone
|
||||
/config/locales/*.fr.yml @aldarone
|
||||
/config/locales/fr.yml @aldarone
|
||||
|
||||
# Dutch
|
||||
/app/javascript/mastodon/locales/nl.json @jeroenpraat
|
||||
/app/javascript/mastodon/locales/whitelist_nl.json @jeroenpraat
|
||||
/app/views/user_mailer/*.nl.html.erb @jeroenpraat
|
||||
/app/views/user_mailer/*.nl.text.erb @jeroenpraat
|
||||
/config/locales/*.nl.yml @jeroenpraat
|
||||
/config/locales/nl.yml @jeroenpraat
|
|
@ -1,3 +1,3 @@
|
|||
patreon: mastodon
|
||||
open_collective: mastodon
|
||||
custom: https://sponsor.joinmastodon.org
|
||||
github: [Gargron]
|
||||
|
|
|
@ -8,17 +8,6 @@ body:
|
|||
Make sure that you are submitting a new bug that was not previously reported or already fixed.
|
||||
|
||||
Please use a concise and distinct title for the issue.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps to reproduce the problem
|
||||
description: What were you trying to do?
|
||||
value: |
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
...
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: Expected behaviour
|
||||
|
@ -31,6 +20,17 @@ body:
|
|||
description: What happened?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps to reproduce the problem
|
||||
description: What were you trying to do?
|
||||
value: |
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
...
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Specifications
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
name: Feature Request
|
||||
description: I have a suggestion
|
||||
labels: suggestion
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
name: Support
|
||||
about: Ask for help with your deployment
|
||||
title: DO NOT CREATE THIS ISSUE
|
||||
---
|
||||
|
||||
We primarily use GitHub as a bug and feature tracker. For usage questions, troubleshooting of deployments and other individual technical assistance, please use one of the resources below:
|
||||
|
||||
- https://discourse.joinmastodon.org
|
||||
- #mastodon on irc.freenode.net
|
|
@ -1,8 +1,5 @@
|
|||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: GitHub Discussions
|
||||
url: https://github.com/mastodon/mastodon/discussions
|
||||
- name: Mastodon Meta Discussion Board
|
||||
url: https://discourse.joinmastodon.org/
|
||||
about: Please ask and answer questions here.
|
||||
- name: Bug Bounty Program
|
||||
url: https://app.intigriti.com/programs/mastodon/mastodonio/detail
|
||||
about: Please report security vulnerabilities here.
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
name: Build container image
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
tags:
|
||||
- '*'
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/build-image.yml
|
||||
- Dockerfile
|
||||
jobs:
|
||||
build-image:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: docker/setup-qemu-action@v1
|
||||
- uses: docker/setup-buildx-action@v1
|
||||
- uses: docker/login-action@v1
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
if: github.event_name != 'pull_request'
|
||||
- uses: docker/metadata-action@v3
|
||||
id: meta
|
||||
with:
|
||||
images: ghcr.io/${{ github.repository_owner }}/mastodon
|
||||
flavor: |
|
||||
latest=true
|
||||
tags: |
|
||||
type=edge,branch=main
|
||||
type=match,pattern=v(.*),group=0
|
||||
type=ref,event=pr
|
||||
- uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
cache-from: type=registry,ref=ghcr.io/${{ github.repository_owner }}/mastodon:latest
|
||||
cache-to: type=inline
|
|
@ -2,9 +2,9 @@ name: Check i18n
|
|||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
branches: [ main ]
|
||||
|
||||
env:
|
||||
RAILS_ENV: test
|
||||
|
@ -14,21 +14,21 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install system dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libicu-dev libidn11-dev
|
||||
- name: Set up Ruby
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: '3.0'
|
||||
bundler-cache: true
|
||||
- name: Check locale file normalization
|
||||
run: bundle exec i18n-tasks check-normalized
|
||||
- name: Check for unused strings
|
||||
run: bundle exec i18n-tasks unused -l en
|
||||
- name: Check for wrong string interpolations
|
||||
run: bundle exec i18n-tasks check-consistent-interpolations
|
||||
- name: Check that all required locale files exist
|
||||
run: bundle exec rake repo:check_locales_files
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install system dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libicu-dev libidn11-dev libprotobuf-dev protobuf-compiler
|
||||
- name: Set up Ruby
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: '2.7'
|
||||
bundler-cache: true
|
||||
- name: Check locale file normalization
|
||||
run: bundle exec i18n-tasks check-normalized
|
||||
- name: Check for unused strings
|
||||
run: bundle exec i18n-tasks unused -l en
|
||||
- name: Check for wrong string interpolations
|
||||
run: bundle exec i18n-tasks check-consistent-interpolations
|
||||
- name: Check that all required locale files exist
|
||||
run: bundle exec rake repo:check_locales_files
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
|
||||
# Ignore postgres + redis + elasticsearch volume optionally created by docker-compose
|
||||
/postgres
|
||||
/postgres14
|
||||
/redis
|
||||
/elasticsearch
|
||||
|
||||
|
|
|
@ -1,78 +0,0 @@
|
|||
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
|
||||
#
|
||||
# If you find yourself ignoring temporary files generated by your text editor
|
||||
# or operating system, you probably want to add a global ignore instead:
|
||||
# git config --global core.excludesfile '~/.gitignore_global'
|
||||
|
||||
# Ignore bundler config and downloaded libraries.
|
||||
/.bundle
|
||||
/vendor/bundle
|
||||
|
||||
# Ignore the default SQLite database.
|
||||
/db/*.sqlite3
|
||||
/db/*.sqlite3-journal
|
||||
|
||||
# Ignore all logfiles and tempfiles.
|
||||
.eslintcache
|
||||
/log/*
|
||||
!/log/.keep
|
||||
/tmp
|
||||
/coverage
|
||||
/public/system
|
||||
/public/assets
|
||||
/public/packs
|
||||
/public/packs-test
|
||||
.env
|
||||
.env.production
|
||||
.env.development
|
||||
/node_modules/
|
||||
/build/
|
||||
|
||||
# Ignore Vagrant files
|
||||
.vagrant/
|
||||
|
||||
# Ignore Capistrano customizations
|
||||
/config/deploy/*
|
||||
|
||||
# Ignore IDE files
|
||||
.vscode/
|
||||
.idea/
|
||||
|
||||
# Ignore postgres + redis + elasticsearch volume optionally created by docker-compose
|
||||
/postgres
|
||||
/postgres14
|
||||
/redis
|
||||
/elasticsearch
|
||||
|
||||
# ignore Helm dependency charts
|
||||
/chart/charts/*.tgz
|
||||
|
||||
# Ignore Apple files
|
||||
.DS_Store
|
||||
|
||||
# Ignore vim files
|
||||
*~
|
||||
*.swp
|
||||
|
||||
# Ignore npm debug log
|
||||
npm-debug.log
|
||||
|
||||
# Ignore yarn log files
|
||||
yarn-error.log
|
||||
yarn-debug.log
|
||||
|
||||
# Ignore vagrant log files
|
||||
*-cloudimg-console.log
|
||||
|
||||
# Ignore Docker option files
|
||||
docker-compose.override.yml
|
||||
|
||||
# Ignore Helm files
|
||||
/chart
|
||||
|
||||
# Ignore emoji map file
|
||||
/app/javascript/mastodon/features/emoji/emoji_map.json
|
||||
|
||||
# Ignore locale files
|
||||
/app/javascript/mastodon/locales
|
||||
/config/locales
|
|
@ -1,3 +0,0 @@
|
|||
module.exports = {
|
||||
singleQuote: true
|
||||
}
|
30
.rubocop.yml
30
.rubocop.yml
|
@ -5,17 +5,17 @@ AllCops:
|
|||
TargetRubyVersion: 2.5
|
||||
NewCops: disable
|
||||
Exclude:
|
||||
- 'spec/**/*'
|
||||
- 'db/**/*'
|
||||
- 'app/views/**/*'
|
||||
- 'config/**/*'
|
||||
- 'bin/*'
|
||||
- 'Rakefile'
|
||||
- 'node_modules/**/*'
|
||||
- 'Vagrantfile'
|
||||
- 'vendor/**/*'
|
||||
- 'lib/json_ld/*'
|
||||
- 'lib/templates/**/*'
|
||||
- 'spec/**/*'
|
||||
- 'db/**/*'
|
||||
- 'app/views/**/*'
|
||||
- 'config/**/*'
|
||||
- 'bin/*'
|
||||
- 'Rakefile'
|
||||
- 'node_modules/**/*'
|
||||
- 'Vagrantfile'
|
||||
- 'vendor/**/*'
|
||||
- 'lib/json_ld/*'
|
||||
- 'lib/templates/**/*'
|
||||
|
||||
Bundler/OrderedGems:
|
||||
Enabled: false
|
||||
|
@ -29,17 +29,13 @@ Layout/EmptyLineAfterMagicComment:
|
|||
Layout/EmptyLineAfterGuardClause:
|
||||
Enabled: false
|
||||
|
||||
Layout/EmptyLineBetweenDefs:
|
||||
AllowAdjacentOneLineDefs: true
|
||||
|
||||
Layout/EmptyLinesAroundAttributeAccessor:
|
||||
Enabled: true
|
||||
|
||||
Layout/FirstHashElementIndentation:
|
||||
EnforcedStyle: consistent
|
||||
|
||||
Layout/HashAlignment:
|
||||
Enabled: false
|
||||
# EnforcedHashRocketStyle: table
|
||||
# EnforcedColonStyle: table
|
||||
|
||||
Layout/SpaceAroundMethodCallOperator:
|
||||
Enabled: true
|
||||
|
|
|
@ -1 +1 @@
|
|||
3.0.3
|
||||
2.7.4
|
||||
|
|
665
AUTHORS.md
665
AUTHORS.md
File diff suppressed because it is too large
Load Diff
2
Aptfile
2
Aptfile
|
@ -4,8 +4,10 @@ libicu-dev
|
|||
libidn11
|
||||
libidn11-dev
|
||||
libpq-dev
|
||||
libprotobuf-dev
|
||||
libxdamage1
|
||||
libxfixes3
|
||||
protobuf-compiler
|
||||
zlib1g-dev
|
||||
libcairo2
|
||||
libcroco3
|
||||
|
|
462
CHANGELOG.md
462
CHANGELOG.md
|
@ -3,440 +3,6 @@ Changelog
|
|||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [3.5.3] - 2022-05-26
|
||||
### Added
|
||||
|
||||
- **Add language dropdown to compose form in web UI** ([Gargron](https://github.com/mastodon/mastodon/pull/18420), [ykzts](https://github.com/mastodon/mastodon/pull/18460))
|
||||
- **Add warning for limited accounts in web UI** ([Gargron](https://github.com/mastodon/mastodon/pull/18344))
|
||||
- Add `limited` attribute to accounts in REST API ([Gargron](https://github.com/mastodon/mastodon/pull/18344))
|
||||
|
||||
### Changed
|
||||
|
||||
- **Change RSS feeds** ([Gargron](https://github.com/mastodon/mastodon/pull/18356), [tribela](https://github.com/mastodon/mastodon/pull/18406))
|
||||
- Titles are now date and time of post
|
||||
- Bodies now render all content faithfully, including polls and emojis
|
||||
- All media attachments are included with Media RSS
|
||||
- Change "dangerous" to "sensitive" in privacy policy and web UI ([Gargron](https://github.com/mastodon/mastodon/pull/18515))
|
||||
- Change unconfirmed accounts to not be visible in REST API ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17530))
|
||||
- Change `tootctl search deploy` to improve performance ([Gargron](https://github.com/mastodon/mastodon/pull/18463), [Gargron](https://github.com/mastodon/mastodon/pull/18514))
|
||||
- Change search indexing to use batches to minimize resource usage ([Gargron](https://github.com/mastodon/mastodon/pull/18451))
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix follower and other counters being able to go negative ([Gargron](https://github.com/mastodon/mastodon/pull/18517))
|
||||
- Fix unnecessary query on when creating a status ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17901))
|
||||
- Fix warning an account outside of a report closing all reports for that account ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18387))
|
||||
- Fix error when resolving a link that redirects to a local post ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18314))
|
||||
- Fix preferred posting language returning unusable value in REST API ([Gargron](https://github.com/mastodon/mastodon/pull/18428))
|
||||
- Fix race condition error when external status is reblogged ([ykzts](https://github.com/mastodon/mastodon/pull/18424))
|
||||
- Fix missing string for appeal validation error ([Gargron](https://github.com/mastodon/mastodon/pull/18410))
|
||||
- Fix block/mute lists showing a follow button in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18364))
|
||||
- Fix Redis configuration not being changed by `mastodon:setup` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18383))
|
||||
- Fix streaming notifications not using quick filter logic in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18316))
|
||||
- Fix ambiguous wording on appeal actions in admin UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18328))
|
||||
- Fix floating action button obscuring last element in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18332))
|
||||
- Fix account warnings not being recorded in audit log ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18338))
|
||||
- Fix leftover icons for direct visibility statuses ([Steffo99](https://github.com/mastodon/mastodon/pull/18305))
|
||||
- Fix link verification requiring case sensitivity on links ([sgolemon](https://github.com/mastodon/mastodon/pull/18320))
|
||||
- Fix embeds not setting their height correctly ([rinsuki](https://github.com/mastodon/mastodon/pull/18301))
|
||||
|
||||
### Security
|
||||
|
||||
- Fix concurrent unfollowing decrementing follower count more than once ([Gargron](https://github.com/mastodon/mastodon/pull/18527))
|
||||
- Fix being able to appeal a strike unlimited times ([Gargron](https://github.com/mastodon/mastodon/pull/18529))
|
||||
- Fix being able to report otherwise inaccessible statuses ([Gargron](https://github.com/mastodon/mastodon/pull/18528))
|
||||
- Fix empty votes arbitrarily increasing voters count in polls ([Gargron](https://github.com/mastodon/mastodon/pull/18526))
|
||||
- Fix moderator identity leak when approving appeal of sensitive marked statuses ([Gargron](https://github.com/mastodon/mastodon/pull/18525))
|
||||
- Fix suspended users being able to access APIs that don't require a user ([Gargron](https://github.com/mastodon/mastodon/pull/18524))
|
||||
- Fix confirmation redirect to app without `Location` header ([Gargron](https://github.com/mastodon/mastodon/pull/18523))
|
||||
|
||||
## [3.5.2] - 2022-05-04
|
||||
### Added
|
||||
|
||||
- Add warning on direct messages screen in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/18289))
|
||||
- We already had a warning when composing a direct message, it has now been reworded to be more clear
|
||||
- Same warning is now displayed when viewing sent and received direct messages
|
||||
- Add ability to set approval-based registration through tootctl ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18248))
|
||||
- Add pre-filling of domain from search filter in domain allow/block admin UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18172))
|
||||
|
||||
## Changed
|
||||
|
||||
- Change name of “Direct” visibility to “Mentioned people only” in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/18146), [Gargron](https://github.com/mastodon/mastodon/pull/18289), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/18291))
|
||||
- Change trending posts to only show one post from each account ([Gargron](https://github.com/mastodon/mastodon/pull/18181))
|
||||
- Change half-life of trending posts from 6 hours to 2 hours ([Gargron](https://github.com/mastodon/mastodon/pull/18182))
|
||||
- Change full-text search feature to also include polls you have voted in ([tribela](https://github.com/mastodon/mastodon/pull/18070))
|
||||
- Change Redis from using one connection per process, to using a connection pool ([Gargron](https://github.com/mastodon/mastodon/pull/18135), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/18160), [Gargron](https://github.com/mastodon/mastodon/pull/18171))
|
||||
- Different threads no longer have to wait on a mutex over a single connection
|
||||
- However, this does increase the number of Redis connections by a fair amount
|
||||
- We are planning to optimize Redis use so that the pool can be made smaller in the future
|
||||
|
||||
## Removed
|
||||
|
||||
- Remove IP matching from e-mail domain blocks ([Gargron](https://github.com/mastodon/mastodon/pull/18190))
|
||||
- The IPs of the blocked e-mail domain or its MX records are no longer checked
|
||||
- Previously it was too easy to block e-mail providers by mistake
|
||||
|
||||
## Fixed
|
||||
|
||||
- Fix compatibility with Friendica's pinned posts ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18254), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/18260))
|
||||
- Fix error when looking up handle with surrounding spaces in REST API ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18225))
|
||||
- Fix double render error when authorizing interaction ([Gargron](https://github.com/mastodon/mastodon/pull/18203))
|
||||
- Fix error when a post references an invalid media attachment ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18211))
|
||||
- Fix error when trying to revoke OAuth token without supplying a token ([Gargron](https://github.com/mastodon/mastodon/pull/18205))
|
||||
- Fix error caused by missing subject in Webfinger response ([Gargron](https://github.com/mastodon/mastodon/pull/18204))
|
||||
- Fix error on attempting to delete an account moderation note ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18196))
|
||||
- Fix light-mode emoji borders in web UI ([Gaelan](https://github.com/mastodon/mastodon/pull/18131))
|
||||
- Fix being able to scroll away from the loading bar in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/18170))
|
||||
- Fix error when a bookmark or favorite has been reported and deleted ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18174))
|
||||
- Fix being offered empty “Server rules violation” report option in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18165))
|
||||
- Fix temporary network errors preventing from authorizing interactions with remote accounts ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18161))
|
||||
- Fix incorrect link in "new trending tags" email ([cdzombak](https://github.com/mastodon/mastodon/pull/18156))
|
||||
- Fix missing indexes on some foreign keys ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18157))
|
||||
- Fix n+1 query on feed merge and populate operations ([Gargron](https://github.com/mastodon/mastodon/pull/18111))
|
||||
- Fix feed unmerge worker being exceptionally slow in some conditions ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18110))
|
||||
- Fix PeerTube videos appearing with an erroneous “Edited at” marker ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18100))
|
||||
- Fix instance actor being created incorrectly when running through migrations ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18109))
|
||||
- Fix web push notifications containing HTML entities ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18071))
|
||||
- Fix inconsistent parsing of `TRUSTED_PROXY_IP` ([ykzts](https://github.com/mastodon/mastodon/pull/18051))
|
||||
- Fix error when fetching pinned posts ([tribela](https://github.com/mastodon/mastodon/pull/18030))
|
||||
- Fix wrong optimization in feed populate operation ([dogelover911](https://github.com/mastodon/mastodon/pull/18009))
|
||||
- Fix error in alias settings page ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18004))
|
||||
|
||||
## [3.5.1] - 2022-04-08
|
||||
### Added
|
||||
|
||||
- Add pagination for trending statuses in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/17976))
|
||||
|
||||
### Changed
|
||||
|
||||
- Change e-mail notifications to only be sent when recipient is offline ([Gargron](https://github.com/mastodon/mastodon/pull/17984))
|
||||
- Send e-mails for mentions and follows by default again
|
||||
- But only when recipient does not have push notifications through an app
|
||||
- Change `website` attribute to be nullable on `Application` entity in REST API ([rinsuki](https://github.com/mastodon/mastodon/pull/17962))
|
||||
|
||||
### Removed
|
||||
|
||||
- Remove sign-in token authentication, instead send e-mail about new sign-in ([Gargron](https://github.com/mastodon/mastodon/pull/17970))
|
||||
- You no longer need to enter a security code sent through e-mail
|
||||
- Instead you get an e-mail about a new sign-in from an unfamiliar IP address
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix error resposes for `from` search prefix ([single-right-quote](https://github.com/mastodon/mastodon/pull/17963))
|
||||
- Fix dangling language-specific trends ([Gargron](https://github.com/mastodon/mastodon/pull/17997))
|
||||
- Fix extremely rare race condition when deleting a status or account ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17994))
|
||||
- Fix trends returning less results per page when filtered in REST API ([Gargron](https://github.com/mastodon/mastodon/pull/17996))
|
||||
- Fix pagination header on empty trends responses in REST API ([Gargron](https://github.com/mastodon/mastodon/pull/17986))
|
||||
- Fix cookies secure flag being set when served over Tor ([Gargron](https://github.com/mastodon/mastodon/pull/17992))
|
||||
- Fix migration error handling ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17991))
|
||||
- Fix error when re-running some migrations if they get interrupted at the wrong moment ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17989))
|
||||
- Fix potentially missing statuses when reconnecting to streaming API in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17981), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17987), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17980))
|
||||
- Fix error when sending warning emails with custom text ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17983))
|
||||
- Fix unset `SMTP_RETURN_PATH` environment variable causing e-mail not to send ([Gargron](https://github.com/mastodon/mastodon/pull/17982))
|
||||
- Fix possible duplicate statuses in timelines in some edge cases in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17971))
|
||||
- Fix spurious edits and require incoming edits to be explicitly marked as such ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17918))
|
||||
- Fix error when encountering invalid pinned statuses ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17964))
|
||||
- Fix inconsistency in error handling when removing a status ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17974))
|
||||
- Fix admin API unconditionally requiring CSRF token ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17975))
|
||||
- Fix trending tags endpoint missing `offset` param in REST API ([Gargron](https://github.com/mastodon/mastodon/pull/17973))
|
||||
- Fix unusual number formatting in some locales ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17929))
|
||||
- Fix `S3_FORCE_SINGLE_REQUEST` environment variable not working ([HolgerHuo](https://github.com/mastodon/mastodon/pull/17922))
|
||||
- Fix failure to build assets with OpenSSL 3 ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17930))
|
||||
- Fix PWA manifest using outdated routes ([HolgerHuo](https://github.com/mastodon/mastodon/pull/17921))
|
||||
- Fix error when indexing statuses into Elasticsearch ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17912))
|
||||
|
||||
## [3.5.0] - 2022-03-30
|
||||
### Added
|
||||
|
||||
- **Add support for incoming edited posts** ([Gargron](https://github.com/mastodon/mastodon/pull/16697), [Gargron](https://github.com/mastodon/mastodon/pull/17727), [Gargron](https://github.com/mastodon/mastodon/pull/17728), [Gargron](https://github.com/mastodon/mastodon/pull/17320), [Gargron](https://github.com/mastodon/mastodon/pull/17404), [Gargron](https://github.com/mastodon/mastodon/pull/17390), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17335), [Gargron](https://github.com/mastodon/mastodon/pull/17696), [Gargron](https://github.com/mastodon/mastodon/pull/17745), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17740), [Gargron](https://github.com/mastodon/mastodon/pull/17697), [Gargron](https://github.com/mastodon/mastodon/pull/17648), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17531), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17499), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17498), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17380), [Gargron](https://github.com/mastodon/mastodon/pull/17373), [Gargron](https://github.com/mastodon/mastodon/pull/17334), [Gargron](https://github.com/mastodon/mastodon/pull/17333), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17699), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17748))
|
||||
- Previous versions remain available for perusal and comparison
|
||||
- People who reblogged a post are notified when it's edited
|
||||
- New REST APIs:
|
||||
- `PUT /api/v1/statuses/:id`
|
||||
- `GET /api/v1/statuses/:id/history`
|
||||
- `GET /api/v1/statuses/:id/source`
|
||||
- New streaming API event:
|
||||
- `status.update`
|
||||
- **Add appeals for moderator decisions** ([Gargron](https://github.com/mastodon/mastodon/pull/17364), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17725), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17566), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17652), [Gargron](https://github.com/mastodon/mastodon/pull/17616), [Gargron](https://github.com/mastodon/mastodon/pull/17615), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17554), [Gargron](https://github.com/mastodon/mastodon/pull/17523))
|
||||
- All default moderator decisions now notify the affected user by e-mail
|
||||
- They now link to an appeal page instead of suggesting replying to the e-mail
|
||||
- They can now be found in account settings and not just e-mail
|
||||
- Users can submit one appeal within 20 days of the decision
|
||||
- Moderators can approve or reject the appeal
|
||||
- **Add notifications for posts deleted by moderators** ([Gargron](https://github.com/mastodon/mastodon/pull/17204), [Gargron](https://github.com/mastodon/mastodon/pull/17668), [Gargron](https://github.com/mastodon/mastodon/pull/17746), [Gargron](https://github.com/mastodon/mastodon/pull/17679), [Gargron](https://github.com/mastodon/mastodon/pull/17487))
|
||||
- New, redesigned report view in admin UI
|
||||
- Common report actions now only take one click to complete
|
||||
- Deleting posts or marking as sensitive from report now notifies user
|
||||
- Reports can be categorized by reason and specific rules violated
|
||||
- The reasons are automatically cited in the notifications, except for spam
|
||||
- Marking posts as sensitive now federates using post editing
|
||||
- **Add explore page with trending posts and links** ([Gargron](https://github.com/mastodon/mastodon/pull/17123), [Gargron](https://github.com/mastodon/mastodon/pull/17431), [Gargron](https://github.com/mastodon/mastodon/pull/16917), [Gargron](https://github.com/mastodon/mastodon/pull/17677), [Gargron](https://github.com/mastodon/mastodon/pull/16938), [Gargron](https://github.com/mastodon/mastodon/pull/17044), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/16978), [Gargron](https://github.com/mastodon/mastodon/pull/16979), [tribela](https://github.com/mastodon/mastodon/pull/17066), [Gargron](https://github.com/mastodon/mastodon/pull/17072), [Gargron](https://github.com/mastodon/mastodon/pull/17403), [noiob](https://github.com/mastodon/mastodon/pull/17624), [mayaeh](https://github.com/mastodon/mastodon/pull/17755), [mayaeh](https://github.com/mastodon/mastodon/pull/17757), [Gargron](https://github.com/mastodon/mastodon/pull/17760), [mayaeh](https://github.com/mastodon/mastodon/pull/17762))
|
||||
- Hashtag trends algorithm is extended to work for posts and links
|
||||
- Links are only considered if they have an adequate preview card
|
||||
- Preview card generation has been improved to support structured data
|
||||
- Links can only trend if the publisher (domain) has been approved
|
||||
- Posts can only trend if the author has been approved
|
||||
- Individual approval and rejection for posts and links is also available
|
||||
- Moderators are notified about pending trends at most once every 2 hours
|
||||
- Posts and link trends are language-specific
|
||||
- Search page is redesigned into explore page in web UI
|
||||
- Discovery tab is coming soon in official iOS and Android apps
|
||||
- New REST APIs:
|
||||
- `GET /api/v1/trends/links`
|
||||
- `GET /api/v1/trends/statuses`
|
||||
- `GET /api/v1/trends/tags` (alias of `GET /api/v1/trends`)
|
||||
- `GET /api/v1/admin/trends/links`
|
||||
- `GET /api/v1/admin/trends/statuses`
|
||||
- `GET /api/v1/admin/trends/tags`
|
||||
- **Add graphs and retention metrics to admin dashboard** ([Gargron](https://github.com/mastodon/mastodon/pull/16829), [Gargron](https://github.com/mastodon/mastodon/pull/17617), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17570), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/16910), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/16909), [mashirozx](https://github.com/mastodon/mastodon/pull/16884), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/16854))
|
||||
- Dashboard shows more numbers with development over time
|
||||
- Other data such as most used interface languages and sign-up sources
|
||||
- User retention graph shows how many new users stick around
|
||||
- New REST APIs:
|
||||
- `POST /api/v1/admin/measures`
|
||||
- `POST /api/v1/admin/dimensions`
|
||||
- `POST /api/v1/admin/retention`
|
||||
- Add `GET /api/v1/accounts/familiar_followers` to REST API ([Gargron](https://github.com/mastodon/mastodon/pull/17700))
|
||||
- Add `POST /api/v1/accounts/:id/remove_from_followers` to REST API ([noellabo](https://github.com/mastodon/mastodon/pull/16864))
|
||||
- Add `category` and `rule_ids` params to `POST /api/v1/reports` IN REST API ([Gargron](https://github.com/mastodon/mastodon/pull/17492), [Gargron](https://github.com/mastodon/mastodon/pull/17682), [Gargron](https://github.com/mastodon/mastodon/pull/17713))
|
||||
- `category` can be one of: `spam`, `violation`, `other` (default)
|
||||
- `rule_ids` must reference `rules` returned in `GET /api/v1/instance`
|
||||
- Add global `lang` param to REST API ([Gargron](https://github.com/mastodon/mastodon/pull/17464), [Gargron](https://github.com/mastodon/mastodon/pull/17592))
|
||||
- Add `types` param to `GET /api/v1/notifications` in REST API ([Gargron](https://github.com/mastodon/mastodon/pull/17767))
|
||||
- **Add notifications for moderators about new sign-ups** ([Gargron](https://github.com/mastodon/mastodon/pull/16953), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17629))
|
||||
- When a new user confirms e-mail, moderators receive a notification
|
||||
- New notification type:
|
||||
- `admin.sign_up`
|
||||
- Add authentication history ([Gargron](https://github.com/mastodon/mastodon/pull/16408), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/16428), [baby-gnu](https://github.com/mastodon/mastodon/pull/16654))
|
||||
- Add ability to automatically delete old posts ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16529), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17691), [tribela](https://github.com/mastodon/mastodon/pull/16653))
|
||||
- Add ability to pin private posts ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16954), [tribela](https://github.com/mastodon/mastodon/pull/17326), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17304), [MitarashiDango](https://github.com/mastodon/mastodon/pull/17647))
|
||||
- Add ability to filter search results by author using `from:` syntax ([tribela](https://github.com/mastodon/mastodon/pull/16526))
|
||||
- Add ability to delete canonical email blocks in admin UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16644))
|
||||
- Add ability to purge undeliverable domains in admin UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16686), [tribela](https://github.com/mastodon/mastodon/pull/17210), [tribela](https://github.com/mastodon/mastodon/pull/17741), [tribela](https://github.com/mastodon/mastodon/pull/17209))
|
||||
- Add ability to disable e-mail token authentication for specific users in admin UI ([Gargron](https://github.com/mastodon/mastodon/pull/16427))
|
||||
- **Add ability to suspend accounts in batches in admin UI** ([Gargron](https://github.com/mastodon/mastodon/pull/17009), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17301), [Gargron](https://github.com/mastodon/mastodon/pull/17444))
|
||||
- New, redesigned accounts list in admin UI
|
||||
- Batch suspensions are meant to help clean up spam and bot accounts
|
||||
- They do not generate notifications
|
||||
- Add ability to filter reports by origin of target account in admin UI ([Gargron](https://github.com/mastodon/mastodon/pull/16487))
|
||||
- Add support for login through OpenID Connect ([chandrn7](https://github.com/mastodon/mastodon/pull/16221))
|
||||
- Add lazy loading for emoji picker in web UI ([mashirozx](https://github.com/mastodon/mastodon/pull/16907), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17011))
|
||||
- Add single option votes tooltip in polls in web UI ([Brawaru](https://github.com/mastodon/mastodon/pull/16849))
|
||||
- Add confirmation modal when closing media edit modal with unsaved changes in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16518))
|
||||
- Add hint about missing media attachment description in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/17845))
|
||||
- Add support for fetching Create and Announce activities by URI in ActivityPub ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16383))
|
||||
- Add `S3_FORCE_SINGLE_REQUEST` environment variable ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16866))
|
||||
- Add `OMNIAUTH_ONLY` environment variable ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17288), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17345))
|
||||
- Add `ES_USER` and `ES_PASS` environment variables for Elasticsearch authentication ([tribela](https://github.com/mastodon/mastodon/pull/16890))
|
||||
- Add `CAS_SECURITY_ASSUME_EMAIL_IS_VERIFIED` environment variable ([baby-gnu](https://github.com/mastodon/mastodon/pull/16655))
|
||||
- Add ability to pass specific domains to `tootctl accounts cull` ([tribela](https://github.com/mastodon/mastodon/pull/16511))
|
||||
- Add `--by-uri` option to `tootctl domains purge` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16434))
|
||||
- Add `--batch-size` option to `tootctl search deploy` ([aquarla](https://github.com/mastodon/mastodon/pull/17049))
|
||||
- Add `--remove-orphans` option to `tootctl statuses remove` ([noellabo](https://github.com/mastodon/mastodon/pull/17067))
|
||||
|
||||
### Changed
|
||||
|
||||
- Change design of federation pages in admin UI ([Gargron](https://github.com/mastodon/mastodon/pull/17704), [noellabo](https://github.com/mastodon/mastodon/pull/17735), [Gargron](https://github.com/mastodon/mastodon/pull/17765))
|
||||
- Change design of account cards in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/17689))
|
||||
- Change `follow` scope to be covered by `read` and `write` scopes in REST API ([Gargron](https://github.com/mastodon/mastodon/pull/17678))
|
||||
- Change design of authorized applications page ([Gargron](https://github.com/mastodon/mastodon/pull/17656), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17686))
|
||||
- Change e-mail domain blocks to block IPs dynamically ([Gargron](https://github.com/mastodon/mastodon/pull/17635), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17650), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17649))
|
||||
- Change report modal to include category selection in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/17565), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17734), [Gargron](https://github.com/mastodon/mastodon/pull/17654), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17632))
|
||||
- Change reblogs to not count towards hashtag trends anymore ([Gargron](https://github.com/mastodon/mastodon/pull/17501))
|
||||
- Change languages to be listed under standard instead of native name in admin UI ([Gargron](https://github.com/mastodon/mastodon/pull/17485))
|
||||
- Change routing paths to use usernames in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/16171), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/16772), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/16773), [mashirozx](https://github.com/mastodon/mastodon/pull/16793), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17060))
|
||||
- Change list title input design in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17092))
|
||||
- Change "Opt-in to profile directory" preference to be general discoverability preference ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16637))
|
||||
- Change API rate limits to use /64 masking on IPv6 addresses ([tribela](https://github.com/mastodon/mastodon/pull/17588), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17600), [zunda](https://github.com/mastodon/mastodon/pull/17590))
|
||||
- Change allowed formats for locally uploaded custom emojis to include GIF ([rgroothuijsen](https://github.com/mastodon/mastodon/pull/17706), [Gargron](https://github.com/mastodon/mastodon/pull/17759))
|
||||
- Change error message when chosen password is too long ([rgroothuijsen](https://github.com/mastodon/mastodon/pull/17082))
|
||||
- Change minimum required Elasticsearch version from 6 to 7 ([noellabo](https://github.com/mastodon/mastodon/pull/16915))
|
||||
|
||||
### Removed
|
||||
|
||||
- Remove profile directory link from main navigation panel in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/17688))
|
||||
- **Remove language detection through cld3** ([Gargron](https://github.com/mastodon/mastodon/pull/17478), [ykzts](https://github.com/mastodon/mastodon/pull/17539), [Gargron](https://github.com/mastodon/mastodon/pull/17496), [Gargron](https://github.com/mastodon/mastodon/pull/17722))
|
||||
- cld3 is very inaccurate on short-form content even with unique alphabets
|
||||
- Post language can be overriden individually using `language` param
|
||||
- Otherwise, it defaults to the user's interface language
|
||||
- Remove support for `OAUTH_REDIRECT_AT_SIGN_IN` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17287))
|
||||
- Use `OMNIAUTH_ONLY` instead
|
||||
- Remove Keybase integration ([Gargron](https://github.com/mastodon/mastodon/pull/17045))
|
||||
- Remove old columns and indexes ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17245), [Gargron](https://github.com/mastodon/mastodon/pull/16409), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17191))
|
||||
- Remove shortcodes from newly-created media attachments ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16730), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/16763))
|
||||
|
||||
### Deprecated
|
||||
|
||||
- `GET /api/v1/trends` → `GET /api/v1/trends/tags`
|
||||
- OAuth `follow` scope → `read` and/or `write`
|
||||
- `text` attribute on `DELETE /api/v1/statuses/:id` → `GET /api/v1/statuses/:id/source`
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix IDN domains not being rendered correctly in a few left-over places ([Gargron](https://github.com/mastodon/mastodon/pull/17848))
|
||||
- Fix Sanskrit translation not being used in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17820))
|
||||
- Fix Kurdish languages having the wrong language codes ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17812))
|
||||
- Fix pghero making database schema suggestions ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17807))
|
||||
- Fix encoding glitch in the OpenGraph description of a profile page ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17821))
|
||||
- Fix web manifest not permitting PWA usage from alternate domains ([HolgerHuo](https://github.com/mastodon/mastodon/pull/16714))
|
||||
- Fix not being able to edit media attachments for scheduled posts ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17690))
|
||||
- Fix subscribed relay activities being recorded as boosts ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17571))
|
||||
- Fix streaming API server error messages when JSON parsing fails not specifying the source ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17559))
|
||||
- Fix browsers autofilling new password field with old password ([mashirozx](https://github.com/mastodon/mastodon/pull/17702))
|
||||
- Fix text being invisible before fonts load in web UI ([tribela](https://github.com/mastodon/mastodon/pull/16330))
|
||||
- Fix public profile pages of unconfirmed users being accessible ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17385), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17457))
|
||||
- Fix nil error when trying to fetch key for signature verification ([Gargron](https://github.com/mastodon/mastodon/pull/17747))
|
||||
- Fix null values being included in some indexes ([Gargron](https://github.com/mastodon/mastodon/pull/17711))
|
||||
- Fix `POST /api/v1/emails/confirmations` not being available after sign-up ([Gargron](https://github.com/mastodon/mastodon/pull/17743))
|
||||
- Fix rare race condition when reblogged post is deleted ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17693), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17730))
|
||||
- Fix being able to add more than 4 hashtags to hashtag column in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/17729))
|
||||
- Fix data integrity of featured tags ([Gargron](https://github.com/mastodon/mastodon/pull/17712))
|
||||
- Fix performance of account timelines ([Gargron](https://github.com/mastodon/mastodon/pull/17709))
|
||||
- Fix returning empty `<p>` tag for blank account `note` in REST API ([Gargron](https://github.com/mastodon/mastodon/pull/17687))
|
||||
- Fix leak of existence of otherwise inaccessible posts in REST API ([Gargron](https://github.com/mastodon/mastodon/pull/17684))
|
||||
- Fix not showing loading indicator when searching in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/17655))
|
||||
- Fix media modal footer's “external link” not being a link ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17561))
|
||||
- Fix reply button on media modal not giving focus to compose form ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17626))
|
||||
- Fix some media attachments being converted with too high framerates ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17619))
|
||||
- Fix sign in token and warning emails failing to send when contact e-mail address is malformed ([helloworldstack](https://github.com/mastodon/mastodon/pull/17589))
|
||||
- Fix opening the emoji picker scrolling the single-column view to the top ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17579))
|
||||
- Fix edge case where settings/admin page sidebar would be incorrectly hidden ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17580))
|
||||
- Fix performance of server-side filtering ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17575))
|
||||
- Fix privacy policy link not being visible on small screens ([Gargron](https://github.com/mastodon/mastodon/pull/17533))
|
||||
- Fix duplicate accounts when searching by IP range in admin UI ([Gargron](https://github.com/mastodon/mastodon/pull/17524), [tribela](https://github.com/mastodon/mastodon/pull/17150))
|
||||
- Fix error when performing a batch action on posts in admin UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17532))
|
||||
- Fix deletes not being signed in authorized fetch mode ([Gargron](https://github.com/mastodon/mastodon/pull/17484))
|
||||
- Fix Undo Announce sometimes inlining the originally Announced status ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17516))
|
||||
- Fix localization of cold-start follow recommendations ([Gargron](https://github.com/mastodon/mastodon/pull/17479), [Gargron](https://github.com/mastodon/mastodon/pull/17486))
|
||||
- Fix replies collection incorrectly looping ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17462))
|
||||
- Fix errors when multiple Delete are received for a given actor ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17460))
|
||||
- Fixed prototype pollution bug and only allow trusted origin ([r0hanSH](https://github.com/mastodon/mastodon/pull/17420))
|
||||
- Fix text being incorrectly pre-selected in composer textarea on /share ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17339))
|
||||
- Fix SMTP_ENABLE_STARTTLS_AUTO/SMTP_TLS/SMTP_SSL environment variables don't work ([kgtkr](https://github.com/mastodon/mastodon/pull/17216))
|
||||
- Fix media upload specific rate limits only being applied to v1 endpoint in REST API ([tribela](https://github.com/mastodon/mastodon/pull/17272))
|
||||
- Fix media descriptions not being used for client-side filtering ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17206))
|
||||
- Fix cold-start follow recommendation favouring older accounts due to wrong sorting ([noellabo](https://github.com/mastodon/mastodon/pull/17126))
|
||||
- Fix not redirect to the right page after authenticating with WebAuthn ([heguro](https://github.com/mastodon/mastodon/pull/17098))
|
||||
- Fix searching for additional hashtags in hashtag column ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17054))
|
||||
- Fix color of hashtag column settings inputs ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17058))
|
||||
- Fix performance of `tootctl statuses remove` ([noellabo](https://github.com/mastodon/mastodon/pull/17052))
|
||||
- Fix `tootctl accounts cull` not excluding domains on timeouts and certificate issues ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16433))
|
||||
- Fix 404 error when filtering admin action logs by non-existent target account ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16643))
|
||||
- Fix error when accessing streaming API without any OAuth scopes ([Brawaru](https://github.com/mastodon/mastodon/pull/16823))
|
||||
- Fix follow request count not updating when new follow requests arrive over streaming API in web UI ([matildepark](https://github.com/mastodon/mastodon/pull/16652))
|
||||
- Fix error when unsuspending a local account ([HolgerHuo](https://github.com/mastodon/mastodon/pull/16605))
|
||||
- Fix crash when a notification contains a not yet processed media attachment in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16573))
|
||||
- Fix wrong color of download button in audio player in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16572))
|
||||
- Fix notes for others accounts not being deleted when an account is deleted ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16579))
|
||||
- Fix error when logging occurrence of unsupported video file ([noellabo](https://github.com/mastodon/mastodon/pull/16581))
|
||||
- Fix wrong elements in trends widget being hidden on smaller screens in web UI ([tribela](https://github.com/mastodon/mastodon/pull/16570))
|
||||
- Fix link to about page being displayed in limited federation mode ([weex](https://github.com/mastodon/mastodon/pull/16432))
|
||||
- Fix styling of boost button in media modal not reflecting ability to boost ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16387))
|
||||
- Fix OCR failure when erroneous lang data is in cache ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16386))
|
||||
- Fix downloading media from blocked domains in `tootctl media refresh` ([tribela](https://github.com/mastodon/mastodon/pull/16914))
|
||||
- Fix login form being displayed on landing page when already logged in ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17348))
|
||||
- Fix polling for media processing status too frequently in web UI ([tribela](https://github.com/mastodon/mastodon/pull/17271))
|
||||
- Fix hashtag autocomplete overriding user-typed case ([weex](https://github.com/mastodon/mastodon/pull/16460))
|
||||
- Fix WebAuthn authentication setup to not prompt for PIN ([truongnmt](https://github.com/mastodon/mastodon/pull/16545))
|
||||
|
||||
### Security
|
||||
|
||||
- Fix being able to post URLs longer than 4096 characters ([Gargron](https://github.com/mastodon/mastodon/pull/17908))
|
||||
- Fix being able to bypass e-mail restrictions ([Gargron](https://github.com/mastodon/mastodon/pull/17909))
|
||||
|
||||
## [3.4.6] - 2022-02-03
|
||||
### Fixed
|
||||
|
||||
- Fix `mastodon:webpush:generate_vapid_key` task requiring a functional environment ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17338))
|
||||
- Fix spurious errors when receiving an Add activity for a private post ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17425))
|
||||
|
||||
### Security
|
||||
|
||||
- Fix error-prone SQL queries ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/15828))
|
||||
- Fix not compacting incoming signed JSON-LD activities ([puckipedia](https://github.com/mastodon/mastodon/pull/17426), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17428)) (CVE-2022-24307)
|
||||
- Fix insufficient sanitization of report comments ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17430))
|
||||
- Fix stop condition of a Common Table Expression ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17427))
|
||||
- Disable legacy XSS filtering ([Wonderfall](https://github.com/mastodon/mastodon/pull/17289))
|
||||
|
||||
## [3.4.5] - 2022-01-31
|
||||
### Added
|
||||
|
||||
- Add more advanced migration tests ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17393))
|
||||
- Add github workflow to build Docker images ([unasuke](https://github.com/mastodon/mastodon/pull/16973), [Gargron](https://github.com/mastodon/mastodon/pull/16980), [Gargron](https://github.com/mastodon/mastodon/pull/17000))
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix some old migrations failing when skipping releases ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17394))
|
||||
- Fix migrations script failing in certain edge cases ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17398))
|
||||
- Fix Docker build ([tribela](https://github.com/mastodon/mastodon/pull/17188))
|
||||
- Fix Ruby 3.0 dependencies ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16723))
|
||||
- Fix followers synchronization mechanism ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16510))
|
||||
|
||||
## [3.4.4] - 2021-11-26
|
||||
### Fixed
|
||||
|
||||
- Fix error when suspending user with an already blocked canonical email ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17036))
|
||||
- Fix overflow of long profile fields in admin UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17010))
|
||||
- Fix confusing error when WebFinger request returns empty document ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16986))
|
||||
- Fix upload of remote media with OpenStack Swift sometimes failing ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16998))
|
||||
- Fix logout link not working in Safari ([noellabo](https://github.com/mastodon/mastodon/pull/16574))
|
||||
- Fix “open” link of media modal not closing modal in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16524))
|
||||
- Fix replying from modal in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16516))
|
||||
- Fix `mastodon:setup` command crashing in some circumstances ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16976))
|
||||
|
||||
### Security
|
||||
|
||||
- Fix filtering DMs from non-followed users ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17042))
|
||||
- Fix handling of recursive toots in WebUI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17041))
|
||||
|
||||
## [3.4.3] - 2021-11-06
|
||||
### Fixed
|
||||
|
||||
- Fix login being broken due to inaccurately applied backport fix in 3.4.2 ([Gargron](https://github.com/mastodon/mastodon/commit/5c47a18c8df3231aa25c6d1f140a71a7fac9cbf9))
|
||||
|
||||
## [3.4.2] - 2021-11-06
|
||||
### Added
|
||||
|
||||
- Add `configuration` attribute to `GET /api/v1/instance` ([Gargron](https://github.com/mastodon/mastodon/pull/16485))
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix handling of back button with modal windows in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16499))
|
||||
- Fix pop-in player when author has long username in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16468))
|
||||
- Fix crash when a status with a playing video gets deleted in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16384))
|
||||
- Fix crash with Microsoft Translate in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16525))
|
||||
- Fix PWA not being usable from alternate domains ([HolgerHuo](https://github.com/mastodon/mastodon/pull/16714))
|
||||
- Fix locale-specific number rounding errors ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16469))
|
||||
- Fix scheduling a status decreasing status count ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16791))
|
||||
- Fix user's canonical email address being blocked when user deletes own account ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16503))
|
||||
- Fix not being able to suspend users that already have their canonical e-mail blocked ([Gargron](https://github.com/mastodon/mastodon/pull/16455))
|
||||
- Fix anonymous access to outbox not being cached by the reverse proxy ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16458))
|
||||
- Fix followers synchronization mechanism not working when URI has empty path ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16744))
|
||||
- Fix serialization of counts in REST API when user hides their network ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16418))
|
||||
- Fix inefficiencies in auto-linking code ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16506))
|
||||
- Fix `tootctl self-destruct` not sending delete activities for recently-suspended accounts ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16688))
|
||||
- Fix suspicious sign-in e-mail text being out of date ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16690))
|
||||
- Fix some frameworks being unnecessarily loaded ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16725))
|
||||
- Fix canonical e-mail blocks missing foreign key constraints ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16448))
|
||||
- Fix inconsistent order on account's statuses page in admin UI ([tribela](https://github.com/mastodon/mastodon/pull/16937))
|
||||
- Fix media from blocked domains being redownloaded by `tootctl media refresh` ([tribela](https://github.com/mastodon/mastodon/pull/16914))
|
||||
- Fix `mastodon:setup` generated env-file syntax ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16896))
|
||||
- Fix link previews being incorrectly generated from earlier links ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16885))
|
||||
- Fix wrong `to`/`cc` values for remote groups in ActivityPub ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16700))
|
||||
- Fix mentions with non-ascii TLDs not being processed ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16689))
|
||||
- Fix authentication failures halfway through a sign-in attempt ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16607), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/16792))
|
||||
- Fix suspended accounts statuses being merged back into timelines ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16628))
|
||||
- Fix crash when encountering invalid account fields ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16598))
|
||||
- Fix invalid blurhash handling for remote activities ([noellabo](https://github.com/mastodon/mastodon/pull/16583))
|
||||
- Fix newlines being added to account notes when an account moves ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16415), [noellabo](https://github.com/mastodon/mastodon/pull/16576))
|
||||
- Fix crash when creating an announcement with links ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16941))
|
||||
- Fix logging out from one browser logging out all other sessions ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16943))
|
||||
|
||||
### Security
|
||||
|
||||
- Fix user notes not having a length limit ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16942))
|
||||
- Fix revoking a specific session not working ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16943))
|
||||
|
||||
## [3.4.1] - 2021-06-03
|
||||
### Added
|
||||
|
||||
|
@ -761,7 +327,7 @@ All notable changes to this project will be documented in this file.
|
|||
- Fix inefficiency when fetching bookmarks ([akihikodaki](https://github.com/mastodon/mastodon/pull/14674))
|
||||
- Fix inefficiency when fetching favourites ([akihikodaki](https://github.com/mastodon/mastodon/pull/14673))
|
||||
- Fix inefficiency when fetching media-only account timeline ([akihikodaki](https://github.com/mastodon/mastodon/pull/14675))
|
||||
- Fix inefficiency when deleting accounts ([Gargron](https://github.com/mastodon/mastodon/pull/15387), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/15409), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/15407), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/15408), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/15402), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/15416), [Gargron](https://github.com/mastodon/mastodon/pull/15421))
|
||||
- Fix inefficieny when deleting accounts ([Gargron](https://github.com/mastodon/mastodon/pull/15387), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/15409), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/15407), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/15408), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/15402), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/15416), [Gargron](https://github.com/mastodon/mastodon/pull/15421))
|
||||
- Fix redundant query when processing batch actions on custom emojis ([niwatori24](https://github.com/mastodon/mastodon/pull/14534))
|
||||
- Fix slow distinct queries where grouped queries are faster ([Gargron](https://github.com/mastodon/mastodon/pull/15287))
|
||||
- Fix performance on instances list in admin UI ([Gargron](https://github.com/mastodon/mastodon/pull/15282))
|
||||
|
@ -848,7 +414,7 @@ All notable changes to this project will be documented in this file.
|
|||
- Add blurhash to link previews ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/13984), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/14143), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/13985), [Sasha-Sorokin](https://github.com/mastodon/mastodon/pull/14267), [Sasha-Sorokin](https://github.com/mastodon/mastodon/pull/14278), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/14126), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/14261), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/14260))
|
||||
- In web UI, toots cannot be marked as sensitive unless there is media attached
|
||||
- However, it's possible to do via API or ActivityPub
|
||||
- Thumbnails of link previews of such posts now use blurhash in web UI
|
||||
- Thumnails of link previews of such posts now use blurhash in web UI
|
||||
- The Card entity in REST API has a new `blurhash` attribute
|
||||
- Add support for `summary` field for media description in ActivityPub ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/13763))
|
||||
- Add hints about incomplete remote content to web UI ([Gargron](https://github.com/mastodon/mastodon/pull/14031), [noellabo](https://github.com/mastodon/mastodon/pull/14195))
|
||||
|
@ -871,7 +437,7 @@ All notable changes to this project will be documented in this file.
|
|||
- The `meta` attribute on the Media Attachment entity in REST API can now have a `colors` attribute which in turn contains three hex colors: `background`, `foreground`, and `accent`
|
||||
- The background color is chosen from the most dominant color around the edges of the thumbnail
|
||||
- The foreground and accent colors are chosen from the colors that are the most different from the background color using the CIEDE2000 algorithm
|
||||
- The most saturated color of the two is designated as the accent color
|
||||
- The most satured color of the two is designated as the accent color
|
||||
- The one with the highest W3C contrast is designated as the foreground color
|
||||
- If there are not enough colors in the thumbnail, new ones are generated using a monochrome pattern
|
||||
- Add a visibility indicator to toots in web UI ([noellabo](https://github.com/mastodon/mastodon/pull/14123), [highemerly](https://github.com/mastodon/mastodon/pull/14292))
|
||||
|
@ -897,7 +463,7 @@ All notable changes to this project will be documented in this file.
|
|||
- Change boost button to no longer serve as visibility indicator in web UI ([noellabo](https://github.com/mastodon/mastodon/pull/14132), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/14373))
|
||||
- Change contrast of flash messages ([cchoi12](https://github.com/mastodon/mastodon/pull/13892))
|
||||
- Change wording from "Hide media" to "Hide image/images" in web UI ([ariasuni](https://github.com/mastodon/mastodon/pull/13834))
|
||||
- Change appearance of settings pages to be more consistent ([ariasuni](https://github.com/mastodon/mastodon/pull/13938))
|
||||
- Change appearence of settings pages to be more consistent ([ariasuni](https://github.com/mastodon/mastodon/pull/13938))
|
||||
- Change "Add media" tooltip to not include long list of formats in web UI ([ariasuni](https://github.com/mastodon/mastodon/pull/13954))
|
||||
- Change how badly contrasting emoji are rendered in web UI ([leo60228](https://github.com/mastodon/mastodon/pull/13773), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/13772), [mfmfuyu](https://github.com/mastodon/mastodon/pull/14020), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/14015))
|
||||
- Change structure of unavailable content section on about page ([ariasuni](https://github.com/mastodon/mastodon/pull/13930))
|
||||
|
@ -913,14 +479,14 @@ All notable changes to this project will be documented in this file.
|
|||
- `EMAIL_DOMAIN_WHITELIST` → `EMAIL_DOMAIN_ALLOWLIST`
|
||||
- CLI option changed:
|
||||
- `tootctl domains purge --whitelist-mode` → `tootctl domains purge --limited-federation-mode`
|
||||
- Remove some unnecessary database indexes ([lfuelling](https://github.com/mastodon/mastodon/pull/13695), [noellabo](https://github.com/mastodon/mastodon/pull/14259))
|
||||
- Remove some unnecessary database indices ([lfuelling](https://github.com/mastodon/mastodon/pull/13695), [noellabo](https://github.com/mastodon/mastodon/pull/14259))
|
||||
- Remove unnecessary Node.js version upper bound ([ykzts](https://github.com/mastodon/mastodon/pull/14139))
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix `following` param not working when exact match is found in account search ([noellabo](https://github.com/mastodon/mastodon/pull/14394))
|
||||
- Fix sometimes occurring duplicate mention notifications ([noellabo](https://github.com/mastodon/mastodon/pull/14378))
|
||||
- Fix RSS feeds not being cacheable ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/14368))
|
||||
- Fix sometimes occuring duplicate mention notifications ([noellabo](https://github.com/mastodon/mastodon/pull/14378))
|
||||
- Fix RSS feeds not being cachable ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/14368))
|
||||
- Fix lack of locking around processing of Announce activities in ActivityPub ([noellabo](https://github.com/mastodon/mastodon/pull/14365))
|
||||
- Fix boosted toots from blocked account not being retroactively removed from TL ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/14339))
|
||||
- Fix large shortened numbers (like 1.2K) using incorrect pluralization ([Sasha-Sorokin](https://github.com/mastodon/mastodon/pull/14061))
|
||||
|
@ -932,7 +498,7 @@ All notable changes to this project will be documented in this file.
|
|||
- Fix new posts pushing down origin of opened dropdown in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/14271), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/14348))
|
||||
- Fix timeline markers not being saved sometimes ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/13887), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/13889), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/14155))
|
||||
- Fix CSV uploads being rejected ([noellabo](https://github.com/mastodon/mastodon/pull/13835))
|
||||
- Fix incompatibility with Elasticsearch 7.x ([noellabo](https://github.com/mastodon/mastodon/pull/13828))
|
||||
- Fix incompatibility with ElasticSearch 7.x ([noellabo](https://github.com/mastodon/mastodon/pull/13828))
|
||||
- Fix being able to search posts where you're in the target audience but not actively mentioned ([noellabo](https://github.com/mastodon/mastodon/pull/13829))
|
||||
- Fix non-local posts appearing on local-only hashtag timelines in web UI ([noellabo](https://github.com/mastodon/mastodon/pull/13827))
|
||||
- Fix `tootctl media remove-orphans` choking on unknown files in storage ([Gargron](https://github.com/mastodon/mastodon/pull/13765))
|
||||
|
@ -1047,7 +613,7 @@ All notable changes to this project will be documented in this file.
|
|||
- Fix poll refresh button not being debounced in web UI ([rasjonell](https://github.com/mastodon/mastodon/pull/13485), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/13490))
|
||||
- Fix confusing error when failing to add an alias to an unknown account ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/13480))
|
||||
- Fix "Email changed" notification sometimes having wrong e-mail ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/13475))
|
||||
- Fix various issues on the account aliases page ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/13452))
|
||||
- Fix varioues issues on the account aliases page ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/13452))
|
||||
- Fix API footer link in web UI ([bubblineyuri](https://github.com/mastodon/mastodon/pull/13441))
|
||||
- Fix pagination of following, followers, follow requests, blocks and mutes lists in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/13445))
|
||||
- Fix styling of polls in JS-less fallback on public pages ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/13436))
|
||||
|
@ -1536,7 +1102,7 @@ All notable changes to this project will be documented in this file.
|
|||
- Fix URLs appearing twice in errors of ActivityPub::DeliveryWorker ([Gargron](https://github.com/mastodon/mastodon/pull/11231))
|
||||
- Fix support for HTTP proxies ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/11245))
|
||||
- Fix HTTP requests to IPv6 hosts ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/11240))
|
||||
- Fix error in Elasticsearch index import ([mayaeh](https://github.com/mastodon/mastodon/pull/11192))
|
||||
- Fix error in ElasticSearch index import ([mayaeh](https://github.com/mastodon/mastodon/pull/11192))
|
||||
- Fix duplicate account error when seeding development database ([ysksn](https://github.com/mastodon/mastodon/pull/11366))
|
||||
- Fix performance of session clean-up scheduler ([abcang](https://github.com/mastodon/mastodon/pull/11871))
|
||||
- Fix older migrations not running ([zunda](https://github.com/mastodon/mastodon/pull/11377))
|
||||
|
@ -1546,8 +1112,8 @@ All notable changes to this project will be documented in this file.
|
|||
- Fix muted text color not applying to all text ([trwnh](https://github.com/mastodon/mastodon/pull/11996))
|
||||
- Fix follower/following lists resetting on back-navigation in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/11986))
|
||||
- Fix n+1 query when approving multiple follow requests ([abcang](https://github.com/mastodon/mastodon/pull/12004))
|
||||
- Fix records not being indexed into Elasticsearch sometimes ([Gargron](https://github.com/mastodon/mastodon/pull/12024))
|
||||
- Fix needlessly indexing unsearchable statuses into Elasticsearch ([Gargron](https://github.com/mastodon/mastodon/pull/12041))
|
||||
- Fix records not being indexed into ElasticSearch sometimes ([Gargron](https://github.com/mastodon/mastodon/pull/12024))
|
||||
- Fix needlessly indexing unsearchable statuses into ElasticSearch ([Gargron](https://github.com/mastodon/mastodon/pull/12041))
|
||||
- Fix new user bootstrapping crashing when to-be-followed accounts are invalid ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/12037))
|
||||
- Fix featured hashtag URL being interpreted as media or replies tab ([Gargron](https://github.com/mastodon/mastodon/pull/12048))
|
||||
- Fix account counters being overwritten by parallel writes ([Gargron](https://github.com/mastodon/mastodon/pull/12045))
|
||||
|
@ -1837,7 +1403,7 @@ All notable changes to this project will be documented in this file.
|
|||
- Change Docker image to use Ubuntu with jemalloc ([Sir-Boops](https://github.com/mastodon/mastodon/pull/10100), [BenLubar](https://github.com/mastodon/mastodon/pull/10212))
|
||||
- Change public pages to be cacheable by proxies ([BenLubar](https://github.com/mastodon/mastodon/pull/9059))
|
||||
- Change the 410 gone response for suspended accounts to be cacheable by proxies ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/10339))
|
||||
- Change web UI to not empty timeline of blocked users on block ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/10359))
|
||||
- Change web UI to not not empty timeline of blocked users on block ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/10359))
|
||||
- Change JSON serializer to remove unused `@context` values ([Gargron](https://github.com/mastodon/mastodon/pull/10378))
|
||||
- Change GIFV file size limit to be the same as for other videos ([rinsuki](https://github.com/mastodon/mastodon/pull/9924))
|
||||
- Change Webpack to not use @babel/preset-env to compile node_modules ([ykzts](https://github.com/mastodon/mastodon/pull/10289))
|
||||
|
@ -2014,7 +1580,7 @@ All notable changes to this project will be documented in this file.
|
|||
- Limit maximum visibility of local silenced users to unlisted ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/9583))
|
||||
- Change API error message for unconfirmed accounts ([noellabo](https://github.com/mastodon/mastodon/pull/9625))
|
||||
- Change the icon to "reply-all" when it's a reply to other accounts ([mayaeh](https://github.com/mastodon/mastodon/pull/9378))
|
||||
- Do not ignore federated reports targeting already-reported accounts ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/9534))
|
||||
- Do not ignore federated reports targetting already-reported accounts ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/9534))
|
||||
- Upgrade default Ruby version to 2.6.0 ([Gargron](https://github.com/mastodon/mastodon/pull/9688))
|
||||
- Change e-mail digest frequency ([Gargron](https://github.com/mastodon/mastodon/pull/9689))
|
||||
- Change Docker images for Tor support in docker-compose.yml ([Sir-Boops](https://github.com/mastodon/mastodon/pull/9438))
|
||||
|
|
26
Dockerfile
26
Dockerfile
|
@ -2,10 +2,9 @@ FROM ubuntu:20.04 as build-dep
|
|||
|
||||
# Use bash for the shell
|
||||
SHELL ["/bin/bash", "-c"]
|
||||
RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
|
||||
|
||||
# Install Node v16 (LTS)
|
||||
ENV NODE_VER="16.14.2"
|
||||
# Install Node v14 (LTS)
|
||||
ENV NODE_VER="14.17.6"
|
||||
RUN ARCH= && \
|
||||
dpkgArch="$(dpkg --print-architecture)" && \
|
||||
case "${dpkgArch##*-}" in \
|
||||
|
@ -19,15 +18,15 @@ RUN ARCH= && \
|
|||
esac && \
|
||||
echo "Etc/UTC" > /etc/localtime && \
|
||||
apt-get update && \
|
||||
apt-get install -y --no-install-recommends ca-certificates wget python apt-utils && \
|
||||
apt-get install -y --no-install-recommends ca-certificates wget python && \
|
||||
cd ~ && \
|
||||
wget -q https://nodejs.org/download/release/v$NODE_VER/node-v$NODE_VER-linux-$ARCH.tar.gz && \
|
||||
tar xf node-v$NODE_VER-linux-$ARCH.tar.gz && \
|
||||
rm node-v$NODE_VER-linux-$ARCH.tar.gz && \
|
||||
mv node-v$NODE_VER-linux-$ARCH /opt/node
|
||||
|
||||
# Install Ruby 3.0
|
||||
ENV RUBY_VER="3.0.3"
|
||||
# Install Ruby
|
||||
ENV RUBY_VER="2.7.4"
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends build-essential \
|
||||
bison libyaml-dev libgdbm-dev libreadline-dev libjemalloc-dev \
|
||||
|
@ -46,19 +45,17 @@ RUN apt-get update && \
|
|||
|
||||
ENV PATH="${PATH}:/opt/ruby/bin:/opt/node/bin"
|
||||
|
||||
RUN npm install -g npm@latest && \
|
||||
npm install -g yarn && \
|
||||
RUN npm install -g yarn && \
|
||||
gem install bundler && \
|
||||
apt-get update && \
|
||||
apt-get install -y --no-install-recommends git libicu-dev libidn11-dev \
|
||||
libpq-dev shared-mime-info
|
||||
libpq-dev libprotobuf-dev protobuf-compiler shared-mime-info
|
||||
|
||||
COPY Gemfile* package.json yarn.lock /opt/mastodon/
|
||||
|
||||
RUN cd /opt/mastodon && \
|
||||
bundle config set --local deployment 'true' && \
|
||||
bundle config set --local without 'development test' && \
|
||||
bundle config set silence_root_warning true && \
|
||||
bundle config set deployment 'true' && \
|
||||
bundle config set without 'development test' && \
|
||||
bundle install -j"$(nproc)" && \
|
||||
yarn install --pure-lockfile
|
||||
|
||||
|
@ -84,12 +81,11 @@ RUN apt-get update && \
|
|||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install mastodon runtime deps
|
||||
RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
|
||||
RUN apt-get update && \
|
||||
apt-get -y --no-install-recommends install \
|
||||
libssl1.1 libpq5 imagemagick ffmpeg libjemalloc2 \
|
||||
libicu66 libidn11 libyaml-0-2 \
|
||||
file ca-certificates tzdata libreadline8 gcc tini apt-utils && \
|
||||
libicu66 libprotobuf17 libidn11 libyaml-0-2 \
|
||||
file ca-certificates tzdata libreadline8 gcc tini && \
|
||||
ln -s /opt/mastodon /mastodon && \
|
||||
gem install bundler && \
|
||||
rm -rf /var/cache && \
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
## ActivityPub federation in Mastodon
|
||||
|
||||
Mastodon largely follows the ActivityPub server-to-server specification but it makes uses of some non-standard extensions, some of which are required for interacting with Mastodon at all.
|
||||
|
||||
Supported vocabulary: https://docs.joinmastodon.org/spec/activitypub/
|
||||
|
||||
### Required extensions
|
||||
|
||||
#### Webfinger
|
||||
|
||||
In Mastodon, users are identified by a `username` and `domain` pair (e.g., `Gargron@mastodon.social`).
|
||||
This is used both for discovery and for unambiguously mentioning users across the fediverse. Furthermore, this is part of Mastodon's database design from its very beginnings.
|
||||
|
||||
As a result, Mastodon requires that each ActivityPub actor uniquely maps back to an `acct:` URI that can be resolved via WebFinger.
|
||||
|
||||
More information and examples are available at: https://docs.joinmastodon.org/spec/webfinger/
|
||||
|
||||
#### HTTP Signatures
|
||||
|
||||
In order to authenticate activities, Mastodon relies on HTTP Signatures, signing every `POST` and `GET` request to other ActivityPub implementations on behalf of the user authoring an activity (for `POST` requests) or an actor representing the Mastodon server itself (for most `GET` requests).
|
||||
|
||||
Mastodon requires all `POST` requests to be signed, and MAY require `GET` requests to be signed, depending on the configuration of the Mastodon server.
|
||||
|
||||
More information on HTTP Signatures, as well as examples, can be found here: https://docs.joinmastodon.org/spec/security/#http
|
||||
|
||||
### Optional extensions
|
||||
|
||||
- Linked-Data Signatures: https://docs.joinmastodon.org/spec/security/#ld
|
||||
- Bearcaps: https://docs.joinmastodon.org/spec/bearcaps/
|
||||
- Followers collection synchronization: https://git.activitypub.dev/ActivityPubDev/Fediverse-Enhancement-Proposals/src/branch/main/feps/fep-8fcf.md
|
86
Gemfile
86
Gemfile
|
@ -1,35 +1,36 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
source 'https://rubygems.org'
|
||||
ruby '>= 2.6.0', '< 3.1.0'
|
||||
ruby '>= 2.5.0', '< 3.1.0'
|
||||
|
||||
gem 'pkg-config', '~> 1.4'
|
||||
gem 'rexml', '~> 3.2'
|
||||
|
||||
gem 'puma', '~> 5.6'
|
||||
gem 'rails', '~> 6.1.6'
|
||||
gem 'puma', '~> 5.4'
|
||||
gem 'rails', '~> 6.1.4'
|
||||
gem 'sprockets', '~> 3.7.2'
|
||||
gem 'thor', '~> 1.2'
|
||||
gem 'thor', '~> 1.1'
|
||||
gem 'rack', '~> 2.2.3'
|
||||
|
||||
gem 'hamlit-rails', '~> 0.2'
|
||||
gem 'pg', '~> 1.3'
|
||||
gem 'pg', '~> 1.2'
|
||||
gem 'makara', '~> 0.5'
|
||||
gem 'pghero', '~> 2.8'
|
||||
gem 'dotenv-rails', '~> 2.7'
|
||||
|
||||
gem 'aws-sdk-s3', '~> 1.114', require: false
|
||||
gem 'aws-sdk-s3', '~> 1.103', require: false
|
||||
gem 'fog-core', '<= 2.1.0'
|
||||
gem 'fog-openstack', '~> 0.3', require: false
|
||||
gem 'kt-paperclip', '~> 7.1'
|
||||
gem 'kt-paperclip', '~> 7.0'
|
||||
gem 'blurhash', '~> 0.1'
|
||||
|
||||
gem 'active_model_serializers', '~> 0.10'
|
||||
gem 'addressable', '~> 2.8'
|
||||
gem 'bootsnap', '~> 1.11.1', require: false
|
||||
gem 'bootsnap', '~> 1.9.1', require: false
|
||||
gem 'browser'
|
||||
gem 'charlock_holmes', '~> 0.7.7'
|
||||
gem 'chewy', '~> 7.2'
|
||||
gem 'iso-639'
|
||||
gem 'chewy', '~> 5.2'
|
||||
gem 'cld3', '~> 3.4.2'
|
||||
gem 'devise', '~> 4.8'
|
||||
gem 'devise-two-factor', '~> 4.0'
|
||||
|
||||
|
@ -40,14 +41,13 @@ end
|
|||
gem 'net-ldap', '~> 0.17'
|
||||
gem 'omniauth-cas', '~> 2.0'
|
||||
gem 'omniauth-saml', '~> 1.10'
|
||||
gem 'gitlab-omniauth-openid-connect', '~>0.9.1', require: 'omniauth_openid_connect'
|
||||
gem 'omniauth', '~> 1.9'
|
||||
gem 'omniauth-rails_csrf_protection', '~> 0.1'
|
||||
|
||||
gem 'color_diff', '~> 0.1'
|
||||
gem 'discard', '~> 1.2'
|
||||
gem 'doorkeeper', '~> 5.5'
|
||||
gem 'ed25519', '~> 1.3'
|
||||
gem 'ed25519', '~> 1.2'
|
||||
gem 'fast_blank', '~> 1.0'
|
||||
gem 'fastimage'
|
||||
gem 'hiredis', '~> 0.6'
|
||||
|
@ -59,54 +59,55 @@ gem 'httplog', '~> 1.5.0'
|
|||
gem 'idn-ruby', require: 'idn'
|
||||
gem 'kaminari', '~> 1.2'
|
||||
gem 'link_header', '~> 0.0'
|
||||
gem 'mime-types', '~> 3.4.1', require: 'mime/types/columnar'
|
||||
gem 'nokogiri', '~> 1.13'
|
||||
gem 'mime-types', '~> 3.3.1', require: 'mime/types/columnar'
|
||||
gem 'nokogiri', '~> 1.12'
|
||||
gem 'nsa', '~> 0.2'
|
||||
gem 'oj', '~> 3.13'
|
||||
gem 'ox', '~> 2.14'
|
||||
gem 'parslet'
|
||||
gem 'parallel', '~> 1.21'
|
||||
gem 'posix-spawn'
|
||||
gem 'pundit', '~> 2.2'
|
||||
gem 'pundit', '~> 2.1'
|
||||
gem 'premailer-rails'
|
||||
gem 'rack-attack', '~> 6.6'
|
||||
gem 'rack-attack', '~> 6.5'
|
||||
gem 'rack-cors', '~> 1.1', require: 'rack/cors'
|
||||
gem 'rails-i18n', '~> 6.0'
|
||||
gem 'rails-settings-cached', '~> 0.6'
|
||||
gem 'redis', '~> 4.5', require: ['redis', 'redis/connection/hiredis']
|
||||
gem 'redis', '~> 4.4', require: ['redis', 'redis/connection/hiredis']
|
||||
gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock'
|
||||
gem 'rqrcode', '~> 2.1'
|
||||
gem 'ruby-progressbar', '~> 1.11'
|
||||
gem 'sanitize', '~> 6.0'
|
||||
gem 'scenic', '~> 1.6'
|
||||
gem 'sidekiq', '~> 6.4'
|
||||
gem 'sidekiq-scheduler', '~> 4.0'
|
||||
gem 'scenic', '~> 1.5'
|
||||
gem 'sidekiq', '~> 6.2'
|
||||
gem 'sidekiq-scheduler', '~> 3.1'
|
||||
gem 'sidekiq-unique-jobs', '~> 7.1'
|
||||
gem 'sidekiq-bulk', '~> 0.2.0'
|
||||
gem 'sidekiq-bulk', '~>0.2.0'
|
||||
gem 'simple-navigation', '~> 4.3'
|
||||
gem 'simple_form', '~> 5.1'
|
||||
gem 'sprockets-rails', '~> 3.4', require: 'sprockets/railtie'
|
||||
gem 'stoplight', '~> 3.0.0'
|
||||
gem 'sprockets-rails', '~> 3.2', require: 'sprockets/railtie'
|
||||
gem 'stoplight', '~> 2.2.1'
|
||||
gem 'strong_migrations', '~> 0.7'
|
||||
gem 'tty-prompt', '~> 0.23', require: false
|
||||
gem 'twitter-text', '~> 3.1.0'
|
||||
gem 'tzinfo-data', '~> 1.2022'
|
||||
gem 'tzinfo-data', '~> 1.2021'
|
||||
gem 'webpacker', '~> 5.4'
|
||||
gem 'webpush', '~> 0.3'
|
||||
gem 'webauthn', '~> 3.0.0.alpha1'
|
||||
|
||||
gem 'json-ld'
|
||||
gem 'json-ld-preloaded', '~> 3.2'
|
||||
gem 'rdf-normalize', '~> 0.5'
|
||||
gem 'json-ld-preloaded', '~> 3.1'
|
||||
gem 'rdf-normalize', '~> 0.4'
|
||||
|
||||
gem 'redcarpet', '~> 3.5'
|
||||
|
||||
group :development, :test do
|
||||
gem 'fabrication', '~> 2.28'
|
||||
gem 'fabrication', '~> 2.22'
|
||||
gem 'fuubar', '~> 2.5'
|
||||
gem 'i18n-tasks', '~> 1.0', require: false
|
||||
gem 'i18n-tasks', '~> 0.9', require: false
|
||||
gem 'pry-byebug', '~> 3.9'
|
||||
gem 'pry-rails', '~> 0.3'
|
||||
gem 'rspec-rails', '~> 5.1'
|
||||
gem 'rspec-rails', '~> 5.0'
|
||||
end
|
||||
|
||||
group :production, :test do
|
||||
|
@ -114,32 +115,33 @@ group :production, :test do
|
|||
end
|
||||
|
||||
group :test do
|
||||
gem 'capybara', '~> 3.37'
|
||||
gem 'capybara', '~> 3.35'
|
||||
gem 'climate_control', '~> 0.2'
|
||||
gem 'faker', '~> 2.21'
|
||||
gem 'faker', '~> 2.19'
|
||||
gem 'microformats', '~> 4.2'
|
||||
gem 'rails-controller-testing', '~> 1.0'
|
||||
gem 'rspec-sidekiq', '~> 3.1'
|
||||
gem 'simplecov', '~> 0.21', require: false
|
||||
gem 'webmock', '~> 3.14'
|
||||
gem 'rspec_junit_formatter', '~> 0.5'
|
||||
gem 'parallel_tests', '~> 3.7'
|
||||
gem 'rspec_junit_formatter', '~> 0.4'
|
||||
end
|
||||
|
||||
group :development do
|
||||
gem 'active_record_query_trace', '~> 1.8'
|
||||
gem 'annotate', '~> 3.2'
|
||||
gem 'annotate', '~> 3.1'
|
||||
gem 'better_errors', '~> 2.9'
|
||||
gem 'binding_of_caller', '~> 1.0'
|
||||
gem 'bullet', '~> 7.0'
|
||||
gem 'letter_opener', '~> 1.8'
|
||||
gem 'letter_opener_web', '~> 2.0'
|
||||
gem 'bullet', '~> 6.1'
|
||||
gem 'letter_opener', '~> 1.7'
|
||||
gem 'letter_opener_web', '~> 1.4'
|
||||
gem 'memory_profiler'
|
||||
gem 'rubocop', '~> 1.29', require: false
|
||||
gem 'rubocop-rails', '~> 2.14', require: false
|
||||
gem 'brakeman', '~> 5.2', require: false
|
||||
gem 'rubocop', '~> 1.21', require: false
|
||||
gem 'rubocop-rails', '~> 2.12', require: false
|
||||
gem 'brakeman', '~> 5.1', require: false
|
||||
gem 'bundler-audit', '~> 0.9', require: false
|
||||
|
||||
gem 'capistrano', '~> 3.17'
|
||||
gem 'capistrano', '~> 3.16'
|
||||
gem 'capistrano-rails', '~> 1.6'
|
||||
gem 'capistrano-rbenv', '~> 2.2'
|
||||
gem 'capistrano-yarn', '~> 2.0'
|
||||
|
@ -148,12 +150,10 @@ group :development do
|
|||
end
|
||||
|
||||
group :production do
|
||||
gem 'lograge', '~> 0.12'
|
||||
gem 'lograge', '~> 0.11'
|
||||
end
|
||||
|
||||
gem 'concurrent-ruby', require: false
|
||||
gem 'connection_pool', require: false
|
||||
|
||||
gem 'xorcist', '~> 1.1'
|
||||
|
||||
gem 'hcaptcha', '~> 7.1'
|
||||
|
|
580
Gemfile.lock
580
Gemfile.lock
File diff suppressed because it is too large
Load Diff
19
SECURITY.md
19
SECURITY.md
|
@ -1,20 +1,13 @@
|
|||
# Security Policy
|
||||
|
||||
If you believe you've identified a security vulnerability in Mastodon (a bug that allows something to happen that shouldn't be possible), you should submit the report through our [Bug Bounty Program][bug-bounty]. Alternatively, you can reach us at <hello@joinmastodon.org>.
|
||||
|
||||
You should *not* report such issues on GitHub or in other public spaces to give us time to publish a fix for the issue without exposing Mastodon's users to increased risk.
|
||||
|
||||
## Scope
|
||||
|
||||
A "vulnerability in Mastodon" is a vulnerability in the code distributed through our main source code repository on GitHub. Vulnerabilities that are specific to a given installation (e.g. misconfiguration) should be reported to the owner of that installation and not us.
|
||||
|
||||
## Supported Versions
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 3.5.x | Yes |
|
||||
| 3.4.x | Yes |
|
||||
| 3.3.x | No |
|
||||
| < 3.3 | No |
|
||||
| 3.4.x | :white_check_mark: |
|
||||
| 3.3.x | :white_check_mark: |
|
||||
| < 3.3 | :x: |
|
||||
|
||||
[bug-bounty]: https://app.intigriti.com/programs/mastodon/mastodonio/detail
|
||||
## Reporting a Vulnerability
|
||||
|
||||
hello@joinmastodon.org
|
||||
|
|
|
@ -33,9 +33,11 @@ sudo apt-get install \
|
|||
redis-tools \
|
||||
postgresql \
|
||||
postgresql-contrib \
|
||||
protobuf-compiler \
|
||||
yarn \
|
||||
libicu-dev \
|
||||
libidn11-dev \
|
||||
libprotobuf-dev \
|
||||
libreadline-dev \
|
||||
libpam0g-dev \
|
||||
-y
|
||||
|
@ -43,8 +45,16 @@ sudo apt-get install \
|
|||
# Install rvm
|
||||
read RUBY_VERSION < .ruby-version
|
||||
|
||||
curl -sSL https://rvm.io/mpapis.asc | gpg --import
|
||||
curl -sSL https://rvm.io/pkuczynski.asc | gpg --import
|
||||
gpg_command="gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB"
|
||||
$($gpg_command)
|
||||
if [ $? -ne 0 ];then
|
||||
echo "GPG command failed, This prevented RVM from installing."
|
||||
echo "Retrying once..." && $($gpg_command)
|
||||
if [ $? -ne 0 ];then
|
||||
echo "GPG failed for the second time, please ensure network connectivity."
|
||||
echo "Exiting..." && exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
curl -sSL https://raw.githubusercontent.com/rvm/rvm/stable/binscripts/rvm-installer | bash -s stable --ruby=$RUBY_VERSION
|
||||
source /home/vagrant/.rvm/scripts/rvm
|
||||
|
|
5
app.json
5
app.json
|
@ -95,5 +95,8 @@
|
|||
"scripts": {
|
||||
"postdeploy": "bundle exec rails db:migrate && bundle exec rails db:seed"
|
||||
},
|
||||
"addons": ["heroku-postgresql", "heroku-redis"]
|
||||
"addons": [
|
||||
"heroku-postgresql",
|
||||
"heroku-redis"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AccountsIndex < Chewy::Index
|
||||
settings index: { refresh_interval: '30s' }, analysis: {
|
||||
settings index: { refresh_interval: '5m' }, analysis: {
|
||||
analyzer: {
|
||||
content: {
|
||||
tokenizer: 'whitespace',
|
||||
|
@ -23,21 +23,21 @@ class AccountsIndex < Chewy::Index
|
|||
},
|
||||
}
|
||||
|
||||
index_scope ::Account.searchable.includes(:account_stat)
|
||||
define_type ::Account.searchable.includes(:account_stat), delete_if: ->(account) { account.destroyed? || !account.searchable? } do
|
||||
root date_detection: false do
|
||||
field :id, type: 'long'
|
||||
|
||||
root date_detection: false do
|
||||
field :id, type: 'long'
|
||||
field :display_name, type: 'text', analyzer: 'content' do
|
||||
field :edge_ngram, type: 'text', analyzer: 'edge_ngram', search_analyzer: 'content'
|
||||
end
|
||||
|
||||
field :display_name, type: 'text', analyzer: 'content' do
|
||||
field :edge_ngram, type: 'text', analyzer: 'edge_ngram', search_analyzer: 'content'
|
||||
field :acct, type: 'text', analyzer: 'content', value: ->(account) { [account.username, account.domain].compact.join('@') } do
|
||||
field :edge_ngram, type: 'text', analyzer: 'edge_ngram', search_analyzer: 'content'
|
||||
end
|
||||
|
||||
field :following_count, type: 'long', value: ->(account) { account.following.local.count }
|
||||
field :followers_count, type: 'long', value: ->(account) { account.followers.local.count }
|
||||
field :last_status_at, type: 'date', value: ->(account) { account.last_status_at || account.created_at }
|
||||
end
|
||||
|
||||
field :acct, type: 'text', analyzer: 'content', value: ->(account) { [account.username, account.domain].compact.join('@') } do
|
||||
field :edge_ngram, type: 'text', analyzer: 'edge_ngram', search_analyzer: 'content'
|
||||
end
|
||||
|
||||
field :following_count, type: 'long', value: ->(account) { account.following_count }
|
||||
field :followers_count, type: 'long', value: ->(account) { account.followers_count }
|
||||
field :last_status_at, type: 'date', value: ->(account) { account.last_status_at || account.created_at }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class StatusesIndex < Chewy::Index
|
||||
include FormattingHelper
|
||||
|
||||
settings index: { refresh_interval: '30s' }, analysis: {
|
||||
settings index: { refresh_interval: '15m' }, analysis: {
|
||||
filter: {
|
||||
english_stop: {
|
||||
type: 'stop',
|
||||
|
@ -33,43 +31,36 @@ class StatusesIndex < Chewy::Index
|
|||
},
|
||||
}
|
||||
|
||||
# We do not use delete_if option here because it would call a method that we
|
||||
# expect to be called with crutches without crutches, causing n+1 queries
|
||||
index_scope ::Status.unscoped.kept.without_reblogs.includes(:media_attachments, :preloadable_poll)
|
||||
|
||||
crutch :mentions do |collection|
|
||||
data = ::Mention.where(status_id: collection.map(&:id)).where(account: Account.local, silent: false).pluck(:status_id, :account_id)
|
||||
data.each.with_object({}) { |(id, name), result| (result[id] ||= []).push(name) }
|
||||
end
|
||||
|
||||
crutch :favourites do |collection|
|
||||
data = ::Favourite.where(status_id: collection.map(&:id)).where(account: Account.local).pluck(:status_id, :account_id)
|
||||
data.each.with_object({}) { |(id, name), result| (result[id] ||= []).push(name) }
|
||||
end
|
||||
|
||||
crutch :reblogs do |collection|
|
||||
data = ::Status.where(reblog_of_id: collection.map(&:id)).where(account: Account.local).pluck(:reblog_of_id, :account_id)
|
||||
data.each.with_object({}) { |(id, name), result| (result[id] ||= []).push(name) }
|
||||
end
|
||||
|
||||
crutch :bookmarks do |collection|
|
||||
data = ::Bookmark.where(status_id: collection.map(&:id)).where(account: Account.local).pluck(:status_id, :account_id)
|
||||
data.each.with_object({}) { |(id, name), result| (result[id] ||= []).push(name) }
|
||||
end
|
||||
|
||||
crutch :votes do |collection|
|
||||
data = ::PollVote.joins(:poll).where(poll: { status_id: collection.map(&:id) }).where(account: Account.local).pluck(:status_id, :account_id)
|
||||
data.each.with_object({}) { |(id, name), result| (result[id] ||= []).push(name) }
|
||||
end
|
||||
|
||||
root date_detection: false do
|
||||
field :id, type: 'long'
|
||||
field :account_id, type: 'long'
|
||||
|
||||
field :text, type: 'text', value: ->(status) { status.searchable_text } do
|
||||
field :stemmed, type: 'text', analyzer: 'content'
|
||||
define_type ::Status.unscoped.kept.without_reblogs.includes(:media_attachments, :preloadable_poll) do
|
||||
crutch :mentions do |collection|
|
||||
data = ::Mention.where(status_id: collection.map(&:id)).where(account: Account.local, silent: false).pluck(:status_id, :account_id)
|
||||
data.each.with_object({}) { |(id, name), result| (result[id] ||= []).push(name) }
|
||||
end
|
||||
|
||||
field :searchable_by, type: 'long', value: ->(status, crutches) { status.searchable_by(crutches) }
|
||||
crutch :favourites do |collection|
|
||||
data = ::Favourite.where(status_id: collection.map(&:id)).where(account: Account.local).pluck(:status_id, :account_id)
|
||||
data.each.with_object({}) { |(id, name), result| (result[id] ||= []).push(name) }
|
||||
end
|
||||
|
||||
crutch :reblogs do |collection|
|
||||
data = ::Status.where(reblog_of_id: collection.map(&:id)).where(account: Account.local).pluck(:reblog_of_id, :account_id)
|
||||
data.each.with_object({}) { |(id, name), result| (result[id] ||= []).push(name) }
|
||||
end
|
||||
|
||||
crutch :bookmarks do |collection|
|
||||
data = ::Bookmark.where(status_id: collection.map(&:id)).where(account: Account.local).pluck(:status_id, :account_id)
|
||||
data.each.with_object({}) { |(id, name), result| (result[id] ||= []).push(name) }
|
||||
end
|
||||
|
||||
root date_detection: false do
|
||||
field :id, type: 'long'
|
||||
field :account_id, type: 'long'
|
||||
|
||||
field :text, type: 'text', value: ->(status) { [status.spoiler_text, Formatter.instance.plaintext(status)].concat(status.media_attachments.map(&:description)).concat(status.preloadable_poll ? status.preloadable_poll.options : []).join("\n\n") } do
|
||||
field :stemmed, type: 'text', analyzer: 'content'
|
||||
end
|
||||
|
||||
field :searchable_by, type: 'long', value: ->(status, crutches) { status.searchable_by(crutches) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class TagsIndex < Chewy::Index
|
||||
settings index: { refresh_interval: '30s' }, analysis: {
|
||||
settings index: { refresh_interval: '15m' }, analysis: {
|
||||
analyzer: {
|
||||
content: {
|
||||
tokenizer: 'keyword',
|
||||
|
@ -23,19 +23,15 @@ class TagsIndex < Chewy::Index
|
|||
},
|
||||
}
|
||||
|
||||
index_scope ::Tag.listable
|
||||
define_type ::Tag.listable, delete_if: ->(tag) { tag.destroyed? || !tag.listable? } do
|
||||
root date_detection: false do
|
||||
field :name, type: 'text', analyzer: 'content' do
|
||||
field :edge_ngram, type: 'text', analyzer: 'edge_ngram', search_analyzer: 'content'
|
||||
end
|
||||
|
||||
crutch :time_period do
|
||||
7.days.ago.to_date..0.days.ago.to_date
|
||||
end
|
||||
|
||||
root date_detection: false do
|
||||
field :name, type: 'text', analyzer: 'content' do
|
||||
field :edge_ngram, type: 'text', analyzer: 'edge_ngram', search_analyzer: 'content'
|
||||
field :reviewed, type: 'boolean', value: ->(tag) { tag.reviewed? }
|
||||
field :usage, type: 'long', value: ->(tag) { tag.history.reduce(0) { |total, day| total + day[:accounts].to_i } }
|
||||
field :last_status_at, type: 'date', value: ->(tag) { tag.last_status_at || tag.created_at }
|
||||
end
|
||||
|
||||
field :reviewed, type: 'boolean', value: ->(tag) { tag.reviewed? }
|
||||
field :usage, type: 'long', value: ->(tag, crutches) { tag.history.aggregate(crutches.time_period).accounts }
|
||||
field :last_status_at, type: 'date', value: ->(tag) { tag.last_status_at || tag.created_at }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -29,7 +29,7 @@ class AccountsController < ApplicationController
|
|||
return
|
||||
end
|
||||
|
||||
@pinned_statuses = cached_filtered_status_pins if show_pinned_statuses?
|
||||
@pinned_statuses = cache_collection(@account.pinned_statuses.not_local_only, Status) if show_pinned_statuses?
|
||||
@statuses = cached_filtered_status_page
|
||||
@rss_url = rss_url
|
||||
|
||||
|
@ -45,6 +45,7 @@ class AccountsController < ApplicationController
|
|||
limit = params[:limit].present? ? [params[:limit].to_i, PAGE_SIZE_MAX].min : PAGE_SIZE
|
||||
@statuses = filtered_statuses.without_reblogs.limit(limit)
|
||||
@statuses = cache_collection(@statuses, Status)
|
||||
render xml: RSS::AccountSerializer.render(@account, @statuses, params[:tag])
|
||||
end
|
||||
|
||||
format.json do
|
||||
|
@ -64,10 +65,6 @@ class AccountsController < ApplicationController
|
|||
[replies_requested?, media_requested?, tag_requested?, params[:max_id].present?, params[:min_id].present?].none?
|
||||
end
|
||||
|
||||
def filtered_pinned_statuses
|
||||
@account.pinned_statuses.not_local_only.where(visibility: [:public, :unlisted])
|
||||
end
|
||||
|
||||
def filtered_statuses
|
||||
default_statuses.tap do |statuses|
|
||||
statuses.merge!(hashtag_scope) if tag_requested?
|
||||
|
@ -146,13 +143,6 @@ class AccountsController < ApplicationController
|
|||
request.path.split('.').first.end_with?(Addressable::URI.parse("/tagged/#{params[:tag]}").normalize)
|
||||
end
|
||||
|
||||
def cached_filtered_status_pins
|
||||
cache_collection(
|
||||
filtered_pinned_statuses,
|
||||
Status
|
||||
)
|
||||
end
|
||||
|
||||
def cached_filtered_status_page
|
||||
cache_collection_paginated_by_id(
|
||||
filtered_statuses,
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
class ActivityPub::BaseController < Api::BaseController
|
||||
skip_before_action :require_authenticated_user!
|
||||
skip_before_action :require_not_suspended!
|
||||
skip_around_action :set_locale
|
||||
|
||||
private
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ class ActivityPub::CollectionsController < ActivityPub::BaseController
|
|||
case params[:id]
|
||||
when 'featured'
|
||||
@items = for_signed_account { cache_collection(@account.pinned_statuses.not_local_only, Status) }
|
||||
@items = @items.map { |item| item.distributable? ? item : ActivityPub::TagManager.instance.uri_for(item) }
|
||||
when 'tags'
|
||||
@items = for_signed_account { @account.featured_tags }
|
||||
when 'devices'
|
||||
|
|
|
@ -62,7 +62,7 @@ class ActivityPub::OutboxesController < ActivityPub::BaseController
|
|||
return unless page_requested?
|
||||
|
||||
@statuses = cache_collection_paginated_by_id(
|
||||
AccountStatusesFilter.new(@account, signed_request_account).results,
|
||||
@account.statuses.permitted_for(@account, signed_request_account),
|
||||
Status,
|
||||
LIMIT,
|
||||
params_slice(:max_id, :min_id, :since_id)
|
||||
|
|
|
@ -63,29 +63,15 @@ class ActivityPub::RepliesController < ActivityPub::BaseController
|
|||
end
|
||||
|
||||
def next_page
|
||||
if only_other_accounts?
|
||||
# Only consider remote accounts
|
||||
return nil if @replies.size < DESCENDANTS_LIMIT
|
||||
only_other_accounts = !(@replies&.last&.account_id == @account.id && @replies.size == DESCENDANTS_LIMIT)
|
||||
|
||||
account_status_replies_url(
|
||||
@account,
|
||||
@status,
|
||||
page: true,
|
||||
min_id: @replies&.last&.id,
|
||||
only_other_accounts: true
|
||||
)
|
||||
else
|
||||
# For now, we're serving only self-replies, but next page might be other accounts
|
||||
next_only_other_accounts = @replies&.last&.account_id != @account.id || @replies.size < DESCENDANTS_LIMIT
|
||||
|
||||
account_status_replies_url(
|
||||
@account,
|
||||
@status,
|
||||
page: true,
|
||||
min_id: next_only_other_accounts ? nil : @replies&.last&.id,
|
||||
only_other_accounts: next_only_other_accounts
|
||||
)
|
||||
end
|
||||
account_status_replies_url(
|
||||
@account,
|
||||
@status,
|
||||
page: true,
|
||||
min_id: only_other_accounts && !only_other_accounts? ? nil : @replies&.last&.id,
|
||||
only_other_accounts: only_other_accounts
|
||||
)
|
||||
end
|
||||
|
||||
def page_params
|
||||
|
|
|
@ -14,7 +14,7 @@ module Admin
|
|||
else
|
||||
@account = @account_moderation_note.target_account
|
||||
@moderation_notes = @account.targeted_moderation_notes.latest
|
||||
@warnings = @account.strikes.custom.latest
|
||||
@warnings = @account.targeted_account_warnings.latest.custom
|
||||
|
||||
render template: 'admin/accounts/show'
|
||||
end
|
||||
|
|
|
@ -2,24 +2,13 @@
|
|||
|
||||
module Admin
|
||||
class AccountsController < BaseController
|
||||
before_action :set_account, except: [:index, :batch]
|
||||
before_action :set_account, except: [:index]
|
||||
before_action :require_remote_account!, only: [:redownload]
|
||||
before_action :require_local_account!, only: [:enable, :memorialize, :approve, :reject]
|
||||
|
||||
def index
|
||||
authorize :account, :index?
|
||||
|
||||
@accounts = filtered_accounts.page(params[:page])
|
||||
@form = Form::AccountBatch.new
|
||||
end
|
||||
|
||||
def batch
|
||||
@form = Form::AccountBatch.new(form_account_batch_params.merge(current_account: current_account, action: action_from_button))
|
||||
@form.save
|
||||
rescue ActionController::ParameterMissing
|
||||
flash[:alert] = I18n.t('admin.accounts.no_account_selected')
|
||||
ensure
|
||||
redirect_to admin_accounts_path(filter_params)
|
||||
end
|
||||
|
||||
def show
|
||||
|
@ -28,7 +17,7 @@ module Admin
|
|||
@deletion_request = @account.deletion_request
|
||||
@account_moderation_note = current_account.account_moderation_notes.new(target_account: @account)
|
||||
@moderation_notes = @account.targeted_moderation_notes.latest
|
||||
@warnings = @account.strikes.includes(:target_account, :account, :appeal).latest
|
||||
@warnings = @account.targeted_account_warnings.latest.custom
|
||||
@domain_block = DomainBlock.rule_for(@account.domain)
|
||||
end
|
||||
|
||||
|
@ -49,13 +38,13 @@ module Admin
|
|||
def approve
|
||||
authorize @account.user, :approve?
|
||||
@account.user.approve!
|
||||
redirect_to admin_accounts_path(status: 'pending'), notice: I18n.t('admin.accounts.approved_msg', username: @account.acct)
|
||||
redirect_to admin_pending_accounts_path, notice: I18n.t('admin.accounts.approved_msg', username: @account.acct)
|
||||
end
|
||||
|
||||
def reject
|
||||
authorize @account.user, :reject?
|
||||
DeleteAccountService.new.call(@account, reserve_email: false, reserve_username: false)
|
||||
redirect_to admin_accounts_path(status: 'pending'), notice: I18n.t('admin.accounts.rejected_msg', username: @account.acct)
|
||||
redirect_to admin_pending_accounts_path, notice: I18n.t('admin.accounts.rejected_msg', username: @account.acct)
|
||||
end
|
||||
|
||||
def destroy
|
||||
|
@ -117,16 +106,6 @@ module Admin
|
|||
redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.removed_header_msg', username: @account.acct)
|
||||
end
|
||||
|
||||
def unblock_email
|
||||
authorize @account, :unblock_email?
|
||||
|
||||
CanonicalEmailBlock.where(reference_account: @account).delete_all
|
||||
|
||||
log_action :unblock_email, @account
|
||||
|
||||
redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.unblocked_email_msg', username: @account.acct)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_account
|
||||
|
@ -142,25 +121,11 @@ module Admin
|
|||
end
|
||||
|
||||
def filtered_accounts
|
||||
AccountFilter.new(filter_params.with_defaults(order: 'recent')).results
|
||||
AccountFilter.new(filter_params).results
|
||||
end
|
||||
|
||||
def filter_params
|
||||
params.slice(:page, *AccountFilter::KEYS).permit(:page, *AccountFilter::KEYS)
|
||||
end
|
||||
|
||||
def form_account_batch_params
|
||||
params.require(:form_account_batch).permit(:action, account_ids: [])
|
||||
end
|
||||
|
||||
def action_from_button
|
||||
if params[:suspend]
|
||||
'suspend'
|
||||
elsif params[:approve]
|
||||
'approve'
|
||||
elsif params[:reject]
|
||||
'reject'
|
||||
end
|
||||
params.slice(*AccountFilter::KEYS).permit(*AccountFilter::KEYS)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -35,9 +35,6 @@ module Admin
|
|||
flash[:alert] = I18n.t('admin.accounts.no_account_selected')
|
||||
rescue Mastodon::NotPermittedError
|
||||
flash[:alert] = I18n.t('admin.custom_emojis.not_permitted')
|
||||
rescue ActiveRecord::RecordInvalid => e
|
||||
error_message = action_from_button == 'copy' ? 'admin.custom_emojis.batch_copy_error' : 'admin.custom_emojis.batch_error'
|
||||
flash[:alert] = I18n.t(error_message, message: e.message)
|
||||
ensure
|
||||
redirect_to admin_custom_emojis_path(filter_params)
|
||||
end
|
||||
|
|
|
@ -1,26 +1,56 @@
|
|||
# frozen_string_literal: true
|
||||
require 'sidekiq/api'
|
||||
|
||||
module Admin
|
||||
class DashboardController < BaseController
|
||||
include Redisable
|
||||
|
||||
def index
|
||||
@system_checks = Admin::SystemCheck.perform
|
||||
@time_period = (29.days.ago.to_date...Time.now.utc.to_date)
|
||||
@users_count = User.count
|
||||
@pending_users_count = User.pending.count
|
||||
@pending_reports_count = Report.unresolved.count
|
||||
@registrations_week = Redis.current.get("activity:accounts:local:#{current_week}") || 0
|
||||
@logins_week = Redis.current.pfcount("activity:logins:#{current_week}")
|
||||
@interactions_week = Redis.current.get("activity:interactions:#{current_week}") || 0
|
||||
@relay_enabled = Relay.enabled.exists?
|
||||
@single_user_mode = Rails.configuration.x.single_user_mode
|
||||
@registrations_enabled = Setting.registrations_mode != 'none'
|
||||
@deletions_enabled = Setting.open_deletion
|
||||
@invites_enabled = Setting.min_invite_role == 'user'
|
||||
@search_enabled = Chewy.enabled?
|
||||
@version = Mastodon::Version.to_s
|
||||
@database_version = ActiveRecord::Base.connection.execute('SELECT VERSION()').first['version'].match(/\A(?:PostgreSQL |)([^\s]+).*\z/)[1]
|
||||
@redis_version = redis_info['redis_version']
|
||||
@reports_count = Report.unresolved.count
|
||||
@queue_backlog = Sidekiq::Stats.new.enqueued
|
||||
@recent_users = User.confirmed.recent.includes(:account).limit(8)
|
||||
@database_size = ActiveRecord::Base.connection.execute('SELECT pg_database_size(current_database())').first['pg_database_size']
|
||||
@redis_size = redis_info['used_memory']
|
||||
@ldap_enabled = ENV['LDAP_ENABLED'] == 'true'
|
||||
@cas_enabled = ENV['CAS_ENABLED'] == 'true'
|
||||
@saml_enabled = ENV['SAML_ENABLED'] == 'true'
|
||||
@pam_enabled = ENV['PAM_ENABLED'] == 'true'
|
||||
@hidden_service = ENV['ALLOW_ACCESS_TO_HIDDEN_SERVICE'] == 'true'
|
||||
@trending_hashtags = TrendingTags.get(10, filtered: false)
|
||||
@pending_tags_count = Tag.pending_review.count
|
||||
@pending_appeals_count = Appeal.pending.count
|
||||
@authorized_fetch = authorized_fetch_mode?
|
||||
@whitelist_enabled = whitelist_mode?
|
||||
@profile_directory = Setting.profile_directory
|
||||
@timeline_preview = Setting.timeline_preview
|
||||
@keybase_integration = Setting.enable_keybase
|
||||
@trends_enabled = Setting.trends
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def current_week
|
||||
@current_week ||= Time.now.utc.to_date.cweek
|
||||
end
|
||||
|
||||
def redis_info
|
||||
@redis_info ||= begin
|
||||
if redis.is_a?(Redis::Namespace)
|
||||
redis.redis.info
|
||||
if Redis.current.is_a?(Redis::Namespace)
|
||||
Redis.current.redis.info
|
||||
else
|
||||
redis.info
|
||||
Redis.current.info
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Admin::Disputes::AppealsController < Admin::BaseController
|
||||
before_action :set_appeal, except: :index
|
||||
|
||||
def index
|
||||
authorize :appeal, :index?
|
||||
|
||||
@appeals = filtered_appeals.page(params[:page])
|
||||
end
|
||||
|
||||
def approve
|
||||
authorize @appeal, :approve?
|
||||
log_action :approve, @appeal
|
||||
ApproveAppealService.new.call(@appeal, current_account)
|
||||
redirect_to disputes_strike_path(@appeal.strike)
|
||||
end
|
||||
|
||||
def reject
|
||||
authorize @appeal, :approve?
|
||||
log_action :reject, @appeal
|
||||
@appeal.reject!(current_account)
|
||||
UserMailer.appeal_rejected(@appeal.account.user, @appeal)
|
||||
redirect_to disputes_strike_path(@appeal.strike)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def filtered_appeals
|
||||
Admin::AppealFilter.new(filter_params.with_defaults(status: 'pending')).results.includes(strike: :account)
|
||||
end
|
||||
|
||||
def filter_params
|
||||
params.slice(:page, *Admin::AppealFilter::KEYS).permit(:page, *Admin::AppealFilter::KEYS)
|
||||
end
|
||||
|
||||
def set_appeal
|
||||
@appeal = Appeal.find(params[:id])
|
||||
end
|
||||
end
|
|
@ -4,17 +4,6 @@ module Admin
|
|||
class DomainBlocksController < BaseController
|
||||
before_action :set_domain_block, only: [:show, :destroy, :edit, :update]
|
||||
|
||||
def batch
|
||||
@form = Form::DomainBlockBatch.new(form_domain_block_batch_params.merge(current_account: current_account, action: action_from_button))
|
||||
@form.save
|
||||
rescue ActionController::ParameterMissing
|
||||
flash[:alert] = I18n.t('admin.email_domain_blocks.no_domain_block_selected')
|
||||
rescue Mastodon::NotPermittedError
|
||||
flash[:alert] = I18n.t('admin.domain_blocks.created_msg')
|
||||
else
|
||||
redirect_to admin_instances_path(limited: '1'), notice: I18n.t('admin.domain_blocks.created_msg')
|
||||
end
|
||||
|
||||
def new
|
||||
authorize :domain_block, :create?
|
||||
@domain_block = DomainBlock.new(domain: params[:_domain])
|
||||
|
@ -67,6 +56,10 @@ module Admin
|
|||
end
|
||||
end
|
||||
|
||||
def show
|
||||
authorize @domain_block, :show?
|
||||
end
|
||||
|
||||
def destroy
|
||||
authorize @domain_block, :destroy?
|
||||
UnblockDomainService.new.call(@domain_block)
|
||||
|
@ -87,15 +80,5 @@ module Admin
|
|||
def resource_params
|
||||
params.require(:domain_block).permit(:domain, :severity, :reject_media, :reject_reports, :private_comment, :public_comment, :obfuscate)
|
||||
end
|
||||
|
||||
def form_domain_block_batch_params
|
||||
params.require(:form_domain_block_batch).permit(domain_blocks_attributes: [:enabled, :domain, :severity, :reject_media, :reject_reports, :private_comment, :public_comment, :obfuscate])
|
||||
end
|
||||
|
||||
def action_from_button
|
||||
if params[:save]
|
||||
'save'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,20 +6,7 @@ module Admin
|
|||
|
||||
def index
|
||||
authorize :email_domain_block, :index?
|
||||
|
||||
@email_domain_blocks = EmailDomainBlock.where(parent_id: nil).includes(:children).order(id: :desc).page(params[:page])
|
||||
@form = Form::EmailDomainBlockBatch.new
|
||||
end
|
||||
|
||||
def batch
|
||||
@form = Form::EmailDomainBlockBatch.new(form_email_domain_block_batch_params.merge(current_account: current_account, action: action_from_button))
|
||||
@form.save
|
||||
rescue ActionController::ParameterMissing
|
||||
flash[:alert] = I18n.t('admin.email_domain_blocks.no_email_domain_block_selected')
|
||||
rescue Mastodon::NotPermittedError
|
||||
flash[:alert] = I18n.t('admin.custom_emojis.not_permitted')
|
||||
ensure
|
||||
redirect_to admin_email_domain_blocks_path
|
||||
end
|
||||
|
||||
def new
|
||||
|
@ -32,27 +19,41 @@ module Admin
|
|||
|
||||
@email_domain_block = EmailDomainBlock.new(resource_params)
|
||||
|
||||
if action_from_button == 'save'
|
||||
EmailDomainBlock.transaction do
|
||||
@email_domain_block.save!
|
||||
log_action :create, @email_domain_block
|
||||
if @email_domain_block.save
|
||||
log_action :create, @email_domain_block
|
||||
|
||||
(@email_domain_block.other_domains || []).uniq.each do |domain|
|
||||
next if EmailDomainBlock.where(domain: domain).exists?
|
||||
if @email_domain_block.with_dns_records?
|
||||
hostnames = []
|
||||
ips = []
|
||||
|
||||
other_email_domain_block = EmailDomainBlock.create!(domain: domain, parent: @email_domain_block)
|
||||
log_action :create, other_email_domain_block
|
||||
Resolv::DNS.open do |dns|
|
||||
dns.timeouts = 5
|
||||
|
||||
hostnames = dns.getresources(@email_domain_block.domain, Resolv::DNS::Resource::IN::MX).to_a.map { |e| e.exchange.to_s }
|
||||
|
||||
([@email_domain_block.domain] + hostnames).uniq.each do |hostname|
|
||||
ips.concat(dns.getresources(hostname, Resolv::DNS::Resource::IN::A).to_a.map { |e| e.address.to_s })
|
||||
ips.concat(dns.getresources(hostname, Resolv::DNS::Resource::IN::AAAA).to_a.map { |e| e.address.to_s })
|
||||
end
|
||||
end
|
||||
|
||||
(hostnames + ips).each do |hostname|
|
||||
another_email_domain_block = EmailDomainBlock.new(domain: hostname, parent: @email_domain_block)
|
||||
log_action :create, another_email_domain_block if another_email_domain_block.save
|
||||
end
|
||||
end
|
||||
|
||||
redirect_to admin_email_domain_blocks_path, notice: I18n.t('admin.email_domain_blocks.created_msg')
|
||||
else
|
||||
set_resolved_records
|
||||
render :new
|
||||
end
|
||||
rescue ActiveRecord::RecordInvalid
|
||||
set_resolved_records
|
||||
render :new
|
||||
end
|
||||
|
||||
def destroy
|
||||
authorize @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')
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -61,27 +62,8 @@ module Admin
|
|||
@email_domain_block = EmailDomainBlock.find(params[:id])
|
||||
end
|
||||
|
||||
def set_resolved_records
|
||||
Resolv::DNS.open do |dns|
|
||||
dns.timeouts = 5
|
||||
@resolved_records = dns.getresources(@email_domain_block.domain, Resolv::DNS::Resource::IN::MX).to_a
|
||||
end
|
||||
end
|
||||
|
||||
def resource_params
|
||||
params.require(:email_domain_block).permit(:domain, other_domains: [])
|
||||
end
|
||||
|
||||
def form_email_domain_block_batch_params
|
||||
params.require(:form_email_domain_block_batch).permit(email_domain_block_ids: [])
|
||||
end
|
||||
|
||||
def action_from_button
|
||||
if params[:delete]
|
||||
'delete'
|
||||
elsif params[:save]
|
||||
'save'
|
||||
end
|
||||
params.require(:email_domain_block).permit(:domain, :with_dns_records)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'csv'
|
||||
|
||||
module Admin
|
||||
class ExportDomainAllowsController < BaseController
|
||||
include AdminExportControllerConcern
|
||||
|
||||
before_action :set_dummy_import!, only: [:new]
|
||||
|
||||
ROWS_PROCESSING_LIMIT = 20_000
|
||||
|
||||
def new
|
||||
authorize :domain_allow, :create?
|
||||
end
|
||||
|
||||
def export
|
||||
authorize :instance, :index?
|
||||
send_export_file
|
||||
end
|
||||
|
||||
def import
|
||||
authorize :domain_allow, :create?
|
||||
begin
|
||||
@import = Admin::Import.new(import_params)
|
||||
parse_import_data!(export_headers)
|
||||
|
||||
@data.take(ROWS_PROCESSING_LIMIT).each do |row|
|
||||
domain = row['#domain'].strip
|
||||
next if DomainAllow.allowed?(domain)
|
||||
|
||||
domain_allow = DomainAllow.new(domain: domain)
|
||||
log_action :create, domain_allow if domain_allow.save
|
||||
end
|
||||
flash[:notice] = I18n.t('admin.domain_allows.created_msg')
|
||||
rescue ActionController::ParameterMissing
|
||||
flash[:error] = I18n.t('admin.export_domain_allows.no_file')
|
||||
end
|
||||
redirect_to admin_instances_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def export_filename
|
||||
'domain_allows.csv'
|
||||
end
|
||||
|
||||
def export_headers
|
||||
%w(#domain)
|
||||
end
|
||||
|
||||
def export_data
|
||||
CSV.generate(headers: export_headers, write_headers: true) do |content|
|
||||
DomainAllow.allowed_domains.each do |instance|
|
||||
content << [instance.domain]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,71 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'csv'
|
||||
|
||||
module Admin
|
||||
class ExportDomainBlocksController < BaseController
|
||||
include AdminExportControllerConcern
|
||||
|
||||
before_action :set_dummy_import!, only: [:new]
|
||||
|
||||
ROWS_PROCESSING_LIMIT = 20_000
|
||||
|
||||
def new
|
||||
authorize :domain_block, :create?
|
||||
end
|
||||
|
||||
def export
|
||||
authorize :instance, :index?
|
||||
send_export_file
|
||||
end
|
||||
|
||||
def import
|
||||
authorize :domain_block, :create?
|
||||
|
||||
@import = Admin::Import.new(import_params)
|
||||
parse_import_data!(export_headers)
|
||||
|
||||
@global_private_comment = I18n.t('admin.export_domain_blocks.import.private_comment_template', source: @import.data_file_name, date: I18n.l(Time.now.utc))
|
||||
|
||||
@form = Form::DomainBlockBatch.new
|
||||
@domain_blocks = @data.take(ROWS_PROCESSING_LIMIT).filter_map do |row|
|
||||
domain = row['#domain'].strip
|
||||
next if DomainBlock.rule_for(domain).present?
|
||||
|
||||
domain_block = DomainBlock.new(domain: domain,
|
||||
severity: row['#severity'].strip,
|
||||
reject_media: row['#reject_media'].strip,
|
||||
reject_reports: row['#reject_reports'].strip,
|
||||
private_comment: @global_private_comment,
|
||||
public_comment: row['#public_comment']&.strip,
|
||||
obfuscate: row['#obfuscate'].strip)
|
||||
|
||||
domain_block if domain_block.valid?
|
||||
end
|
||||
|
||||
@warning_domains = Instance.where(domain: @domain_blocks.map(&:domain)).where('EXISTS (SELECT 1 FROM follows JOIN accounts ON follows.account_id = accounts.id OR follows.target_account_id = accounts.id WHERE accounts.domain = instances.domain)').pluck(:domain)
|
||||
rescue ActionController::ParameterMissing
|
||||
flash.now[:alert] = I18n.t('admin.export_domain_blocks.no_file')
|
||||
set_dummy_import!
|
||||
render :new
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def export_filename
|
||||
'domain_blocks.csv'
|
||||
end
|
||||
|
||||
def export_headers
|
||||
%w(#domain #severity #reject_media #reject_reports #public_comment #obfuscate)
|
||||
end
|
||||
|
||||
def export_data
|
||||
CSV.generate(headers: export_headers, write_headers: true) do |content|
|
||||
DomainBlock.with_user_facing_limitations.each do |instance|
|
||||
content << [instance.domain, instance.severity, instance.reject_media, instance.reject_reports, instance.public_comment, instance.obfuscate]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -4,26 +4,19 @@ module Admin
|
|||
class InstancesController < BaseController
|
||||
before_action :set_instances, only: :index
|
||||
before_action :set_instance, except: :index
|
||||
before_action :set_exhausted_deliveries_days, only: :show
|
||||
|
||||
def index
|
||||
authorize :instance, :index?
|
||||
preload_delivery_failures!
|
||||
end
|
||||
|
||||
def show
|
||||
authorize :instance, :show?
|
||||
@time_period = (6.days.ago.to_date...Time.now.utc.to_date)
|
||||
end
|
||||
|
||||
def destroy
|
||||
authorize :instance, :destroy?
|
||||
Admin::DomainPurgeWorker.perform_async(@instance.domain)
|
||||
log_action :destroy, @instance
|
||||
redirect_to admin_instances_path, notice: I18n.t('admin.instances.destroyed_msg', domain: @instance.domain)
|
||||
end
|
||||
|
||||
def clear_delivery_errors
|
||||
authorize :delivery, :clear_delivery_errors?
|
||||
|
||||
@instance.delivery_failure_tracker.clear_failures!
|
||||
redirect_to admin_instance_path(@instance.domain)
|
||||
end
|
||||
|
@ -31,9 +24,11 @@ module Admin
|
|||
def restart_delivery
|
||||
authorize :delivery, :restart_delivery?
|
||||
|
||||
if @instance.unavailable?
|
||||
last_unavailable_domain = unavailable_domain
|
||||
|
||||
if last_unavailable_domain.present?
|
||||
@instance.delivery_failure_tracker.track_success!
|
||||
log_action :destroy, @instance.unavailable_domain
|
||||
log_action :destroy, last_unavailable_domain
|
||||
end
|
||||
|
||||
redirect_to admin_instance_path(@instance.domain)
|
||||
|
@ -41,7 +36,8 @@ module Admin
|
|||
|
||||
def stop_delivery
|
||||
authorize :delivery, :stop_delivery?
|
||||
unavailable_domain = UnavailableDomain.create!(domain: @instance.domain)
|
||||
|
||||
UnavailableDomain.create(domain: @instance.domain)
|
||||
log_action :create, unavailable_domain
|
||||
redirect_to admin_instance_path(@instance.domain)
|
||||
end
|
||||
|
@ -52,11 +48,12 @@ module Admin
|
|||
@instance = Instance.find(params[:id])
|
||||
end
|
||||
|
||||
def set_instances
|
||||
@instances = filtered_instances.page(params[:page])
|
||||
def set_exhausted_deliveries_days
|
||||
@exhausted_deliveries_days = @instance.delivery_failure_tracker.exhausted_deliveries_days
|
||||
end
|
||||
|
||||
def preload_delivery_failures!
|
||||
def set_instances
|
||||
@instances = filtered_instances.page(params[:page])
|
||||
warning_domains_map = DeliveryFailureTracker.warning_domains_map
|
||||
|
||||
@instances.each do |instance|
|
||||
|
@ -64,6 +61,10 @@ module Admin
|
|||
end
|
||||
end
|
||||
|
||||
def unavailable_domain
|
||||
UnavailableDomain.find_by(domain: @instance.domain)
|
||||
end
|
||||
|
||||
def filtered_instances
|
||||
InstanceFilter.new(whitelist_mode? ? { allowed: true } : filter_params).results
|
||||
end
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Admin
|
||||
class PendingAccountsController < BaseController
|
||||
before_action :set_accounts, only: :index
|
||||
|
||||
def index
|
||||
@form = Form::AccountBatch.new
|
||||
end
|
||||
|
||||
def batch
|
||||
@form = Form::AccountBatch.new(form_account_batch_params.merge(current_account: current_account, action: action_from_button))
|
||||
@form.save
|
||||
rescue ActionController::ParameterMissing
|
||||
flash[:alert] = I18n.t('admin.accounts.no_account_selected')
|
||||
ensure
|
||||
redirect_to admin_pending_accounts_path(current_params)
|
||||
end
|
||||
|
||||
def approve_all
|
||||
Form::AccountBatch.new(current_account: current_account, account_ids: User.pending.pluck(:account_id), action: 'approve').save
|
||||
redirect_to admin_pending_accounts_path(current_params)
|
||||
end
|
||||
|
||||
def reject_all
|
||||
Form::AccountBatch.new(current_account: current_account, account_ids: User.pending.pluck(:account_id), action: 'reject').save
|
||||
redirect_to admin_pending_accounts_path(current_params)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_accounts
|
||||
@accounts = Account.joins(:user).merge(User.pending.recent).includes(user: :invite_request).page(params[:page])
|
||||
end
|
||||
|
||||
def form_account_batch_params
|
||||
params.require(:form_account_batch).permit(:action, account_ids: [])
|
||||
end
|
||||
|
||||
def action_from_button
|
||||
if params[:approve]
|
||||
'approve'
|
||||
elsif params[:reject]
|
||||
'reject'
|
||||
end
|
||||
end
|
||||
|
||||
def current_params
|
||||
params.slice(:page).permit(:page)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -9,8 +9,7 @@ module Admin
|
|||
def index
|
||||
authorize :account, :index?
|
||||
|
||||
@accounts = RelationshipFilter.new(@account, filter_params).results.includes(:account_stat, user: [:ips, :invite_request]).page(params[:page]).per(PER_PAGE)
|
||||
@form = Form::AccountBatch.new
|
||||
@accounts = RelationshipFilter.new(@account, filter_params).results.page(params[:page]).per(PER_PAGE)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -14,17 +14,20 @@ module Admin
|
|||
if params[:create_and_resolve]
|
||||
@report.resolve!(current_account)
|
||||
log_action :resolve, @report
|
||||
elsif params[:create_and_unresolve]
|
||||
|
||||
redirect_to admin_reports_path, notice: I18n.t('admin.reports.resolved_msg')
|
||||
return
|
||||
end
|
||||
|
||||
if params[:create_and_unresolve]
|
||||
@report.unresolve!
|
||||
log_action :reopen, @report
|
||||
end
|
||||
|
||||
redirect_to after_create_redirect_path, notice: I18n.t('admin.report_notes.created_msg')
|
||||
redirect_to admin_report_path(@report), notice: I18n.t('admin.report_notes.created_msg')
|
||||
else
|
||||
@report_notes = @report.notes.includes(:account).order(id: :desc)
|
||||
@action_logs = @report.history.includes(:target)
|
||||
@form = Admin::StatusBatchAction.new
|
||||
@statuses = @report.statuses.with_includes
|
||||
@report_notes = (@report.notes.latest + @report.history + @report.target_account.targeted_account_warnings.latest.custom).sort_by(&:created_at)
|
||||
@form = Form::StatusBatch.new
|
||||
|
||||
render template: 'admin/reports/show'
|
||||
end
|
||||
|
@ -38,14 +41,6 @@ module Admin
|
|||
|
||||
private
|
||||
|
||||
def after_create_redirect_path
|
||||
if params[:create_and_resolve]
|
||||
admin_reports_path
|
||||
else
|
||||
admin_report_path(@report)
|
||||
end
|
||||
end
|
||||
|
||||
def resource_params
|
||||
params.require(:report_note).permit(
|
||||
:content,
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Admin
|
||||
class ReportedStatusesController < BaseController
|
||||
before_action :set_report
|
||||
|
||||
def create
|
||||
authorize :status, :update?
|
||||
|
||||
@form = Form::StatusBatch.new(form_status_batch_params.merge(current_account: current_account, action: action_from_button))
|
||||
flash[:alert] = I18n.t('admin.statuses.failed_to_execute') unless @form.save
|
||||
|
||||
redirect_to admin_report_path(@report)
|
||||
rescue ActionController::ParameterMissing
|
||||
flash[:alert] = I18n.t('admin.statuses.no_status_selected')
|
||||
|
||||
redirect_to admin_report_path(@report)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def status_params
|
||||
params.require(:status).permit(:sensitive)
|
||||
end
|
||||
|
||||
def form_status_batch_params
|
||||
params.require(:form_status_batch).permit(status_ids: [])
|
||||
end
|
||||
|
||||
def action_from_button
|
||||
if params[:nsfw_on]
|
||||
'nsfw_on'
|
||||
elsif params[:nsfw_off]
|
||||
'nsfw_off'
|
||||
elsif params[:delete]
|
||||
'delete'
|
||||
end
|
||||
end
|
||||
|
||||
def set_report
|
||||
@report = Report.find(params[:report_id])
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,52 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Admin::Reports::ActionsController < Admin::BaseController
|
||||
before_action :set_report
|
||||
|
||||
def create
|
||||
authorize @report, :show?
|
||||
|
||||
case action_from_button
|
||||
when 'delete', 'mark_as_sensitive'
|
||||
status_batch_action = Admin::StatusBatchAction.new(
|
||||
type: action_from_button,
|
||||
status_ids: @report.status_ids,
|
||||
current_account: current_account,
|
||||
report_id: @report.id,
|
||||
send_email_notification: !@report.spam?
|
||||
)
|
||||
|
||||
status_batch_action.save!
|
||||
when 'silence', 'suspend'
|
||||
account_action = Admin::AccountAction.new(
|
||||
type: action_from_button,
|
||||
report_id: @report.id,
|
||||
target_account: @report.target_account,
|
||||
current_account: current_account,
|
||||
send_email_notification: !@report.spam?
|
||||
)
|
||||
|
||||
account_action.save!
|
||||
end
|
||||
|
||||
redirect_to admin_reports_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_report
|
||||
@report = Report.find(params[:report_id])
|
||||
end
|
||||
|
||||
def action_from_button
|
||||
if params[:delete]
|
||||
'delete'
|
||||
elsif params[:mark_as_sensitive]
|
||||
'mark_as_sensitive'
|
||||
elsif params[:silence]
|
||||
'silence'
|
||||
elsif params[:suspend]
|
||||
'suspend'
|
||||
end
|
||||
end
|
||||
end
|
|
@ -13,10 +13,8 @@ module Admin
|
|||
authorize @report, :show?
|
||||
|
||||
@report_note = @report.notes.new
|
||||
@report_notes = @report.notes.includes(:account).order(id: :desc)
|
||||
@action_logs = @report.history.includes(:target)
|
||||
@form = Admin::StatusBatchAction.new
|
||||
@statuses = @report.statuses.with_includes
|
||||
@report_notes = (@report.notes.latest + @report.history + @report.target_account.targeted_account_warnings.latest.custom).sort_by(&:created_at)
|
||||
@form = Form::StatusBatch.new
|
||||
end
|
||||
|
||||
def assign_to_self
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Admin
|
||||
class SignInTokenAuthenticationsController < BaseController
|
||||
before_action :set_target_user
|
||||
|
||||
def create
|
||||
authorize @user, :enable_sign_in_token_auth?
|
||||
@user.update(skip_sign_in_token: false)
|
||||
log_action :enable_sign_in_token_auth, @user
|
||||
redirect_to admin_account_path(@user.account_id)
|
||||
end
|
||||
|
||||
def destroy
|
||||
authorize @user, :disable_sign_in_token_auth?
|
||||
@user.update(skip_sign_in_token: true)
|
||||
log_action :disable_sign_in_token_auth, @user
|
||||
redirect_to admin_account_path(@user.account_id)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_target_user
|
||||
@user = User.find(params[:user_id])
|
||||
end
|
||||
end
|
||||
end
|
|
@ -2,62 +2,71 @@
|
|||
|
||||
module Admin
|
||||
class StatusesController < BaseController
|
||||
helper_method :current_params
|
||||
|
||||
before_action :set_account
|
||||
before_action :set_statuses
|
||||
|
||||
PER_PAGE = 20
|
||||
|
||||
def index
|
||||
authorize :status, :index?
|
||||
|
||||
@status_batch_action = Admin::StatusBatchAction.new
|
||||
@statuses = @account.statuses.where(visibility: [:public, :unlisted])
|
||||
|
||||
if params[:media]
|
||||
@statuses.merge!(Status.joins(:media_attachments).merge(@account.media_attachments.reorder(nil)).group(:id))
|
||||
end
|
||||
|
||||
@statuses = @statuses.preload(:media_attachments, :mentions).page(params[:page]).per(PER_PAGE)
|
||||
@form = Form::StatusBatch.new
|
||||
end
|
||||
|
||||
def batch
|
||||
@status_batch_action = Admin::StatusBatchAction.new(admin_status_batch_action_params.merge(current_account: current_account, report_id: params[:report_id], type: action_from_button))
|
||||
@status_batch_action.save!
|
||||
def show
|
||||
authorize :status, :index?
|
||||
|
||||
@statuses = @account.statuses.where(id: params[:id])
|
||||
authorize @statuses.first, :show?
|
||||
|
||||
@form = Form::StatusBatch.new
|
||||
end
|
||||
|
||||
def create
|
||||
authorize :status, :update?
|
||||
|
||||
@form = Form::StatusBatch.new(form_status_batch_params.merge(current_account: current_account, action: action_from_button))
|
||||
flash[:alert] = I18n.t('admin.statuses.failed_to_execute') unless @form.save
|
||||
|
||||
redirect_to admin_account_statuses_path(@account.id, current_params)
|
||||
rescue ActionController::ParameterMissing
|
||||
flash[:alert] = I18n.t('admin.statuses.no_status_selected')
|
||||
ensure
|
||||
redirect_to after_create_redirect_path
|
||||
|
||||
redirect_to admin_account_statuses_path(@account.id, current_params)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def admin_status_batch_action_params
|
||||
params.require(:admin_status_batch_action).permit(status_ids: [])
|
||||
end
|
||||
|
||||
def after_create_redirect_path
|
||||
report_id = @status_batch_action&.report_id || params[:report_id]
|
||||
if report_id.present?
|
||||
admin_report_path(report_id)
|
||||
else
|
||||
admin_account_statuses_path(params[:account_id], current_params)
|
||||
end
|
||||
def form_status_batch_params
|
||||
params.require(:form_status_batch).permit(:action, status_ids: [])
|
||||
end
|
||||
|
||||
def set_account
|
||||
@account = Account.find(params[:account_id])
|
||||
end
|
||||
|
||||
def set_statuses
|
||||
@statuses = Admin::StatusFilter.new(@account, filter_params).results.preload(:application, :preloadable_poll, :media_attachments, active_mentions: :account, reblog: [:account, :application, :preloadable_poll, :media_attachments, active_mentions: :account]).page(params[:page]).per(PER_PAGE)
|
||||
end
|
||||
|
||||
def filter_params
|
||||
params.slice(*Admin::StatusFilter::KEYS).permit(*Admin::StatusFilter::KEYS)
|
||||
end
|
||||
|
||||
def current_params
|
||||
params.slice(:media, :page).permit(:media, :page)
|
||||
page = (params[:page] || 1).to_i
|
||||
|
||||
{
|
||||
media: params[:media],
|
||||
page: page > 1 && page,
|
||||
}.select { |_, value| value.present? }
|
||||
end
|
||||
|
||||
def action_from_button
|
||||
if params[:report]
|
||||
'report'
|
||||
elsif params[:remove_from_report]
|
||||
'remove_from_report'
|
||||
if params[:nsfw_on]
|
||||
'nsfw_on'
|
||||
elsif params[:nsfw_off]
|
||||
'nsfw_off'
|
||||
elsif params[:delete]
|
||||
'delete'
|
||||
end
|
||||
|
|
|
@ -2,12 +2,38 @@
|
|||
|
||||
module Admin
|
||||
class TagsController < BaseController
|
||||
before_action :set_tag
|
||||
before_action :set_tag, except: [:index, :batch, :approve_all, :reject_all]
|
||||
before_action :set_usage_by_domain, except: [:index, :batch, :approve_all, :reject_all]
|
||||
before_action :set_counters, except: [:index, :batch, :approve_all, :reject_all]
|
||||
|
||||
def index
|
||||
authorize :tag, :index?
|
||||
|
||||
@tags = filtered_tags.page(params[:page])
|
||||
@form = Form::TagBatch.new
|
||||
end
|
||||
|
||||
def batch
|
||||
@form = Form::TagBatch.new(form_tag_batch_params.merge(current_account: current_account, action: action_from_button))
|
||||
@form.save
|
||||
rescue ActionController::ParameterMissing
|
||||
flash[:alert] = I18n.t('admin.accounts.no_account_selected')
|
||||
ensure
|
||||
redirect_to admin_tags_path(filter_params)
|
||||
end
|
||||
|
||||
def approve_all
|
||||
Form::TagBatch.new(current_account: current_account, tag_ids: Tag.pending_review.pluck(:id), action: 'approve').save
|
||||
redirect_to admin_tags_path(filter_params)
|
||||
end
|
||||
|
||||
def reject_all
|
||||
Form::TagBatch.new(current_account: current_account, tag_ids: Tag.pending_review.pluck(:id), action: 'reject').save
|
||||
redirect_to admin_tags_path(filter_params)
|
||||
end
|
||||
|
||||
def show
|
||||
authorize @tag, :show?
|
||||
|
||||
@time_period = (6.days.ago.to_date...Time.now.utc.to_date)
|
||||
end
|
||||
|
||||
def update
|
||||
|
@ -26,8 +52,52 @@ module Admin
|
|||
@tag = Tag.find(params[:id])
|
||||
end
|
||||
|
||||
def set_usage_by_domain
|
||||
@usage_by_domain = @tag.statuses
|
||||
.with_public_visibility
|
||||
.excluding_silenced_accounts
|
||||
.where(Status.arel_table[:id].gteq(Mastodon::Snowflake.id_at(Time.now.utc.beginning_of_day)))
|
||||
.joins(:account)
|
||||
.group('accounts.domain')
|
||||
.reorder(statuses_count: :desc)
|
||||
.pluck(Arel.sql('accounts.domain, count(*) AS statuses_count'))
|
||||
end
|
||||
|
||||
def set_counters
|
||||
@accounts_today = @tag.history.first[:accounts]
|
||||
@accounts_week = Redis.current.pfcount(*current_week_days.map { |day| "activity:tags:#{@tag.id}:#{day}:accounts" })
|
||||
end
|
||||
|
||||
def filtered_tags
|
||||
TagFilter.new(filter_params).results
|
||||
end
|
||||
|
||||
def filter_params
|
||||
params.slice(:page, *TagFilter::KEYS).permit(:page, *TagFilter::KEYS)
|
||||
end
|
||||
|
||||
def tag_params
|
||||
params.require(:tag).permit(:name, :trendable, :usable, :listable)
|
||||
end
|
||||
|
||||
def current_week_days
|
||||
now = Time.now.utc.beginning_of_day.to_date
|
||||
|
||||
(Date.commercial(now.cwyear, now.cweek)..now).map do |date|
|
||||
date.to_time(:utc).beginning_of_day.to_i
|
||||
end
|
||||
end
|
||||
|
||||
def form_tag_batch_params
|
||||
params.require(:form_tag_batch).permit(:action, tag_ids: [])
|
||||
end
|
||||
|
||||
def action_from_button
|
||||
if params[:approve]
|
||||
'approve'
|
||||
elsif params[:reject]
|
||||
'reject'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Admin::Trends::Links::PreviewCardProvidersController < Admin::BaseController
|
||||
def index
|
||||
authorize :preview_card_provider, :index?
|
||||
|
||||
@preview_card_providers = filtered_preview_card_providers.page(params[:page])
|
||||
@form = Trends::PreviewCardProviderBatch.new
|
||||
end
|
||||
|
||||
def batch
|
||||
@form = Trends::PreviewCardProviderBatch.new(trends_preview_card_provider_batch_params.merge(current_account: current_account, action: action_from_button))
|
||||
@form.save
|
||||
rescue ActionController::ParameterMissing
|
||||
flash[:alert] = I18n.t('admin.accounts.no_account_selected')
|
||||
ensure
|
||||
redirect_to admin_trends_links_preview_card_providers_path(filter_params)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def filtered_preview_card_providers
|
||||
Trends::PreviewCardProviderFilter.new(filter_params).results
|
||||
end
|
||||
|
||||
def filter_params
|
||||
params.slice(:page, *Trends::PreviewCardProviderFilter::KEYS).permit(:page, *Trends::PreviewCardProviderFilter::KEYS)
|
||||
end
|
||||
|
||||
def trends_preview_card_provider_batch_params
|
||||
params.require(:trends_preview_card_provider_batch).permit(:action, preview_card_provider_ids: [])
|
||||
end
|
||||
|
||||
def action_from_button
|
||||
if params[:approve]
|
||||
'approve'
|
||||
elsif params[:reject]
|
||||
'reject'
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,45 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Admin::Trends::LinksController < Admin::BaseController
|
||||
def index
|
||||
authorize :preview_card, :index?
|
||||
|
||||
@preview_cards = filtered_preview_cards.page(params[:page])
|
||||
@form = Trends::PreviewCardBatch.new
|
||||
end
|
||||
|
||||
def batch
|
||||
@form = Trends::PreviewCardBatch.new(trends_preview_card_batch_params.merge(current_account: current_account, action: action_from_button))
|
||||
@form.save
|
||||
rescue ActionController::ParameterMissing
|
||||
flash[:alert] = I18n.t('admin.accounts.no_account_selected')
|
||||
ensure
|
||||
redirect_to admin_trends_links_path(filter_params)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def filtered_preview_cards
|
||||
Trends::PreviewCardFilter.new(filter_params.with_defaults(trending: 'all')).results
|
||||
end
|
||||
|
||||
def filter_params
|
||||
params.slice(:page, *Trends::PreviewCardFilter::KEYS).permit(:page, *Trends::PreviewCardFilter::KEYS)
|
||||
end
|
||||
|
||||
def trends_preview_card_batch_params
|
||||
params.require(:trends_preview_card_batch).permit(:action, preview_card_ids: [])
|
||||
end
|
||||
|
||||
def action_from_button
|
||||
if params[:approve]
|
||||
'approve'
|
||||
elsif params[:approve_providers]
|
||||
'approve_providers'
|
||||
elsif params[:reject]
|
||||
'reject'
|
||||
elsif params[:reject_providers]
|
||||
'reject_providers'
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,45 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Admin::Trends::StatusesController < Admin::BaseController
|
||||
def index
|
||||
authorize :status, :index?
|
||||
|
||||
@statuses = filtered_statuses.page(params[:page])
|
||||
@form = Trends::StatusBatch.new
|
||||
end
|
||||
|
||||
def batch
|
||||
@form = Trends::StatusBatch.new(trends_status_batch_params.merge(current_account: current_account, action: action_from_button))
|
||||
@form.save
|
||||
rescue ActionController::ParameterMissing
|
||||
flash[:alert] = I18n.t('admin.accounts.no_account_selected')
|
||||
ensure
|
||||
redirect_to admin_trends_statuses_path(filter_params)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def filtered_statuses
|
||||
Trends::StatusFilter.new(filter_params.with_defaults(trending: 'all')).results.includes(:account, :media_attachments, :active_mentions)
|
||||
end
|
||||
|
||||
def filter_params
|
||||
params.slice(:page, *Trends::StatusFilter::KEYS).permit(:page, *Trends::StatusFilter::KEYS)
|
||||
end
|
||||
|
||||
def trends_status_batch_params
|
||||
params.require(:trends_status_batch).permit(:action, status_ids: [])
|
||||
end
|
||||
|
||||
def action_from_button
|
||||
if params[:approve]
|
||||
'approve'
|
||||
elsif params[:approve_accounts]
|
||||
'approve_accounts'
|
||||
elsif params[:reject]
|
||||
'reject'
|
||||
elsif params[:reject_accounts]
|
||||
'reject_accounts'
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,41 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Admin::Trends::TagsController < Admin::BaseController
|
||||
def index
|
||||
authorize :tag, :index?
|
||||
|
||||
@tags = filtered_tags.page(params[:page])
|
||||
@form = Trends::TagBatch.new
|
||||
end
|
||||
|
||||
def batch
|
||||
@form = Trends::TagBatch.new(trends_tag_batch_params.merge(current_account: current_account, action: action_from_button))
|
||||
@form.save
|
||||
rescue ActionController::ParameterMissing
|
||||
flash[:alert] = I18n.t('admin.accounts.no_account_selected')
|
||||
ensure
|
||||
redirect_to admin_trends_tags_path(filter_params)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def filtered_tags
|
||||
Trends::TagFilter.new(filter_params).results
|
||||
end
|
||||
|
||||
def filter_params
|
||||
params.slice(:page, *Trends::TagFilter::KEYS).permit(:page, *Trends::TagFilter::KEYS)
|
||||
end
|
||||
|
||||
def trends_tag_batch_params
|
||||
params.require(:trends_tag_batch).permit(:action, tag_ids: [])
|
||||
end
|
||||
|
||||
def action_from_button
|
||||
if params[:approve]
|
||||
'approve'
|
||||
elsif params[:reject]
|
||||
'reject'
|
||||
end
|
||||
end
|
||||
end
|
|
@ -5,17 +5,17 @@ class Api::BaseController < ApplicationController
|
|||
DEFAULT_ACCOUNTS_LIMIT = 40
|
||||
|
||||
include RateLimitHeaders
|
||||
include AccessTokenTrackingConcern
|
||||
|
||||
skip_before_action :store_current_location
|
||||
skip_before_action :require_functional!, unless: :whitelist_mode?
|
||||
|
||||
before_action :require_authenticated_user!, if: :disallow_unauthenticated_api_access?
|
||||
before_action :require_not_suspended!
|
||||
before_action :set_cache_headers
|
||||
|
||||
protect_from_forgery with: :null_session
|
||||
|
||||
skip_around_action :set_locale
|
||||
|
||||
rescue_from ActiveRecord::RecordInvalid, Mastodon::ValidationError do |e|
|
||||
render json: { error: e.to_s }, status: 422
|
||||
end
|
||||
|
@ -98,10 +98,6 @@ class Api::BaseController < ApplicationController
|
|||
render json: { error: 'This method requires an authenticated user' }, status: 401 unless current_user
|
||||
end
|
||||
|
||||
def require_not_suspended!
|
||||
render json: { error: 'Your login is currently disabled' }, status: 403 if current_user&.account&.suspended?
|
||||
end
|
||||
|
||||
def require_user!
|
||||
if !current_user
|
||||
render json: { error: 'This method requires an authenticated user' }, status: 422
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::ProofsController < Api::BaseController
|
||||
include AccountOwnedConcern
|
||||
|
||||
skip_before_action :require_authenticated_user!
|
||||
|
||||
before_action :set_provider
|
||||
|
||||
def index
|
||||
render json: @account, serializer: @provider.serializer_class
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_provider
|
||||
@provider = ProofProvider.find(params[:provider]) || raise(ActiveRecord::RecordNotFound)
|
||||
end
|
||||
|
||||
def username_param
|
||||
params[:username]
|
||||
end
|
||||
end
|
|
@ -1,25 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::Accounts::FamiliarFollowersController < Api::BaseController
|
||||
before_action -> { doorkeeper_authorize! :read, :'read:follows' }
|
||||
before_action :require_user!
|
||||
before_action :set_accounts
|
||||
|
||||
def index
|
||||
render json: familiar_followers.accounts, each_serializer: REST::FamiliarFollowersSerializer
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_accounts
|
||||
@accounts = Account.without_suspended.where(id: account_ids).select('id, hide_collections').index_by(&:id).values_at(*account_ids).compact
|
||||
end
|
||||
|
||||
def familiar_followers
|
||||
FamiliarFollowersPresenter.new(@accounts, current_user.account_id)
|
||||
end
|
||||
|
||||
def account_ids
|
||||
Array(params[:id]).map(&:to_i)
|
||||
end
|
||||
end
|
|
@ -5,7 +5,8 @@ class Api::V1::Accounts::IdentityProofsController < Api::BaseController
|
|||
before_action :set_account
|
||||
|
||||
def index
|
||||
render json: []
|
||||
@proofs = @account.suspended? ? [] : @account.identity_proofs.active
|
||||
render json: @proofs, each_serializer: REST::IdentityProofSerializer
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -12,7 +12,5 @@ class Api::V1::Accounts::LookupController < Api::BaseController
|
|||
|
||||
def set_account
|
||||
@account = ResolveAccountService.new.call(params[:acct], skip_webfinger: true) || raise(ActiveRecord::RecordNotFound)
|
||||
rescue Addressable::URI::InvalidURIError
|
||||
raise(ActiveRecord::RecordNotFound)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -22,16 +22,55 @@ class Api::V1::Accounts::StatusesController < Api::BaseController
|
|||
end
|
||||
|
||||
def cached_account_statuses
|
||||
statuses = truthy_param?(:pinned) ? pinned_scope : permitted_account_statuses
|
||||
|
||||
statuses.merge!(only_media_scope) if truthy_param?(:only_media)
|
||||
statuses.merge!(no_replies_scope) if truthy_param?(:exclude_replies)
|
||||
statuses.merge!(no_reblogs_scope) if truthy_param?(:exclude_reblogs)
|
||||
statuses.merge!(hashtag_scope) if params[:tagged].present?
|
||||
|
||||
cache_collection_paginated_by_id(
|
||||
AccountStatusesFilter.new(@account, current_account, params).results,
|
||||
statuses,
|
||||
Status,
|
||||
limit_param(DEFAULT_STATUSES_LIMIT),
|
||||
params_slice(:max_id, :since_id, :min_id)
|
||||
)
|
||||
end
|
||||
|
||||
def permitted_account_statuses
|
||||
@account.statuses.permitted_for(@account, current_account)
|
||||
end
|
||||
|
||||
def only_media_scope
|
||||
Status.joins(:media_attachments).merge(@account.media_attachments.reorder(nil)).group(:id)
|
||||
end
|
||||
|
||||
def pinned_scope
|
||||
return Status.none if @account.blocking?(current_account)
|
||||
|
||||
@account.pinned_statuses
|
||||
end
|
||||
|
||||
def no_replies_scope
|
||||
Status.without_replies
|
||||
end
|
||||
|
||||
def no_reblogs_scope
|
||||
Status.without_reblogs
|
||||
end
|
||||
|
||||
def hashtag_scope
|
||||
tag = Tag.find_normalized(params[:tagged])
|
||||
|
||||
if tag
|
||||
Status.tagged_with(tag.id)
|
||||
else
|
||||
Status.none
|
||||
end
|
||||
end
|
||||
|
||||
def pagination_params(core_params)
|
||||
params.slice(:limit, *AccountStatusesFilter::KEYS).permit(:limit, *AccountStatusesFilter::KEYS).merge(core_params)
|
||||
params.slice(:limit, :only_media, :exclude_replies).permit(:limit, :only_media, :exclude_replies).merge(core_params)
|
||||
end
|
||||
|
||||
def insert_pagination_headers
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::AccountsController < Api::BaseController
|
||||
before_action -> { authorize_if_got_token! :read, :'read:accounts' }, except: [:create, :follow, :unfollow, :remove_from_followers, :block, :unblock, :mute, :unmute]
|
||||
before_action -> { doorkeeper_authorize! :follow, :write, :'write:follows' }, only: [:follow, :unfollow, :remove_from_followers]
|
||||
before_action -> { doorkeeper_authorize! :follow, :write, :'write:mutes' }, only: [:mute, :unmute]
|
||||
before_action -> { doorkeeper_authorize! :follow, :write, :'write:blocks' }, only: [:block, :unblock]
|
||||
before_action -> { authorize_if_got_token! :read, :'read:accounts' }, except: [:create, :follow, :unfollow, :block, :unblock, :mute, :unmute]
|
||||
before_action -> { doorkeeper_authorize! :follow, :'write:follows' }, only: [:follow, :unfollow]
|
||||
before_action -> { doorkeeper_authorize! :follow, :'write:mutes' }, only: [:mute, :unmute]
|
||||
before_action -> { doorkeeper_authorize! :follow, :'write:blocks' }, only: [:block, :unblock]
|
||||
before_action -> { doorkeeper_authorize! :write, :'write:accounts' }, only: [:create]
|
||||
|
||||
before_action :require_user!, except: [:show, :create]
|
||||
before_action :set_account, except: [:create]
|
||||
before_action :check_account_approval, except: [:create]
|
||||
before_action :check_account_confirmation, except: [:create]
|
||||
before_action :check_enabled_registrations, only: [:create]
|
||||
|
||||
skip_before_action :require_authenticated_user!, only: :create
|
||||
|
@ -55,11 +53,6 @@ class Api::V1::AccountsController < Api::BaseController
|
|||
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
|
||||
end
|
||||
|
||||
def remove_from_followers
|
||||
RemoveFromFollowersService.new.call(current_user.account, @account)
|
||||
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
|
||||
end
|
||||
|
||||
def unblock
|
||||
UnblockService.new.call(current_user.account, @account)
|
||||
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
|
||||
|
@ -76,14 +69,6 @@ class Api::V1::AccountsController < Api::BaseController
|
|||
@account = Account.find(params[:id])
|
||||
end
|
||||
|
||||
def check_account_approval
|
||||
raise(ActiveRecord::RecordNotFound) if @account.local? && @account.user_pending?
|
||||
end
|
||||
|
||||
def check_account_confirmation
|
||||
raise(ActiveRecord::RecordNotFound) if @account.local? && !@account.user_confirmed?
|
||||
end
|
||||
|
||||
def relationships(**options)
|
||||
AccountRelationshipsPresenter.new([@account.id], current_user.account_id, **options)
|
||||
end
|
||||
|
@ -93,14 +78,10 @@ class Api::V1::AccountsController < Api::BaseController
|
|||
end
|
||||
|
||||
def check_enabled_registrations
|
||||
forbidden if single_user_mode? || omniauth_only? || !allowed_registrations?
|
||||
forbidden if single_user_mode? || !allowed_registrations?
|
||||
end
|
||||
|
||||
def allowed_registrations?
|
||||
Setting.registrations_mode != 'none'
|
||||
end
|
||||
|
||||
def omniauth_only?
|
||||
ENV['OMNIAUTH_ONLY'] == 'true'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::Admin::AccountActionsController < Api::BaseController
|
||||
before_action -> { authorize_if_got_token! :'admin:write', :'admin:write:accounts' }
|
||||
before_action -> { doorkeeper_authorize! :'admin:write', :'admin:write:accounts' }
|
||||
before_action :require_staff!
|
||||
before_action :set_account
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@ class Api::V1::Admin::AccountsController < Api::BaseController
|
|||
|
||||
LIMIT = 100
|
||||
|
||||
before_action -> { authorize_if_got_token! :'admin:read', :'admin:read:accounts' }, only: [:index, :show]
|
||||
before_action -> { authorize_if_got_token! :'admin:write', :'admin:write:accounts' }, except: [:index, :show]
|
||||
before_action -> { doorkeeper_authorize! :'admin:read', :'admin:read:accounts' }, only: [:index, :show]
|
||||
before_action -> { doorkeeper_authorize! :'admin:write', :'admin:write:accounts' }, except: [:index, :show]
|
||||
before_action :require_staff!
|
||||
before_action :set_accounts, only: :index
|
||||
before_action :set_account, except: :index
|
||||
|
@ -65,9 +65,8 @@ class Api::V1::Admin::AccountsController < Api::BaseController
|
|||
|
||||
def destroy
|
||||
authorize @account, :destroy?
|
||||
json = render_to_body json: @account, serializer: REST::Admin::AccountSerializer
|
||||
Admin::AccountDeletionWorker.perform_async(@account.id)
|
||||
render json: json
|
||||
render json: @account, serializer: REST::Admin::AccountSerializer
|
||||
end
|
||||
|
||||
def unsensitive
|
||||
|
@ -95,7 +94,7 @@ class Api::V1::Admin::AccountsController < Api::BaseController
|
|||
private
|
||||
|
||||
def set_accounts
|
||||
@accounts = filtered_accounts.order(id: :desc).includes(user: [:invite_request, :invite, :ips]).to_a_paginated_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id))
|
||||
@accounts = filtered_accounts.order(id: :desc).includes(user: [:invite_request, :invite]).to_a_paginated_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id))
|
||||
end
|
||||
|
||||
def set_account
|
||||
|
@ -103,27 +102,13 @@ class Api::V1::Admin::AccountsController < Api::BaseController
|
|||
end
|
||||
|
||||
def filtered_accounts
|
||||
AccountFilter.new(translated_filter_params).results
|
||||
AccountFilter.new(filter_params).results
|
||||
end
|
||||
|
||||
def filter_params
|
||||
params.permit(*FILTER_PARAMS)
|
||||
end
|
||||
|
||||
def translated_filter_params
|
||||
translated_params = { origin: 'local', status: 'active' }.merge(filter_params.slice(*AccountFilter::KEYS))
|
||||
|
||||
translated_params[:origin] = 'remote' if params[:remote].present?
|
||||
|
||||
%i(active pending disabled silenced suspended).each do |status|
|
||||
translated_params[:status] = status.to_s if params[status].present?
|
||||
end
|
||||
|
||||
translated_params[:permissions] = 'staff' if params[:staff].present?
|
||||
|
||||
translated_params
|
||||
end
|
||||
|
||||
def insert_pagination_headers
|
||||
set_pagination_headers(next_path, prev_path)
|
||||
end
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::Admin::DimensionsController < Api::BaseController
|
||||
before_action -> { authorize_if_got_token! :'admin:read' }
|
||||
before_action :require_staff!
|
||||
before_action :set_dimensions
|
||||
|
||||
def create
|
||||
render json: @dimensions, each_serializer: REST::Admin::DimensionSerializer
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_dimensions
|
||||
@dimensions = Admin::Metrics::Dimension.retrieve(
|
||||
params[:keys],
|
||||
params[:start_at],
|
||||
params[:end_at],
|
||||
params[:limit],
|
||||
params
|
||||
)
|
||||
end
|
||||
end
|
|
@ -1,22 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::Admin::MeasuresController < Api::BaseController
|
||||
before_action -> { authorize_if_got_token! :'admin:read' }
|
||||
before_action :require_staff!
|
||||
before_action :set_measures
|
||||
|
||||
def create
|
||||
render json: @measures, each_serializer: REST::Admin::MeasureSerializer
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_measures
|
||||
@measures = Admin::Metrics::Measure.retrieve(
|
||||
params[:keys],
|
||||
params[:start_at],
|
||||
params[:end_at],
|
||||
params
|
||||
)
|
||||
end
|
||||
end
|
|
@ -6,8 +6,8 @@ class Api::V1::Admin::ReportsController < Api::BaseController
|
|||
|
||||
LIMIT = 100
|
||||
|
||||
before_action -> { authorize_if_got_token! :'admin:read', :'admin:read:reports' }, only: [:index, :show]
|
||||
before_action -> { authorize_if_got_token! :'admin:write', :'admin:write:reports' }, except: [:index, :show]
|
||||
before_action -> { doorkeeper_authorize! :'admin:read', :'admin:read:reports' }, only: [:index, :show]
|
||||
before_action -> { doorkeeper_authorize! :'admin:write', :'admin:write:reports' }, except: [:index, :show]
|
||||
before_action :require_staff!
|
||||
before_action :set_reports, only: :index
|
||||
before_action :set_report, except: :index
|
||||
|
@ -32,12 +32,6 @@ class Api::V1::Admin::ReportsController < Api::BaseController
|
|||
render json: @report, serializer: REST::Admin::ReportSerializer
|
||||
end
|
||||
|
||||
def update
|
||||
authorize @report, :update?
|
||||
@report.update!(report_params)
|
||||
render json: @report, serializer: REST::Admin::ReportSerializer
|
||||
end
|
||||
|
||||
def assign_to_self
|
||||
authorize @report, :update?
|
||||
@report.update!(assigned_account_id: current_account.id)
|
||||
|
@ -80,10 +74,6 @@ class Api::V1::Admin::ReportsController < Api::BaseController
|
|||
ReportFilter.new(filter_params).results
|
||||
end
|
||||
|
||||
def report_params
|
||||
params.permit(:category, rule_ids: [])
|
||||
end
|
||||
|
||||
def filter_params
|
||||
params.permit(*FILTER_PARAMS)
|
||||
end
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::Admin::RetentionController < Api::BaseController
|
||||
before_action -> { authorize_if_got_token! :'admin:read' }
|
||||
before_action :require_staff!
|
||||
before_action :set_cohorts
|
||||
|
||||
def create
|
||||
render json: @cohorts, each_serializer: REST::Admin::CohortSerializer
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_cohorts
|
||||
@cohorts = Admin::Metrics::Retention.new(
|
||||
params[:start_at],
|
||||
params[:end_at],
|
||||
params[:frequency]
|
||||
).cohorts
|
||||
end
|
||||
end
|
|
@ -1,17 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::Admin::Trends::LinksController < Api::BaseController
|
||||
before_action -> { authorize_if_got_token! :'admin:read' }
|
||||
before_action :require_staff!
|
||||
before_action :set_links
|
||||
|
||||
def index
|
||||
render json: @links, each_serializer: REST::Trends::LinkSerializer
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_links
|
||||
@links = Trends.links.query.limit(limit_param(10))
|
||||
end
|
||||
end
|
|
@ -1,17 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::Admin::Trends::StatusesController < Api::BaseController
|
||||
before_action -> { authorize_if_got_token! :'admin:read' }
|
||||
before_action :require_staff!
|
||||
before_action :set_statuses
|
||||
|
||||
def index
|
||||
render json: @statuses, each_serializer: REST::StatusSerializer
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_statuses
|
||||
@statuses = cache_collection(Trends.statuses.query.limit(limit_param(DEFAULT_STATUSES_LIMIT)), Status)
|
||||
end
|
||||
end
|
|
@ -1,17 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::Admin::Trends::TagsController < Api::BaseController
|
||||
before_action -> { authorize_if_got_token! :'admin:read' }
|
||||
before_action :require_staff!
|
||||
before_action :set_tags
|
||||
|
||||
def index
|
||||
render json: @tags, each_serializer: REST::Admin::TagSerializer
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_tags
|
||||
@tags = Trends.tags.query.limit(limit_param(10))
|
||||
end
|
||||
end
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::BlocksController < Api::BaseController
|
||||
before_action -> { doorkeeper_authorize! :follow, :read, :'read:blocks' }
|
||||
before_action -> { doorkeeper_authorize! :follow, :'read:blocks' }
|
||||
before_action :require_user!
|
||||
after_action :insert_pagination_headers
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ class Api::V1::BookmarksController < Api::BaseController
|
|||
end
|
||||
|
||||
def results
|
||||
@_results ||= account_bookmarks.joins(:status).eager_load(:status).to_a_paginated_by_id(
|
||||
@_results ||= account_bookmarks.eager_load(:status).to_a_paginated_by_id(
|
||||
limit_param(DEFAULT_STATUSES_LIMIT),
|
||||
params_slice(:max_id, :since_id, :min_id)
|
||||
)
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
class Api::V1::DomainBlocksController < Api::BaseController
|
||||
BLOCK_LIMIT = 100
|
||||
|
||||
before_action -> { doorkeeper_authorize! :follow, :read, :'read:blocks' }, only: :show
|
||||
before_action -> { doorkeeper_authorize! :follow, :write, :'write:blocks' }, except: :show
|
||||
before_action -> { doorkeeper_authorize! :follow, :'read:blocks' }, only: :show
|
||||
before_action -> { doorkeeper_authorize! :follow, :'write:blocks' }, except: :show
|
||||
before_action :require_user!
|
||||
after_action :insert_pagination_headers, only: :show
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::Emails::ConfirmationsController < Api::BaseController
|
||||
before_action -> { doorkeeper_authorize! :write, :'write:accounts' }
|
||||
before_action :doorkeeper_authorize!
|
||||
before_action :require_user_owned_by_application!
|
||||
before_action :require_user_not_confirmed!
|
||||
|
||||
|
@ -19,6 +19,6 @@ class Api::V1::Emails::ConfirmationsController < Api::BaseController
|
|||
end
|
||||
|
||||
def require_user_not_confirmed!
|
||||
render json: { error: 'This method is only available while the e-mail is awaiting confirmation' }, status: :forbidden unless !current_user.confirmed? || current_user.unconfirmed_email.present?
|
||||
render json: { error: 'This method is only available while the e-mail is awaiting confirmation' }, status: :forbidden if current_user.confirmed? || current_user.unconfirmed_email.blank?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -21,7 +21,7 @@ class Api::V1::FavouritesController < Api::BaseController
|
|||
end
|
||||
|
||||
def results
|
||||
@_results ||= account_favourites.joins(:status).eager_load(:status).to_a_paginated_by_id(
|
||||
@_results ||= account_favourites.eager_load(:status).to_a_paginated_by_id(
|
||||
limit_param(DEFAULT_STATUSES_LIMIT),
|
||||
params_slice(:max_id, :since_id, :min_id)
|
||||
)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::FollowRequestsController < Api::BaseController
|
||||
before_action -> { doorkeeper_authorize! :follow, :read, :'read:follows' }, only: :index
|
||||
before_action -> { doorkeeper_authorize! :follow, :write, :'write:follows' }, except: :index
|
||||
before_action -> { doorkeeper_authorize! :follow, :'read:follows' }, only: :index
|
||||
before_action -> { doorkeeper_authorize! :follow, :'write:follows' }, except: :index
|
||||
before_action :require_user!
|
||||
after_action :insert_pagination_headers, only: :index
|
||||
|
||||
|
@ -13,7 +13,7 @@ class Api::V1::FollowRequestsController < Api::BaseController
|
|||
|
||||
def authorize
|
||||
AuthorizeFollowService.new.call(account, current_account)
|
||||
LocalNotificationWorker.perform_async(current_account.id, Follow.find_by(account: account, target_account: current_account).id, 'Follow', 'follow')
|
||||
NotifyService.new.call(current_account, :follow, Follow.find_by(account: account, target_account: current_account))
|
||||
render json: account, serializer: REST::RelationshipSerializer, relationships: relationships
|
||||
end
|
||||
|
||||
|
|
|
@ -14,21 +14,22 @@ class Api::V1::Instances::ActivityController < Api::BaseController
|
|||
private
|
||||
|
||||
def activity
|
||||
statuses_tracker = ActivityTracker.new('activity:statuses:local', :basic)
|
||||
logins_tracker = ActivityTracker.new('activity:logins', :unique)
|
||||
registrations_tracker = ActivityTracker.new('activity:accounts:local', :basic)
|
||||
weeks = []
|
||||
|
||||
(0...12).map do |i|
|
||||
start_of_week = i.weeks.ago
|
||||
end_of_week = start_of_week + 6.days
|
||||
12.times do |i|
|
||||
day = i.weeks.ago.to_date
|
||||
week_id = day.cweek
|
||||
week = Date.commercial(day.cwyear, week_id)
|
||||
|
||||
{
|
||||
week: start_of_week.to_i.to_s,
|
||||
statuses: statuses_tracker.sum(start_of_week, end_of_week).to_s,
|
||||
logins: logins_tracker.sum(start_of_week, end_of_week).to_s,
|
||||
registrations: registrations_tracker.sum(start_of_week, end_of_week).to_s,
|
||||
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!
|
||||
|
|
|
@ -20,7 +20,7 @@ class Api::V1::MediaController < Api::BaseController
|
|||
end
|
||||
|
||||
def update
|
||||
@media_attachment.update!(updateable_media_attachment_params)
|
||||
@media_attachment.update!(media_attachment_params)
|
||||
render json: @media_attachment, serializer: REST::MediaAttachmentSerializer, status: status_code_for_media_attachment
|
||||
end
|
||||
|
||||
|
@ -31,7 +31,7 @@ class Api::V1::MediaController < Api::BaseController
|
|||
end
|
||||
|
||||
def set_media_attachment
|
||||
@media_attachment = current_account.media_attachments.where(status_id: nil).find(params[:id])
|
||||
@media_attachment = current_account.media_attachments.unattached.find(params[:id])
|
||||
end
|
||||
|
||||
def check_processing
|
||||
|
@ -42,10 +42,6 @@ class Api::V1::MediaController < Api::BaseController
|
|||
params.permit(:file, :thumbnail, :description, :focus)
|
||||
end
|
||||
|
||||
def updateable_media_attachment_params
|
||||
params.permit(:thumbnail, :description, :focus)
|
||||
end
|
||||
|
||||
def file_type_error
|
||||
{ error: 'File type of uploaded media could not be verified' }
|
||||
end
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::MutesController < Api::BaseController
|
||||
before_action -> { doorkeeper_authorize! :follow, :read, :'read:mutes' }
|
||||
before_action -> { doorkeeper_authorize! :follow, :'read:mutes' }
|
||||
before_action :require_user!
|
||||
after_action :insert_pagination_headers
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::NotificationsController < Api::BaseController
|
||||
before_action -> { doorkeeper_authorize! :read, :'read:notifications' }, except: [:clear, :dismiss, :destroy, :destroy_multiple]
|
||||
before_action -> { doorkeeper_authorize! :write, :'write:notifications' }, only: [:clear, :dismiss, :destroy, :destroy_multiple]
|
||||
before_action -> { doorkeeper_authorize! :read, :'read:notifications' }, except: [:clear, :dismiss]
|
||||
before_action -> { doorkeeper_authorize! :write, :'write:notifications' }, only: [:clear, :dismiss]
|
||||
before_action :require_user!
|
||||
after_action :insert_pagination_headers, only: :index
|
||||
|
||||
|
@ -44,18 +44,13 @@ class Api::V1::NotificationsController < Api::BaseController
|
|||
limit_param(DEFAULT_NOTIFICATIONS_LIMIT),
|
||||
params_slice(:max_id, :since_id, :min_id)
|
||||
)
|
||||
|
||||
Notification.preload_cache_collection_target_statuses(notifications) do |target_statuses|
|
||||
cache_collection(target_statuses, Status)
|
||||
end
|
||||
end
|
||||
|
||||
def browserable_account_notifications
|
||||
current_account.notifications.without_suspended.browserable(
|
||||
types: Array(browserable_params[:types]),
|
||||
exclude_types: Array(browserable_params[:exclude_types]),
|
||||
from_account_id: browserable_params[:account_id]
|
||||
)
|
||||
current_account.notifications.without_suspended.browserable(exclude_types, from_account)
|
||||
end
|
||||
|
||||
def target_statuses_from_notifications
|
||||
|
@ -86,11 +81,17 @@ class Api::V1::NotificationsController < Api::BaseController
|
|||
@notifications.first.id
|
||||
end
|
||||
|
||||
def browserable_params
|
||||
params.permit(:account_id, types: [], exclude_types: [])
|
||||
def exclude_types
|
||||
val = params.permit(exclude_types: [])[:exclude_types] || []
|
||||
val = [val] unless val.is_a?(Enumerable)
|
||||
val
|
||||
end
|
||||
|
||||
def from_account
|
||||
params[:account_id]
|
||||
end
|
||||
|
||||
def pagination_params(core_params)
|
||||
params.slice(:limit, :account_id, :types, :exclude_types).permit(:limit, :account_id, types: [], exclude_types: []).merge(core_params)
|
||||
params.slice(:limit, :exclude_types).permit(:limit, exclude_types: []).merge(core_params)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -10,7 +10,9 @@ class Api::V1::ReportsController < Api::BaseController
|
|||
@report = ReportService.new.call(
|
||||
current_account,
|
||||
reported_account,
|
||||
report_params
|
||||
status_ids: reported_status_ids,
|
||||
comment: report_params[:comment],
|
||||
forward: report_params[:forward]
|
||||
)
|
||||
|
||||
render json: @report, serializer: REST::ReportSerializer
|
||||
|
@ -18,11 +20,19 @@ class Api::V1::ReportsController < Api::BaseController
|
|||
|
||||
private
|
||||
|
||||
def reported_status_ids
|
||||
reported_account.statuses.with_discarded.find(status_ids).pluck(:id)
|
||||
end
|
||||
|
||||
def status_ids
|
||||
Array(report_params[:status_ids])
|
||||
end
|
||||
|
||||
def reported_account
|
||||
Account.find(report_params[:account_id])
|
||||
end
|
||||
|
||||
def report_params
|
||||
params.permit(:account_id, :comment, :category, :forward, status_ids: [], rule_ids: [])
|
||||
params.permit(:account_id, :comment, :forward, status_ids: [])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::Statuses::HistoriesController < Api::BaseController
|
||||
include Authorization
|
||||
|
||||
before_action -> { authorize_if_got_token! :read, :'read:statuses' }
|
||||
before_action :set_status
|
||||
|
||||
def show
|
||||
render json: @status.edits.includes(:account, status: [:account]), each_serializer: REST::StatusEditSerializer
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_status
|
||||
@status = Status.find(params[:status_id])
|
||||
authorize @status, :show?
|
||||
rescue Mastodon::NotPermittedError
|
||||
not_found
|
||||
end
|
||||
end
|
|
@ -1,21 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::Statuses::SourcesController < Api::BaseController
|
||||
include Authorization
|
||||
|
||||
before_action -> { doorkeeper_authorize! :read, :'read:statuses' }
|
||||
before_action :set_status
|
||||
|
||||
def show
|
||||
render json: @status, serializer: REST::StatusSourceSerializer
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_status
|
||||
@status = Status.find(params[:status_id])
|
||||
authorize @status, :show?
|
||||
rescue Mastodon::NotPermittedError
|
||||
not_found
|
||||
end
|
||||
end
|
|
@ -3,14 +3,13 @@
|
|||
class Api::V1::StatusesController < Api::BaseController
|
||||
include Authorization
|
||||
|
||||
before_action -> { authorize_if_got_token! :read, :'read:statuses' }, except: [:create, :update, :destroy]
|
||||
before_action -> { doorkeeper_authorize! :write, :'write:statuses' }, only: [:create, :update, :destroy]
|
||||
before_action -> { authorize_if_got_token! :read, :'read:statuses' }, except: [:create, :destroy]
|
||||
before_action -> { doorkeeper_authorize! :write, :'write:statuses' }, only: [:create, :destroy]
|
||||
before_action :require_user!, except: [:show, :context]
|
||||
before_action :set_status, only: [:show, :context]
|
||||
before_action :set_thread, only: [:create]
|
||||
|
||||
override_rate_limit_headers :create, family: :statuses
|
||||
override_rate_limit_headers :update, family: :statuses
|
||||
|
||||
# This API was originally unlimited, pagination cannot be introduced without
|
||||
# breaking backwards-compatibility. Arbitrarily high number to cover most
|
||||
|
@ -36,55 +35,32 @@ class Api::V1::StatusesController < Api::BaseController
|
|||
end
|
||||
|
||||
def create
|
||||
@status = PostStatusService.new.call(
|
||||
current_user.account,
|
||||
text: status_params[:status],
|
||||
thread: @thread,
|
||||
media_ids: status_params[:media_ids],
|
||||
sensitive: status_params[:sensitive],
|
||||
spoiler_text: status_params[:spoiler_text],
|
||||
visibility: status_params[:visibility],
|
||||
language: status_params[:language],
|
||||
scheduled_at: status_params[:scheduled_at],
|
||||
application: doorkeeper_token.application,
|
||||
poll: status_params[:poll],
|
||||
content_type: status_params[:content_type],
|
||||
idempotency: request.headers['Idempotency-Key'],
|
||||
with_rate_limit: true
|
||||
)
|
||||
@status = PostStatusService.new.call(current_user.account,
|
||||
text: status_params[:status],
|
||||
thread: @thread,
|
||||
media_ids: status_params[:media_ids],
|
||||
sensitive: status_params[:sensitive],
|
||||
spoiler_text: status_params[:spoiler_text],
|
||||
visibility: status_params[:visibility],
|
||||
scheduled_at: status_params[:scheduled_at],
|
||||
application: doorkeeper_token.application,
|
||||
poll: status_params[:poll],
|
||||
content_type: status_params[:content_type],
|
||||
idempotency: request.headers['Idempotency-Key'],
|
||||
with_rate_limit: true)
|
||||
|
||||
render json: @status, serializer: @status.is_a?(ScheduledStatus) ? REST::ScheduledStatusSerializer : REST::StatusSerializer
|
||||
end
|
||||
|
||||
def update
|
||||
@status = Status.where(account: current_account).find(params[:id])
|
||||
authorize @status, :update?
|
||||
|
||||
UpdateStatusService.new.call(
|
||||
@status,
|
||||
current_account.id,
|
||||
text: status_params[:status],
|
||||
media_ids: status_params[:media_ids],
|
||||
sensitive: status_params[:sensitive],
|
||||
spoiler_text: status_params[:spoiler_text],
|
||||
poll: status_params[:poll],
|
||||
content_type: status_params[:content_type]
|
||||
)
|
||||
|
||||
render json: @status, serializer: REST::StatusSerializer
|
||||
end
|
||||
|
||||
def destroy
|
||||
@status = Status.where(account: current_account).find(params[:id])
|
||||
@status = Status.where(account_id: current_user.account).find(params[:id])
|
||||
authorize @status, :destroy?
|
||||
|
||||
@status.discard
|
||||
RemovalWorker.perform_async(@status.id, redraft: true)
|
||||
@status.account.statuses_count = @status.account.statuses_count - 1
|
||||
json = render_to_body json: @status, serializer: REST::StatusSerializer, source_requested: true
|
||||
|
||||
RemovalWorker.perform_async(@status.id, { 'redraft' => true })
|
||||
|
||||
render json: json
|
||||
render json: @status, serializer: REST::StatusSerializer, source_requested: true
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -97,9 +73,8 @@ class Api::V1::StatusesController < Api::BaseController
|
|||
end
|
||||
|
||||
def set_thread
|
||||
@thread = Status.find(status_params[:in_reply_to_id]) if status_params[:in_reply_to_id].present?
|
||||
authorize(@thread, :show?) if @thread.present?
|
||||
rescue ActiveRecord::RecordNotFound, Mastodon::NotPermittedError
|
||||
@thread = status_params[:in_reply_to_id].blank? ? nil : Status.find(status_params[:in_reply_to_id])
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render json: { error: I18n.t('statuses.errors.in_reply_not_found') }, status: 404
|
||||
end
|
||||
|
||||
|
@ -110,7 +85,6 @@ class Api::V1::StatusesController < Api::BaseController
|
|||
:sensitive,
|
||||
:spoiler_text,
|
||||
:visibility,
|
||||
:language,
|
||||
:scheduled_at,
|
||||
:content_type,
|
||||
media_ids: [],
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::Trends::LinksController < Api::BaseController
|
||||
before_action :set_links
|
||||
|
||||
after_action :insert_pagination_headers
|
||||
|
||||
DEFAULT_LINKS_LIMIT = 10
|
||||
|
||||
def index
|
||||
render json: @links, each_serializer: REST::Trends::LinkSerializer
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_links
|
||||
@links = begin
|
||||
if Setting.trends
|
||||
links_from_trends
|
||||
else
|
||||
[]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def links_from_trends
|
||||
Trends.links.query.allowed.in_locale(content_locale).offset(offset_param).limit(limit_param(DEFAULT_LINKS_LIMIT))
|
||||
end
|
||||
|
||||
def insert_pagination_headers
|
||||
set_pagination_headers(next_path, prev_path)
|
||||
end
|
||||
|
||||
def pagination_params(core_params)
|
||||
params.slice(:limit).permit(:limit).merge(core_params)
|
||||
end
|
||||
|
||||
def next_path
|
||||
api_v1_trends_links_url pagination_params(offset: offset_param + limit_param(DEFAULT_LINKS_LIMIT)) if records_continue?
|
||||
end
|
||||
|
||||
def prev_path
|
||||
api_v1_trends_links_url pagination_params(offset: offset_param - limit_param(DEFAULT_LINKS_LIMIT)) if offset_param > limit_param(DEFAULT_LINKS_LIMIT)
|
||||
end
|
||||
|
||||
def records_continue?
|
||||
@links.size == limit_param(DEFAULT_LINKS_LIMIT)
|
||||
end
|
||||
|
||||
def offset_param
|
||||
params[:offset].to_i
|
||||
end
|
||||
end
|
|
@ -1,53 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::Trends::StatusesController < Api::BaseController
|
||||
before_action :set_statuses
|
||||
|
||||
after_action :insert_pagination_headers
|
||||
|
||||
def index
|
||||
render json: @statuses, each_serializer: REST::StatusSerializer
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_statuses
|
||||
@statuses = begin
|
||||
if Setting.trends
|
||||
cache_collection(statuses_from_trends, Status)
|
||||
else
|
||||
[]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def statuses_from_trends
|
||||
scope = Trends.statuses.query.allowed.in_locale(content_locale)
|
||||
scope = scope.filtered_for(current_account) if user_signed_in?
|
||||
scope.offset(offset_param).limit(limit_param(DEFAULT_STATUSES_LIMIT))
|
||||
end
|
||||
|
||||
def insert_pagination_headers
|
||||
set_pagination_headers(next_path, prev_path)
|
||||
end
|
||||
|
||||
def pagination_params(core_params)
|
||||
params.slice(:limit).permit(:limit).merge(core_params)
|
||||
end
|
||||
|
||||
def next_path
|
||||
api_v1_trends_statuses_url pagination_params(offset: offset_param + limit_param(DEFAULT_STATUSES_LIMIT)) if records_continue?
|
||||
end
|
||||
|
||||
def prev_path
|
||||
api_v1_trends_statuses_url pagination_params(offset: offset_param - limit_param(DEFAULT_STATUSES_LIMIT)) if offset_param > limit_param(DEFAULT_STATUSES_LIMIT)
|
||||
end
|
||||
|
||||
def offset_param
|
||||
params[:offset].to_i
|
||||
end
|
||||
|
||||
def records_continue?
|
||||
@statuses.size == limit_param(DEFAULT_STATUSES_LIMIT)
|
||||
end
|
||||
end
|
|
@ -1,49 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::Trends::TagsController < Api::BaseController
|
||||
before_action :set_tags
|
||||
|
||||
after_action :insert_pagination_headers
|
||||
|
||||
DEFAULT_TAGS_LIMIT = 10
|
||||
|
||||
def index
|
||||
render json: @tags, each_serializer: REST::TagSerializer
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_tags
|
||||
@tags = begin
|
||||
if Setting.trends
|
||||
Trends.tags.query.allowed.offset(offset_param).limit(limit_param(DEFAULT_TAGS_LIMIT))
|
||||
else
|
||||
[]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def insert_pagination_headers
|
||||
set_pagination_headers(next_path, prev_path)
|
||||
end
|
||||
|
||||
def pagination_params(core_params)
|
||||
params.slice(:limit).permit(:limit).merge(core_params)
|
||||
end
|
||||
|
||||
def next_path
|
||||
api_v1_trends_tags_url pagination_params(offset: offset_param + limit_param(DEFAULT_TAGS_LIMIT)) if records_continue?
|
||||
end
|
||||
|
||||
def prev_path
|
||||
api_v1_trends_tags_url pagination_params(offset: offset_param - limit_param(DEFAULT_TAGS_LIMIT)) if offset_param > limit_param(DEFAULT_TAGS_LIMIT)
|
||||
end
|
||||
|
||||
def offset_param
|
||||
params[:offset].to_i
|
||||
end
|
||||
|
||||
def records_continue?
|
||||
@tags.size == limit_param(DEFAULT_TAGS_LIMIT)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::TrendsController < Api::BaseController
|
||||
before_action :set_tags
|
||||
|
||||
def index
|
||||
render json: @tags, each_serializer: REST::TagSerializer
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_tags
|
||||
@tags = TrendingTags.get(limit_param(10))
|
||||
end
|
||||
end
|
|
@ -1,31 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::V2::Admin::AccountsController < Api::V1::Admin::AccountsController
|
||||
FILTER_PARAMS = %i(
|
||||
origin
|
||||
status
|
||||
permissions
|
||||
username
|
||||
by_domain
|
||||
display_name
|
||||
email
|
||||
ip
|
||||
invited_by
|
||||
).freeze
|
||||
|
||||
PAGINATION_PARAMS = (%i(limit) + FILTER_PARAMS).freeze
|
||||
|
||||
private
|
||||
|
||||
def filtered_accounts
|
||||
AccountFilter.new(filter_params).results
|
||||
end
|
||||
|
||||
def filter_params
|
||||
params.permit(*FILTER_PARAMS)
|
||||
end
|
||||
|
||||
def pagination_params(core_params)
|
||||
params.slice(*PAGINATION_PARAMS).permit(*PAGINATION_PARAMS).merge(core_params)
|
||||
end
|
||||
end
|
|
@ -11,10 +11,6 @@ class Api::V2::SearchController < Api::BaseController
|
|||
def index
|
||||
@search = Search.new(search_results)
|
||||
render json: @search, serializer: REST::SearchSerializer
|
||||
rescue Mastodon::SyntaxError
|
||||
unprocessable_entity
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
not_found
|
||||
end
|
||||
|
||||
private
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue