Compare commits

..

1 commit

Author SHA1 Message Date
Eugen Rochko
1bfbfb0317 Add deduplication for JSON payloads in job queue 2022-10-25 15:19:33 +02:00
1150 changed files with 22069 additions and 59650 deletions

View file

@ -1,8 +1,8 @@
version: 2.1
orbs:
ruby: circleci/ruby@2.0.0
node: circleci/node@5.0.3
ruby: circleci/ruby@1.4.1
node: circleci/node@5.0.1
executors:
default:
@ -19,11 +19,11 @@ executors:
DB_USER: root
DISABLE_SIMPLECOV: true
RAILS_ENV: test
- image: cimg/postgres:14.5
- image: cimg/postgres:14.0
environment:
POSTGRES_USER: root
POSTGRES_HOST_AUTH_METHOD: trust
- image: cimg/redis:7.0
- image: cimg/redis:6.2
commands:
install-system-dependencies:
@ -45,7 +45,7 @@ commands:
bundle config without 'development production'
name: Set bundler settings
- ruby/install-deps:
bundler-version: '2.3.26'
bundler-version: '2.3.8'
key: ruby<< parameters.ruby-version >>-gems-v1
wait-db:
steps:
@ -68,9 +68,7 @@ jobs:
cache-version: v1
pkg-manager: yarn
- run:
command: |
export NODE_OPTIONS=--openssl-legacy-provider
./bin/rails assets:precompile
command: ./bin/rails assets:precompile
name: Precompile assets
- persist_to_workspace:
paths:
@ -221,5 +219,5 @@ workflows:
pkg-manager: yarn
requires:
- build
version: '16.18'
version: lts
yarn-run: test:jest

View file

@ -9,7 +9,7 @@ FROM mcr.microsoft.com/vscode/devcontainers/ruby:${VARIANT}
# The value is a comma-separated list of allowed domains
ENV RAILS_DEVELOPMENT_HOSTS=".githubpreview.dev"
# [Choice] Node.js version: lts/*, 18, 16, 14
# [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"

View file

@ -2,7 +2,7 @@
"name": "Mastodon",
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/mastodon",
"workspaceFolder": "/workspaces/mastodon",
// Set *default* container specific settings.json values on container create.
"settings": {},
@ -20,7 +20,7 @@
"forwardPorts": [3000, 4000],
// Use 'postCreateCommand' to run commands after the container is created.
"postCreateCommand": ".devcontainer/post-create.sh",
"postCreateCommand": "bundle install --path vendor/bundle && yarn install && git checkout -- Gemfile.lock && ./bin/rails db:setup",
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "vscode"

View file

@ -11,9 +11,9 @@ services:
# Use -bullseye variants on local arm64/Apple Silicon.
VARIANT: '3.0-bullseye'
# Optional Node.js version to install
NODE_VERSION: '16'
NODE_VERSION: '14'
volumes:
- ..:/mastodon:cached
- ..:/workspaces/mastodon:cached
environment:
RAILS_ENV: development
NODE_ENV: development

View file

@ -1,21 +0,0 @@
#!/bin/bash
set -e # Fail the whole script on first error
# Fetch Ruby gem dependencies
bundle install --path vendor/bundle --with='development test'
# Fetch Javascript dependencies
yarn install
# Make Gemfile.lock pristine again
git checkout -- Gemfile.lock
# [re]create, migrate, and seed the test database
RAILS_ENV=test ./bin/rails db:setup
# Precompile assets for development
RAILS_ENV=development ./bin/rails assets:precompile
# Precompile assets for test
RAILS_ENV=test NODE_ENV=tests ./bin/rails assets:precompile

View file

@ -54,7 +54,7 @@ VAPID_PUBLIC_KEY=
# Sending mail
# ------------
SMTP_SERVER=
SMTP_SERVER=smtp.mailgun.org
SMTP_PORT=587
SMTP_LOGIN=
SMTP_PASSWORD=

View file

@ -1,10 +1,6 @@
module.exports = {
root: true,
extends: [
'eslint:recommended',
],
env: {
browser: true,
node: true,
@ -68,8 +64,8 @@ module.exports = {
eqeqeq: 'error',
indent: ['warn', 2],
'jsx-quotes': ['error', 'prefer-single'],
'no-case-declarations': 'off',
'no-catch-shadow': 'error',
'no-cond-assign': 'error',
'no-console': [
'warn',
{
@ -79,16 +75,18 @@ module.exports = {
],
},
],
'no-empty': 'off',
'no-fallthrough': 'error',
'no-irregular-whitespace': 'error',
'no-mixed-spaces-and-tabs': 'warn',
'no-nested-ternary': 'warn',
'no-prototype-builtins': 'off',
'no-restricted-properties': [
'error',
{ property: 'substring', message: 'Use .slice instead of .substring.' },
{ property: 'substr', message: 'Use .slice instead of .substr.' },
],
'no-self-assign': 'off',
'no-trailing-spaces': 'warn',
'no-undef': 'error',
'no-unreachable': 'error',
'no-unused-expressions': 'error',
'no-unused-vars': [
'error',
@ -98,7 +96,6 @@ module.exports = {
ignoreRestSiblings: true,
},
],
'no-useless-escape': 'off',
'object-curly-spacing': ['error', 'always'],
'padded-blocks': [
'error',
@ -108,6 +105,7 @@ module.exports = {
],
quotes: ['error', 'single'],
semi: 'error',
strict: 'off',
'valid-typeof': 'error',
'react/jsx-boolean-value': 'error',

View file

@ -1,6 +1,6 @@
name: Bug Report
description: If something isn't working as expected
labels: [bug]
labels: bug
body:
- type: markdown
attributes:

View file

@ -1,6 +1,6 @@
name: Feature Request
description: I have a suggestion
labels: [suggestion]
labels: suggestion
body:
- type: markdown
attributes:

View file

@ -3,3 +3,6 @@ contact_links:
- name: GitHub Discussions
url: https://github.com/mastodon/mastodon/discussions
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.

View file

@ -18,7 +18,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: hadolint/hadolint-action@v3.0.0
- uses: docker/setup-qemu-action@v2
- uses: docker/setup-buildx-action@v2
- uses: docker/login-action@v2
@ -41,8 +40,7 @@ jobs:
with:
context: .
platforms: linux/amd64,linux/arm64
builder: ${{ steps.buildx.outputs.name }}
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
cache-from: type=gha
cache-to: type=gha,mode=max
cache-from: type=registry,ref=tootsuite/mastodon:edge
cache-to: type=inline

View file

@ -25,7 +25,7 @@ jobs:
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: .ruby-version
ruby-version: '3.0'
bundler-cache: true
- name: Check locale file normalization
run: bundle exec i18n-tasks check-normalized

View file

@ -1,62 +0,0 @@
name: 'CodeQL'
on:
push:
branches: ['main']
pull_request:
# The branches below must be a subset of the branches above
branches: ['main']
schedule:
- cron: '22 6 * * 1'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: ['javascript', 'ruby']
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: '/language:${{matrix.language}}'

View file

@ -53,12 +53,10 @@ jobs:
- name: Set-up Node.js
uses: actions/setup-node@v3
with:
node-version-file: .nvmrc
node-version: 16.x
cache: yarn
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Check prettier formatting
run: yarn format-check
- name: Set-up RuboCop Problem Mathcher
uses: r7kamura/rubocop-problem-matchers-action@v1
- name: Set-up Stylelint Problem Matcher

View file

@ -1,17 +0,0 @@
name: PR Needs Rebase
on:
push:
pull_request_target:
types: [synchronize]
jobs:
label-rebase-needed:
runs-on: ubuntu-latest
steps:
- name: Check for merge conflicts
uses: eps1lon/actions-label-merge-conflict@releases/2.x
with:
dirtyLabel: 'rebase needed :construction:'
repoToken: '${{ secrets.GITHUB_TOKEN }}'
commentOnDirty: This pull request has merge conflicts that must be resolved before it can be merged.

3
.gitignore vendored
View file

@ -44,6 +44,9 @@
/redis
/elasticsearch
# ignore Helm dependency charts
/chart/charts/*.tgz
# Ignore Apple files
.DS_Store

2
.nvmrc
View file

@ -1 +1 @@
16
14

View file

@ -44,6 +44,9 @@
/redis
/elasticsearch
# ignore Helm dependency charts
/chart/charts/*.tgz
# Ignore Apple files
.DS_Store
@ -64,6 +67,9 @@ yarn-debug.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

View file

@ -1,18 +1,12 @@
require:
- rubocop-rails
- rubocop-rspec
- rubocop-performance
AllCops:
TargetRubyVersion: 2.7
DisplayCopNames: true
DisplayStyleGuide: true
ExtraDetails: true
UseCache: true
CacheRootDirectory: tmp
NewCops: enable
TargetRubyVersion: 2.5
NewCops: disable
Exclude:
- db/schema.rb
- 'spec/**/*'
- 'db/**/*'
- 'app/views/**/*'
- 'config/**/*'
- 'bin/*'
@ -73,57 +67,15 @@ Lint/UselessAccessModifier:
- class_methods
Metrics/AbcSize:
Max: 34 # RuboCop default 17
Max: 115
Exclude:
- 'lib/**/*cli*.rb'
- db/*migrate/**/*
- lib/paperclip/color_extractor.rb
- app/workers/scheduler/follow_recommendations_scheduler.rb
- app/services/activitypub/fetch*_service.rb
- lib/paperclip/**/*
CountRepeatedAttributes: false
AllowedMethods:
- update_media_attachments!
- account_link_to
- attempt_oembed
- build_crutches
- calculate_scores
- cc
- dump_actor!
- filter_from_home?
- hydrate
- import_bookmarks!
- import_relationships!
- initialize
- link_to_mention
- log_target
- matches_time_window?
- parse_metadata
- perform_statuses_search!
- privatize_media_attachments!
- process_update
- publish_media_attachments!
- remotable_attachment
- render_initial_state
- render_with_cache
- searchable_by
- self.cached_filters_for
- set_fetchable_attributes!
- signed_request_actor
- statuses_to_delete
- update_poll!
- 'lib/mastodon/*_cli.rb'
Metrics/BlockLength:
Max: 55
Exclude:
- 'lib/tasks/**/*'
- 'lib/mastodon/*_cli.rb'
CountComments: false
CountAsOne: [array, heredoc]
AllowedMethods:
- task
- namespace
- class_methods
- included
Metrics/BlockNesting:
Max: 3
@ -133,144 +85,34 @@ Metrics/BlockNesting:
Metrics/ClassLength:
CountComments: false
Max: 500
CountAsOne: [array, heredoc]
Exclude:
- 'lib/mastodon/*_cli.rb'
Metrics/CyclomaticComplexity:
Max: 12
Max: 25
Exclude:
- lib/mastodon/*cli*.rb
- db/*migrate/**/*
AllowedMethods:
- attempt_oembed
- blocked?
- build_crutches
- calculate_scores
- cc
- discover_endpoint!
- filter_from_home?
- hydrate
- klass
- link_to_mention
- log_target
- matches_time_window?
- patch_for_forwarding!
- preprocess_attributes!
- process_update
- remotable_attachment
- scan_text!
- self.cached_filters_for
- set_fetchable_attributes!
- setup_redis_env_url
- update_media_attachments!
- 'lib/mastodon/*_cli.rb'
Layout/LineLength:
Max: 140 # RuboCop default 120
AllowHeredoc: true
AllowURI: true
IgnoreCopDirectives: true
AllowedPatterns:
# Allow comments to be long lines
- !ruby/regexp / \# .*$/
- !ruby/regexp /^\# .*$/
Exclude:
- lib/**/*cli*.rb
- db/*migrate/**/*
- db/seeds/**/*
Enabled: false
Metrics/MethodLength:
CountComments: false
CountAsOne: [array, heredoc]
Max: 25 # RuboCop default 10
Max: 65
Exclude:
- 'lib/mastodon/*_cli.rb'
AllowedMethods:
- account_link_to
- attempt_oembed
- body_with_limit
- build_crutches
- cached_filters_for
- calculate_scores
- check_webfinger!
- clean_feeds!
- collection_items
- collection_presenter
- copy_account_notes!
- deduplicate_accounts!
- deduplicate_conversations!
- deduplicate_local_accounts!
- deduplicate_statuses!
- deduplicate_tags!
- deduplicate_users!
- discover_endpoint!
- extract_extra_uris_with_indices
- extract_hashtags_with_indices
- extract_mentions_or_lists_with_indices
- filter_from_home?
- from_elasticsearch
- handle_explicit_update!
- handle_mark_as_sensitive!
- hsl_to_rgb
- import_bookmarks!
- import_domain_blocks!
- import_relationships!
- ldap_options
- matches_time_window?
- outbox_presenter
- pam_get_user
- parallelize_with_progress
- parse_and_transform
- patch_for_forwarding!
- populate_home
- post_process_style
- preload_cache_collection_target_statuses
- privatize_media_attachments!
- provides_callback_for
- publish_media_attachments!
- relevant_account_timestamp
- remotable_attachment
- rgb_to_hsl
- rss_status_content_format
- set_fetchable_attributes!
- setup_redis_env_url
- signed_request_actor
- to_preview_card_attributes
- upgrade_storage_filesystem
- upgrade_storage_s3
- user_settings_params
- hydrate
- cc
- self_destruct
Metrics/ModuleLength:
CountComments: false
Max: 200
CountAsOne: [array, heredoc]
Metrics/ParameterLists:
Max: 5 # RuboCop default 5
CountKeywordArgs: true # RuboCop default true
MaxOptionalParameters: 3 # RuboCop default 3
Exclude:
- app/models/concerns/account_interactions.rb
- app/services/activitypub/fetch_remote_account_service.rb
- app/services/activitypub/fetch_remote_actor_service.rb
Max: 5
CountKeywordArgs: true
Metrics/PerceivedComplexity:
Max: 16 # RuboCop default 8
AllowedMethods:
- attempt_oembed
- build_crutches
- calculate_scores
- deduplicate_users!
- discover_endpoint!
- filter_from_home?
- hydrate
- patch_for_forwarding!
- process_update
- remove_orphans
- update_media_attachments!
Max: 25
Naming/MemoizedInstanceVariableName:
Enabled: false
@ -401,10 +243,6 @@ Style/HashTransformKeys:
Style/HashTransformValues:
Enabled: false
Style/HashSyntax:
Enabled: true
EnforcedStyle: ruby19_no_mixed_keys
Style/IfUnlessModifier:
Enabled: false
@ -425,6 +263,9 @@ Style/PercentLiteralDelimiters:
Style/PerlBackrefs:
AutoCorrect: false
Style/RedundantAssignment:
Enabled: false
Style/RedundantFetchBlock:
Enabled: true
@ -447,7 +288,7 @@ Style/RegexpLiteral:
Enabled: false
Style/RescueStandardError:
Enabled: true
Enabled: false
Style/SignalException:
Enabled: false
@ -466,14 +307,3 @@ Style/TrailingCommaInHashLiteral:
Style/UnpackFirst:
Enabled: false
RSpec/ScatteredSetup:
Enabled: false
RSpec/ImplicitExpect:
Enabled: false
RSpec/NamedSubject:
Enabled: false
RSpec/DescribeClass:
Enabled: false
RSpec/LetSetup:
Enabled: false

1103
AUTHORS.md

File diff suppressed because it is too large Load diff

22
Aptfile
View file

@ -1,4 +1,26 @@
ffmpeg
libicu[0-9][0-9]
libicu-dev
libidn11
libidn11-dev
libpq-dev
libxdamage1
libxfixes3
zlib1g-dev
libcairo2
libcroco3
libdatrie1
libgdk-pixbuf2.0-0
libgraphite2-3
libharfbuzz0b
libpango-1.0-0
libpangocairo-1.0-0
libpangoft2-1.0-0
libpixman-1-0
librsvg2-2
libthai-data
libthai0
libvpx[5-9]
libxcb-render0
libxcb-shm0
libxrender1

View file

@ -3,216 +3,6 @@ Changelog
All notable changes to this project will be documented in this file.
## [4.0.2] - 2022-11-15
### Fixed
- Fix wrong color on mentions hidden behind content warning in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/20724))
- Fix filters from other users being used in the streaming service ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/20719))
- Fix `unsafe-eval` being used when `wasm-unsafe-eval` is enough in Content Security Policy ([Gargron](https://github.com/mastodon/mastodon/pull/20729), [prplecake](https://github.com/mastodon/mastodon/pull/20606))
## [4.0.1] - 2022-11-14
### Fixed
- Fix nodes order being sometimes mangled when rewriting emoji ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/20677))
## [4.0.0] - 2022-11-14
Some of the features in this release have been funded through the [NGI0 Discovery](https://nlnet.nl/discovery) Fund, a fund established by [NLnet](https://nlnet.nl/) with financial support from the European Commission's [Next Generation Internet](https://ngi.eu/) programme, under the aegis of DG Communications Networks, Content and Technology under grant agreement No 825322.
### Added
- Add ability to filter followed accounts' posts by language ([Gargron](https://github.com/mastodon/mastodon/pull/19095), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19268))
- **Add ability to follow hashtags** ([Gargron](https://github.com/mastodon/mastodon/pull/18809), [Gargron](https://github.com/mastodon/mastodon/pull/18862), [Gargron](https://github.com/mastodon/mastodon/pull/19472), [noellabo](https://github.com/mastodon/mastodon/pull/18924))
- Add ability to filter individual posts ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18945))
- **Add ability to translate posts** ([Gargron](https://github.com/mastodon/mastodon/pull/19218), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19433), [Gargron](https://github.com/mastodon/mastodon/pull/19453), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19434), [Gargron](https://github.com/mastodon/mastodon/pull/19388), [ykzts](https://github.com/mastodon/mastodon/pull/19244), [Gargron](https://github.com/mastodon/mastodon/pull/19245))
- Add featured tags to web UI ([noellabo](https://github.com/mastodon/mastodon/pull/19408), [noellabo](https://github.com/mastodon/mastodon/pull/19380), [noellabo](https://github.com/mastodon/mastodon/pull/19358), [noellabo](https://github.com/mastodon/mastodon/pull/19409), [Gargron](https://github.com/mastodon/mastodon/pull/19382), [ykzts](https://github.com/mastodon/mastodon/pull/19418), [noellabo](https://github.com/mastodon/mastodon/pull/19403), [noellabo](https://github.com/mastodon/mastodon/pull/19404), [Gargron](https://github.com/mastodon/mastodon/pull/19398), [Gargron](https://github.com/mastodon/mastodon/pull/19712), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/20018))
- **Add support for language preferences for trending statuses and links** ([Gargron](https://github.com/mastodon/mastodon/pull/18288), [Gargron](https://github.com/mastodon/mastodon/pull/19349), [ykzts](https://github.com/mastodon/mastodon/pull/19335))
- Previously, you could only see trends in your current language
- For less popular languages, that meant empty trends
- Now, trends in your preferred languages' are shown on top, with others beneath
- Add server rules to sign-up flow ([Gargron](https://github.com/mastodon/mastodon/pull/19296))
- Add privacy icons to report modal in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19190))
- Add `noopener` to links to remote profiles in web UI ([shleeable](https://github.com/mastodon/mastodon/pull/19014))
- Add option to open original page in dropdowns of remote content in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/20299))
- Add warning for sensitive audio posts in web UI ([rgroothuijsen](https://github.com/mastodon/mastodon/pull/17885))
- Add language attribute to posts in web UI ([tribela](https://github.com/mastodon/mastodon/pull/18544))
- Add support for uploading WebP files ([Saiv46](https://github.com/mastodon/mastodon/pull/18506))
- Add support for uploading `audio/vnd.wave` files ([tribela](https://github.com/mastodon/mastodon/pull/18737))
- Add support for uploading AVIF files ([txt-file](https://github.com/mastodon/mastodon/pull/19647))
- Add support for uploading HEIC files ([Gargron](https://github.com/mastodon/mastodon/pull/19618))
- Add more debug information when processing remote accounts ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/15605), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19209))
- **Add retention policy for cached content and media** ([Gargron](https://github.com/mastodon/mastodon/pull/19232), [zunda](https://github.com/mastodon/mastodon/pull/19478), [Gargron](https://github.com/mastodon/mastodon/pull/19458), [Gargron](https://github.com/mastodon/mastodon/pull/19248))
- Set for how long remote posts or media should be cached on your server
- Hands-off alternative to `tootctl` commands
- **Add customizable user roles** ([Gargron](https://github.com/mastodon/mastodon/pull/18641), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/18812), [Gargron](https://github.com/mastodon/mastodon/pull/19040), [tribela](https://github.com/mastodon/mastodon/pull/18825), [tribela](https://github.com/mastodon/mastodon/pull/18826), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/18776), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/18777), [unextro](https://github.com/mastodon/mastodon/pull/18786), [tribela](https://github.com/mastodon/mastodon/pull/18824), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19436))
- Previously, there were 3 hard-coded roles, user, moderator, and admin
- Create your own roles and decide which permissions they should have
- Add notifications for new reports ([Gargron](https://github.com/mastodon/mastodon/pull/18697), [Gargron](https://github.com/mastodon/mastodon/pull/19475))
- Add ability to select all accounts matching search for batch actions in admin UI ([Gargron](https://github.com/mastodon/mastodon/pull/19053), [Gargron](https://github.com/mastodon/mastodon/pull/19054))
- Add ability to view previous edits of a status in admin UI ([Gargron](https://github.com/mastodon/mastodon/pull/19462))
- Add ability to block sign-ups from IP ([Gargron](https://github.com/mastodon/mastodon/pull/19037))
- **Add webhooks to admin UI** ([Gargron](https://github.com/mastodon/mastodon/pull/18510))
- Add admin API for managing domain allows ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18668))
- Add admin API for managing domain blocks ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18247))
- Add admin API for managing e-mail domain blocks ([Gargron](https://github.com/mastodon/mastodon/pull/19066))
- Add admin API for managing canonical e-mail blocks ([Gargron](https://github.com/mastodon/mastodon/pull/19067))
- Add admin API for managing IP blocks ([Gargron](https://github.com/mastodon/mastodon/pull/19065), [trwnh](https://github.com/mastodon/mastodon/pull/20207))
- Add `sensitized` attribute to accounts in admin REST API ([trwnh](https://github.com/mastodon/mastodon/pull/20094))
- Add `services` and `metadata` to the NodeInfo endpoint ([MFTabriz](https://github.com/mastodon/mastodon/pull/18563))
- Add `--remove-role` option to `tootctl accounts modify` ([Gargron](https://github.com/mastodon/mastodon/pull/19477))
- Add `--days` option to `tootctl media refresh` ([tribela](https://github.com/mastodon/mastodon/pull/18425))
- Add `EMAIL_DOMAIN_LISTS_APPLY_AFTER_CONFIRMATION` environment variable ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18642))
- Add `IP_RETENTION_PERIOD` and `SESSION_RETENTION_PERIOD` environment variables ([kescherCode](https://github.com/mastodon/mastodon/pull/18757))
- Add `http_hidden_proxy` environment variable ([tribela](https://github.com/mastodon/mastodon/pull/18427))
- Add `ENABLE_STARTTLS` environment variable ([erbridge](https://github.com/mastodon/mastodon/pull/20321))
- Add caching for payload serialization during fan-out ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19637), [Gargron](https://github.com/mastodon/mastodon/pull/19642), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19746), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19747), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19963))
- Add assets from Twemoji 14.0 ([Gargron](https://github.com/mastodon/mastodon/pull/19733))
- Add reputation and followers score boost to SQL-only account search ([Gargron](https://github.com/mastodon/mastodon/pull/19251))
- Add Scots, Balaibalan, Láadan, Lingua Franca Nova, Lojban, Toki Pona to languages list ([VyrCossont](https://github.com/mastodon/mastodon/pull/20168))
- Set autocomplete hints for e-mail, password and OTP fields ([rcombs](https://github.com/mastodon/mastodon/pull/19833), [offbyone](https://github.com/mastodon/mastodon/pull/19946), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/20071))
- Add support for DigitalOcean Spaces in setup wizard ([v-aisac](https://github.com/mastodon/mastodon/pull/20573))
### Changed
- **Change brand color and logotypes** ([Gargron](https://github.com/mastodon/mastodon/pull/18592), [Gargron](https://github.com/mastodon/mastodon/pull/18639), [Gargron](https://github.com/mastodon/mastodon/pull/18691), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/18634), [Gargron](https://github.com/mastodon/mastodon/pull/19254), [mayaeh](https://github.com/mastodon/mastodon/pull/18710))
- **Change post editing to be enabled in web UI** ([Gargron](https://github.com/mastodon/mastodon/pull/19103))
- **Change web UI to work for logged-out users** ([Gargron](https://github.com/mastodon/mastodon/pull/18961), [Gargron](https://github.com/mastodon/mastodon/pull/19250), [Gargron](https://github.com/mastodon/mastodon/pull/19294), [Gargron](https://github.com/mastodon/mastodon/pull/19306), [Gargron](https://github.com/mastodon/mastodon/pull/19315), [ykzts](https://github.com/mastodon/mastodon/pull/19322), [Gargron](https://github.com/mastodon/mastodon/pull/19412), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19437), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19415), [Gargron](https://github.com/mastodon/mastodon/pull/19348), [Gargron](https://github.com/mastodon/mastodon/pull/19295), [Gargron](https://github.com/mastodon/mastodon/pull/19422), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19414), [Gargron](https://github.com/mastodon/mastodon/pull/19319), [Gargron](https://github.com/mastodon/mastodon/pull/19345), [Gargron](https://github.com/mastodon/mastodon/pull/19310), [Gargron](https://github.com/mastodon/mastodon/pull/19301), [Gargron](https://github.com/mastodon/mastodon/pull/19423), [ykzts](https://github.com/mastodon/mastodon/pull/19471), [ykzts](https://github.com/mastodon/mastodon/pull/19333), [ykzts](https://github.com/mastodon/mastodon/pull/19337), [ykzts](https://github.com/mastodon/mastodon/pull/19272), [ykzts](https://github.com/mastodon/mastodon/pull/19468), [Gargron](https://github.com/mastodon/mastodon/pull/19466), [Gargron](https://github.com/mastodon/mastodon/pull/19457), [Gargron](https://github.com/mastodon/mastodon/pull/19426), [Gargron](https://github.com/mastodon/mastodon/pull/19427), [Gargron](https://github.com/mastodon/mastodon/pull/19421), [Gargron](https://github.com/mastodon/mastodon/pull/19417), [Gargron](https://github.com/mastodon/mastodon/pull/19413), [Gargron](https://github.com/mastodon/mastodon/pull/19397), [Gargron](https://github.com/mastodon/mastodon/pull/19387), [Gargron](https://github.com/mastodon/mastodon/pull/19396), [Gargron](https://github.com/mastodon/mastodon/pull/19385), [ykzts](https://github.com/mastodon/mastodon/pull/19334), [ykzts](https://github.com/mastodon/mastodon/pull/19329), [Gargron](https://github.com/mastodon/mastodon/pull/19324), [Gargron](https://github.com/mastodon/mastodon/pull/19318), [Gargron](https://github.com/mastodon/mastodon/pull/19316), [Gargron](https://github.com/mastodon/mastodon/pull/19263), [trwnh](https://github.com/mastodon/mastodon/pull/19305), [ykzts](https://github.com/mastodon/mastodon/pull/19273), [Gargron](https://github.com/mastodon/mastodon/pull/19801), [Gargron](https://github.com/mastodon/mastodon/pull/19790), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19773), [Gargron](https://github.com/mastodon/mastodon/pull/19798), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19724), [Gargron](https://github.com/mastodon/mastodon/pull/19709), [Gargron](https://github.com/mastodon/mastodon/pull/19514), [Gargron](https://github.com/mastodon/mastodon/pull/19562), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19981), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19978), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/20148), [Gargron](https://github.com/mastodon/mastodon/pull/20302), [cutls](https://github.com/mastodon/mastodon/pull/20400))
- The web app can now be accessed without being logged in
- No more `/web` prefix on web app paths
- Profiles, posts, and other public pages now use the same interface for logged in and logged out users
- The web app displays a server information banner
- Pop-up windows for remote interaction have been replaced with a modal window
- No need to type in your username for remote interaction, copy-paste-to-search method explained
- Various hints throughout the app explain what the different timelines are
- New about page design
- New privacy policy page design shows when the policy was last updated
- All sections of the web app now have appropriate window titles
- The layout of the interface has been streamlined between different screen sizes
- Posts now use more horizontal space
- Change label of publish button to be "Publish" again in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/18583))
- Change language to be carried over on reply in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18557))
- Change "Unfollow" to "Cancel follow request" when request still pending in web UI ([prplecake](https://github.com/mastodon/mastodon/pull/19363))
- **Change post filtering system** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18058), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19050), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/18894), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19051), [noellabo](https://github.com/mastodon/mastodon/pull/18923), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/18956), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/18744), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19878), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/20567))
- Filtered keywords and phrases can now be grouped into named categories
- Filtered posts show which exact filter was hit
- Individual posts can be added to a filter
- You can peek inside filtered posts anyway
- Change path of privacy policy page from `/terms` to `/privacy-policy` ([Gargron](https://github.com/mastodon/mastodon/pull/19249))
- Change how hashtags are normalized ([Gargron](https://github.com/mastodon/mastodon/pull/18795), [Gargron](https://github.com/mastodon/mastodon/pull/18863), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/18854))
- Change settings area to be separated into categories in admin UI ([Gargron](https://github.com/mastodon/mastodon/pull/19407), [Gargron](https://github.com/mastodon/mastodon/pull/19533))
- Change "No accounts selected" errors to use the appropriate noun in admin UI ([prplecake](https://github.com/mastodon/mastodon/pull/19356))
- Change e-mail domain blocks to match subdomains of blocked domains ([Gargron](https://github.com/mastodon/mastodon/pull/18979))
- Change custom emoji file size limit from 50 KB to 256 KB ([Gargron](https://github.com/mastodon/mastodon/pull/18788))
- Change "Allow trends without prior review" setting to also work for trending posts ([Gargron](https://github.com/mastodon/mastodon/pull/17977))
- Change admin announcements form to use single inputs for date and time in admin UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18321))
- Change search API to be accessible without being logged in ([Gargron](https://github.com/mastodon/mastodon/pull/18963), [Gargron](https://github.com/mastodon/mastodon/pull/19326))
- Change following and followers API to be accessible without being logged in ([Gargron](https://github.com/mastodon/mastodon/pull/18964))
- Change `AUTHORIZED_FETCH` to not block unauthenticated REST API access ([Gargron](https://github.com/mastodon/mastodon/pull/19803))
- Change Helm configuration ([deepy](https://github.com/mastodon/mastodon/pull/18997), [jgsmith](https://github.com/mastodon/mastodon/pull/18415), [deepy](https://github.com/mastodon/mastodon/pull/18941))
- Change mentions of blocked users to not be processed ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19725))
- Change max. thumbnail dimensions to 640x360px (360p) ([Gargron](https://github.com/mastodon/mastodon/pull/19619))
- Change post-processing to be deferred only for large media types ([Gargron](https://github.com/mastodon/mastodon/pull/19617))
- Change link verification to only work for https links without unicode ([Gargron](https://github.com/mastodon/mastodon/pull/20304), [Gargron](https://github.com/mastodon/mastodon/pull/20295))
- Change account deletion requests to spread out over time ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/20222))
- Change larger reblogs/favourites numbers to be shortened in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/20303))
- Change incoming activity processing to happen in `ingress` queue ([Gargron](https://github.com/mastodon/mastodon/pull/20264))
- Change notifications to not link show preview cards in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/20335))
- Change amount of replies returned for logged out users in REST API ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/20355))
- Change in-app links to keep you in-app in web UI ([trwnh](https://github.com/mastodon/mastodon/pull/20540), [Gargron](https://github.com/mastodon/mastodon/pull/20628))
- Change table header to be sticky in admin UI ([sk22](https://github.com/mastodon/mastodon/pull/20442))
### Removed
- Remove setting that disables account deletes ([Gargron](https://github.com/mastodon/mastodon/pull/17683))
- Remove digest e-mails ([Gargron](https://github.com/mastodon/mastodon/pull/17985))
- Remove unnecessary sections from welcome e-mail ([Gargron](https://github.com/mastodon/mastodon/pull/19299))
- Remove item titles from RSS feeds ([Gargron](https://github.com/mastodon/mastodon/pull/18640))
- Remove volume number from hashtags in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/19253))
- Remove Nanobox configuration ([tonyjiang](https://github.com/mastodon/mastodon/pull/17881))
### Fixed
- Fix rules with same priority being sorted non-deterministically ([Gargron](https://github.com/mastodon/mastodon/pull/20623))
- Fix error when invalid domain name is submitted ([Gargron](https://github.com/mastodon/mastodon/pull/19474))
- Fix icons having an image role ([Gargron](https://github.com/mastodon/mastodon/pull/20600))
- Fix connections to IPv6-only servers ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/20108))
- Fix unnecessary service worker registration and preloading when logged out in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/20341))
- Fix unnecessary and slow regex construction ([raggi](https://github.com/mastodon/mastodon/pull/20215))
- Fix `mailers` queue not being used for mailers ([Gargron](https://github.com/mastodon/mastodon/pull/20274))
- Fix error in webfinger redirect handling ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/20260))
- Fix report category not being set to `violation` if rule IDs are provided ([trwnh](https://github.com/mastodon/mastodon/pull/20137))
- Fix nodeinfo metadata attribute being an array instead of an object ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/20114))
- Fix account endorsements not being idempotent ([trwnh](https://github.com/mastodon/mastodon/pull/20118))
- Fix status and rule IDs not being strings in admin reports REST API ([trwnh](https://github.com/mastodon/mastodon/pull/20122))
- Fix error on invalid `replies_policy` in REST API ([trwnh](https://github.com/mastodon/mastodon/pull/20126))
- Fix redrafting a currently-editing post not leaving edit mode in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/20023))
- Fix performance by avoiding method cache busts ([raggi](https://github.com/mastodon/mastodon/pull/19957))
- Fix opening the language picker scrolling the single-column view to the top in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19983))
- Fix content warning button missing `aria-expanded` attribute in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19975))
- Fix redundant `aria-pressed` attributes in web UI ([Brawaru](https://github.com/mastodon/mastodon/pull/19912))
- Fix crash when external auth provider has no display name set ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19962))
- Fix followers count not being updated when migrating follows ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19998))
- Fix double button to clear emoji search input in web UI ([sunny](https://github.com/mastodon/mastodon/pull/19888))
- Fix missing null check on applications on strike disputes ([kescherCode](https://github.com/mastodon/mastodon/pull/19851))
- Fix featured tags not saving preferred casing ([Gargron](https://github.com/mastodon/mastodon/pull/19732))
- Fix language not being saved when editing status ([Gargron](https://github.com/mastodon/mastodon/pull/19543))
- Fix not being able to input featured tag with hash symbol ([Gargron](https://github.com/mastodon/mastodon/pull/19535))
- Fix user clean-up scheduler crash when an unconfirmed account has a moderation note ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19629))
- Fix being unable to withdraw follow request when confirmation modal is disabled in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19687))
- Fix inaccurate admin log entry for re-sending confirmation e-mails ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19674))
- Fix edits not being immediately reflected ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19673))
- Fix bookmark import stopping at the first failure ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19669))
- Fix account action type validation ([Gargron](https://github.com/mastodon/mastodon/pull/19476))
- Fix upload progress not communicating processing phase in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/19530))
- Fix wrong host being used for custom.css when asset host configured ([Gargron](https://github.com/mastodon/mastodon/pull/19521))
- Fix account migration form ever using outdated account data ([Gargron](https://github.com/mastodon/mastodon/pull/18429), [nightpool](https://github.com/mastodon/mastodon/pull/19883))
- Fix error when uploading malformed CSV import ([Gargron](https://github.com/mastodon/mastodon/pull/19509))
- Fix avatars not using image tags in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/19488))
- Fix handling of duplicate and out-of-order notifications in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19693))
- Fix reblogs being discarded after the reblogged status ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19731))
- Fix indexing scheduler trying to index when Elasticsearch is disabled ([Gargron](https://github.com/mastodon/mastodon/pull/19805))
- Fix n+1 queries when rendering initial state JSON ([Gargron](https://github.com/mastodon/mastodon/pull/19795))
- Fix n+1 query during status removal ([Gargron](https://github.com/mastodon/mastodon/pull/19753))
- Fix OCR not working due to Content Security Policy in web UI ([prplecake](https://github.com/mastodon/mastodon/pull/18817))
- Fix `nofollow` rel being removed in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/19455))
- Fix language dropdown causing zoom on mobile devices in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/19428))
- Fix button to dismiss suggestions not showing up in search results in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19325))
- Fix language dropdown sometimes not appearing in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/19246))
- Fix quickly switching notification filters resulting in empty or incorrect list in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19052), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/18960))
- Fix media modal link button in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18877))
- Fix error upon successful account migration ([Gargron](https://github.com/mastodon/mastodon/pull/19386))
- Fix negatives values in search index causing queries to fail ([Gargron](https://github.com/mastodon/mastodon/pull/19464), [Gargron](https://github.com/mastodon/mastodon/pull/19481))
- Fix error when searching for invalid URL ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18580))
- Fix IP blocks not having a unique index ([Gargron](https://github.com/mastodon/mastodon/pull/19456))
- Fix remote account in contact account setting not being used ([Gargron](https://github.com/mastodon/mastodon/pull/19351))
- Fix swallowing mentions of unconfirmed/unapproved users ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19191))
- Fix incorrect and slow cache invalidation when blocking domain and removing media attachments ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19062))
- Fix HTTPs redirect behaviour when running as I2P service ([gi-yt](https://github.com/mastodon/mastodon/pull/18929))
- Fix deleted pinned posts potentially counting towards the pinned posts limit ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19005))
- Fix compatibility with OpenSSL 3.0 ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18449))
- Fix error when a remote report includes a private post the server has no access to ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18760))
- Fix suspicious sign-in mails never being sent ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18599))
- Fix fallback locale when somehow user's locale is an empty string ([tribela](https://github.com/mastodon/mastodon/pull/18543))
- Fix avatar/header not being deleted locally when deleted on remote account ([tribela](https://github.com/mastodon/mastodon/pull/18973))
- Fix missing `,` in Blurhash validation ([noellabo](https://github.com/mastodon/mastodon/pull/18660))
- Fix order by most recent not working for relationships page in admin UI ([tribela](https://github.com/mastodon/mastodon/pull/18996))
- Fix uncaught error when invalid date is supplied to API ([Gargron](https://github.com/mastodon/mastodon/pull/19480))
- Fix REST API sometimes returning HTML on error ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19135))
- Fix ambiguous column names in `tootctl media refresh` ([tribela](https://github.com/mastodon/mastodon/pull/19206))
- Fix ambiguous column names in `tootctl search deploy` ([mashirozx](https://github.com/mastodon/mastodon/pull/18993))
- Fix `CDN_HOST` not being used in some asset URLs ([tribela](https://github.com/mastodon/mastodon/pull/18662))
- Fix `CAS_DISPLAY_NAME`, `SAML_DISPLAY_NAME` and `OIDC_DISPLAY_NAME` being ignored ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18568))
- Fix various typos in comments throughout the codebase ([luzpaz](https://github.com/mastodon/mastodon/pull/18604))
- Fix CSV import error when rows include unicode characters ([HamptonMakes](https://github.com/mastodon/mastodon/pull/20592))
### Security
- Fix being able to spoof link verification ([Gargron](https://github.com/mastodon/mastodon/pull/20217))
- Fix emoji substitution not applying only to text nodes in backend code ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/20641))
- Fix emoji substitution not applying only to text nodes in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/20640))
- Fix rate limiting for paths with formats ([Gargron](https://github.com/mastodon/mastodon/pull/20675))
- Fix out-of-bound reads in blurhash transcoder ([delroth](https://github.com/mastodon/mastodon/pull/20388))
## [3.5.3] - 2022-05-26
### Added
@ -332,7 +122,7 @@ Some of the features in this release have been funded through the [NGI0 Discover
### Fixed
- Fix error responses for `from` search prefix ([single-right-quote](https://github.com/mastodon/mastodon/pull/17963))
- 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))
@ -467,7 +257,7 @@ Some of the features in this release have been funded through the [NGI0 Discover
- 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 overridden individually using `language` param
- 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

View file

@ -40,7 +40,7 @@ Project maintainers who do not follow or enforce the Code of Conduct in good fai
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [https://contributor-covenant.org/version/1/4][version]
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: https://contributor-covenant.org
[version]: https://contributor-covenant.org/version/1/4/
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

View file

@ -42,8 +42,6 @@ It is not always possible to phrase every change in such a manner, but it is des
- Code style rules (rubocop, eslint)
- Normalization of locale files (i18n-tasks)
**Note**: You may need to log in and authorise the GitHub account your fork of this repository belongs to with CircleCI to enable some of the automated checks to run.
## Documentation
The [Mastodon documentation](https://docs.joinmastodon.org) is a statically generated site. You can [submit merge requests to mastodon/documentation](https://github.com/mastodon/documentation).

View file

@ -1,99 +1,121 @@
# syntax=docker/dockerfile:1.4
# This needs to be bullseye-slim because the Ruby image is built on bullseye-slim
ARG NODE_VERSION="16.18.1-bullseye-slim"
FROM ubuntu:20.04 as build-dep
FROM ghcr.io/moritzheiber/ruby-jemalloc:3.0.4-slim as ruby
FROM node:${NODE_VERSION} as build
# Use bash for the shell
SHELL ["/bin/bash", "-c"]
RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
COPY --link --from=ruby /opt/ruby /opt/ruby
# Install Node v16 (LTS)
ENV NODE_VER="16.17.1"
RUN ARCH= && \
dpkgArch="$(dpkg --print-architecture)" && \
case "${dpkgArch##*-}" in \
amd64) ARCH='x64';; \
ppc64el) ARCH='ppc64le';; \
s390x) ARCH='s390x';; \
arm64) ARCH='arm64';; \
armhf) ARCH='armv7l';; \
i386) ARCH='x86';; \
*) echo "unsupported architecture"; exit 1 ;; \
esac && \
echo "Etc/UTC" > /etc/localtime && \
apt-get update && \
apt-get install -y --no-install-recommends ca-certificates wget python3 apt-utils && \
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
ENV DEBIAN_FRONTEND="noninteractive" \
PATH="${PATH}:/opt/ruby/bin"
# Install Ruby 3.0
ENV RUBY_VER="3.0.4"
RUN apt-get update && \
apt-get install -y --no-install-recommends build-essential \
bison libyaml-dev libgdbm-dev libreadline-dev libjemalloc-dev \
libncurses5-dev libffi-dev zlib1g-dev libssl-dev && \
cd ~ && \
wget https://cache.ruby-lang.org/pub/ruby/${RUBY_VER%.*}/ruby-$RUBY_VER.tar.gz && \
tar xf ruby-$RUBY_VER.tar.gz && \
cd ruby-$RUBY_VER && \
./configure --prefix=/opt/ruby \
--with-jemalloc \
--with-shared \
--disable-install-doc && \
make -j"$(nproc)" > /dev/null && \
make install && \
rm -rf ../ruby-$RUBY_VER.tar.gz ../ruby-$RUBY_VER
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
ENV PATH="${PATH}:/opt/ruby/bin:/opt/node/bin"
RUN npm install -g npm@latest && \
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
WORKDIR /opt/mastodon
COPY Gemfile* package.json yarn.lock /opt/mastodon/
# hadolint ignore=DL3008
RUN apt-get update && \
apt-get install -y --no-install-recommends build-essential \
ca-certificates \
git \
libicu-dev \
libidn11-dev \
libpq-dev \
libjemalloc-dev \
zlib1g-dev \
libgdbm-dev \
libgmp-dev \
libssl-dev \
libyaml-0-2 \
ca-certificates \
libreadline8 \
python3 \
shared-mime-info && \
bundle config set --local deployment 'true' && \
bundle config set --local without 'development test' && \
bundle config set silence_root_warning true && \
bundle install -j"$(nproc)" && \
yarn install --pure-lockfile --network-timeout 600000
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 install -j"$(nproc)" && \
yarn install --pure-lockfile
FROM node:${NODE_VERSION}
FROM ubuntu:20.04
ARG UID="991"
ARG GID="991"
# Copy over all the langs needed for runtime
COPY --from=build-dep /opt/node /opt/node
COPY --from=build-dep /opt/ruby /opt/ruby
COPY --link --from=ruby /opt/ruby /opt/ruby
# Add more PATHs to the PATH
ENV PATH="${PATH}:/opt/ruby/bin:/opt/node/bin:/opt/mastodon/bin"
# Create the mastodon user
ARG UID=991
ARG GID=991
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
ENV DEBIAN_FRONTEND="noninteractive" \
PATH="${PATH}:/opt/ruby/bin:/opt/mastodon/bin"
# Ignoreing these here since we don't want to pin any versions and the Debian image removes apt-get content after use
# hadolint ignore=DL3008,DL3009
RUN apt-get update && \
echo "Etc/UTC" > /etc/localtime && \
groupadd -g "${GID}" mastodon && \
useradd -l -u "$UID" -g "${GID}" -m -d /opt/mastodon mastodon && \
apt-get -y --no-install-recommends install whois \
wget \
procps \
libssl1.1 \
libpq5 \
imagemagick \
ffmpeg \
libjemalloc2 \
libicu67 \
libidn11 \
libyaml-0-2 \
file \
ca-certificates \
tzdata \
libreadline8 \
tini && \
ln -s /opt/mastodon /mastodon
echo "Etc/UTC" > /etc/localtime && \
apt-get install -y --no-install-recommends whois wget && \
addgroup --gid $GID mastodon && \
useradd -m -u $UID -g $GID -d /opt/mastodon mastodon && \
echo "mastodon:$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 24 | mkpasswd -s -m sha-256)" | chpasswd && \
rm -rf /var/lib/apt/lists/*
# Note: no, cleaning here since Debian does this automatically
# See the file /etc/apt/apt.conf.d/docker-clean within the Docker image's filesystem
# 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 && \
ln -s /opt/mastodon /mastodon && \
gem install bundler && \
rm -rf /var/cache && \
rm -rf /var/lib/apt/lists/*
# Copy over mastodon source, and dependencies from building, and set permissions
COPY --chown=mastodon:mastodon . /opt/mastodon
COPY --chown=mastodon:mastodon --from=build /opt/mastodon /opt/mastodon
COPY --from=build-dep --chown=mastodon:mastodon /opt/mastodon /opt/mastodon
ENV RAILS_ENV="production" \
NODE_ENV="production" \
RAILS_SERVE_STATIC_FILES="true" \
BIND="0.0.0.0"
# Run mastodon services in prod mode
ENV RAILS_ENV="production"
ENV NODE_ENV="production"
# Tell rails to serve static files
ENV RAILS_SERVE_STATIC_FILES="true"
ENV BIND="0.0.0.0"
# Set the run user
USER mastodon
WORKDIR /opt/mastodon
# Precompile assets
RUN OTP_SECRET=precompile_placeholder SECRET_KEY_BASE=precompile_placeholder rails assets:precompile && \
yarn cache clean
RUN cd ~ && \
OTP_SECRET=precompile_placeholder SECRET_KEY_BASE=precompile_placeholder rails assets:precompile && \
yarn cache clean
# Set the work dir and the container entry point
WORKDIR /opt/mastodon
ENTRYPOINT ["/usr/bin/tini", "--"]
EXPOSE 3000 4000

39
Gemfile
View file

@ -1,9 +1,9 @@
# frozen_string_literal: true
source 'https://rubygems.org'
ruby '>= 2.7.0', '< 3.1.0'
ruby '>= 2.6.0', '< 3.1.0'
gem 'pkg-config', '~> 1.5'
gem 'pkg-config', '~> 1.4'
gem 'rexml', '~> 3.2'
gem 'puma', '~> 5.6'
@ -18,15 +18,15 @@ gem 'makara', '~> 0.5'
gem 'pghero', '~> 2.8'
gem 'dotenv-rails', '~> 2.8'
gem 'aws-sdk-s3', '~> 1.117', require: false
gem 'fog-core', '<= 2.4.0'
gem 'aws-sdk-s3', '~> 1.114', require: false
gem 'fog-core', '<= 2.1.0'
gem 'fog-openstack', '~> 0.3', require: false
gem 'kt-paperclip', '~> 7.1'
gem 'blurhash', '~> 0.1'
gem 'active_model_serializers', '~> 0.10'
gem 'addressable', '~> 2.8'
gem 'bootsnap', '~> 1.15.0', require: false
gem 'bootsnap', '~> 1.13.0', require: false
gem 'browser'
gem 'charlock_holmes', '~> 0.7.7'
gem 'chewy', '~> 7.2'
@ -55,7 +55,7 @@ gem 'redis-namespace', '~> 1.9'
gem 'htmlentities', '~> 4.3'
gem 'http', '~> 5.1'
gem 'http_accept_language', '~> 2.1'
gem 'httplog', '~> 1.6.2'
gem 'httplog', '~> 1.6.0'
gem 'idn-ruby', require: 'idn'
gem 'kaminari', '~> 1.2'
gem 'link_header', '~> 0.0'
@ -66,8 +66,7 @@ gem 'oj', '~> 3.13'
gem 'ox', '~> 2.14'
gem 'parslet'
gem 'posix-spawn'
gem 'public_suffix', '~> 5.0'
gem 'pundit', '~> 2.3'
gem 'pundit', '~> 2.2'
gem 'premailer-rails'
gem 'rack-attack', '~> 6.6'
gem 'rack-cors', '~> 1.1', require: 'rack/cors'
@ -79,7 +78,7 @@ 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.7'
gem 'scenic', '~> 1.6'
gem 'sidekiq', '~> 6.5'
gem 'sidekiq-scheduler', '~> 4.0'
gem 'sidekiq-unique-jobs', '~> 7.1'
@ -87,13 +86,13 @@ gem 'sidekiq-bulk', '~> 0.2.0'
gem 'simple-navigation', '~> 4.4'
gem 'simple_form', '~> 5.1'
gem 'sprockets-rails', '~> 3.4', require: 'sprockets/railtie'
gem 'stoplight', '~> 3.0.1'
gem 'stoplight', '~> 3.0.0'
gem 'strong_migrations', '~> 0.7'
gem 'tty-prompt', '~> 0.23', require: false
gem 'twitter-text', '~> 3.1.0'
gem 'tzinfo-data', '~> 1.2022'
gem 'webpacker', '~> 5.4'
gem 'webpush', github: 'ClearlyClaire/webpush', ref: 'f14a4d52e201128b1b00245d11b6de80d6cfdcd9'
gem 'webpush', git: 'https://github.com/ClearlyClaire/webpush.git', ref: 'f14a4d52e201128b1b00245d11b6de80d6cfdcd9'
gem 'webauthn', '~> 2.5'
gem 'json-ld'
@ -107,10 +106,6 @@ group :development, :test do
gem 'pry-byebug', '~> 3.10'
gem 'pry-rails', '~> 0.3'
gem 'rspec-rails', '~> 5.1'
gem 'rubocop-performance', require: false
gem 'rubocop-rails', require: false
gem 'rubocop-rspec', require: false
gem 'rubocop', require: false
end
group :production, :test do
@ -118,17 +113,15 @@ group :production, :test do
end
group :test do
gem 'capybara', '~> 3.38'
gem 'capybara', '~> 3.37'
gem 'climate_control', '~> 0.2'
gem 'faker', '~> 3.0'
gem 'json-schema', '~> 3.0'
gem 'faker', '~> 2.23'
gem 'microformats', '~> 4.4'
gem 'rack-test', '~> 2.0'
gem 'rails-controller-testing', '~> 1.0'
gem 'rspec_junit_formatter', '~> 0.6'
gem 'rspec-sidekiq', '~> 3.1'
gem 'simplecov', '~> 0.21', require: false
gem 'webmock', '~> 3.18'
gem 'rspec_junit_formatter', '~> 0.6'
end
group :development do
@ -140,7 +133,9 @@ group :development do
gem 'letter_opener', '~> 1.8'
gem 'letter_opener_web', '~> 2.0'
gem 'memory_profiler'
gem 'brakeman', '~> 5.4', require: false
gem 'rubocop', '~> 1.30', require: false
gem 'rubocop-rails', '~> 2.15', require: false
gem 'brakeman', '~> 5.3', require: false
gem 'bundler-audit', '~> 0.9', require: false
gem 'capistrano', '~> 3.17'
@ -157,5 +152,7 @@ end
gem 'concurrent-ruby', require: false
gem 'connection_pool', require: false
gem 'xorcist', '~> 1.1'
gem 'cocoon', '~> 1.2'

View file

@ -90,20 +90,20 @@ GEM
attr_required (1.0.1)
awrence (1.2.1)
aws-eventstream (1.2.0)
aws-partitions (1.670.0)
aws-sdk-core (3.168.2)
aws-partitions (1.587.0)
aws-sdk-core (3.130.2)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.651.0)
aws-sigv4 (~> 1.5)
jmespath (~> 1, >= 1.6.1)
aws-sdk-kms (1.60.0)
aws-sdk-core (~> 3, >= 3.165.0)
aws-partitions (~> 1, >= 1.525.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.117.2)
aws-sdk-core (~> 3, >= 3.165.0)
jmespath (~> 1.0)
aws-sdk-kms (1.56.0)
aws-sdk-core (~> 3, >= 3.127.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.114.0)
aws-sdk-core (~> 3, >= 3.127.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.4)
aws-sigv4 (1.5.2)
aws-sigv4 (1.5.0)
aws-eventstream (~> 1, >= 1.0.2)
bcrypt (3.1.17)
better_errors (2.9.1)
@ -122,15 +122,15 @@ GEM
debug_inspector (>= 0.0.1)
blurhash (0.1.6)
ffi (~> 1.14)
bootsnap (1.15.0)
bootsnap (1.13.0)
msgpack (~> 1.2)
brakeman (5.4.0)
brakeman (5.3.1)
browser (4.2.0)
brpoplpush-redis_script (0.1.3)
brpoplpush-redis_script (0.1.2)
concurrent-ruby (~> 1.0, >= 1.0.5)
redis (>= 1.0, < 6)
redis (>= 1.0, <= 5.0)
builder (3.2.4)
bullet (7.0.4)
bullet (7.0.3)
activesupport (>= 3.0.0)
uniform_notifier (~> 1.11)
bundler-audit (0.9.1)
@ -152,7 +152,7 @@ GEM
sshkit (~> 1.3)
capistrano-yarn (2.0.2)
capistrano (~> 3.0)
capybara (3.38.0)
capybara (3.37.1)
addressable
matrix
mini_mime (>= 0.1.3)
@ -182,7 +182,7 @@ GEM
crack (0.4.5)
rexml
crass (1.0.6)
css_parser (1.12.0)
css_parser (1.7.1)
addressable
debug_inspector (1.0.0)
devise (4.8.1)
@ -206,7 +206,7 @@ GEM
docile (1.3.4)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
doorkeeper (5.6.2)
doorkeeper (5.6.0)
railties (>= 5)
dotenv (2.8.1)
dotenv-rails (2.8.1)
@ -226,9 +226,9 @@ GEM
erubi (1.11.0)
et-orbi (1.2.7)
tzinfo
excon (0.95.0)
excon (0.76.0)
fabrication (2.30.0)
faker (3.0.0)
faker (2.23.0)
i18n (>= 1.8.11, < 2)
faraday (1.9.3)
faraday-em_http (~> 1.0)
@ -271,7 +271,7 @@ GEM
fog-core (>= 1.45, <= 2.1.0)
fog-json (>= 1.0)
ipaddress (>= 0.8)
formatador (0.3.0)
formatador (0.2.5)
fugit (1.7.1)
et-orbi (~> 1, >= 1.2.7)
raabro (~> 1.4)
@ -299,7 +299,7 @@ GEM
hiredis (0.6.3)
hkdf (0.3.0)
htmlentities (4.3.4)
http (5.1.1)
http (5.1.0)
addressable (~> 2.8)
http-cookie (~> 1.0)
http-form_data (~> 2.2)
@ -309,7 +309,7 @@ GEM
http-form_data (2.3.0)
http_accept_language (2.1.1)
httpclient (2.8.3)
httplog (1.6.2)
httplog (1.6.0)
rack (>= 2.0)
rainbow (>= 2.0.0)
i18n (1.12.0)
@ -325,9 +325,9 @@ GEM
rails-i18n
rainbow (>= 2.2.2, < 4.0)
terminal-table (>= 1.5.1)
idn-ruby (0.1.5)
idn-ruby (0.1.4)
ipaddress (0.8.3)
jmespath (1.6.2)
jmespath (1.6.1)
json (2.6.2)
json-canonicalization (0.3.0)
json-jwt (1.13.0)
@ -341,11 +341,9 @@ GEM
multi_json (~> 1.15)
rack (~> 2.2)
rdf (~> 3.2, >= 3.2.9)
json-ld-preloaded (3.2.2)
json-ld-preloaded (3.2.0)
json-ld (~> 3.2)
rdf (~> 3.2)
json-schema (3.0.0)
addressable (>= 2.8)
jsonapi-renderer (0.2.2)
jwt (2.4.1)
kaminari (1.2.2)
@ -384,7 +382,7 @@ GEM
activesupport (>= 4)
railties (>= 4)
request_store (~> 1.0)
loofah (2.19.1)
loofah (2.19.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
mail (2.7.1)
@ -395,7 +393,7 @@ GEM
mario-redis-lock (1.2.1)
redis (>= 3.0.5)
matrix (0.4.2)
memory_profiler (1.0.1)
memory_profiler (1.0.0)
method_source (1.0.0)
microformats (4.4.1)
json (~> 2.2)
@ -406,19 +404,15 @@ GEM
mini_mime (1.1.2)
mini_portile2 (2.8.0)
minitest (5.16.3)
msgpack (1.6.0)
msgpack (1.5.4)
multi_json (1.15.0)
multipart-post (2.1.1)
net-ldap (0.17.1)
net-protocol (0.1.3)
timeout
net-scp (4.0.0.rc1)
net-ssh (>= 2.6.5, < 8.0.0)
net-smtp (0.3.3)
net-protocol
net-ssh (7.0.1)
nio4r (2.5.8)
nokogiri (1.13.10)
nokogiri (1.13.8)
mini_portile2 (~> 2.8.0)
racc (~> 1.4)
nsa (0.2.8)
@ -426,7 +420,7 @@ GEM
concurrent-ruby (~> 1.0, >= 1.0.2)
sidekiq (>= 3.5)
statsd-ruby (~> 1.4, >= 1.4.0)
oj (3.13.23)
oj (3.13.21)
omniauth (1.9.2)
hashie (>= 3.4.6)
rack (>= 1.6.2, < 3)
@ -461,18 +455,17 @@ GEM
parslet (2.0.0)
pastel (0.8.0)
tty-color (~> 0.5)
pg (1.4.5)
pg (1.4.3)
pghero (2.8.3)
activerecord (>= 5)
pkg-config (1.5.1)
pkg-config (1.4.9)
posix-spawn (0.3.15)
premailer (1.18.0)
premailer (1.14.2)
addressable
css_parser (>= 1.12.0)
css_parser (>= 1.6.0)
htmlentities (>= 4.0.0)
premailer-rails (1.12.0)
premailer-rails (1.11.1)
actionmailer (>= 3)
net-smtp
premailer (~> 1.7, >= 1.7.9)
private_address_check (0.5.0)
pry (0.14.1)
@ -483,13 +476,13 @@ GEM
pry (>= 0.13, < 0.15)
pry-rails (0.3.9)
pry (>= 0.10.4)
public_suffix (5.0.1)
public_suffix (5.0.0)
puma (5.6.5)
nio4r (~> 2.0)
pundit (2.3.0)
pundit (2.2.0)
activesupport (>= 3.0.0)
raabro (1.4.0)
racc (1.6.1)
racc (1.6.0)
rack (2.2.4)
rack-attack (6.6.1)
rack (>= 1.0, < 3)
@ -527,8 +520,8 @@ GEM
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
nokogiri (>= 1.6)
rails-html-sanitizer (1.4.4)
loofah (~> 2.19, >= 2.19.1)
rails-html-sanitizer (1.4.3)
loofah (~> 2.3)
rails-i18n (6.0.0)
i18n (>= 0.7, < 2)
railties (>= 6.0.0, < 7)
@ -544,15 +537,13 @@ GEM
rake (13.0.6)
rdf (3.2.9)
link_header (~> 0.0, >= 0.0.8)
rdf-normalize (0.5.1)
rdf-normalize (0.5.0)
rdf (~> 3.2)
redcarpet (3.5.1)
redis (4.5.1)
redis-namespace (1.9.0)
redis (>= 4)
redlock (1.3.2)
redis (>= 3.0.0, < 6.0)
regexp_parser (2.6.0)
regexp_parser (2.5.0)
request_store (1.5.1)
rack (>= 1.4)
responders (3.0.1)
@ -587,27 +578,21 @@ GEM
rspec-support (3.11.1)
rspec_junit_formatter (0.6.0)
rspec-core (>= 2, < 4, != 2.12.0)
rubocop (1.39.0)
json (~> 2.3)
rubocop (1.30.1)
parallel (~> 1.10)
parser (>= 3.1.2.1)
parser (>= 3.1.0.0)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.23.0, < 2.0)
rubocop-ast (>= 1.18.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 3.0)
rubocop-ast (1.23.0)
rubocop-ast (1.18.0)
parser (>= 3.1.1.0)
rubocop-performance (1.15.1)
rubocop (>= 1.7.0, < 2.0)
rubocop-ast (>= 0.4.0)
rubocop-rails (2.17.2)
rubocop-rails (2.15.0)
activesupport (>= 4.2.0)
rack (>= 1.1)
rubocop (>= 1.33.0, < 2.0)
rubocop-rspec (2.15.0)
rubocop (~> 1.33)
rubocop (>= 1.7.0, < 2.0)
ruby-progressbar (1.11.0)
ruby-saml (1.13.0)
nokogiri (>= 1.10.5)
@ -620,12 +605,12 @@ GEM
sanitize (6.0.0)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
scenic (1.7.0)
scenic (1.6.0)
activerecord (>= 4.0.0)
railties (>= 4.0.0)
semantic_range (3.0.0)
sidekiq (6.5.8)
connection_pool (>= 2.2.5, < 3)
sidekiq (6.5.7)
connection_pool (>= 2.2.5)
rack (~> 2.0)
redis (>= 4.5.0, < 5)
sidekiq-bulk (0.2.0)
@ -635,11 +620,10 @@ GEM
rufus-scheduler (~> 3.2)
sidekiq (>= 4, < 7)
tilt (>= 1.4.0)
sidekiq-unique-jobs (7.1.29)
sidekiq-unique-jobs (7.1.27)
brpoplpush-redis_script (> 0.1.1, <= 2.0.0)
concurrent-ruby (~> 1.0, >= 1.0.5)
redis (< 5.0)
sidekiq (>= 5.0, < 7.0)
sidekiq (>= 5.0, < 8.0)
thor (>= 0.20, < 3.0)
simple-navigation (4.4.0)
activesupport (>= 2.3.2)
@ -663,10 +647,9 @@ GEM
sshkit (1.21.2)
net-scp (>= 1.1.2)
net-ssh (>= 2.8.0)
stackprof (0.2.23)
stackprof (0.2.22)
statsd-ruby (1.5.0)
stoplight (3.0.1)
redlock (~> 1.0)
stoplight (3.0.0)
strong_migrations (0.7.9)
activerecord (>= 5)
swd (1.3.0)
@ -680,7 +663,6 @@ GEM
climate_control (>= 0.0.3, < 1.0)
thor (1.2.1)
tilt (2.0.11)
timeout (0.3.0)
tpm-key_attestation (0.11.0)
bindata (~> 2.4)
openssl (> 2.0, < 3.1)
@ -700,7 +682,7 @@ GEM
unf (~> 0.1.0)
tzinfo (2.0.5)
concurrent-ruby (~> 1.0)
tzinfo-data (1.2022.7)
tzinfo-data (1.2022.4)
tzinfo (>= 1.0.0)
unf (0.1.4)
unf_ext
@ -743,7 +725,7 @@ GEM
xorcist (1.1.3)
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.6.6)
zeitwerk (2.6.0)
PLATFORMS
ruby
@ -753,12 +735,12 @@ DEPENDENCIES
active_record_query_trace (~> 1.8)
addressable (~> 2.8)
annotate (~> 3.2)
aws-sdk-s3 (~> 1.117)
aws-sdk-s3 (~> 1.114)
better_errors (~> 2.9)
binding_of_caller (~> 1.0)
blurhash (~> 0.1)
bootsnap (~> 1.15.0)
brakeman (~> 5.4)
bootsnap (~> 1.13.0)
brakeman (~> 5.3)
browser
bullet (~> 7.0)
bundler-audit (~> 0.9)
@ -766,7 +748,7 @@ DEPENDENCIES
capistrano-rails (~> 1.6)
capistrano-rbenv (~> 2.2)
capistrano-yarn (~> 2.0)
capybara (~> 3.38)
capybara (~> 3.37)
charlock_holmes (~> 0.7.7)
chewy (~> 7.2)
climate_control (~> 0.2)
@ -782,10 +764,10 @@ DEPENDENCIES
dotenv-rails (~> 2.8)
ed25519 (~> 1.3)
fabrication (~> 2.30)
faker (~> 3.0)
faker (~> 2.23)
fast_blank (~> 1.0)
fastimage
fog-core (<= 2.4.0)
fog-core (<= 2.1.0)
fog-openstack (~> 0.3)
fuubar (~> 2.5)
gitlab-omniauth-openid-connect (~> 0.10.0)
@ -794,12 +776,11 @@ DEPENDENCIES
htmlentities (~> 4.3)
http (~> 5.1)
http_accept_language (~> 2.1)
httplog (~> 1.6.2)
httplog (~> 1.6.0)
i18n-tasks (~> 1.0)
idn-ruby
json-ld
json-ld-preloaded (~> 3.2)
json-schema (~> 3.0)
kaminari (~> 1.2)
kt-paperclip (~> 7.1)
letter_opener (~> 1.8)
@ -823,19 +804,17 @@ DEPENDENCIES
parslet
pg (~> 1.4)
pghero (~> 2.8)
pkg-config (~> 1.5)
pkg-config (~> 1.4)
posix-spawn
premailer-rails
private_address_check (~> 0.5)
pry-byebug (~> 3.10)
pry-rails (~> 0.3)
public_suffix (~> 5.0)
puma (~> 5.6)
pundit (~> 2.3)
pundit (~> 2.2)
rack (~> 2.2.4)
rack-attack (~> 6.6)
rack-cors (~> 1.1)
rack-test (~> 2.0)
rails (~> 6.1.7)
rails-controller-testing (~> 1.0)
rails-i18n (~> 6.0)
@ -849,13 +828,11 @@ DEPENDENCIES
rspec-rails (~> 5.1)
rspec-sidekiq (~> 3.1)
rspec_junit_formatter (~> 0.6)
rubocop
rubocop-performance
rubocop-rails
rubocop-rspec
rubocop (~> 1.30)
rubocop-rails (~> 2.15)
ruby-progressbar (~> 1.11)
sanitize (~> 6.0)
scenic (~> 1.7)
scenic (~> 1.6)
sidekiq (~> 6.5)
sidekiq-bulk (~> 0.2.0)
sidekiq-scheduler (~> 4.0)
@ -866,7 +843,7 @@ DEPENDENCIES
sprockets (~> 3.7.2)
sprockets-rails (~> 3.4)
stackprof
stoplight (~> 3.0.1)
stoplight (~> 3.0.0)
strong_migrations (~> 0.7)
thor (~> 1.2)
tty-prompt (~> 0.23)
@ -877,9 +854,3 @@ DEPENDENCIES
webpacker (~> 5.4)
webpush!
xorcist (~> 1.1)
RUBY VERSION
ruby 3.0.4p208
BUNDLED WITH
2.2.33

View file

@ -72,8 +72,8 @@ Mastodon acts as an OAuth2 provider, so 3rd party apps can use the REST and Stre
- **PostgreSQL** 9.5+
- **Redis** 4+
- **Ruby** 2.7+
- **Node.js** 16+
- **Ruby** 2.6+
- **Node.js** 14+
The repository includes deployment configurations for **Docker and docker-compose** as well as specific platforms like **Heroku**, **Scalingo**, and **Nanobox**. The [**standalone** installation guide](https://docs.joinmastodon.org/admin/install/) is available in the documentation.

View file

@ -1,6 +1,6 @@
# 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 can reach us at <security@joinmastodon.org>.
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.
@ -10,8 +10,11 @@ A "vulnerability in Mastodon" is a vulnerability in the code distributed through
## Supported Versions
| Version | Supported |
| ------- | ----------|
| 4.0.x | Yes |
| 3.5.x | Yes |
| < 3.5 | No |
| Version | Supported |
| ------- | ------------------ |
| 3.5.x | Yes |
| 3.4.x | Yes |
| 3.3.x | No |
| < 3.3 | No |
[bug-bounty]: https://app.intigriti.com/programs/mastodon/mastodonio/detail

71
Vagrantfile vendored
View file

@ -3,14 +3,16 @@
ENV["PORT"] ||= "3000"
$provisionA = <<SCRIPT
$provision = <<SCRIPT
cd /vagrant # This is where the host folder/repo is mounted
# Add the yarn repo + yarn repo keys
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
sudo apt-add-repository 'deb https://dl.yarnpkg.com/debian/ stable main'
# Add repo for NodeJS
curl -sL https://deb.nodesource.com/setup_16.x | sudo bash -
curl -sL https://deb.nodesource.com/setup_14.x | sudo bash -
# Add firewall rule to redirect 80 to PORT and save
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port #{ENV["PORT"]}
@ -31,56 +33,32 @@ sudo apt-get install \
redis-tools \
postgresql \
postgresql-contrib \
yarn \
libicu-dev \
libidn11-dev \
libreadline6-dev \
autoconf \
bison \
build-essential \
ffmpeg \
file \
gcc \
libffi-dev \
libgdbm-dev \
libjemalloc-dev \
libncurses5-dev \
libprotobuf-dev \
libssl-dev \
libyaml-dev \
pkg-config \
protobuf-compiler \
zlib1g-dev \
libreadline-dev \
libpam0g-dev \
-y
# Install rvm
sudo apt-add-repository -y ppa:rael-gc/rvm
sudo apt-get install rvm -y
read RUBY_VERSION < .ruby-version
sudo usermod -a -G rvm $USER
curl -sSL https://rvm.io/mpapis.asc | gpg --import
curl -sSL https://rvm.io/pkuczynski.asc | gpg --import
SCRIPT
$provisionB = <<SCRIPT
source "/etc/profile.d/rvm.sh"
curl -sSL https://raw.githubusercontent.com/rvm/rvm/stable/binscripts/rvm-installer | bash -s stable --ruby=$RUBY_VERSION
source /home/vagrant/.rvm/scripts/rvm
# Install Ruby
read RUBY_VERSION < /vagrant/.ruby-version
rvm install ruby-$RUBY_VERSION --disable-binary
rvm reinstall ruby-$RUBY_VERSION --disable-binary
# Configure database
sudo -u postgres createuser -U postgres vagrant -s
sudo -u postgres createdb -U postgres mastodon_development
cd /vagrant # This is where the host folder/repo is mounted
# Install gems
# Install gems and node modules
gem install bundler foreman
bundle install
# Install node modules
sudo corepack enable
yarn set version classic
yarn install
# Build Mastodon
@ -94,11 +72,18 @@ echo 'export $(cat "/vagrant/.env.vagrant" | xargs)' >> ~/.bash_profile
SCRIPT
$start = <<SCRIPT
echo 'To start server'
echo ' $ vagrant ssh -c "cd /vagrant && foreman start"'
SCRIPT
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "ubuntu/focal64"
config.vm.box = "ubuntu/bionic64"
config.vm.provider :virtualbox do |vb|
vb.name = "mastodon"
@ -115,6 +100,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# Use "virtio" network interfaces for better performance.
vb.customize ["modifyvm", :id, "--nictype1", "virtio"]
vb.customize ["modifyvm", :id, "--nictype2", "virtio"]
end
# This uses the vagrant-hostsupdater plugin, and lets you
@ -132,7 +118,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
end
if config.vm.networks.any? { |type, options| type == :private_network }
config.vm.synced_folder ".", "/vagrant", type: "nfs", mount_options: ['rw', 'actimeo=1']
config.vm.synced_folder ".", "/vagrant", type: "nfs", mount_options: ['rw', 'vers=3', 'tcp', 'actimeo=1']
else
config.vm.synced_folder ".", "/vagrant"
end
@ -143,12 +129,9 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.network :forwarded_port, guest: 8080, host: 8080
# Full provisioning script, only runs on first 'vagrant up' or with 'vagrant provision'
config.vm.provision :shell, inline: $provisionA, privileged: false, reset: true
config.vm.provision :shell, inline: $provisionB, privileged: false
config.vm.provision :shell, inline: $provision, privileged: false
config.vm.post_up_message = <<MESSAGE
To start server
$ vagrant ssh -c "cd /vagrant && foreman start"
MESSAGE
# Start up script, runs on every 'vagrant up'
config.vm.provision :shell, inline: $start, run: 'always', privileged: false
end

View file

@ -79,13 +79,8 @@
"description": "SMTP server certificate verification mode. Defaults is 'peer'.",
"required": false
},
"SMTP_ENABLE_STARTTLS": {
"description": "Enable STARTTLS? Default is 'auto'.",
"value": "auto",
"required": false
},
"SMTP_ENABLE_STARTTLS_AUTO": {
"description": "Enable STARTTLS if SMTP server supports it? Deprecated by SMTP_ENABLE_STARTTLS.",
"description": "Enable STARTTLS if SMTP server supports it? Default is true.",
"required": false
}
},

View file

@ -17,8 +17,6 @@ class AccountsController < ApplicationController
respond_to do |format|
format.html do
expires_in 0, public: true unless user_signed_in?
@rss_url = rss_url
end
format.rss do

View file

@ -55,14 +55,12 @@ module Admin
def approve
authorize @account.user, :approve?
@account.user.approve!
log_action :approve, @account.user
redirect_to admin_accounts_path(status: 'pending'), 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)
log_action :reject, @account.user
redirect_to admin_accounts_path(status: 'pending'), notice: I18n.t('admin.accounts.rejected_msg', username: @account.acct)
end

View file

@ -17,7 +17,7 @@ module Admin
@user.resend_confirmation_instructions
log_action :resend, @user
log_action :confirm, @user
flash[:notice] = I18n.t('admin.accounts.resend_confirmation.success')
redirect_to admin_accounts_path

View file

@ -4,18 +4,6 @@ module Admin
class DomainBlocksController < BaseController
before_action :set_domain_block, only: [:show, :destroy, :edit, :update]
def batch
authorize :domain_block, :create?
@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.domain_blocks.no_domain_block_selected')
rescue Mastodon::NotPermittedError
flash[:alert] = I18n.t('admin.domain_blocks.not_permitted')
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])
@ -55,8 +43,12 @@ module Admin
def update
authorize :domain_block, :update?
if @domain_block.update(update_params)
DomainBlockWorker.perform_async(@domain_block.id, @domain_block.severity_previously_changed?)
@domain_block.update(update_params)
severity_changed = @domain_block.severity_changed?
if @domain_block.save
DomainBlockWorker.perform_async(@domain_block.id, severity_changed)
log_action :update, @domain_block
redirect_to admin_instances_path(limited: '1'), notice: I18n.t('admin.domain_blocks.created_msg')
else
@ -84,15 +76,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

View file

@ -19,7 +19,7 @@ module Admin
rescue ActionController::ParameterMissing
flash[:alert] = I18n.t('admin.email_domain_blocks.no_email_domain_block_selected')
rescue Mastodon::NotPermittedError
flash[:alert] = I18n.t('admin.email_domain_blocks.not_permitted')
flash[:alert] = I18n.t('admin.custom_emojis.not_permitted')
ensure
redirect_to admin_email_domain_blocks_path
end

View file

@ -1,60 +0,0 @@
# frozen_string_literal: true
require 'csv'
module Admin
class ExportDomainAllowsController < BaseController
include AdminExportControllerConcern
before_action :set_dummy_import!, only: [:new]
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)
return render :new unless @import.validate
parse_import_data!(export_headers)
@data.take(Admin::Import::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

View file

@ -1,71 +0,0 @@
# frozen_string_literal: true
require 'csv'
module Admin
class ExportDomainBlocksController < BaseController
include AdminExportControllerConcern
before_action :set_dummy_import!, only: [:new]
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)
return render :new unless @import.validate
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(Admin::Import::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_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

View file

@ -57,7 +57,7 @@ module Admin
end
def preload_delivery_failures!
warning_domains_map = DeliveryFailureTracker.warning_domains_map(@instances.map(&:domain))
warning_domains_map = DeliveryFailureTracker.warning_domains_map
@instances.each do |instance|
instance.failure_days = warning_domains_map[instance.domain]

View file

@ -5,7 +5,7 @@ module Admin
def index
authorize :ip_block, :index?
@ip_blocks = IpBlock.order(ip: :asc).page(params[:page])
@ip_blocks = IpBlock.page(params[:page])
@form = Form::IpBlockBatch.new
end

View file

@ -3,7 +3,7 @@
module Admin
class RelaysController < BaseController
before_action :set_relay, except: [:index, :new, :create]
before_action :warn_signatures_not_enabled!, only: [:new, :create, :enable]
before_action :require_signatures_enabled!, only: [:new, :create, :enable]
def index
authorize :relay, :update?
@ -56,8 +56,8 @@ module Admin
params.require(:relay).permit(:inbox_url)
end
def warn_signatures_not_enabled!
flash.now[:error] = I18n.t('admin.relays.signatures_not_enabled') if authorized_fetch_mode?
def require_signatures_enabled!
redirect_to admin_relays_path, alert: I18n.t('admin.relays.signatures_not_enabled') if authorized_fetch_mode?
end
end
end

View file

@ -3,23 +3,18 @@
module Admin
class StatusesController < BaseController
before_action :set_account
before_action :set_statuses, except: :show
before_action :set_status, only: :show
before_action :set_statuses
PER_PAGE = 20
def index
authorize [:admin, :status], :index?
authorize :status, :index?
@status_batch_action = Admin::StatusBatchAction.new
end
def show
authorize [:admin, @status], :show?
end
def batch
authorize [:admin, :status], :index?
authorize :status, :index?
@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!
@ -37,7 +32,6 @@ module Admin
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
@ -49,10 +43,6 @@ module Admin
@account = Account.find(params[:account_id])
end
def set_status
@status = @account.statuses.find(params[: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

View file

@ -2,7 +2,7 @@
class Admin::Trends::StatusesController < Admin::BaseController
def index
authorize [:admin, :status], :review?
authorize :status, :review?
@locales = StatusTrend.pluck('distinct language')
@statuses = filtered_statuses.page(params[:page])
@ -10,7 +10,7 @@ class Admin::Trends::StatusesController < Admin::BaseController
end
def batch
authorize [:admin, :status], :review?
authorize :status, :review?
@form = Trends::StatusBatch.new(trends_status_batch_params.merge(current_account: current_account, action: action_from_button))
@form.save

View file

@ -16,26 +16,6 @@ class Api::BaseController < ApplicationController
protect_from_forgery with: :null_session
content_security_policy do |p|
# Set every directive that does not have a fallback
p.default_src :none
p.frame_ancestors :none
p.form_action :none
# Disable every directive with a fallback to cut on response size
p.base_uri false
p.font_src false
p.img_src false
p.style_src false
p.media_src false
p.frame_src false
p.manifest_src false
p.connect_src false
p.script_src false
p.child_src false
p.worker_src false
end
rescue_from ActiveRecord::RecordInvalid, Mastodon::ValidationError do |e|
render json: { error: e.to_s }, status: 422
end
@ -44,10 +24,6 @@ class Api::BaseController < ApplicationController
render json: { error: 'Duplicate record' }, status: 422
end
rescue_from Date::Error do
render json: { error: 'Invalid date supplied' }, status: 422
end
rescue_from ActiveRecord::RecordNotFound do
render json: { error: 'Record not found' }, status: 404
end
@ -77,7 +53,7 @@ class Api::BaseController < ApplicationController
render json: { error: I18n.t('errors.429') }, status: 429
end
rescue_from ActionController::ParameterMissing, Mastodon::InvalidParameterError do |e|
rescue_from ActionController::ParameterMissing do |e|
render json: { error: e.to_s }, status: 400
end
@ -149,11 +125,11 @@ class Api::BaseController < ApplicationController
end
def set_cache_headers
response.headers['Cache-Control'] = 'private, no-store'
response.headers['Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate'
end
def disallow_unauthenticated_api_access?
ENV['DISALLOW_UNAUTHENTICATED_API_ACCESS'] == 'true' || Rails.configuration.x.whitelist_mode
authorized_fetch_mode?
end
private

View file

@ -8,7 +8,7 @@ class Api::V1::Accounts::PinsController < Api::BaseController
before_action :set_account
def create
AccountPin.find_or_create_by!(account: current_account, target_account: @account)
AccountPin.create!(account: current_account, target_account: @account)
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships_presenter
end

View file

@ -54,21 +54,20 @@ class Api::V1::Admin::AccountsController < Api::BaseController
def approve
authorize @account.user, :approve?
@account.user.approve!
log_action :approve, @account.user
render json: @account, serializer: REST::Admin::AccountSerializer
end
def reject
authorize @account.user, :reject?
DeleteAccountService.new.call(@account, reserve_email: false, reserve_username: false)
log_action :reject, @account.user
render_empty
render json: @account, serializer: REST::Admin::AccountSerializer
end
def destroy
authorize @account, :destroy?
json = render_to_body json: @account, serializer: REST::Admin::AccountSerializer
Admin::AccountDeletionWorker.perform_async(@account.id)
render_empty
render json: json
end
def unsensitive

View file

@ -35,16 +35,20 @@ class Api::V1::Admin::CanonicalEmailBlocksController < Api::BaseController
def create
authorize :canonical_email_block, :create?
@canonical_email_block = CanonicalEmailBlock.create!(resource_params)
log_action :create, @canonical_email_block
render json: @canonical_email_block, serializer: REST::Admin::CanonicalEmailBlockSerializer
end
def destroy
authorize @canonical_email_block, :destroy?
@canonical_email_block.destroy!
log_action :destroy, @canonical_email_block
render_empty
render json: @canonical_email_block, serializer: REST::Admin::CanonicalEmailBlockSerializer
end
private

View file

@ -43,7 +43,7 @@ class Api::V1::Admin::DomainAllowsController < Api::BaseController
authorize @domain_allow, :destroy?
UnallowDomainService.new.call(@domain_allow)
log_action :destroy, @domain_allow
render_empty
render json: @domain_allow, serializer: REST::Admin::DomainAllowSerializer
end
private

View file

@ -40,8 +40,11 @@ class Api::V1::Admin::DomainBlocksController < Api::BaseController
def update
authorize @domain_block, :update?
@domain_block.update!(domain_block_params)
DomainBlockWorker.perform_async(@domain_block.id, @domain_block.severity_previously_changed?)
@domain_block.update(domain_block_params)
severity_changed = @domain_block.severity_changed?
@domain_block.save!
DomainBlockWorker.perform_async(@domain_block.id, severity_changed)
log_action :update, @domain_block
render json: @domain_block, serializer: REST::Admin::DomainBlockSerializer
end
@ -50,7 +53,7 @@ class Api::V1::Admin::DomainBlocksController < Api::BaseController
authorize @domain_block, :destroy?
UnblockDomainService.new.call(@domain_block)
log_action :destroy, @domain_block
render_empty
render json: @domain_block, serializer: REST::Admin::DomainBlockSerializer
end
private

View file

@ -39,9 +39,11 @@ class Api::V1::Admin::EmailDomainBlocksController < Api::BaseController
def destroy
authorize @email_domain_block, :destroy?
@email_domain_block.destroy!
log_action :destroy, @email_domain_block
render_empty
render json: @email_domain_block, serializer: REST::Admin::EmailDomainBlockSerializer
end
private

View file

@ -20,8 +20,10 @@ class Api::V1::Admin::IpBlocksController < Api::BaseController
def create
authorize :ip_block, :create?
@ip_block = IpBlock.create!(resource_params)
log_action :create, @ip_block
render json: @ip_block, serializer: REST::Admin::IpBlockSerializer
end
@ -37,16 +39,20 @@ class Api::V1::Admin::IpBlocksController < Api::BaseController
def update
authorize @ip_block, :update?
@ip_block.update(resource_params)
log_action :update, @ip_block
render json: @ip_block, serializer: REST::Admin::IpBlockSerializer
end
def destroy
authorize @ip_block, :destroy?
@ip_block.destroy!
log_action :destroy, @ip_block
render_empty
render json: @ip_block, serializer: REST::Admin::IpBlockSerializer
end
private

View file

@ -1,6 +1,6 @@
# frozen_string_literal: true
class Api::V2::Filters::KeywordsController < Api::BaseController
class Api::V1::Filters::KeywordsController < Api::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:filters' }, only: [:index, :show]
before_action -> { doorkeeper_authorize! :write, :'write:filters' }, except: [:index, :show]
before_action :require_user!

View file

@ -1,6 +1,6 @@
# frozen_string_literal: true
class Api::V2::Filters::StatusesController < Api::BaseController
class Api::V1::Filters::StatusesController < Api::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:filters' }, only: [:index, :show]
before_action -> { doorkeeper_authorize! :write, :'write:filters' }, except: [:index, :show]
before_action :require_user!

View file

@ -13,7 +13,7 @@ class Api::V1::FiltersController < Api::BaseController
def create
ApplicationRecord.transaction do
filter_category = current_account.custom_filters.create!(filter_params)
filter_category = current_account.custom_filters.create!(resource_params)
@filter = filter_category.keywords.create!(keyword_params)
end
@ -56,7 +56,7 @@ class Api::V1::FiltersController < Api::BaseController
end
def filter_params
resource_params.slice(:phrase, :expires_in, :irreversible, :context)
resource_params.slice(:expires_in, :irreversible, :context)
end
def keyword_params

View file

@ -3,11 +3,11 @@
class Api::V1::FollowedTagsController < Api::BaseController
TAGS_LIMIT = 100
before_action -> { doorkeeper_authorize! :follow, :read, :'read:follows' }
before_action -> { doorkeeper_authorize! :follow, :read, :'read:follows' }, except: :show
before_action :require_user!
before_action :set_results
after_action :insert_pagination_headers
after_action :insert_pagination_headers, only: :show
def index
render json: @results.map(&:tag), each_serializer: REST::TagSerializer, relationships: TagRelationshipsPresenter.new(@results.map(&:tag), current_user&.account_id)
@ -43,7 +43,7 @@ class Api::V1::FollowedTagsController < Api::BaseController
end
def records_continue?
@results.size == limit_param(TAGS_LIMIT)
@results.size == limit_param(TAG_LIMIT)
end
def pagination_params(core_params)

View file

@ -7,10 +7,6 @@ class Api::V1::ListsController < Api::BaseController
before_action :require_user!
before_action :set_list, except: [:index, :create]
rescue_from ArgumentError do |e|
render json: { error: e.to_s }, status: 422
end
def index
@lists = List.where(account: current_account).all
render json: @lists, each_serializer: REST::ListSerializer

View file

@ -31,7 +31,7 @@ class Api::V1::NotificationsController < Api::BaseController
private
def load_notifications
notifications = browserable_account_notifications.includes(from_account: [:account_stat, :user]).to_a_paginated_by_id(
notifications = browserable_account_notifications.includes(from_account: :account_stat).to_a_paginated_by_id(
limit_param(DEFAULT_NOTIFICATIONS_LIMIT),
params_slice(:max_id, :since_id, :min_id)
)

View file

@ -18,29 +18,14 @@ class Api::V1::StatusesController < Api::BaseController
# than this anyway
CONTEXT_LIMIT = 4_096
# This remains expensive and we don't want to show everything to logged-out users
ANCESTORS_LIMIT = 40
DESCENDANTS_LIMIT = 60
DESCENDANTS_DEPTH_LIMIT = 20
def show
@status = cache_collection([@status], Status).first
render json: @status, serializer: REST::StatusSerializer
end
def context
ancestors_limit = CONTEXT_LIMIT
descendants_limit = CONTEXT_LIMIT
descendants_depth_limit = nil
if current_account.nil?
ancestors_limit = ANCESTORS_LIMIT
descendants_limit = DESCENDANTS_LIMIT
descendants_depth_limit = DESCENDANTS_DEPTH_LIMIT
end
ancestors_results = @status.in_reply_to_id.nil? ? [] : @status.ancestors(ancestors_limit, current_account)
descendants_results = @status.descendants(descendants_limit, current_account, descendants_depth_limit)
ancestors_results = @status.in_reply_to_id.nil? ? [] : @status.ancestors(CONTEXT_LIMIT, current_account)
descendants_results = @status.descendants(CONTEXT_LIMIT, current_account)
loaded_ancestors = cache_collection(ancestors_results, Status)
loaded_descendants = cache_collection(descendants_results, Status)
@ -80,7 +65,6 @@ class Api::V1::StatusesController < Api::BaseController
text: status_params[:status],
media_ids: status_params[:media_ids],
sensitive: status_params[:sensitive],
language: status_params[:language],
spoiler_text: status_params[:spoiler_text],
poll: status_params[:poll]
)
@ -92,7 +76,7 @@ class Api::V1::StatusesController < Api::BaseController
@status = Status.where(account: current_account).find(params[:id])
authorize @status, :destroy?
@status.discard_with_reblogs
@status.discard
StatusPin.find_by(status: @status)&.destroy
@status.account.statuses_count = @status.account.statuses_count - 1
json = render_to_body json: @status, serializer: REST::StatusSerializer, source_requested: true

View file

@ -12,7 +12,7 @@ class Api::V1::TagsController < Api::BaseController
end
def follow
TagFollow.create_with(rate_limit: true).find_or_create_by!(tag: @tag, account: current_account)
TagFollow.create!(tag: @tag, account: current_account, rate_limit: true)
render json: @tag, serializer: REST::TagSerializer
end
@ -24,7 +24,7 @@ class Api::V1::TagsController < Api::BaseController
private
def set_or_create_tag
return not_found unless Tag::HASHTAG_NAME_RE.match?(params[:id])
return not_found unless /\A(#{Tag::HASHTAG_NAME_RE})\z/.match?(params[:id])
@tag = Tag.find_normalized(params[:id]) || Tag.new(name: Tag.normalize(params[:id]), display_name: params[:id])
end
end

View file

@ -35,6 +35,7 @@ class Api::V1::Timelines::PublicController < Api::BaseController
def public_feed
PublicFeed.new(
current_account,
locale: content_locale,
local: truthy_param?(:local),
remote: truthy_param?(:remote),
only_media: truthy_param?(:only_media)

View file

@ -36,6 +36,7 @@ class Api::V1::Timelines::TagController < Api::BaseController
TagFeed.new(
@tag,
current_account,
locale: content_locale,
any: params[:any],
all: params[:all],
none: params[:none],

View file

@ -33,7 +33,7 @@ class Api::V2::Admin::AccountsController < Api::V1::Admin::AccountsController
end
def filter_params
params.permit(*FILTER_PARAMS, role_ids: [])
params.permit(*FILTER_PARAMS)
end
def pagination_params(core_params)

View file

@ -3,7 +3,7 @@
class Api::V2::MediaController < Api::V1::MediaController
def create
@media_attachment = current_account.media_attachments.create!({ delay_processing: true }.merge(media_attachment_params))
render json: @media_attachment, serializer: REST::MediaAttachmentSerializer, status: @media_attachment.not_processed? ? 202 : 200
render json: @media_attachment, serializer: REST::MediaAttachmentSerializer, status: 202
rescue Paperclip::Errors::NotIdentifiedByImageMagickError
render json: file_type_error, status: 422
rescue Paperclip::Error

View file

@ -6,7 +6,6 @@ class Api::V2::SearchController < Api::BaseController
RESULTS_LIMIT = 20
before_action -> { authorize_if_got_token! :read, :'read:search' }
before_action :validate_search_params!
def index
@search = Search.new(search_results)
@ -19,22 +18,12 @@ class Api::V2::SearchController < Api::BaseController
private
def validate_search_params!
params.require(:q)
return if user_signed_in?
return render json: { error: 'Search queries pagination is not supported without authentication' }, status: 401 if params[:offset].present?
render json: { error: 'Search queries that resolve remote resources are not supported without authentication' }, status: 401 if truthy_param?(:resolve)
end
def search_results
SearchService.new.call(
params[:q],
current_account,
limit_param(RESULTS_LIMIT),
search_params.merge(resolve: truthy_param?(:resolve), exclude_unreviewed: truthy_param?(:exclude_unreviewed))
search_params.merge(resolve: user_signed_in? ? truthy_param?(:resolve) : false, exclude_unreviewed: truthy_param?(:exclude_unreviewed))
)
end

View file

@ -18,8 +18,7 @@ class Auth::OmniauthCallbacksController < Devise::OmniauthCallbacksController
)
sign_in_and_redirect @user, event: :authentication
label = Devise.omniauth_configs[provider]&.strategy&.display_name.presence || I18n.t("auth.providers.#{provider}", default: provider.to_s.chomp('_oauth2').capitalize)
set_flash_message(:notice, :success, kind: label) if is_navigational_format?
set_flash_message(:notice, :success, kind: Devise.omniauth_configs[provider].strategy.display_name.capitalize) if is_navigational_format?
else
session["devise.#{provider}_data"] = request.env['omniauth.auth']
redirect_to new_user_registration_url

View file

@ -10,8 +10,6 @@ class Auth::PasswordsController < Devise::PasswordsController
super do |resource|
if resource.errors.empty?
resource.session_activations.destroy_all
resource.revoke_access!
end
end
end

View file

@ -56,8 +56,8 @@ class Auth::RegistrationsController < Devise::RegistrationsController
end
def configure_sign_up_params
devise_parameter_sanitizer.permit(:sign_up) do |user_params|
user_params.permit({ account_attributes: [:username, :display_name], invite_request_attributes: [:text] }, :email, :password, :password_confirmation, :invite_code, :agreement, :website, :confirm_password)
devise_parameter_sanitizer.permit(:sign_up) do |u|
u.permit({ account_attributes: [:username, :display_name], invite_request_attributes: [:text] }, :email, :password, :password_confirmation, :invite_code, :agreement, :website, :confirm_password)
end
end
@ -148,12 +148,11 @@ class Auth::RegistrationsController < Devise::RegistrationsController
return if @rules.empty? || (session[:accept_token].present? && params[:accept] == session[:accept_token])
@accept_token = session[:accept_token] = SecureRandom.hex
@invite_code = invite_code
set_locale { render :rules }
end
def set_cache_headers
response.headers['Cache-Control'] = 'private, no-store'
response.headers['Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate'
end
end

View file

@ -14,10 +14,6 @@ class Auth::SessionsController < Devise::SessionsController
before_action :set_instance_presenter, only: [:new]
before_action :set_body_classes
content_security_policy only: :new do |p|
p.form_action(false)
end
def check_suspicious!
user = find_user
@login_is_suspicious = suspicious_sign_in?(user) unless user.nil?

View file

@ -1,39 +0,0 @@
# frozen_string_literal: true
module AdminExportControllerConcern
extend ActiveSupport::Concern
private
def send_export_file
respond_to do |format|
format.csv { send_data export_data, filename: export_filename }
end
end
def export_data
raise 'Override in controller'
end
def export_filename
raise 'Override in controller'
end
def set_dummy_import!
@import = Admin::Import.new
end
def import_params
params.require(:admin_import).permit(:data)
end
def import_data_path
params[:admin_import][:data].path
end
def parse_import_data!(default_headers)
data = CSV.read(import_data_path, headers: true, encoding: 'UTF-8')
data = CSV.read(import_data_path, headers: default_headers, encoding: 'UTF-8') unless data.headers&.first&.strip&.include?(default_headers[0])
@data = data.reject(&:blank?)
end
end

View file

@ -58,7 +58,7 @@ module RateLimitHeaders
end
def api_throttle_data
most_limited_type, = request.env['rack.attack.throttle_data'].min_by { |_key, value| value[:limit] - value[:count] }
most_limited_type, = request.env['rack.attack.throttle_data'].min_by { |_, v| v[:limit] - v[:count] }
request.env['rack.attack.throttle_data'][most_limited_type]
end

View file

@ -28,8 +28,8 @@ module SignatureVerification
end
class SignatureParamsTransformer < Parslet::Transform
rule(params: subtree(:param)) do
(param.is_a?(Array) ? param : [param]).each_with_object({}) { |(key, value), hash| hash[key] = value }
rule(params: subtree(:p)) do
(p.is_a?(Array) ? p : [p]).each_with_object({}) { |(key, val), h| h[key] = val }
end
rule(param: { key: simple(:key), value: simple(:val) }) do

View file

@ -0,0 +1,87 @@
# frozen_string_literal: true
module StatusControllerConcern
extend ActiveSupport::Concern
ANCESTORS_LIMIT = 40
DESCENDANTS_LIMIT = 60
DESCENDANTS_DEPTH_LIMIT = 20
def create_descendant_thread(starting_depth, statuses)
depth = starting_depth + statuses.size
if depth < DESCENDANTS_DEPTH_LIMIT
{
statuses: statuses,
starting_depth: starting_depth,
}
else
next_status = statuses.pop
{
statuses: statuses,
starting_depth: starting_depth,
next_status: next_status,
}
end
end
def set_ancestors
@ancestors = @status.reply? ? cache_collection(@status.ancestors(ANCESTORS_LIMIT, current_account), Status) : []
@next_ancestor = @ancestors.size < ANCESTORS_LIMIT ? nil : @ancestors.shift
end
def set_descendants
@max_descendant_thread_id = params[:max_descendant_thread_id]&.to_i
@since_descendant_thread_id = params[:since_descendant_thread_id]&.to_i
descendants = cache_collection(
@status.descendants(
DESCENDANTS_LIMIT,
current_account,
@max_descendant_thread_id,
@since_descendant_thread_id,
DESCENDANTS_DEPTH_LIMIT
),
Status
)
@descendant_threads = []
if descendants.present?
statuses = [descendants.first]
starting_depth = 0
descendants.drop(1).each_with_index do |descendant, index|
if descendants[index].id == descendant.in_reply_to_id
statuses << descendant
else
@descendant_threads << create_descendant_thread(starting_depth, statuses)
# The thread is broken, assume it's a reply to the root status
starting_depth = 0
# ... unless we can find its ancestor in one of the already-processed threads
@descendant_threads.reverse_each do |descendant_thread|
statuses = descendant_thread[:statuses]
index = statuses.find_index do |thread_status|
thread_status.id == descendant.in_reply_to_id
end
if index.present?
starting_depth = descendant_thread[:starting_depth] + index + 1
break
end
end
statuses = [descendant]
end
end
@descendant_threads << create_descendant_thread(starting_depth, statuses)
end
@max_descendant_thread_id = @descendant_threads.pop[:statuses].first.id if descendants.size >= DESCENDANTS_LIMIT
end
end

View file

@ -63,7 +63,7 @@ class FollowerAccountsController < ApplicationController
id: account_followers_url(@account, page: params.fetch(:page, 1)),
type: :ordered,
size: @account.followers_count,
items: follows.map { |follow| ActivityPub::TagManager.instance.uri_for(follow.account) },
items: follows.map { |f| ActivityPub::TagManager.instance.uri_for(f.account) },
part_of: account_followers_url(@account),
next: next_page_url,
prev: prev_page_url

View file

@ -66,7 +66,7 @@ class FollowingAccountsController < ApplicationController
id: account_following_index_url(@account, page: params.fetch(:page, 1)),
type: :ordered,
size: @account.following_count,
items: follows.map { |follow| ActivityPub::TagManager.instance.uri_for(follow.target_account) },
items: follows.map { |f| ActivityPub::TagManager.instance.uri_for(f.target_account) },
part_of: account_following_index_url(@account),
next: next_page_url,
prev: prev_page_url

View file

@ -12,8 +12,8 @@ class MediaController < ApplicationController
before_action :check_playable, only: :player
before_action :allow_iframing, only: :player
content_security_policy only: :player do |policy|
policy.frame_ancestors(false)
content_security_policy only: :player do |p|
p.frame_ancestors(false)
end
def show

View file

@ -7,10 +7,6 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
before_action :authenticate_resource_owner!
before_action :set_cache_headers
content_security_policy do |p|
p.form_action(false)
end
include Localized
private
@ -34,6 +30,6 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
end
def set_cache_headers
response.headers['Cache-Control'] = 'private, no-store'
response.headers['Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate'
end
end

View file

@ -14,7 +14,7 @@ class Settings::BaseController < ApplicationController
end
def set_cache_headers
response.headers['Cache-Control'] = 'private, no-store'
response.headers['Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate'
end
def require_not_suspended!

View file

@ -23,7 +23,7 @@ class Settings::FeaturedTagsController < Settings::BaseController
end
def destroy
RemoveFeaturedTagService.new.call(current_account, @featured_tag)
RemoveFeaturedTagWorker.perform_async(current_account.id, @featured_tag.id)
redirect_to settings_featured_tags_path
end

View file

@ -19,10 +19,6 @@ class StatusesCleanupController < ApplicationController
# Do nothing
end
def require_functional!
redirect_to edit_user_registration_path unless current_user.functional_or_moved?
end
private
def set_policy

View file

@ -2,6 +2,7 @@
class StatusesController < ApplicationController
include WebAppControllerConcern
include StatusControllerConcern
include SignatureAuthentication
include Authorization
include AccountOwnedConcern
@ -17,8 +18,8 @@ class StatusesController < ApplicationController
skip_around_action :set_locale, if: -> { request.format == :json }
skip_before_action :require_functional!, only: [:show, :embed], unless: :whitelist_mode?
content_security_policy only: :embed do |policy|
policy.frame_ancestors(false)
content_security_policy only: :embed do |p|
p.frame_ancestors(false)
end
def show

View file

@ -65,7 +65,7 @@ class TagsController < ApplicationController
id: tag_url(@tag),
type: :ordered,
size: @tag.statuses.count,
items: @statuses.map { |status| ActivityPub::TagManager.instance.uri_for(status) }
items: @statuses.map { |s| ActivityPub::TagManager.instance.uri_for(s) }
)
end
end

View file

@ -4,19 +4,15 @@ module Admin::ActionLogsHelper
def log_target(log)
case log.target_type
when 'Account'
link_to (log.human_identifier.presence || I18n.t('admin.action_logs.deleted_account')), admin_account_path(log.target_id)
link_to log.human_identifier, admin_account_path(log.target_id)
when 'User'
if log.route_param.present?
link_to log.human_identifier, admin_account_path(log.route_param)
else
I18n.t('admin.action_logs.deleted_account')
end
link_to log.human_identifier, admin_account_path(log.route_param)
when 'UserRole'
link_to log.human_identifier, admin_roles_path(log.target_id)
when 'Report'
link_to "##{log.human_identifier.presence || log.target_id}", admin_report_path(log.target_id)
link_to "##{log.human_identifier}", admin_report_path(log.target_id)
when 'DomainBlock', 'DomainAllow', 'EmailDomainBlock', 'UnavailableDomain'
link_to log.human_identifier, "https://#{log.human_identifier.presence}"
link_to log.human_identifier, "https://#{log.human_identifier}"
when 'Status'
link_to log.human_identifier, log.permalink
when 'AccountWarning'
@ -26,13 +22,9 @@ module Admin::ActionLogsHelper
when 'IpBlock', 'Instance', 'CustomEmoji'
log.human_identifier
when 'CanonicalEmailBlock'
content_tag(:samp, (log.human_identifier.presence || '')[0...7], title: log.human_identifier)
content_tag(:samp, log.human_identifier[0...7], title: log.human_identifier)
when 'Appeal'
if log.route_param.present?
link_to log.human_identifier, disputes_strike_path(log.route_param.presence)
else
I18n.t('admin.action_logs.deleted_account')
end
link_to log.human_identifier, disputes_strike_path(log.route_param)
end
end
end

View file

@ -203,7 +203,7 @@ module ApplicationHelper
permit_visibilities.shift(permit_visibilities.index(default_privacy) + 1) if default_privacy.present?
state_params[:visibility] = params[:visibility] if permit_visibilities.include? params[:visibility]
if user_signed_in? && current_user.functional?
if user_signed_in?
state_params[:settings] = state_params[:settings].merge(Web::Setting.find_by(user: current_user)&.data || {})
state_params[:push_subscription] = current_account.user.web_push_subscription(current_session)
state_params[:current_account] = current_account
@ -211,11 +211,6 @@ module ApplicationHelper
state_params[:admin] = Account.find_local(Setting.site_contact_username.strip.gsub(/\A@/, ''))
end
if user_signed_in? && !current_user.functional?
state_params[:disabled_account] = current_account
state_params[:moved_to_account] = current_account.moved_to_account
end
if single_user_mode?
state_params[:owner] = Account.local.without_suspended.where('id > 0').first
end

View file

@ -23,28 +23,19 @@ module FormattingHelper
before_html = begin
if status.spoiler_text?
tag.p do
tag.strong do
I18n.t('rss.content_warning', locale: available_locale_or_nil(status.language) || I18n.default_locale)
end
status.spoiler_text
end + tag.hr
"<p><strong>#{I18n.t('rss.content_warning', locale: available_locale_or_nil(status.language) || I18n.default_locale)}</strong> #{h(status.spoiler_text)}</p><hr />"
else
''
end
end
end.html_safe # rubocop:disable Rails/OutputSafety
after_html = begin
if status.preloadable_poll
tag.p do
safe_join(
status.preloadable_poll.options.map do |o|
tag.send(status.preloadable_poll.multiple? ? 'checkbox' : 'radio', o, disabled: true)
end,
tag.br
)
end
"<p>#{status.preloadable_poll.options.map { |o| "<input type=#{status.preloadable_poll.multiple? ? 'checkbox' : 'radio'} disabled /> #{h(o)}" }.join('<br />')}</p>"
else
''
end
end
end.html_safe # rubocop:disable Rails/OutputSafety
prerender_custom_emojis(
safe_join([before_html, html, after_html]),

View file

@ -23,7 +23,7 @@ module HomeHelper
else
link_to(path || ActivityPub::TagManager.instance.url_for(account), class: 'account__display-name') do
content_tag(:div, class: 'account__avatar-wrapper') do
image_tag(full_asset_url(current_account&.user&.setting_auto_play_gif ? account.avatar_original_url : account.avatar_static_url), class: 'account__avatar', width: 46, height: 46)
image_tag(full_asset_url(current_account&.user&.setting_auto_play_gif ? account.avatar_original_url : account.avatar_static_url), class: 'account__avatar')
end +
content_tag(:span, class: 'display-name') do
content_tag(:bdi) do

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
# rubocop:disable Metrics/ModuleLength, Style/WordArray
module LanguagesHelper
ISO_639_1 = {
@ -98,7 +97,7 @@ module LanguagesHelper
lg: ['Ganda', 'Luganda'].freeze,
li: ['Limburgish', 'Limburgs'].freeze,
ln: ['Lingala', 'Lingála'].freeze,
lo: ['Lao', 'ລາວ'].freeze,
lo: ['Lao', 'ພາສາ'].freeze,
lt: ['Lithuanian', 'lietuvių kalba'].freeze,
lu: ['Luba-Katanga', 'Tshiluba'].freeze,
lv: ['Latvian', 'latviešu valoda'].freeze,
@ -190,17 +189,8 @@ module LanguagesHelper
ISO_639_3 = {
ast: ['Asturian', 'Asturianu'].freeze,
ckb: ['Sorani (Kurdish)', 'سۆرانی'].freeze,
cnr: ['Montenegrin', 'crnogorski'].freeze,
jbo: ['Lojban', 'la .lojban.'].freeze,
kab: ['Kabyle', 'Taqbaylit'].freeze,
kmr: ['Kurmanji (Kurdish)', 'Kurmancî'].freeze,
ldn: ['Láadan', 'Láadan'].freeze,
lfn: ['Lingua Franca Nova', 'lingua franca nova'].freeze,
sco: ['Scots', 'Scots'].freeze,
sma: ['Southern Sami', 'Åarjelsaemien Gïele'].freeze,
smj: ['Lule Sami', 'Julevsámegiella'].freeze,
tok: ['Toki Pona', 'toki pona'].freeze,
zba: ['Balaibalan', 'باليبلن'].freeze,
zgh: ['Standard Moroccan Tamazight', 'ⵜⴰⵎⴰⵣⵉⵖⵜ'].freeze,
}.freeze
@ -269,5 +259,3 @@ module LanguagesHelper
locale_name.to_sym if locale_name.present? && I18n.available_locales.include?(locale_name.to_sym)
end
end
# rubocop:enable Metrics/ModuleLength, Style/WordArray

View file

@ -21,7 +21,7 @@ module StatusesHelper
def media_summary(status)
attachments = { image: 0, video: 0, audio: 0 }
status.ordered_media_attachments.each do |media|
status.media_attachments.each do |media|
if media.video?
attachments[:video] += 1
elsif media.audio?

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 950 B

After

Width:  |  Height:  |  Size: 1 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 102 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

Before After
Before After

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