1
0
mirror of https://github.com/mastodon/mastodon synced 2025-01-22 09:43:25 +09:00

Merge branch 'main' into fixes/out-of-order-private-posts

This commit is contained in:
Claire 2025-01-09 11:27:27 +01:00 committed by GitHub
commit 248bef6322
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1590 changed files with 38392 additions and 24432 deletions

59
.annotaterb.yml Normal file
View File

@ -0,0 +1,59 @@
---
:position: before
:position_in_additional_file_patterns: before
:position_in_class: before
:position_in_factory: before
:position_in_fixture: before
:position_in_routes: before
:position_in_serializer: before
:position_in_test: before
:classified_sort: true
:exclude_controllers: true
:exclude_factories: true
:exclude_fixtures: true
:exclude_helpers: true
:exclude_scaffolds: true
:exclude_serializers: true
:exclude_sti_subclasses: true
:exclude_tests: true
:force: false
:format_markdown: false
:format_rdoc: false
:format_yard: false
:frozen: false
:ignore_model_sub_dir: false
:ignore_unknown_models: false
:include_version: false
:show_complete_foreign_keys: false
:show_foreign_keys: false
:show_indexes: false
:simple_indexes: false
:sort: false
:timestamp: false
:trace: false
:with_comment: true
:with_column_comments: true
:with_table_comments: true
:active_admin: false
:command:
:debug: false
:hide_default_column_types: ''
:hide_limit_column_types: 'integer,boolean'
:ignore_columns:
:ignore_routes:
:models: true
:routes: false
:skip_on_db_migrate: false
:target_action: :do_annotations
:wrapper:
:wrapper_close:
:wrapper_open:
:classes_default_to_s: []
:additional_file_patterns: []
:model_dir:
- app/models
:require: []
:root_dir:
- ''
:show_check_constraints: false

View File

@ -1,10 +1,6 @@
[production]
defaults
> 0.2%
firefox >= 78
ios >= 15.6
not dead
not OperaMini all
[development]
supports es6-module

View File

@ -69,7 +69,7 @@ services:
hard: -1
libretranslate:
image: libretranslate/libretranslate:v1.6.1
image: libretranslate/libretranslate:v1.6.2
restart: unless-stopped
volumes:
- lt-data:/home/libretranslate/.local

View File

@ -45,6 +45,17 @@ ES_PASS=password
SECRET_KEY_BASE=
OTP_SECRET=
# Encryption secrets
# ------------------
# Must be available (and set to same values) for all server processes
# These are private/secret values, do not share outside hosting environment
# Use `bin/rails db:encryption:init` to generate fresh secrets
# Do not change these secrets once in use, as this would cause data loss and other issues
# ------------------
# ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY=
# ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT=
# ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY=
# Web Push
# --------
# Generate with `bundle exec rails mastodon:webpush:generate_vapid_key`

View File

@ -109,7 +109,7 @@ module.exports = defineConfig({
'react/jsx-equals-spacing': 'error',
'react/jsx-no-bind': 'error',
'react/jsx-no-useless-fragment': 'error',
'react/jsx-no-target-blank': 'off',
'react/jsx-no-target-blank': ['error', { allowReferrer: true }],
'react/jsx-tag-spacing': 'error',
'react/jsx-uses-react': 'off', // not needed with new JSX transform
'react/jsx-wrap-multilines': 'error',

View File

@ -1,6 +1,7 @@
name: Bug Report (Web Interface)
description: If you are using Mastodon's web interface and something is not working as expected
labels: [bug, 'status/to triage', 'area/web interface']
description: There is a problem using Mastodon's web interface.
labels: ['status/to triage', 'area/web interface']
type: Bug
body:
- type: markdown
attributes:
@ -47,8 +48,8 @@ body:
attributes:
label: Mastodon version
description: |
This is displayed at the bottom of the About page, eg. `v4.1.2+nightly-20230627`
placeholder: v4.1.2
This is displayed at the bottom of the About page, eg. `v4.4.0-alpha.1`
placeholder: v4.3.0
validations:
required: true
- type: input
@ -56,7 +57,7 @@ body:
label: Browser name and version
description: |
What browser are you using when getting this bug? Please specify the version as well.
placeholder: Firefox 105.0.3
placeholder: Firefox 131.0.0
validations:
required: true
- type: input
@ -64,7 +65,7 @@ body:
label: Operating system
description: |
What OS are you running? Please specify the version as well.
placeholder: macOS 13.4.1
placeholder: macOS 15.0.1
validations:
required: true
- type: textarea

View File

@ -1,7 +1,8 @@
name: Bug Report (server / API)
description: |
If something is not working as expected, but is not from using the web interface.
labels: [bug, 'status/to triage']
There is a problem with the HTTP server, REST API, ActivityPub interaction, etc.
labels: ['status/to triage']
type: 'Bug'
body:
- type: markdown
attributes:
@ -48,8 +49,8 @@ body:
attributes:
label: Mastodon version
description: |
This is displayed at the bottom of the About page, eg. `v4.1.2+nightly-20230627`
placeholder: v4.1.2
This is displayed at the bottom of the About page, eg. `v4.4.0-alpha.1`
placeholder: v4.3.0
validations:
required: false
- type: textarea
@ -59,7 +60,7 @@ body:
Any additional technical details you may have, like logs or error traces
value: |
If this is happening on your own Mastodon server, please fill out those:
- Ruby version: (from `ruby --version`, eg. v3.1.2)
- Node.js version: (from `node --version`, eg. v18.16.0)
- Ruby version: (from `ruby --version`, eg. v3.4.1)
- Node.js version: (from `node --version`, eg. v20.18.0)
validations:
required: false

View File

@ -0,0 +1,74 @@
name: Deployment troubleshooting
description: |
You are a server administrator and you are encountering a technical issue during installation, upgrade or operations of Mastodon.
labels: ['status/to triage']
type: 'Troubleshooting'
body:
- type: markdown
attributes:
value: |
Make sure that you are submitting a new bug that was not previously reported or already fixed.
Please use a concise and distinct title for the issue.
- type: textarea
attributes:
label: Steps to reproduce the problem
description: What were you trying to do?
value: |
1.
2.
3.
...
validations:
required: true
- type: input
attributes:
label: Expected behaviour
description: What should have happened?
validations:
required: true
- type: input
attributes:
label: Actual behaviour
description: What happened?
validations:
required: true
- type: textarea
attributes:
label: Detailed description
validations:
required: false
- type: input
attributes:
label: Mastodon instance
description: The address of the Mastodon instance where you experienced the issue
placeholder: mastodon.social
validations:
required: true
- type: input
attributes:
label: Mastodon version
description: |
This is displayed at the bottom of the About page, eg. `v4.4.0-alpha.1`
placeholder: v4.3.0
validations:
required: false
- type: textarea
attributes:
label: Environment
description: |
Details about your environment, like how Mastodon is deployed, if containers are used, version numbers, etc.
value: |
Please at least include those informations:
- Operating system: (eg. Ubuntu 22.04)
- Ruby version: (from `ruby --version`, eg. v3.4.1)
- Node.js version: (from `node --version`, eg. v20.18.0)
validations:
required: false
- type: textarea
attributes:
label: Technical details
description: |
Any additional technical details you may have, like logs or error traces
validations:
required: false

View File

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

View File

@ -92,6 +92,7 @@ jobs:
build-args: |
MASTODON_VERSION_PRERELEASE=${{ inputs.version_prerelease }}
MASTODON_VERSION_METADATA=${{ inputs.version_metadata }}
SOURCE_COMMIT=${{ github.sha }}
platforms: ${{ inputs.platforms }}
provenance: false
builder: ${{ steps.buildx.outputs.name || steps.buildx-native.outputs.name }}

View File

@ -21,9 +21,11 @@ jobs:
uses: actions/checkout@v4
- id: version_vars
run: |
echo mastodon_version_metadata=pr-${{ github.event.pull_request.number }}-$(git rev-parse --short HEAD) >> $GITHUB_OUTPUT
echo mastodon_version_metadata=pr-${{ github.event.pull_request.number }}-$(git rev-parse --short ${{github.event.pull_request.head.sha}}) >> $GITHUB_OUTPUT
echo mastodon_short_sha=$(git rev-parse --short ${{github.event.pull_request.head.sha}}) >> $GITHUB_OUTPUT
outputs:
metadata: ${{ steps.version_vars.outputs.mastodon_version_metadata }}
short_sha: ${{ steps.version_vars.outputs.mastodon_short_sha }}
build-image:
needs: compute-suffix
@ -39,6 +41,7 @@ jobs:
latest=auto
tags: |
type=ref,event=pr
type=ref,event=pr,suffix=-${{ needs.compute-suffix.outputs.short_sha }}
secrets: inherit
build-image-streaming:
@ -55,4 +58,5 @@ jobs:
latest=auto
tags: |
type=ref,event=pr
type=ref,event=pr,suffix=-${{ needs.compute-suffix.outputs.short_sha }}
secrets: inherit

View File

@ -23,7 +23,7 @@ jobs:
# Only tag with latest when ran against the latest stable branch
# This needs to be updated after each minor version release
flavor: |
latest=${{ startsWith(github.ref, 'refs/tags/v4.2.') }}
latest=${{ startsWith(github.ref, 'refs/tags/v4.3.') }}
tags: |
type=pep440,pattern={{raw}}
type=pep440,pattern=v{{major}}.{{minor}}

View File

@ -36,4 +36,4 @@ jobs:
bundler-cache: true
- name: Run bundler-audit
run: bundle exec bundler-audit check --update
run: bin/bundler-audit check --update

View File

@ -18,7 +18,7 @@ permissions:
jobs:
check-i18n:
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
@ -35,18 +35,18 @@ jobs:
git diff --exit-code
- name: Check locale file normalization
run: bundle exec i18n-tasks check-normalized
run: bin/i18n-tasks check-normalized
- name: Check for unused strings
run: bundle exec i18n-tasks unused
run: bin/i18n-tasks unused
- name: Check for missing strings in English YML
run: |
bundle exec i18n-tasks add-missing -l en
bin/i18n-tasks add-missing -l en
git diff --exit-code
- name: Check for wrong string interpolations
run: bundle exec i18n-tasks check-consistent-interpolations
run: bin/i18n-tasks check-consistent-interpolations
- name: Check that all required locale files exist
run: bundle exec rake repo:check_locales_files
run: bin/rake repo:check_locales_files

View File

@ -46,11 +46,11 @@ jobs:
uses: ./.github/actions/setup-ruby
- name: Run i18n normalize task
run: bundle exec i18n-tasks normalize
run: bin/i18n-tasks normalize
# Create or update the pull request
- name: Create Pull Request
uses: peter-evans/create-pull-request@v7.0.5
uses: peter-evans/create-pull-request@v7.0.6
with:
commit-message: 'New Crowdin translations'
title: 'New Crowdin Translations for ${{ github.base_ref || github.ref_name }} (automated)'

View File

@ -48,11 +48,11 @@ jobs:
uses: ./.github/actions/setup-ruby
- name: Run i18n normalize task
run: bundle exec i18n-tasks normalize
run: bin/i18n-tasks normalize
# Create or update the pull request
- name: Create Pull Request
uses: peter-evans/create-pull-request@v7.0.5
uses: peter-evans/create-pull-request@v7
with:
commit-message: 'New Crowdin translations'
title: 'New Crowdin Translations (automated)'

View File

@ -1,7 +1,6 @@
name: Crowdin / Upload translations
on:
merge_group:
push:
branches:
- 'main'

View File

@ -40,4 +40,4 @@ jobs:
uses: ./.github/actions/setup-javascript
- name: Stylelint
run: yarn lint:css -f github
run: yarn lint:css --custom-formatter @csstools/stylelint-formatter-github

View File

@ -43,4 +43,4 @@ jobs:
- name: Run haml-lint
run: |
echo "::add-matcher::.github/workflows/haml-lint-problem-matcher.json"
bundle exec haml-lint --reporter github
bin/haml-lint --reporter github

View File

@ -9,6 +9,7 @@ on:
- 'Gemfile*'
- '.rubocop*.yml'
- '.ruby-version'
- 'bin/rubocop'
- 'config/brakeman.ignore'
- '**/*.rb'
- '**/*.rake'
@ -19,6 +20,7 @@ on:
- 'Gemfile*'
- '.rubocop*.yml'
- '.ruby-version'
- 'bin/rubocop'
- 'config/brakeman.ignore'
- '**/*.rb'
- '**/*.rake'

View File

@ -12,6 +12,7 @@ on:
- '**/*.rb'
- '.github/workflows/test-migrations.yml'
- 'lib/tasks/tests.rake'
- 'lib/tasks/db.rake'
pull_request:
paths:
@ -32,6 +33,8 @@ jobs:
postgres:
- 14-alpine
- 15-alpine
- 16-alpine
- 17-alpine
services:
postgres:
@ -88,6 +91,11 @@ jobs:
bin/rails db:drop
bin/rails db:create
SKIP_POST_DEPLOYMENT_MIGRATIONS=true bin/rails tests:migrations:prepare_database
# Migrate up to v4.2.0 breakpoint
bin/rails db:migrate VERSION=20230907150100
# Migrate the rest
SKIP_POST_DEPLOYMENT_MIGRATIONS=true bin/rails db:migrate
bin/rails db:migrate
bin/rails tests:migrations:check_database

View File

@ -124,8 +124,8 @@ jobs:
fail-fast: false
matrix:
ruby-version:
- '3.1'
- '3.2'
- '3.3'
- '.ruby-version'
steps:
- uses: actions/checkout@v4
@ -143,7 +143,7 @@ jobs:
uses: ./.github/actions/setup-ruby
with:
ruby-version: ${{ matrix.ruby-version}}
additional-system-dependencies: ffmpeg libpam-dev
additional-system-dependencies: ffmpeg imagemagick libpam-dev
- name: Load database schema
run: |
@ -167,7 +167,7 @@ jobs:
- name: Upload coverage reports to Codecov
if: matrix.ruby-version == '.ruby-version'
uses: codecov/codecov-action@v4
uses: codecov/codecov-action@v5
with:
files: coverage/lcov/*.lcov
env:
@ -175,7 +175,7 @@ jobs:
test-libvips:
name: Libvips tests
runs-on: ubuntu-24.04
runs-on: ubuntu-latest
needs:
- build
@ -226,8 +226,8 @@ jobs:
fail-fast: false
matrix:
ruby-version:
- '3.1'
- '3.2'
- '3.3'
- '.ruby-version'
steps:
- uses: actions/checkout@v4
@ -245,7 +245,7 @@ jobs:
uses: ./.github/actions/setup-ruby
with:
ruby-version: ${{ matrix.ruby-version}}
additional-system-dependencies: ffmpeg libpam-dev libyaml-dev
additional-system-dependencies: ffmpeg libpam-dev
- name: Load database schema
run: './bin/rails db:create db:schema:load db:seed'
@ -254,7 +254,7 @@ jobs:
- name: Upload coverage reports to Codecov
if: matrix.ruby-version == '.ruby-version'
uses: codecov/codecov-action@v4
uses: codecov/codecov-action@v5
with:
files: coverage/lcov/mastodon.lcov
env:
@ -305,8 +305,8 @@ jobs:
fail-fast: false
matrix:
ruby-version:
- '3.1'
- '3.2'
- '3.3'
- '.ruby-version'
steps:
@ -325,7 +325,7 @@ jobs:
uses: ./.github/actions/setup-ruby
with:
ruby-version: ${{ matrix.ruby-version}}
additional-system-dependencies: ffmpeg
additional-system-dependencies: ffmpeg imagemagick
- name: Set up Javascript environment
uses: ./.github/actions/setup-javascript
@ -422,8 +422,8 @@ jobs:
fail-fast: false
matrix:
ruby-version:
- '3.1'
- '3.2'
- '3.3'
- '.ruby-version'
search-image:
- docker.elastic.co/elasticsearch/elasticsearch:7.17.13
@ -445,7 +445,7 @@ jobs:
uses: ./.github/actions/setup-ruby
with:
ruby-version: ${{ matrix.ruby-version}}
additional-system-dependencies: ffmpeg
additional-system-dependencies: ffmpeg imagemagick
- name: Set up Javascript environment
uses: ./.github/actions/setup-javascript

2
.nvmrc
View File

@ -1 +1 @@
20.17
22.13

View File

@ -8,7 +8,7 @@ AllCops:
- lib/mastodon/migration_helpers.rb
ExtraDetails: true
NewCops: enable
TargetRubyVersion: 3.1 # Oldest supported ruby version
TargetRubyVersion: 3.2 # Oldest supported ruby version
inherit_from:
- .rubocop/layout.yml

View File

@ -1,4 +1,7 @@
---
Style/ArrayIntersect:
Enabled: false
Style/ClassAndModuleChildren:
Enabled: false
@ -19,6 +22,13 @@ Style/HashSyntax:
EnforcedShorthandSyntax: either
EnforcedStyle: ruby19_no_mixed_keys
Style/IfUnlessModifier:
Exclude:
- '**/*.haml'
Style/KeywordArgumentsMerging:
Enabled: false
Style/NumericLiterals:
AllowedPatterns:
- \d{4}_\d{2}_\d{2}_\d{6}
@ -37,6 +47,9 @@ Style/RedundantFetchBlock:
Style/RescueStandardError:
EnforcedStyle: implicit
Style/SafeNavigationChainLength:
Enabled: false
Style/SymbolArray:
Enabled: false

View File

@ -1,6 +1,6 @@
# This configuration was generated by
# `rubocop --auto-gen-config --auto-gen-only-exclude --no-offense-counts --no-auto-gen-timestamp`
# using RuboCop version 1.66.1.
# using RuboCop version 1.69.1.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
@ -35,7 +35,6 @@ Rails/OutputSafety:
# Configuration parameters: AllowedVars.
Style/FetchEnvVar:
Exclude:
- 'app/lib/translation_service.rb'
- 'config/environments/production.rb'
- 'config/initializers/2_limited_federation_mode.rb'
- 'config/initializers/3_omniauth.rb'

View File

@ -1 +1 @@
3.3.5
3.4.1

View File

@ -2,7 +2,91 @@
All notable changes to this project will be documented in this file.
## [4.3.0] - UNRELEASED
## [4.3.2] - 2024-12-03
### Added
- Add `tootctl feeds vacuum` (#33065 by @ClearlyClaire)
- Add error message when user tries to follow their own account (#31910 by @lenikadali)
- Add client_secret_expires_at to OAuth Applications (#30317 by @ThisIsMissEm)
### Changed
- Change design of Content Warnings and filters (#32543 by @ClearlyClaire)
### Fixed
- Fix processing incoming post edits with mentions to unresolvable accounts (#33129 by @ClearlyClaire)
- Fix error when including multiple instances of `embed.js` (#33107 by @YKWeyer)
- Fix inactive users' timelines being backfilled on follow and unsuspend (#33094 by @ClearlyClaire)
- Fix direct inbox delivery pushing posts into inactive followers' timelines (#33067 by @ClearlyClaire)
- Fix `TagFollow` records not being correctly handled in account operations (#33063 by @ClearlyClaire)
- Fix pushing hashtag-followed posts to feeds of inactive users (#33018 by @Gargron)
- Fix duplicate notifications in notification groups when using slow mode (#33014 by @ClearlyClaire)
- Fix posts made in the future being allowed to trend (#32996 by @ClearlyClaire)
- Fix uploading higher-than-wide GIF profile picture with libvips enabled (#32911 by @ClearlyClaire)
- Fix domain attribution field having autocorrect and autocapitalize enabled (#32903 by @ClearlyClaire)
- Fix titles being escaped twice (#32889 by @ClearlyClaire)
- Fix list creation limit check (#32869 by @ClearlyClaire)
- Fix error in `tootctl email_domain_blocks` when supplying `--with-dns-records` (#32863 by @mjankowski)
- Fix `min_id` and `max_id` causing error in search API (#32857 by @Gargron)
- Fix inefficiencies when processing removal of posts that use featured tags (#32787 by @ClearlyClaire)
- Fix alt-text pop-in not using the translated description (#32766 by @ClearlyClaire)
- Fix preview cards with long titles erroneously causing layout changes (#32678 by @ClearlyClaire)
- Fix embed modal layout on mobile (#32641 by @DismalShadowX)
- Fix and improve batch attachment deletion handling when using OpenStack Swift (#32637 by @hugogameiro)
- Fix blocks not being applied on link timeline (#32625 by @tribela)
- Fix follow counters being incorrectly changed (#32622 by @oneiros)
- Fix 'unknown' media attachment type rendering (#32613 and #32713 by @ThisIsMissEm and @renatolond)
- Fix tl language native name (#32606 by @seav)
### Security
- Update dependencies
## [4.3.1] - 2024-10-21
### Added
- Add more explicit explanations about author attribution and `fediverse:creator` (#32383 by @ClearlyClaire)
- Add ability to group follow notifications in WebUI, can be disabled in the column settings (#32520 by @renchap)
- Add back a 6 hours mute duration option (#32522 by @renchap)
- Add note about not changing ActiveRecord encryption secrets once they are set (#32413, #32476, #32512, and #32537 by @ClearlyClaire and @mjankowski)
### Changed
- Change translation feature to translate to selected regional variant (e.g. pt-BR) if available (#32428 by @c960657)
### Removed
- Remove ability to get embed code for remote posts (#32578 by @ClearlyClaire)\
Getting the embed code is only reliable for local posts.\
It never worked for non-Mastodon servers, and stopped working correctly with the changes made in 4.3.0.\
We have therefore decided to remove the menu entry while we investigate solutions.
### Fixed
- Fix follow recommendation moderation page default language when using regional variant (#32580 by @ClearlyClaire)
- Fix column-settings spacing in local timeline in advanced view (#32567 by @lindwurm)
- Fix broken i18n in text welcome mailer tags area (#32571 by @mjankowski)
- Fix missing or incorrect cache-control headers for Streaming server (#32551 by @ThisIsMissEm)
- Fix only the first paragraph being displayed in some notifications (#32348 by @ClearlyClaire)
- Fix reblog icons on account media view (#32506 by @tribela)
- Fix Content-Security-Policy not allowing OpenStack SWIFT object storage URI (#32439 by @kenkiku1021)
- Fix back arrow pointing to the incorrect direction in RTL languages (#32485 by @renchap)
- Fix streaming server using `REDIS_USERNAME` instead of `REDIS_USER` (#32493 by @ThisIsMissEm)
- Fix follow recommendation carrousel scrolling on RTL layouts (#32462 and #32505 by @ClearlyClaire)
- Fix follow recommendation suppressions not applying immediately (#32392 by @ClearlyClaire)
- Fix language of push notifications (#32415 by @ClearlyClaire)
- Fix mute duration not being shown in list of muted accounts in web UI (#32388 by @ClearlyClaire)
- Fix “Mark every notification as read” not updating the read marker if scrolled down (#32385 by @ClearlyClaire)
- Fix “Mention” appearing for otherwise filtered posts (#32356 by @ClearlyClaire)
- Fix notification requests from suspended accounts still being listed (#32354 by @ClearlyClaire)
- Fix list edition modal styling (#32358 and #32367 by @ClearlyClaire and @vmstan)
- Fix 4 columns barely not fitting on 1920px screen (#32361 by @ClearlyClaire)
- Fix icon alignment in applications list (#32293 by @mjankowski)
## [4.3.0] - 2024-10-08
The following changelog entries focus on changes visible to users, administrators, client developers or federated software developers, but there has also been a lot of code modernization, refactoring, and tooling work, in particular by @mjankowski.
@ -11,12 +95,12 @@ The following changelog entries focus on changes visible to users, administrator
- **Add confirmation interstitial instead of silently redirecting logged-out visitors to remote resources** (#27792, #28902, and #30651 by @ClearlyClaire and @Gargron)\
This fixes a longstanding open redirect in Mastodon, at the cost of added friction when local links to remote resources are shared.
- Fix ReDoS vulnerability on some Ruby versions ([GHSA-jpxp-r43f-rhvx](https://github.com/mastodon/mastodon/security/advisories/GHSA-jpxp-r43f-rhvx))
- Change `form-action` Content-Security-Policy directive to be more restrictive (#26897 by @ClearlyClaire)
- Change `form-action` Content-Security-Policy directive to be more restrictive (#26897 and #32241 by @ClearlyClaire)
- Update dependencies
### Added
- **Add server-side notification grouping** (#29889, #30576, #30685, #30688, #30707, #30776, #30779, #30781, #30440, #31062, #31098, #31076, #31111, #31123, #31223, #31214, #31224, #31299, #31325, #31347, #31304, #31326, #31384, #31403, #31433, #31509, #31486, #31513, #31592, #31594, #31638, #31746, #31652, #31709, #31725, #31745, #31613, #31657, #31840, #31610, #31929, #32089 and #32085 by @ClearlyClaire, @Gargron, @mgmn, and @renchap)\
- **Add server-side notification grouping** (#29889, #30576, #30685, #30688, #30707, #30776, #30779, #30781, #30440, #31062, #31098, #31076, #31111, #31123, #31223, #31214, #31224, #31299, #31325, #31347, #31304, #31326, #31384, #31403, #31433, #31509, #31486, #31513, #31592, #31594, #31638, #31746, #31652, #31709, #31725, #31745, #31613, #31657, #31840, #31610, #31929, #32089, #32085, #32243, #32179 and #32254 by @ClearlyClaire, @Gargron, @mgmn, and @renchap)\
Group notifications of the same type for the same target, so that your notifications no longer get cluttered by boost and favorite notifications as soon as a couple of your posts get traction.\
This is done server-side so that clients can efficiently get relevant groups without having to go through numerous pages of individual notifications.\
As part of this, the visual design of the entire notifications feature has been revamped.\
@ -26,9 +110,9 @@ The following changelog entries focus on changes visible to users, administrator
- `GET /api/v2/notifications`: https://docs.joinmastodon.org/methods/grouped_notifications/#get-grouped
- `GET /api/v2/notifications/:group_key`: https://docs.joinmastodon.org/methods/grouped_notifications/#get-notification-group
- `GET /api/v2/notifications/:group_key/accounts`: https://docs.joinmastodon.org/methods/grouped_notifications/#get-group-accounts
- `POST /api/v2/notifications/:group_key/dimsiss`: https://docs.joinmastodon.org/methods/grouped_notifications/#dismiss-group
- `POST /api/v2/notifications/:group_key/dismiss`: https://docs.joinmastodon.org/methods/grouped_notifications/#dismiss-group
- `GET /api/v2/notifications/:unread_count`: https://docs.joinmastodon.org/methods/grouped_notifications/#unread-group-count
- **Add notification policies, filtered notifications and notification requests** (#29366, #29529, #29433, #29565, #29567, #29572, #29575, #29588, #29646, #29652, #29658, #29666, #29693, #29699, #29737, #29706, #29570, #29752, #29810, #29826, #30114, #30251, #30559, #29868, #31008, #31011, #30996, #31149, #31220, #31222, #31225, #31242, #31262, #31250, #31273, #31310, #31316, #31322, #31329, #31324, #31331, #31343, #31342, #31309, #31358, #31378, #31406, #31256, #31456, #31419, #31457, #31508, #31540, #31541, #31723 and #32062 by @ClearlyClaire, @Gargron, @TheEssem, @mgmn, @oneiros, and @renchap)\
- **Add notification policies, filtered notifications and notification requests** (#29366, #29529, #29433, #29565, #29567, #29572, #29575, #29588, #29646, #29652, #29658, #29666, #29693, #29699, #29737, #29706, #29570, #29752, #29810, #29826, #30114, #30251, #30559, #29868, #31008, #31011, #30996, #31149, #31220, #31222, #31225, #31242, #31262, #31250, #31273, #31310, #31316, #31322, #31329, #31324, #31331, #31343, #31342, #31309, #31358, #31378, #31406, #31256, #31456, #31419, #31457, #31508, #31540, #31541, #31723, #32062 and #32281 by @ClearlyClaire, @Gargron, @TheEssem, @mgmn, @oneiros, and @renchap)\
The old “Block notifications from non-followers”, “Block notifications from people you don't follow” and “Block direct messages from people you don't follow” notification settings have been replaced by a new set of settings found directly in the notification column.\
You can now separately filter or drop notifications from people you don't follow, people who don't follow you, accounts created within the past 30 days, as well as unsolicited private mentions, and accounts limited by the moderation.\
Instead of being outright dropped, notifications that you chose to filter are put in a separate “Filtered notifications” box that you can review separately without it clogging your main notifications.\
@ -51,7 +135,7 @@ The following changelog entries focus on changes visible to users, administrator
- **Add notifications of severed relationships** (#27511, #29665, #29668, #29670, #29700, #29714, #29712, and #29731 by @ClearlyClaire and @Gargron)\
Notify local users when they lose relationships as a result of a local moderator blocking a remote account or server, allowing the affected user to retrieve the list of broken relationships.\
Note that this does not notify remote users.\
This adds the `severed_relationships` notification type to the REST API and streaming, with a new [`relationship_severance_event` attribute](https://docs.joinmastodon.org/entities/Notification/#relationship_severance_event).
This adds the `severed_relationships` notification type to the REST API and streaming, with a new [`event` attribute](https://docs.joinmastodon.org/entities/Notification/#relationship_severance_event).
- **Add hover cards in web UI** (#30754, #30864, #30850, #30879, #30928, #30949, #30948, #30931, and #31300 by @ClearlyClaire, @Gargron, and @renchap)\
Hovering over an avatar or username will now display a hover card with the first two lines of the user's description and their first two profile fields.\
This can be disabled in the “Animations and accessibility” section of the preferences.
@ -61,13 +145,13 @@ The following changelog entries focus on changes visible to users, administrator
- **Add timeline of public posts about a trending link** (#30381 and #30840 by @Gargron)\
You can now see public posts mentioning currently-trending articles from people who have opted into discovery features.\
This adds a new REST API endpoint: https://docs.joinmastodon.org/methods/timelines/#link
- **Add author highlight for news articles whose authors are on the fediverse** (#30398, #30670, #30521, #30846, #31819, and #31900 by @Gargron and @oneiros)\
- **Add author highlight for news articles whose authors are on the fediverse** (#30398, #30670, #30521, #30846, #31819, #31900 and #32188 by @Gargron, @mjankowski and @oneiros)\
This adds a mechanism to [highlight the author of news articles](https://blog.joinmastodon.org/2024/07/highlighting-journalism-on-mastodon/) shared on Mastodon.\
Articles hosted outside the fediverse can indicate a fediverse author with a meta tag:
```html
<meta name="fediverse:creator" content="username@domain" />
```
On the API side, this is represented by a new `authors` attribute to the `PreviewCard` entity: https://docs.joinmastodon.org/entities/PreviewCard/#authors\
On the API side, this is represented by a new `authors` attribute to the `PreviewCard` entity: https://docs.joinmastodon.org/entities/PreviewCard/#authors \
Users can allow arbitrary domains to use `fediverse:creator` to credit them by visiting `/settings/verification`.\
This is federated as a new `attributionDomains` property in the `http://joinmastodon.org/ns` namespace, containing an array of domain names: https://docs.joinmastodon.org/spec/activitypub/#properties-used-1
- **Add in-app notifications for moderation actions and warnings** (#30065, #30082, and #30081 by @ClearlyClaire)\
@ -150,10 +234,12 @@ The following changelog entries focus on changes visible to users, administrator
- Add groundwork for annual reports for accounts (#28693 by @Gargron)\
This lays the groundwork for a “year-in-review”/“wrapped” style report for local users, but is currently not in use.
- Add notification email on invalid second authenticator (#28822 by @ClearlyClaire)
- Add date of account deletion in list of accounts in the admin interface (#25640 by @tribela)
- Add new emojis from `jdecked/twemoji` 15.0 (#28404 by @TheEssem)
- Add configurable error handling in attachment batch deletion (#28184 by @vmstan)\
This makes the S3 batch size configurable through the `S3_BATCH_DELETE_LIMIT` environment variable (defaults to 1000), and adds some retry logic, configurable through the `S3_BATCH_DELETE_RETRY` environment variable (defaults to 3).
- Add VAPID public key to instance serializer (#28006 by @ThisIsMissEm)
- Add support for serving JRD `/.well-known/host-meta.json` in addition to XRD host-meta (#32206 by @c960657)
- Add `nodeName` and `nodeDescription` to nodeinfo `metadata` (#28079 by @6543)
- Add Thai diacritics and tone marks in `HASHTAG_INVALID_CHARS_RE` (#26576 by @ppnplus)
- Add variable delay before link verification of remote account links (#27774 by @ClearlyClaire)
@ -168,7 +254,7 @@ The following changelog entries focus on changes visible to users, administrator
### Changed
- **Change icons throughout the web interface** (#27385, #27539, #27555, #27579, #27700, #27817, #28519, #28709, #28064, #28775, #28780, #27924, #29294, #29395, #29537, #29569, #29610, #29612, #29649, #29844, #27780, #30974, #30963, #30962, #30961, #31362, #31363, #31359, #31371, #31360, #31512, #31511, and #31525 by @ClearlyClaire, @Gargron, @arbolitoloco1, @mjankowski, @nclm, @renchap, @ronilaukkarinen, and @zunda)\
- **Change icons throughout the web interface** (#27385, #27539, #27555, #27579, #27700, #27817, #28519, #28709, #28064, #28775, #28780, #27924, #29294, #29395, #29537, #29569, #29610, #29612, #29649, #29844, #27780, #30974, #30963, #30962, #30961, #31362, #31363, #31359, #31371, #31360, #31512, #31511, #31525, #32153, and #32201 by @ClearlyClaire, @Gargron, @arbolitoloco1, @mjankowski, @nclm, @renchap, @ronilaukkarinen, and @zunda)\
This changes all the interface icons from FontAwesome to Material Symbols for a more modern look, consistent with the official Mastodon Android app.\
In addition, better care is given to pixel alignment, and icon variants are used to better highlight active/inactive state.
- **Change design of compose form in web UI** (#28119, #29059, #29248, #29372, #29384, #29417, #29456, #29406, #29651, #29659, #31889 and #32033 by @ClearlyClaire, @Gargron, @eai04191, @hinaloe, and @ronilaukkarinen)\
@ -192,9 +278,9 @@ The following changelog entries focus on changes visible to users, administrator
Administrators may need to update their setup accordingly.
- Change how content warnings and filters are displayed in web UI (#31365, and #31761 by @Gargron)
- Change preview card processing to ignore `undefined` as canonical url (#31882 by @oneiros)
- Change embedded posts to use web UI (#31766 and #32135 by @Gargron)
- Change embedded posts to use web UI (#31766, #32135 and #32271 by @Gargron)
- Change inner borders in media galleries in web UI (#31852 by @Gargron)
- Change design of media attachments and profile media tab in web UI (#31807, #32048, and #31967 by @Gargron)
- Change design of media attachments and profile media tab in web UI (#31807, #32048, #31967, #32217, #32224 and #32257 by @ClearlyClaire and @Gargron)
- Change labels on thread indicators in web UI (#31806 by @Gargron)
- Change label of "Data export" menu item in settings interface (#32099 by @c960657)
- Change responsive break points on navigation panel in web UI (#32034 by @Gargron)
@ -284,9 +370,10 @@ The following changelog entries focus on changes visible to users, administrator
- Fix error when accepting an appeal for sensitive posts deleted in the meantime (#32037 by @ClearlyClaire)
- Fix error when encountering reblog of deleted post in feed rebuild (#32001 by @ClearlyClaire)
- Fix Safari browser glitch related to horizontal scrolling (#31960 by @Gargron)
- Fix unresolvable mentions sometimes preventing processing incoming posts (#29215 by @tribela and @ClearlyClaire)
- Fix too many requests caused by relationship look-ups in web UI (#32042 by @Gargron)
- Fix links for reblogs in moderation interface (#31979 by @ClearlyClaire)
- Fix the appearance of avatars when they do not load (#31966 by @renchap)
- Fix the appearance of avatars when they do not load (#31966 and #32270 by @Gargron and @renchap)
- Fix spurious error notifications for aborted requests in web UI (#31952 by @c960657)
- Fix HTTP 500 error in `/api/v1/polls/:id/votes` when required `choices` parameter is missing (#25598 by @danielmbrasil)
- Fix security context sometimes not being added in LD-Signed activities (#31871 by @ClearlyClaire)
@ -309,10 +396,12 @@ The following changelog entries focus on changes visible to users, administrator
- Fix “Redirect URI” field not being marked as required in “New application” form (#30311 by @ThisIsMissEm)
- Fix right-to-left text in preview cards (#30930 by @ClearlyClaire)
- Fix rack attack `match_type` value typo in logging config (#30514 by @mjankowski)
- Fix various cases of duplicate, missing, or inconsistent borders or scrollbar styles (#31068, #31286, #31268, #31275, #31284, #31305, #31346, #31372, #31373, #31389, #31432, #31391, #31445 and #32091 by @ClearlyClaire, @valtlai and @vmstan)
- Fix various cases of duplicate, missing, or inconsistent borders or scrollbar styles (#31068, #31286, #31268, #31275, #31284, #31305, #31346, #31372, #31373, #31389, #31432, #31391, #31445, #32091, #32147 and #32137 by @ClearlyClaire, @mjankowski, @valtlai and @vmstan)
- Fix editing description of media uploads with custom thumbnails (#32221 by @ClearlyClaire)
- Fix race condition in `POST /api/v1/push/subscription` (#30166 by @ClearlyClaire)
- Fix post deletion not being delayed when those are part of an account warning (#30163 by @ClearlyClaire)
- Fix rendering error on `/start` when not logged in (#30023 by @timothyjrogers)
- Fix unneeded requests to blocked domains when receiving relayed signed activities from them (#31161 by @ClearlyClaire)
- Fix logo pushing header buttons out of view on certain conditions in mobile layout (#29787 by @ClearlyClaire)
- Fix notification-related records not being reattributed when merging accounts (#29694 by @ClearlyClaire)
- Fix results/query in `api/v1/featured_tags/suggestions` (#29597 by @mjankowski)
@ -322,6 +411,7 @@ The following changelog entries focus on changes visible to users, administrator
- Fix full date display not respecting the locale 12/24h format (#29448 by @renchap)
- Fix filters title and keywords overflow (#29396 by @GeopJr)
- Fix incorrect date format in “Follows and followers” (#29390 by @JasonPunyon)
- Fix navigation item active highlight for some paths (#32159 by @mjankowski)
- Fix “Edit media” modal sizing and layout when space-constrained (#27095 by @ronilaukkarinen)
- Fix modal container bounds (#29185 by @nico3333fr)
- Fix inefficient HTTP signature parsing using regexps and `StringScanner` (#29133 by @ClearlyClaire)
@ -351,7 +441,7 @@ The following changelog entries focus on changes visible to users, administrator
- Fix empty environment variables not using default nil value (#27400 by @renchap)
- Fix language sorting in settings (#27158 by @gunchleoc)
## |4.2.11] - 2024-08-16
## [4.2.11] - 2024-08-16
### Added

View File

@ -12,7 +12,7 @@ You can contribute in the following ways:
If your contributions are accepted into Mastodon, you can request to be paid through [our OpenCollective](https://opencollective.com/mastodon).
Please review the org-level [contribution guidelines] for high-level acceptance
criteria guidance.
criteria guidance and the [DEVELOPMENT] guide for environment-specific details.
[contribution guidelines]: https://github.com/mastodon/.github/blob/main/CONTRIBUTING.md
@ -53,3 +53,5 @@ It is not always possible to phrase every change in such a manner, but it is des
## 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).
[DEVELOPMENT]: docs/DEVELOPMENT.md

View File

@ -1,4 +1,4 @@
# syntax=docker/dockerfile:1.10
# syntax=docker/dockerfile:1.12
# This file is designed for production server deployment, not local development work
# For a containerized local dev environment, see: https://github.com/mastodon/mastodon/blob/main/README.md#docker
@ -10,17 +10,17 @@
ARG TARGETPLATFORM=${TARGETPLATFORM}
ARG BUILDPLATFORM=${BUILDPLATFORM}
# Ruby image to use for base image, change with [--build-arg RUBY_VERSION="3.3.x"]
# Ruby image to use for base image, change with [--build-arg RUBY_VERSION="3.4.x"]
# renovate: datasource=docker depName=docker.io/ruby
ARG RUBY_VERSION="3.3.5"
ARG RUBY_VERSION="3.4.1"
# # Node version to use in base image, change with [--build-arg NODE_MAJOR_VERSION="20"]
# renovate: datasource=node-version depName=node
ARG NODE_MAJOR_VERSION="20"
ARG NODE_MAJOR_VERSION="22"
# Debian image to use for base image, change with [--build-arg DEBIAN_VERSION="bookworm"]
ARG DEBIAN_VERSION="bookworm"
# Node image to use for base image based on combined variables (ex: 20-bookworm-slim)
FROM docker.io/node:${NODE_MAJOR_VERSION}-${DEBIAN_VERSION}-slim AS node
# Ruby image to use for base image based on combined variables (ex: 3.3.x-slim-bookworm)
# Ruby image to use for base image based on combined variables (ex: 3.4.x-slim-bookworm)
FROM docker.io/ruby:${RUBY_VERSION}-slim-${DEBIAN_VERSION} AS ruby
# Resulting version string is vX.X.X-MASTODON_VERSION_PRERELEASE+MASTODON_VERSION_METADATA
@ -29,6 +29,8 @@ FROM docker.io/ruby:${RUBY_VERSION}-slim-${DEBIAN_VERSION} AS ruby
ARG MASTODON_VERSION_PRERELEASE=""
# Append build metadata or fork information to version.rb [--build-arg MASTODON_VERSION_METADATA="pr-123456"]
ARG MASTODON_VERSION_METADATA=""
# Will be available as Mastodon::Version.source_commit
ARG SOURCE_COMMIT=""
# Allow Ruby on Rails to serve static files
# See: https://docs.joinmastodon.org/admin/config/#rails_serve_static_files
@ -45,30 +47,31 @@ ARG GID="991"
# Apply Mastodon build options based on options above
ENV \
# Apply Mastodon version information
# Apply Mastodon version information
MASTODON_VERSION_PRERELEASE="${MASTODON_VERSION_PRERELEASE}" \
MASTODON_VERSION_METADATA="${MASTODON_VERSION_METADATA}" \
# Apply Mastodon static files and YJIT options
SOURCE_COMMIT="${SOURCE_COMMIT}" \
# Apply Mastodon static files and YJIT options
RAILS_SERVE_STATIC_FILES=${RAILS_SERVE_STATIC_FILES} \
RUBY_YJIT_ENABLE=${RUBY_YJIT_ENABLE} \
# Apply timezone
# Apply timezone
TZ=${TZ}
ENV \
# Configure the IP to bind Mastodon to when serving traffic
# Configure the IP to bind Mastodon to when serving traffic
BIND="0.0.0.0" \
# Use production settings for Yarn, Node and related nodejs based tools
# Use production settings for Yarn, Node and related nodejs based tools
NODE_ENV="production" \
# Use production settings for Ruby on Rails
# Use production settings for Ruby on Rails
RAILS_ENV="production" \
# Add Ruby and Mastodon installation to the PATH
# Add Ruby and Mastodon installation to the PATH
DEBIAN_FRONTEND="noninteractive" \
PATH="${PATH}:/opt/ruby/bin:/opt/mastodon/bin" \
# Optimize jemalloc 5.x performance
# Optimize jemalloc 5.x performance
MALLOC_CONF="narenas:2,background_thread:true,thp:never,dirty_decay_ms:1000,muzzy_decay_ms:0" \
# Enable libvips, should not be changed
# Enable libvips, should not be changed
MASTODON_USE_LIBVIPS=true \
# Sidekiq will touch tmp/sidekiq_process_has_started_and_will_begin_processing_jobs to indicate it is ready. This can be used for a readiness check in Kubernetes
# Sidekiq will touch tmp/sidekiq_process_has_started_and_will_begin_processing_jobs to indicate it is ready. This can be used for a readiness check in Kubernetes
MASTODON_SIDEKIQ_READY_FILENAME=sidekiq_process_has_started_and_will_begin_processing_jobs
# Set default shell used for running commands
@ -79,14 +82,14 @@ ARG TARGETPLATFORM
RUN echo "Target platform is $TARGETPLATFORM"
RUN \
# Remove automatic apt cache Docker cleanup scripts
# Remove automatic apt cache Docker cleanup scripts
rm -f /etc/apt/apt.conf.d/docker-clean; \
# Sets timezone
# Sets timezone
echo "${TZ}" > /etc/localtime; \
# Creates mastodon user/group and sets home directory
# Creates mastodon user/group and sets home directory
groupadd -g "${GID}" mastodon; \
useradd -l -u "${UID}" -g "${GID}" -m -d /opt/mastodon mastodon; \
# Creates /mastodon symlink to /opt/mastodon
# Creates /mastodon symlink to /opt/mastodon
ln -s /opt/mastodon /mastodon;
# Set /opt/mastodon as working directory
@ -94,28 +97,28 @@ WORKDIR /opt/mastodon
# hadolint ignore=DL3008,DL3005
RUN \
# Mount Apt cache and lib directories from Docker buildx caches
--mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \
--mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \
# Apt update & upgrade to check for security updates to Debian image
# Mount Apt cache and lib directories from Docker buildx caches
--mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \
--mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \
# Apt update & upgrade to check for security updates to Debian image
apt-get update; \
apt-get dist-upgrade -yq; \
# Install jemalloc, curl and other necessary components
# Install jemalloc, curl and other necessary components
apt-get install -y --no-install-recommends \
curl \
file \
libjemalloc2 \
patchelf \
procps \
tini \
tzdata \
wget \
curl \
file \
libjemalloc2 \
patchelf \
procps \
tini \
tzdata \
wget \
; \
# Patch Ruby to use jemalloc
# Patch Ruby to use jemalloc
patchelf --add-needed libjemalloc.so.2 /usr/local/bin/ruby; \
# Discard patchelf after use
# Discard patchelf after use
apt-get purge -y \
patchelf \
patchelf \
;
# Create temporary build layer from base image
@ -132,56 +135,56 @@ ARG TARGETPLATFORM
# hadolint ignore=DL3008
RUN \
# Mount Apt cache and lib directories from Docker buildx caches
--mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \
--mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \
# Install build tools and bundler dependencies from APT
# Mount Apt cache and lib directories from Docker buildx caches
--mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \
--mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \
# Install build tools and bundler dependencies from APT
apt-get install -y --no-install-recommends \
autoconf \
automake \
build-essential \
cmake \
git \
libgdbm-dev \
libglib2.0-dev \
libgmp-dev \
libicu-dev \
libidn-dev \
libpq-dev \
libssl-dev \
libtool \
meson \
nasm \
pkg-config \
shared-mime-info \
xz-utils \
# libvips components
libcgif-dev \
libexif-dev \
libexpat1-dev \
libgirepository1.0-dev \
libheif-dev \
libimagequant-dev \
libjpeg62-turbo-dev \
liblcms2-dev \
liborc-dev \
libspng-dev \
libtiff-dev \
libwebp-dev \
autoconf \
automake \
build-essential \
cmake \
git \
libgdbm-dev \
libglib2.0-dev \
libgmp-dev \
libicu-dev \
libidn-dev \
libpq-dev \
libssl-dev \
libtool \
meson \
nasm \
pkg-config \
shared-mime-info \
xz-utils \
# libvips components
libcgif-dev \
libexif-dev \
libexpat1-dev \
libgirepository1.0-dev \
libheif-dev \
libimagequant-dev \
libjpeg62-turbo-dev \
liblcms2-dev \
liborc-dev \
libspng-dev \
libtiff-dev \
libwebp-dev \
# ffmpeg components
libdav1d-dev \
liblzma-dev \
libmp3lame-dev \
libopus-dev \
libsnappy-dev \
libvorbis-dev \
libvpx-dev \
libx264-dev \
libx265-dev \
libdav1d-dev \
liblzma-dev \
libmp3lame-dev \
libopus-dev \
libsnappy-dev \
libvorbis-dev \
libvpx-dev \
libx264-dev \
libx265-dev \
;
RUN \
# Configure Corepack
# Configure Corepack
rm /usr/local/bin/yarn*; \
corepack enable; \
corepack prepare --activate;
@ -191,7 +194,7 @@ FROM build AS libvips
# libvips version to compile, change with [--build-arg VIPS_VERSION="8.15.2"]
# renovate: datasource=github-releases depName=libvips packageName=libvips/libvips
ARG VIPS_VERSION=8.15.3
ARG VIPS_VERSION=8.16.0
# libvips download URL, change with [--build-arg VIPS_URL="https://github.com/libvips/libvips/releases/download"]
ARG VIPS_URL=https://github.com/libvips/libvips/releases/download
@ -214,7 +217,7 @@ FROM build AS ffmpeg
# ffmpeg version to compile, change with [--build-arg FFMPEG_VERSION="7.0.x"]
# renovate: datasource=repology depName=ffmpeg packageName=openpkg_current/ffmpeg
ARG FFMPEG_VERSION=7.0.2
ARG FFMPEG_VERSION=7.1
# ffmpeg download URL, change with [--build-arg FFMPEG_URL="https://ffmpeg.org/releases"]
ARG FFMPEG_URL=https://ffmpeg.org/releases
@ -228,28 +231,28 @@ WORKDIR /usr/local/ffmpeg/src/ffmpeg-${FFMPEG_VERSION}
# Configure and compile ffmpeg
RUN \
./configure \
--prefix=/usr/local/ffmpeg \
--toolchain=hardened \
--disable-debug \
--disable-devices \
--disable-doc \
--disable-ffplay \
--disable-network \
--disable-static \
--enable-ffmpeg \
--enable-ffprobe \
--enable-gpl \
--enable-libdav1d \
--enable-libmp3lame \
--enable-libopus \
--enable-libsnappy \
--enable-libvorbis \
--enable-libvpx \
--enable-libwebp \
--enable-libx264 \
--enable-libx265 \
--enable-shared \
--enable-version3 \
--prefix=/usr/local/ffmpeg \
--toolchain=hardened \
--disable-debug \
--disable-devices \
--disable-doc \
--disable-ffplay \
--disable-network \
--disable-static \
--enable-ffmpeg \
--enable-ffprobe \
--enable-gpl \
--enable-libdav1d \
--enable-libmp3lame \
--enable-libopus \
--enable-libsnappy \
--enable-libvorbis \
--enable-libvpx \
--enable-libwebp \
--enable-libx264 \
--enable-libx265 \
--enable-shared \
--enable-version3 \
; \
make -j$(nproc); \
make install;
@ -263,17 +266,17 @@ ARG TARGETPLATFORM
COPY Gemfile* /opt/mastodon/
RUN \
# Mount Ruby Gem caches
--mount=type=cache,id=gem-cache-${TARGETPLATFORM},target=/usr/local/bundle/cache/,sharing=locked \
# Configure bundle to prevent changes to Gemfile and Gemfile.lock
# Mount Ruby Gem caches
--mount=type=cache,id=gem-cache-${TARGETPLATFORM},target=/usr/local/bundle/cache/,sharing=locked \
# Configure bundle to prevent changes to Gemfile and Gemfile.lock
bundle config set --global frozen "true"; \
# Configure bundle to not cache downloaded Gems
# Configure bundle to not cache downloaded Gems
bundle config set --global cache_all "false"; \
# Configure bundle to only process production Gems
# Configure bundle to only process production Gems
bundle config set --local without "development test"; \
# Configure bundle to not warn about root user
# Configure bundle to not warn about root user
bundle config set silence_root_warning "true"; \
# Download and install required Gems
# Download and install required Gems
bundle install -j"$(nproc)";
# Create temporary node specific build layer from build layer
@ -288,9 +291,9 @@ COPY .yarn /opt/mastodon/.yarn
# hadolint ignore=DL3008
RUN \
--mount=type=cache,id=corepack-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/corepack,sharing=locked \
--mount=type=cache,id=yarn-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/yarn,sharing=locked \
# Install Node packages
--mount=type=cache,id=corepack-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/corepack,sharing=locked \
--mount=type=cache,id=yarn-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/yarn,sharing=locked \
# Install Node packages
yarn workspaces focus --production @mastodon/mastodon;
# Create temporary assets build layer from build layer
@ -311,10 +314,10 @@ ARG TARGETPLATFORM
RUN \
ldconfig; \
# Use Ruby on Rails to create Mastodon assets
# Use Ruby on Rails to create Mastodon assets
SECRET_KEY_BASE_DUMMY=1 \
bundle exec rails assets:precompile; \
# Cleanup temporary files
# Cleanup temporary files
rm -fr /opt/mastodon/tmp;
# Prep final Mastodon Ruby layer
@ -324,49 +327,49 @@ ARG TARGETPLATFORM
# hadolint ignore=DL3008
RUN \
# Mount Apt cache and lib directories from Docker buildx caches
--mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \
--mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \
# Mount Corepack and Yarn caches from Docker buildx caches
--mount=type=cache,id=corepack-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/corepack,sharing=locked \
--mount=type=cache,id=yarn-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/yarn,sharing=locked \
# Apt update install non-dev versions of necessary components
# Mount Apt cache and lib directories from Docker buildx caches
--mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \
--mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \
# Mount Corepack and Yarn caches from Docker buildx caches
--mount=type=cache,id=corepack-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/corepack,sharing=locked \
--mount=type=cache,id=yarn-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/yarn,sharing=locked \
# Apt update install non-dev versions of necessary components
apt-get install -y --no-install-recommends \
libexpat1 \
libglib2.0-0 \
libicu72 \
libidn12 \
libpq5 \
libreadline8 \
libssl3 \
libyaml-0-2 \
libexpat1 \
libglib2.0-0 \
libicu72 \
libidn12 \
libpq5 \
libreadline8 \
libssl3 \
libyaml-0-2 \
# libvips components
libcgif0 \
libexif12 \
libheif1 \
libimagequant0 \
libjpeg62-turbo \
liblcms2-2 \
liborc-0.4-0 \
libspng0 \
libtiff6 \
libwebp7 \
libwebpdemux2 \
libwebpmux3 \
libcgif0 \
libexif12 \
libheif1 \
libimagequant0 \
libjpeg62-turbo \
liblcms2-2 \
liborc-0.4-0 \
libspng0 \
libtiff6 \
libwebp7 \
libwebpdemux2 \
libwebpmux3 \
# ffmpeg components
libdav1d6 \
libmp3lame0 \
libopencore-amrnb0 \
libopencore-amrwb0 \
libopus0 \
libsnappy1v5 \
libtheora0 \
libvorbis0a \
libvorbisenc2 \
libvorbisfile3 \
libvpx7 \
libx264-164 \
libx265-199 \
libdav1d6 \
libmp3lame0 \
libopencore-amrnb0 \
libopencore-amrwb0 \
libopus0 \
libsnappy1v5 \
libtheora0 \
libvorbis0a \
libvorbisenc2 \
libvorbisfile3 \
libvpx7 \
libx264-164 \
libx265-199 \
;
# Copy Mastodon sources into final layer
@ -386,7 +389,7 @@ COPY --from=ffmpeg /usr/local/ffmpeg/lib /usr/local/lib
RUN \
ldconfig; \
# Smoketest media processors
# Smoketest media processors
vips -v; \
ffmpeg -version; \
ffprobe -version;
@ -396,10 +399,10 @@ RUN \
bundle exec bootsnap precompile --gemfile app/ lib/;
RUN \
# Pre-create and chown system volume to Mastodon user
# Pre-create and chown system volume to Mastodon user
mkdir -p /opt/mastodon/public/system; \
chown mastodon:mastodon /opt/mastodon/public/system; \
# Set Mastodon user as owner of tmp folder
# Set Mastodon user as owner of tmp folder
chown -R mastodon:mastodon /opt/mastodon/tmp;
# Set the running user for resulting container

34
Gemfile
View File

@ -1,12 +1,12 @@
# frozen_string_literal: true
source 'https://rubygems.org'
ruby '>= 3.1.0'
ruby '>= 3.2.0', '< 3.5.0'
gem 'propshaft'
gem 'puma', '~> 6.3'
gem 'rack', '~> 2.2.7'
gem 'rails', '~> 7.1.1'
gem 'rails', '~> 8.0'
gem 'thor', '~> 1.2'
gem 'dotenv'
@ -16,16 +16,16 @@ gem 'pghero'
gem 'aws-sdk-s3', '~> 1.123', require: false
gem 'blurhash', '~> 0.1'
gem 'fog-core', '<= 2.5.0'
gem 'fog-core', '<= 2.6.0'
gem 'fog-openstack', '~> 1.0', require: false
gem 'jd-paperclip-azure', '~> 3.0', require: false
gem 'kt-paperclip', '~> 7.2'
gem 'md-paperclip-azure', '~> 2.2', require: false
gem 'ruby-vips', '~> 2.2', require: false
gem 'active_model_serializers', '~> 0.10'
gem 'addressable', '~> 2.8'
gem 'bootsnap', '~> 1.18.0', require: false
gem 'browser', '< 6' # https://github.com/fnando/browser/issues/543
gem 'browser'
gem 'charlock_holmes', '~> 0.7.7'
gem 'chewy', '~> 7.3'
gem 'devise', '~> 4.9'
@ -47,13 +47,14 @@ gem 'color_diff', '~> 0.1'
gem 'csv', '~> 3.2'
gem 'discard', '~> 1.2'
gem 'doorkeeper', '~> 5.6'
gem 'faraday-httpclient'
gem 'fast_blank', '~> 1.0'
gem 'fastimage'
gem 'hiredis', '~> 0.6'
gem 'htmlentities', '~> 4.3'
gem 'http', '~> 5.2.0'
gem 'http_accept_language', '~> 2.1'
gem 'httplog', '~> 1.7.0'
gem 'httplog', '~> 1.7.0', require: false
gem 'i18n'
gem 'idn-ruby', require: 'idn'
gem 'inline_svg'
@ -61,7 +62,8 @@ gem 'irb', '~> 1.8'
gem 'kaminari', '~> 1.2'
gem 'link_header', '~> 0.0'
gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock'
gem 'mime-types', '~> 3.5.0', require: 'mime/types/columnar'
gem 'mime-types', '~> 3.6.0', require: 'mime/types/columnar'
gem 'mutex_m'
gem 'nokogiri', '~> 1.15'
gem 'oj', '~> 3.14'
gem 'ox', '~> 2.14'
@ -71,13 +73,13 @@ gem 'public_suffix', '~> 6.0'
gem 'pundit', '~> 2.3'
gem 'rack-attack', '~> 6.6'
gem 'rack-cors', '~> 2.0', require: 'rack/cors'
gem 'rails-i18n', '~> 7.0'
gem 'rails-i18n', '~> 8.0'
gem 'redcarpet', '~> 3.6'
gem 'redis', '~> 4.5', require: ['redis', 'redis/connection/hiredis']
gem 'redis-namespace', '~> 1.10'
gem 'rqrcode', '~> 2.2'
gem 'ruby-progressbar', '~> 1.13'
gem 'sanitize', '~> 6.0'
gem 'sanitize', '~> 7.0'
gem 'scenic', '~> 1.7'
gem 'sidekiq', '~> 6.5'
gem 'sidekiq-bulk', '~> 0.2.0'
@ -103,16 +105,16 @@ gem 'opentelemetry-api', '~> 1.4.0'
group :opentelemetry do
gem 'opentelemetry-exporter-otlp', '~> 0.29.0', require: false
gem 'opentelemetry-instrumentation-active_job', '~> 0.7.1', require: false
gem 'opentelemetry-instrumentation-active_model_serializers', '~> 0.20.1', require: false
gem 'opentelemetry-instrumentation-active_model_serializers', '~> 0.21.0', require: false
gem 'opentelemetry-instrumentation-concurrent_ruby', '~> 0.21.2', require: false
gem 'opentelemetry-instrumentation-excon', '~> 0.22.0', require: false
gem 'opentelemetry-instrumentation-faraday', '~> 0.24.1', require: false
gem 'opentelemetry-instrumentation-faraday', '~> 0.25.0', require: false
gem 'opentelemetry-instrumentation-http', '~> 0.23.2', require: false
gem 'opentelemetry-instrumentation-http_client', '~> 0.22.3', require: false
gem 'opentelemetry-instrumentation-net_http', '~> 0.22.4', require: false
gem 'opentelemetry-instrumentation-pg', '~> 0.29.0', require: false
gem 'opentelemetry-instrumentation-rack', '~> 0.24.1', require: false
gem 'opentelemetry-instrumentation-rails', '~> 0.31.0', require: false
gem 'opentelemetry-instrumentation-rack', '~> 0.25.0', require: false
gem 'opentelemetry-instrumentation-rails', '~> 0.34.0', require: false
gem 'opentelemetry-instrumentation-redis', '~> 0.25.3', require: false
gem 'opentelemetry-instrumentation-sidekiq', '~> 0.25.2', require: false
gem 'opentelemetry-sdk', '~> 1.4', require: false
@ -170,7 +172,7 @@ group :development do
gem 'rubocop-rspec_rails', require: false
# Annotates modules with schema
gem 'annotate', '~> 3.2'
gem 'annotaterb', '~> 4.13'
# Enhanced error message pages for development
gem 'better_errors', '~> 2.9'
@ -181,7 +183,7 @@ group :development do
gem 'letter_opener_web', '~> 3.0'
# Security analysis CLI tools
gem 'brakeman', '~> 6.0', require: false
gem 'brakeman', '~> 7.0', require: false
gem 'bundler-audit', '~> 0.9', require: false
# Linter CLI for HAML files
@ -220,7 +222,7 @@ gem 'concurrent-ruby', require: false
gem 'connection_pool', require: false
gem 'xorcist', '~> 1.1'
gem 'net-http', '~> 0.4.0'
gem 'net-http', '~> 0.6.0'
gem 'rubyzip', '~> 2.3'
gem 'hcaptcha', '~> 7.1'

View File

@ -10,136 +10,125 @@ GIT
GEM
remote: https://rubygems.org/
specs:
actioncable (7.1.4)
actionpack (= 7.1.4)
activesupport (= 7.1.4)
actioncable (8.0.1)
actionpack (= 8.0.1)
activesupport (= 8.0.1)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
zeitwerk (~> 2.6)
actionmailbox (7.1.4)
actionpack (= 7.1.4)
activejob (= 7.1.4)
activerecord (= 7.1.4)
activestorage (= 7.1.4)
activesupport (= 7.1.4)
mail (>= 2.7.1)
net-imap
net-pop
net-smtp
actionmailer (7.1.4)
actionpack (= 7.1.4)
actionview (= 7.1.4)
activejob (= 7.1.4)
activesupport (= 7.1.4)
mail (~> 2.5, >= 2.5.4)
net-imap
net-pop
net-smtp
actionmailbox (8.0.1)
actionpack (= 8.0.1)
activejob (= 8.0.1)
activerecord (= 8.0.1)
activestorage (= 8.0.1)
activesupport (= 8.0.1)
mail (>= 2.8.0)
actionmailer (8.0.1)
actionpack (= 8.0.1)
actionview (= 8.0.1)
activejob (= 8.0.1)
activesupport (= 8.0.1)
mail (>= 2.8.0)
rails-dom-testing (~> 2.2)
actionpack (7.1.4)
actionview (= 7.1.4)
activesupport (= 7.1.4)
actionpack (8.0.1)
actionview (= 8.0.1)
activesupport (= 8.0.1)
nokogiri (>= 1.8.5)
racc
rack (>= 2.2.4)
rack-session (>= 1.0.1)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
actiontext (7.1.4)
actionpack (= 7.1.4)
activerecord (= 7.1.4)
activestorage (= 7.1.4)
activesupport (= 7.1.4)
useragent (~> 0.16)
actiontext (8.0.1)
actionpack (= 8.0.1)
activerecord (= 8.0.1)
activestorage (= 8.0.1)
activesupport (= 8.0.1)
globalid (>= 0.6.0)
nokogiri (>= 1.8.5)
actionview (7.1.4)
activesupport (= 7.1.4)
actionview (8.0.1)
activesupport (= 8.0.1)
builder (~> 3.1)
erubi (~> 1.11)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
active_model_serializers (0.10.14)
active_model_serializers (0.10.15)
actionpack (>= 4.1)
activemodel (>= 4.1)
case_transform (>= 0.2)
jsonapi-renderer (>= 0.1.1.beta1, < 0.3)
activejob (7.1.4)
activesupport (= 7.1.4)
activejob (8.0.1)
activesupport (= 8.0.1)
globalid (>= 0.3.6)
activemodel (7.1.4)
activesupport (= 7.1.4)
activerecord (7.1.4)
activemodel (= 7.1.4)
activesupport (= 7.1.4)
activemodel (8.0.1)
activesupport (= 8.0.1)
activerecord (8.0.1)
activemodel (= 8.0.1)
activesupport (= 8.0.1)
timeout (>= 0.4.0)
activestorage (7.1.4)
actionpack (= 7.1.4)
activejob (= 7.1.4)
activerecord (= 7.1.4)
activesupport (= 7.1.4)
activestorage (8.0.1)
actionpack (= 8.0.1)
activejob (= 8.0.1)
activerecord (= 8.0.1)
activesupport (= 8.0.1)
marcel (~> 1.0)
activesupport (7.1.4)
activesupport (8.0.1)
base64
benchmark (>= 0.3)
bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2)
concurrent-ruby (~> 1.0, >= 1.3.1)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
logger (>= 1.4.2)
minitest (>= 5.1)
mutex_m
tzinfo (~> 2.0)
securerandom (>= 0.3)
tzinfo (~> 2.0, >= 2.0.5)
uri (>= 0.13.1)
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
aes_key_wrap (1.1.0)
android_key_attestation (0.3.0)
annotate (3.2.0)
activerecord (>= 3.2, < 8.0)
rake (>= 10.4, < 14.0)
annotaterb (4.13.0)
ast (2.4.2)
attr_required (1.0.2)
awrence (1.2.1)
aws-eventstream (1.3.0)
aws-partitions (1.978.0)
aws-sdk-core (3.209.0)
aws-partitions (1.1032.0)
aws-sdk-core (3.214.1)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.651.0)
aws-partitions (~> 1, >= 1.992.0)
aws-sigv4 (~> 1.9)
jmespath (~> 1, >= 1.6.1)
aws-sdk-kms (1.94.0)
aws-sdk-core (~> 3, >= 3.207.0)
aws-sdk-kms (1.96.0)
aws-sdk-core (~> 3, >= 3.210.0)
aws-sigv4 (~> 1.5)
aws-sdk-s3 (1.166.0)
aws-sdk-core (~> 3, >= 3.207.0)
aws-sdk-s3 (1.177.0)
aws-sdk-core (~> 3, >= 3.210.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.5)
aws-sigv4 (1.10.0)
aws-sigv4 (1.10.1)
aws-eventstream (~> 1, >= 1.0.2)
azure-storage-blob (2.0.3)
azure-storage-common (~> 2.0)
nokogiri (~> 1, >= 1.10.8)
azure-storage-common (2.0.4)
faraday (~> 1.0)
faraday_middleware (~> 1.0, >= 1.0.0.rc1)
net-http-persistent (~> 4.0)
nokogiri (~> 1, >= 1.10.8)
azure-blob (0.5.4)
rexml
base64 (0.2.0)
bcp47_spec (0.2.1)
bcrypt (3.1.20)
benchmark (0.4.0)
better_errors (2.10.1)
erubi (>= 1.0.0)
rack (>= 0.9.0)
rouge (>= 1.0.0)
bigdecimal (3.1.8)
bigdecimal (3.1.9)
bindata (2.5.0)
binding_of_caller (1.0.1)
debug_inspector (>= 1.2.0)
blurhash (0.1.8)
bootsnap (1.18.4)
msgpack (~> 1.2)
brakeman (6.2.1)
brakeman (7.0.0)
racc
browser (5.3.1)
browser (6.2.0)
brpoplpush-redis_script (0.1.3)
concurrent-ruby (~> 1.0, >= 1.0.5)
redis (>= 1.0, < 6)
@ -171,7 +160,7 @@ GEM
cocoon (1.2.15)
color_diff (0.1)
concurrent-ruby (1.3.4)
connection_pool (2.4.1)
connection_pool (2.5.0)
cose (1.3.1)
cbor (~> 0.5.9)
openssl-signature_algorithm (~> 1.0)
@ -179,15 +168,15 @@ GEM
bigdecimal
rexml
crass (1.0.6)
css_parser (1.19.0)
css_parser (1.21.0)
addressable
csv (3.3.0)
csv (3.3.2)
database_cleaner-active_record (2.2.0)
activerecord (>= 5.a)
database_cleaner-core (~> 2.0.0)
database_cleaner-core (2.0.1)
date (3.3.4)
debug (1.9.2)
date (3.4.1)
debug (1.10.0)
irb (~> 1.10)
reline (>= 0.3.8)
debug_inspector (1.2.0)
@ -197,22 +186,22 @@ GEM
railties (>= 4.1.0)
responders
warden (~> 1.2.3)
devise-two-factor (6.0.0)
activesupport (~> 7.0)
devise-two-factor (6.1.0)
activesupport (>= 7.0, < 8.1)
devise (~> 4.0)
railties (~> 7.0)
railties (>= 7.0, < 8.1)
rotp (~> 6.0)
devise_pam_authenticatable2 (9.2.0)
devise (>= 4.0.0)
rpam2 (~> 4.0)
diff-lcs (1.5.1)
discard (1.3.0)
activerecord (>= 4.2, < 8)
discard (1.4.0)
activerecord (>= 4.2, < 9.0)
docile (1.4.1)
domain_name (0.6.20240107)
doorkeeper (5.7.1)
doorkeeper (5.8.1)
railties (>= 5)
dotenv (3.1.4)
dotenv (3.1.7)
drb (2.2.1)
elasticsearch (7.17.11)
elasticsearch-api (= 7.17.11)
@ -228,49 +217,32 @@ GEM
htmlentities (~> 4.3.3)
launchy (>= 2.1, < 4.0)
mail (~> 2.7)
erubi (1.13.0)
erubi (1.13.1)
et-orbi (1.2.11)
tzinfo
excon (0.111.0)
excon (0.112.0)
fabrication (2.31.0)
faker (3.4.2)
faker (3.5.1)
i18n (>= 1.8.11, < 2)
faraday (1.10.3)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
faraday-httpclient (~> 1.0)
faraday-multipart (~> 1.0)
faraday-net_http (~> 1.0)
faraday-net_http_persistent (~> 1.0)
faraday-patron (~> 1.0)
faraday-rack (~> 1.0)
faraday-retry (~> 1.0)
ruby2_keywords (>= 0.0.4)
faraday-em_http (1.0.0)
faraday-em_synchrony (1.0.0)
faraday-excon (1.1.0)
faraday-httpclient (1.0.1)
faraday-multipart (1.0.4)
multipart-post (~> 2)
faraday-net_http (1.0.2)
faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0)
faraday-rack (1.0.0)
faraday-retry (1.0.3)
faraday_middleware (1.2.0)
faraday (~> 1.0)
faraday (2.12.2)
faraday-net_http (>= 2.0, < 3.5)
json
logger
faraday-httpclient (2.0.1)
httpclient (>= 2.2)
faraday-net_http (3.4.0)
net-http (>= 0.5.0)
fast_blank (1.0.1)
fastimage (2.3.1)
ffi (1.16.3)
fastimage (2.4.0)
ffi (1.17.1)
ffi-compiler (1.3.2)
ffi (>= 1.15.5)
rake
flatware (2.3.3)
flatware (2.3.4)
drb
thor (< 2.0)
flatware-rspec (2.3.3)
flatware (= 2.3.3)
flatware-rspec (2.3.4)
flatware (= 2.3.4)
rspec (>= 3.6)
fog-core (2.5.0)
builder
@ -307,7 +279,7 @@ GEM
rainbow
rubocop (>= 1.0)
sysexits (~> 1.1)
hashdiff (1.1.1)
hashdiff (1.1.2)
hashie (5.0.0)
hcaptcha (7.1.0)
json
@ -322,7 +294,7 @@ GEM
http-cookie (~> 1.0)
http-form_data (~> 2.2)
llhttp-ffi (~> 0.5.0)
http-cookie (1.0.5)
http-cookie (1.0.8)
domain_name (~> 0.5)
http-form_data (2.3.0)
http_accept_language (2.1.1)
@ -346,12 +318,16 @@ GEM
inline_svg (1.10.0)
activesupport (>= 3.0)
nokogiri (>= 1.6)
io-console (0.7.2)
irb (1.14.1)
io-console (0.8.0)
irb (1.14.3)
rdoc (>= 4.0.0)
reline (>= 0.4.2)
jd-paperclip-azure (3.0.0)
addressable (~> 2.5)
azure-blob (~> 0.5.2)
hashie (~> 5.0)
jmespath (1.6.2)
json (2.7.2)
json (2.9.1)
json-canonicalization (1.0.0)
json-jwt (1.15.3.1)
activesupport (>= 4.2)
@ -366,13 +342,15 @@ GEM
rack (>= 2.2, < 4)
rdf (~> 3.3)
rexml (~> 3.2)
json-ld-preloaded (3.3.0)
json-ld-preloaded (3.3.1)
json-ld (~> 3.3)
rdf (~> 3.3)
json-schema (5.0.0)
json-schema (5.1.1)
addressable (~> 2.8)
bigdecimal (~> 3.1)
jsonapi-renderer (0.2.2)
jwt (2.7.1)
jwt (2.9.3)
base64
kaminari (1.2.2)
activesupport (>= 4.1.0)
kaminari-actionview (= 1.2.2)
@ -406,13 +384,13 @@ GEM
llhttp-ffi (0.5.0)
ffi-compiler (~> 1.0)
rake (~> 13.0)
logger (1.6.1)
logger (1.6.4)
lograge (0.14.0)
actionpack (>= 4)
activesupport (>= 4)
railties (>= 4)
request_store (~> 1.0)
loofah (2.22.0)
loofah (2.24.0)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
mail (2.8.1)
@ -424,26 +402,20 @@ GEM
mario-redis-lock (1.2.1)
redis (>= 3.0.5)
matrix (0.4.2)
md-paperclip-azure (2.2.0)
addressable (~> 2.5)
azure-storage-blob (~> 2.0.1)
hashie (~> 5.0)
memory_profiler (1.1.0)
mime-types (3.5.2)
mime-types (3.6.0)
logger
mime-types-data (~> 3.2015)
mime-types-data (3.2024.0820)
mime-types-data (3.2024.1203)
mini_mime (1.1.5)
mini_portile2 (2.8.7)
minitest (5.25.1)
msgpack (1.7.2)
mini_portile2 (2.8.8)
minitest (5.25.4)
msgpack (1.7.5)
multi_json (1.15.0)
multipart-post (2.4.1)
mutex_m (0.2.0)
net-http (0.4.1)
mutex_m (0.3.0)
net-http (0.6.0)
uri
net-http-persistent (4.0.2)
connection_pool (~> 2.2)
net-imap (0.4.15)
net-imap (0.5.4)
date
net-protocol
net-ldap (0.19.0)
@ -453,11 +425,11 @@ GEM
timeout
net-smtp (0.5.0)
net-protocol
nio4r (2.7.3)
nokogiri (1.16.7)
nio4r (2.7.4)
nokogiri (1.18.1)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
oj (3.16.6)
oj (3.16.9)
bigdecimal (>= 3.0)
ostruct (>= 0.2)
omniauth (2.1.2)
@ -488,43 +460,44 @@ GEM
validate_email
validate_url
webfinger (~> 1.2)
openssl (3.2.0)
openssl (3.2.1)
openssl-signature_algorithm (1.3.0)
openssl (> 2.0)
opentelemetry-api (1.4.0)
opentelemetry-common (0.21.0)
opentelemetry-api (~> 1.0)
opentelemetry-exporter-otlp (0.29.0)
opentelemetry-exporter-otlp (0.29.1)
google-protobuf (>= 3.18)
googleapis-common-protos-types (~> 1.3)
opentelemetry-api (~> 1.1)
opentelemetry-common (~> 0.20)
opentelemetry-sdk (~> 1.2)
opentelemetry-semantic_conventions
opentelemetry-helpers-sql-obfuscation (0.2.0)
opentelemetry-helpers-sql-obfuscation (0.2.1)
opentelemetry-common (~> 0.21)
opentelemetry-instrumentation-action_mailer (0.1.0)
opentelemetry-instrumentation-action_mailer (0.3.0)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-active_support (~> 0.1)
opentelemetry-instrumentation-active_support (~> 0.7)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-action_pack (0.9.0)
opentelemetry-instrumentation-action_pack (0.10.0)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-rack (~> 0.21)
opentelemetry-instrumentation-action_view (0.7.2)
opentelemetry-instrumentation-action_view (0.8.0)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-active_support (~> 0.1)
opentelemetry-instrumentation-active_support (~> 0.7)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-active_job (0.7.7)
opentelemetry-instrumentation-active_job (0.7.8)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-active_model_serializers (0.20.2)
opentelemetry-instrumentation-active_model_serializers (0.21.1)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-active_support (>= 0.7.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-active_record (0.8.1)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-active_record (0.7.3)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-active_support (0.6.0)
opentelemetry-instrumentation-active_support (0.7.0)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-base (0.22.6)
@ -534,36 +507,36 @@ GEM
opentelemetry-instrumentation-concurrent_ruby (0.21.4)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-excon (0.22.4)
opentelemetry-instrumentation-excon (0.22.5)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-faraday (0.24.6)
opentelemetry-instrumentation-faraday (0.25.0)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-http (0.23.4)
opentelemetry-instrumentation-http (0.23.5)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-http_client (0.22.7)
opentelemetry-instrumentation-http_client (0.22.8)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-net_http (0.22.7)
opentelemetry-instrumentation-net_http (0.22.8)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-pg (0.29.0)
opentelemetry-instrumentation-pg (0.29.2)
opentelemetry-api (~> 1.0)
opentelemetry-helpers-sql-obfuscation
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-rack (0.24.6)
opentelemetry-instrumentation-rack (0.25.0)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-rails (0.31.2)
opentelemetry-instrumentation-rails (0.34.0)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-action_mailer (~> 0.1.0)
opentelemetry-instrumentation-action_pack (~> 0.9.0)
opentelemetry-instrumentation-action_view (~> 0.7.0)
opentelemetry-instrumentation-action_mailer (~> 0.3.0)
opentelemetry-instrumentation-action_pack (~> 0.10.0)
opentelemetry-instrumentation-action_view (~> 0.8.0)
opentelemetry-instrumentation-active_job (~> 0.7.0)
opentelemetry-instrumentation-active_record (~> 0.7.0)
opentelemetry-instrumentation-active_support (~> 0.6.0)
opentelemetry-instrumentation-active_record (~> 0.8.0)
opentelemetry-instrumentation-active_support (~> 0.7.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-redis (0.25.7)
opentelemetry-api (~> 1.0)
@ -573,7 +546,7 @@ GEM
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-registry (0.3.1)
opentelemetry-api (~> 1.1)
opentelemetry-sdk (1.5.0)
opentelemetry-sdk (1.6.0)
opentelemetry-api (~> 1.1)
opentelemetry-common (~> 0.20)
opentelemetry-registry (~> 0.2)
@ -581,17 +554,18 @@ GEM
opentelemetry-semantic_conventions (1.10.1)
opentelemetry-api (~> 1.0)
orm_adapter (0.5.0)
ostruct (0.6.0)
ox (2.14.18)
ostruct (0.6.1)
ox (2.14.19)
bigdecimal (>= 3.0)
parallel (1.26.3)
parser (3.3.5.0)
parser (3.3.6.0)
ast (~> 2.4.1)
racc
parslet (2.0.0)
pastel (0.8.0)
tty-color (~> 0.5)
pg (1.5.8)
pghero (3.6.0)
pg (1.5.9)
pghero (3.6.1)
activerecord (>= 6.1)
premailer (1.27.0)
addressable
@ -606,16 +580,17 @@ GEM
activesupport (>= 7.0.0)
rack
railties (>= 7.0.0)
psych (5.1.2)
psych (5.2.2)
date
stringio
public_suffix (6.0.1)
puma (6.4.3)
puma (6.5.0)
nio4r (~> 2.0)
pundit (2.4.0)
activesupport (>= 3.0.0)
raabro (1.4.0)
racc (1.8.1)
rack (2.2.9)
rack (2.2.10)
rack-attack (6.7.0)
rack (>= 1.0, < 4)
rack-cors (2.0.2)
@ -633,25 +608,25 @@ GEM
rack
rack-session (1.0.2)
rack (< 3)
rack-test (2.1.0)
rack-test (2.2.0)
rack (>= 1.3)
rackup (1.0.0)
rackup (1.0.1)
rack (< 3)
webrick
rails (7.1.4)
actioncable (= 7.1.4)
actionmailbox (= 7.1.4)
actionmailer (= 7.1.4)
actionpack (= 7.1.4)
actiontext (= 7.1.4)
actionview (= 7.1.4)
activejob (= 7.1.4)
activemodel (= 7.1.4)
activerecord (= 7.1.4)
activestorage (= 7.1.4)
activesupport (= 7.1.4)
rails (8.0.1)
actioncable (= 8.0.1)
actionmailbox (= 8.0.1)
actionmailer (= 8.0.1)
actionpack (= 8.0.1)
actiontext (= 8.0.1)
actionview (= 8.0.1)
activejob (= 8.0.1)
activemodel (= 8.0.1)
activerecord (= 8.0.1)
activestorage (= 8.0.1)
activesupport (= 8.0.1)
bundler (>= 1.15.0)
railties (= 7.1.4)
railties (= 8.0.1)
rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1)
actionview (>= 5.0.1.rc1)
@ -660,16 +635,16 @@ GEM
activesupport (>= 5.0.0)
minitest
nokogiri (>= 1.6)
rails-html-sanitizer (1.6.0)
rails-html-sanitizer (1.6.2)
loofah (~> 2.21)
nokogiri (~> 1.14)
rails-i18n (7.0.9)
nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
rails-i18n (8.0.1)
i18n (>= 0.7, < 2)
railties (>= 6.0.0, < 8)
railties (7.1.4)
actionpack (= 7.1.4)
activesupport (= 7.1.4)
irb
railties (>= 8.0.0, < 9)
railties (8.0.1)
actionpack (= 8.0.1)
activesupport (= 8.0.1)
irb (~> 1.13)
rackup (>= 1.0.0)
rake (>= 12.2)
thor (~> 1.0, >= 1.2.2)
@ -682,7 +657,7 @@ GEM
link_header (~> 0.0, >= 0.0.8)
rdf-normalize (0.7.0)
rdf (~> 3.3)
rdoc (6.7.0)
rdoc (6.10.0)
psych (>= 4.0.0)
redcarpet (3.6.0)
redis (4.8.1)
@ -690,17 +665,17 @@ GEM
redis (>= 4)
redlock (1.3.2)
redis (>= 3.0.0, < 6.0)
regexp_parser (2.9.2)
reline (0.5.10)
regexp_parser (2.10.0)
reline (0.6.0)
io-console (~> 0.5)
request_store (1.6.0)
request_store (1.7.0)
rack (>= 1.4)
responders (3.1.1)
actionpack (>= 5.2)
railties (>= 5.2)
rexml (3.3.8)
rexml (3.4.0)
rotp (6.3.0)
rouge (4.3.0)
rouge (4.5.1)
rpam2 (4.0.2)
rqrcode (2.2.0)
chunky_png (~> 1.0)
@ -710,17 +685,17 @@ GEM
rspec-core (~> 3.13.0)
rspec-expectations (~> 3.13.0)
rspec-mocks (~> 3.13.0)
rspec-core (3.13.1)
rspec-core (3.13.2)
rspec-support (~> 3.13.0)
rspec-expectations (3.13.2)
rspec-expectations (3.13.3)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-github (2.4.0)
rspec-core (~> 3.0)
rspec-mocks (3.13.1)
rspec-mocks (3.13.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-rails (7.0.1)
rspec-rails (7.1.0)
actionpack (>= 7.0)
activesupport (>= 7.0)
railties (>= 7.0)
@ -733,35 +708,35 @@ GEM
rspec-expectations (~> 3.0)
rspec-mocks (~> 3.0)
sidekiq (>= 5, < 8)
rspec-support (3.13.1)
rubocop (1.66.1)
rspec-support (3.13.2)
rubocop (1.69.2)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 2.4, < 3.0)
rubocop-ast (>= 1.32.2, < 2.0)
regexp_parser (>= 2.9.3, < 3.0)
rubocop-ast (>= 1.36.2, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.32.3)
unicode-display_width (>= 2.4.0, < 4.0)
rubocop-ast (1.37.0)
parser (>= 3.3.1.0)
rubocop-capybara (2.21.0)
rubocop (~> 1.41)
rubocop-performance (1.22.1)
rubocop-performance (1.23.1)
rubocop (>= 1.48.1, < 2.0)
rubocop-ast (>= 1.31.1, < 2.0)
rubocop-rails (2.26.2)
rubocop-rails (2.28.0)
activesupport (>= 4.2.0)
rack (>= 1.1)
rubocop (>= 1.52.0, < 2.0)
rubocop-ast (>= 1.31.1, < 2.0)
rubocop-rspec (3.1.0)
rubocop-rspec (3.3.0)
rubocop (~> 1.61)
rubocop-rspec_rails (2.30.0)
rubocop (~> 1.61)
rubocop-rspec (~> 3, >= 3.0.1)
ruby-prof (1.7.0)
ruby-prof (1.7.1)
ruby-progressbar (1.13.0)
ruby-saml (1.17.0)
nokogiri (>= 1.13.10)
@ -769,25 +744,25 @@ GEM
ruby-vips (2.2.2)
ffi (~> 1.12)
logger
ruby2_keywords (0.0.5)
rubyzip (2.3.2)
rufus-scheduler (3.9.1)
fugit (~> 1.1, >= 1.1.6)
rubyzip (2.4.1)
rufus-scheduler (3.9.2)
fugit (~> 1.1, >= 1.11.1)
safety_net_attestation (0.4.0)
jwt (~> 2.0)
sanitize (6.1.3)
sanitize (7.0.0)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
nokogiri (>= 1.16.8)
scenic (1.8.0)
activerecord (>= 4.0.0)
railties (>= 4.0.0)
selenium-webdriver (4.25.0)
securerandom (0.4.1)
selenium-webdriver (4.27.0)
base64 (~> 0.2)
logger (~> 1.4)
rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 3.0)
websocket (~> 1.0)
semantic_range (3.0.0)
semantic_range (3.1.0)
shoulda-matchers (6.4.0)
activesupport (>= 5.2.0)
sidekiq (6.5.12)
@ -821,8 +796,8 @@ GEM
stackprof (0.2.26)
stoplight (4.1.0)
redlock (~> 1.0)
stringio (3.1.1)
strong_migrations (2.0.0)
stringio (3.1.2)
strong_migrations (2.1.0)
activerecord (>= 6.1)
swd (1.3.0)
activesupport (>= 3)
@ -834,10 +809,10 @@ GEM
unicode-display_width (>= 1.1.1, < 3)
terrapin (1.0.1)
climate_control
test-prof (1.4.2)
test-prof (1.4.4)
thor (1.3.2)
tilt (2.4.0)
timeout (0.4.1)
tilt (2.5.0)
timeout (0.4.3)
tpm-key_attestation (0.12.1)
bindata (~> 2.4)
openssl (> 2.0)
@ -863,7 +838,8 @@ GEM
unf_ext
unf_ext (0.0.9.1)
unicode-display_width (2.6.0)
uri (0.13.1)
uri (1.0.2)
useragent (0.16.11)
validate_email (0.1.6)
activemodel (>= 3.0)
mail (>= 2.2.5)
@ -872,9 +848,8 @@ GEM
public_suffix
warden (1.2.9)
rack (>= 2.0.9)
webauthn (3.1.0)
webauthn (3.2.2)
android_key_attestation (~> 0.3.0)
awrence (~> 1.1)
bindata (~> 2.4)
cbor (~> 0.5.9)
cose (~> 1.1)
@ -893,7 +868,7 @@ GEM
rack-proxy (>= 0.6.1)
railties (>= 5.2)
semantic_range (>= 2.3.0)
webrick (1.8.2)
webrick (1.9.1)
websocket (1.2.11)
websocket-driver (0.7.6)
websocket-extensions (>= 0.1.0)
@ -902,7 +877,7 @@ GEM
xorcist (1.1.3)
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.6.18)
zeitwerk (2.7.1)
PLATFORMS
ruby
@ -910,14 +885,14 @@ PLATFORMS
DEPENDENCIES
active_model_serializers (~> 0.10)
addressable (~> 2.8)
annotate (~> 3.2)
annotaterb (~> 4.13)
aws-sdk-s3 (~> 1.123)
better_errors (~> 2.9)
binding_of_caller (~> 1.0)
blurhash (~> 0.1)
bootsnap (~> 1.18.0)
brakeman (~> 6.0)
browser (< 6)
brakeman (~> 7.0)
browser
bundler-audit (~> 0.9)
capybara (~> 3.39)
charlock_holmes (~> 0.7.7)
@ -939,10 +914,11 @@ DEPENDENCIES
email_spec
fabrication (~> 2.30)
faker (~> 3.2)
faraday-httpclient
fast_blank (~> 1.0)
fastimage
flatware-rspec
fog-core (<= 2.5.0)
fog-core (<= 2.6.0)
fog-openstack (~> 1.0)
haml-rails (~> 2.0)
haml_lint
@ -957,6 +933,7 @@ DEPENDENCIES
idn-ruby
inline_svg
irb (~> 1.8)
jd-paperclip-azure (~> 3.0)
json-ld
json-ld-preloaded (~> 3.2)
json-schema (~> 5.0)
@ -968,10 +945,10 @@ DEPENDENCIES
lograge (~> 0.12)
mail (~> 2.8)
mario-redis-lock (~> 1.2)
md-paperclip-azure (~> 2.2)
memory_profiler
mime-types (~> 3.5.0)
net-http (~> 0.4.0)
mime-types (~> 3.6.0)
mutex_m
net-http (~> 0.6.0)
net-ldap (~> 0.18)
nokogiri (~> 1.15)
oj (~> 3.14)
@ -983,16 +960,16 @@ DEPENDENCIES
opentelemetry-api (~> 1.4.0)
opentelemetry-exporter-otlp (~> 0.29.0)
opentelemetry-instrumentation-active_job (~> 0.7.1)
opentelemetry-instrumentation-active_model_serializers (~> 0.20.1)
opentelemetry-instrumentation-active_model_serializers (~> 0.21.0)
opentelemetry-instrumentation-concurrent_ruby (~> 0.21.2)
opentelemetry-instrumentation-excon (~> 0.22.0)
opentelemetry-instrumentation-faraday (~> 0.24.1)
opentelemetry-instrumentation-faraday (~> 0.25.0)
opentelemetry-instrumentation-http (~> 0.23.2)
opentelemetry-instrumentation-http_client (~> 0.22.3)
opentelemetry-instrumentation-net_http (~> 0.22.4)
opentelemetry-instrumentation-pg (~> 0.29.0)
opentelemetry-instrumentation-rack (~> 0.24.1)
opentelemetry-instrumentation-rails (~> 0.31.0)
opentelemetry-instrumentation-rack (~> 0.25.0)
opentelemetry-instrumentation-rails (~> 0.34.0)
opentelemetry-instrumentation-redis (~> 0.25.3)
opentelemetry-instrumentation-sidekiq (~> 0.25.2)
opentelemetry-sdk (~> 1.4)
@ -1009,9 +986,9 @@ DEPENDENCIES
rack-attack (~> 6.6)
rack-cors (~> 2.0)
rack-test (~> 2.1)
rails (~> 7.1.1)
rails (~> 8.0)
rails-controller-testing (~> 1.0)
rails-i18n (~> 7.0)
rails-i18n (~> 8.0)
rdf-normalize (~> 0.5)
redcarpet (~> 3.6)
redis (~> 4.5)
@ -1030,7 +1007,7 @@ DEPENDENCIES
ruby-progressbar (~> 1.13)
ruby-vips (~> 2.2)
rubyzip (~> 2.3)
sanitize (~> 6.0)
sanitize (~> 7.0)
scenic (~> 1.7)
selenium-webdriver
shoulda-matchers
@ -1057,7 +1034,7 @@ DEPENDENCIES
xorcist (~> 1.1)
RUBY VERSION
ruby 3.3.4p94
ruby 3.4.1p0
BUNDLED WITH
2.5.18
2.6.2

149
README.md
View File

@ -1,24 +1,24 @@
<h1><picture>
<source media="(prefers-color-scheme: dark)" srcset="./lib/assets/wordmark.dark.png?raw=true">
<source media="(prefers-color-scheme: light)" srcset="./lib/assets/wordmark.light.png?raw=true">
<img alt="Mastodon" src="./lib/assets/wordmark.light.png?raw=true" height="34">
</picture></h1>
> [!NOTE]
> Want to learn more about Mastodon?
> Click below to find out more in a video.
[![GitHub release](https://img.shields.io/github/release/mastodon/mastodon.svg)][releases]
[![Ruby Testing](https://github.com/mastodon/mastodon/actions/workflows/test-ruby.yml/badge.svg)](https://github.com/mastodon/mastodon/actions/workflows/test-ruby.yml)
[![Crowdin](https://d322cqt584bo4o.cloudfront.net/mastodon/localized.svg)][crowdin]
<p align="center">
<a style="text-decoration:none" href="https://www.youtube.com/watch?v=IPSbNdBmWKE">
<img alt="Mastodon hero image" src="https://github.com/user-attachments/assets/ef53f5e9-c0d8-484d-9f53-00efdebb92c3" />
</a>
</p>
[releases]: https://github.com/mastodon/mastodon/releases
[crowdin]: https://crowdin.com/project/mastodon
<p align="center">
<a style="text-decoration:none" href="https://github.com/mastodon/mastodon/releases">
<img src="https://img.shields.io/github/release/mastodon/mastodon.svg" alt="Release" /></a>
<a style="text-decoration:none" href="https://github.com/mastodon/mastodon/actions/workflows/test-ruby.yml">
<img src="https://github.com/mastodon/mastodon/actions/workflows/test-ruby.yml/badge.svg" alt="Ruby Testing" /></a>
<a style="text-decoration:none" href="https://crowdin.com/project/mastodon">
<img src="https://d322cqt584bo4o.cloudfront.net/mastodon/localized.svg" alt="Crowdin" /></a>
</p>
Mastodon is a **free, open-source social network server** based on ActivityPub where users can follow friends and discover new ones. On Mastodon, users can publish anything they want: links, pictures, text, and video. All Mastodon servers are interoperable as a federated network (users on one server can seamlessly communicate with users from another one, including non-Mastodon software that implements ActivityPub!)
Click below to **learn more** in a video:
[![Screenshot](https://blog.joinmastodon.org/2018/06/why-activitypub-is-the-future/ezgif-2-60f1b00403.gif)][youtube_demo]
[youtube_demo]: https://www.youtube.com/watch?v=IPSbNdBmWKE
## Navigation
- [Project homepage 🐘](https://joinmastodon.org)
@ -37,25 +37,15 @@ Click below to **learn more** in a video:
<img src="/app/javascript/images/elephant_ui_working.svg?raw=true" align="right" width="30%" />
### No vendor lock-in: Fully interoperable with any conforming platform
**No vendor lock-in: Fully interoperable with any conforming platform** - It doesn't have to be Mastodon; whatever implements ActivityPub is part of the social network! [Learn more](https://blog.joinmastodon.org/2018/06/why-activitypub-is-the-future/)
It doesn't have to be Mastodon; whatever implements ActivityPub is part of the social network! [Learn more](https://blog.joinmastodon.org/2018/06/why-activitypub-is-the-future/)
**Real-time, chronological timeline updates** - updates of people you're following appear in real-time in the UI via WebSockets. There's a firehose view as well!
### Real-time, chronological timeline updates
**Media attachments like images and short videos** - upload and view images and WebM/MP4 videos attached to the updates. Videos with no audio track are treated like GIFs; normal videos loop continuously!
Updates of people you're following appear in real-time in the UI via WebSockets. There's a firehose view as well!
**Safety and moderation tools** - Mastodon includes private posts, locked accounts, phrase filtering, muting, blocking, and all sorts of other features, along with a reporting and moderation system. [Learn more](https://blog.joinmastodon.org/2018/07/cage-the-mastodon/)
### Media attachments like images and short videos
Upload and view images and WebM/MP4 videos attached to the updates. Videos with no audio track are treated like GIFs; normal videos loop continuously!
### Safety and moderation tools
Mastodon includes private posts, locked accounts, phrase filtering, muting, blocking, and all sorts of other features, along with a reporting and moderation system. [Learn more](https://blog.joinmastodon.org/2018/07/cage-the-mastodon/)
### OAuth2 and a straightforward REST API
Mastodon acts as an OAuth2 provider, so 3rd party apps can use the REST and Streaming APIs. This results in a rich app ecosystem with a lot of choices!
**OAuth2 and a straightforward REST API** - Mastodon acts as an OAuth2 provider, so 3rd party apps can use the REST and Streaming APIs. This results in a rich app ecosystem with a lot of choices!
## Deployment
@ -69,90 +59,45 @@ Mastodon acts as an OAuth2 provider, so 3rd party apps can use the REST and Stre
- **PostgreSQL** 12+
- **Redis** 4+
- **Ruby** 3.1+
- **Ruby** 3.2+
- **Node.js** 18+
The repository includes deployment configurations for **Docker and docker-compose** as well as specific platforms like **Heroku**, and **Scalingo**. For Helm charts, reference the [mastodon/chart repository](https://github.com/mastodon/chart). The [**standalone** installation guide](https://docs.joinmastodon.org/admin/install/) is available in the documentation.
## Development
### Vagrant
A **Vagrant** configuration is included for development purposes. To use it, complete the following steps:
- Install Vagrant and Virtualbox
- Install the `vagrant-hostsupdater` plugin: `vagrant plugin install vagrant-hostsupdater`
- Run `vagrant up`
- Run `vagrant ssh -c "cd /vagrant && bin/dev"`
- Open `http://mastodon.local` in your browser
### macOS
To set up **macOS** for native development, complete the following steps:
- Install [Homebrew] and run `brew install postgresql@14 redis imagemagick
libidn nvm` to install the required project dependencies
- Use a Ruby version manager to activate the ruby in `.ruby-version` and run
`nvm use` to activate the node version from `.nvmrc`
- Run the `bin/setup` script, which will install the required ruby gems and node
packages and prepare the database for local development
- Finally, run the `bin/dev` script which will launch services via `overmind`
(if installed) or `foreman`
### Docker
For production hosting and deployment with **Docker**, use the `Dockerfile` and
`docker-compose.yml` in the project root directory.
For local development, install and launch [Docker], and run:
```shell
docker compose -f .devcontainer/compose.yaml up -d
docker compose -f .devcontainer/compose.yaml exec app bin/setup
docker compose -f .devcontainer/compose.yaml exec app bin/dev
```
### Dev Containers
Within IDEs that support the [Development Containers] specification, start the
"Mastodon on local machine" container from the editor. The necessary `docker
compose` commands to build and setup the container should run automatically. For
**Visual Studio Code** this requires installing the [Dev Container extension].
### GitHub Codespaces
[GitHub Codespaces] provides a web-based version of VS Code and a cloud hosted
development environment configured with the software needed for this project.
[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)][codespace]
- Click the button to create a new codespace, and confirm the options
- Wait for the environment to build (takes a few minutes)
- When the editor is ready, run `bin/dev` in the terminal
- Wait for an _Open in Browser_ prompt. This will open Mastodon
- On the _Ports_ tab "stream" setting change _Port visibility_ → _Public_
## Contributing
Mastodon is **free, open-source software** licensed under **AGPLv3**.
You can open issues for bugs you've found or features you think are missing. You can also submit pull requests to this repository or submit translations using Crowdin. To get started, take a look at [CONTRIBUTING.md](CONTRIBUTING.md). If your contributions are accepted into Mastodon, you can request to be paid through [our OpenCollective](https://opencollective.com/mastodon).
You can open issues for bugs you've found or features you think are missing. You
can also submit pull requests to this repository or translations via Crowdin. To
get started, look at the [CONTRIBUTING] and [DEVELOPMENT] guides. For changes
accepted into Mastodon, you can request to be paid through our [OpenCollective].
**IRC channel**: #mastodon on irc.libera.chat
**IRC channel**: #mastodon on [`irc.libera.chat`](https://libera.chat)
## License
Copyright (C) 2016-2024 Eugen Rochko & other Mastodon contributors (see [AUTHORS.md](AUTHORS.md))
Copyright (c) 2016-2024 Eugen Rochko (+ [`mastodon authors`](AUTHORS.md))
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Licensed under GNU Affero General Public License as stated in the [LICENSE](LICENSE):
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
```
Copyright (c) 2016-2024 Eugen Rochko & other Mastodon contributors
You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
This program is free software: you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option) any
later version.
[codespace]: https://codespaces.new/mastodon/mastodon?quickstart=1&devcontainer_path=.devcontainer%2Fcodespaces%2Fdevcontainer.json
[Dev Container extension]: https://containers.dev/supporting#dev-containers
[Development Containers]: https://containers.dev/supporting
[Docker]: https://docs.docker.com
[GitHub Codespaces]: https://docs.github.com/en/codespaces
[Homebrew]: https://brew.sh
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
details.
You should have received a copy of the GNU Affero General Public License along
with this program. If not, see https://www.gnu.org/licenses/
```
[CONTRIBUTING]: CONTRIBUTING.md
[DEVELOPMENT]: docs/DEVELOPMENT.md
[OpenCollective]: https://opencollective.com/mastodon

View File

@ -3,6 +3,6 @@
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
require File.expand_path('config/application', __dir__)
require_relative 'config/application'
Rails.application.load_tasks

View File

@ -13,8 +13,9 @@ A "vulnerability in Mastodon" is a vulnerability in the code distributed through
## Supported Versions
| Version | Supported |
| ------- | --------- |
| 4.2.x | Yes |
| 4.1.x | Yes |
| < 4.1 | No |
| Version | Supported |
| ------- | ---------------- |
| 4.3.x | Yes |
| 4.2.x | Yes |
| 4.1.x | Until 2025-04-08 |
| < 4.1 | No |

2
Vagrantfile vendored
View File

@ -174,7 +174,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
if config.vm.networks.any? { |type, options| type == :private_network }
config.vm.synced_folder ".", "/vagrant", type: "nfs", mount_options: ['rw', 'actimeo=1']
else
config.vm.synced_folder ".", "/vagrant"
config.vm.synced_folder ".", "/vagrant", type: "rsync", create: true, rsync__args: ["--verbose", "--archive", "--delete", "-z"]
end
# Otherwise, you can access the site at http://localhost:3000 and http://localhost:4000 , http://localhost:8080

View File

@ -41,11 +41,11 @@ class ActivityPub::OutboxesController < ActivityPub::BaseController
end
end
def outbox_url(**kwargs)
def outbox_url(**)
if params[:account_username].present?
account_outbox_url(@account, **kwargs)
account_outbox_url(@account, **)
else
instance_actor_outbox_url(**kwargs)
instance_actor_outbox_url(**)
end
end

View File

@ -6,6 +6,7 @@ class Admin::AnnouncementsController < Admin::BaseController
def index
authorize :announcement, :index?
@published_announcements_count = Announcement.published.async_count
end
def new

View File

@ -8,6 +8,7 @@ module Admin
layout 'admin'
before_action :set_cache_headers
before_action :set_referrer_policy_header
after_action :verify_authorized
@ -17,6 +18,10 @@ module Admin
response.cache_control.replace(private: true, no_store: true)
end
def set_referrer_policy_header
response.headers['Referrer-Policy'] = 'same-origin'
end
def set_user
@user = Account.find(params[:account_id]).user || raise(ActiveRecord::RecordNotFound)
end

View File

@ -6,6 +6,7 @@ class Admin::Disputes::AppealsController < Admin::BaseController
def index
authorize :appeal, :index?
@pending_appeals_count = Appeal.pending.async_count
@appeals = filtered_appeals.page(params[:page])
end

View File

@ -5,7 +5,7 @@ module Admin
def index
authorize :email_domain_block, :index?
@email_domain_blocks = EmailDomainBlock.where(parent_id: nil).includes(:children).order(id: :desc).page(params[:page])
@email_domain_blocks = EmailDomainBlock.parents.includes(:children).order(id: :desc).page(params[:page])
@form = Form::EmailDomainBlockBatch.new
end
@ -58,10 +58,7 @@ module Admin
private
def set_resolved_records
Resolv::DNS.open do |dns|
dns.timeouts = 5
@resolved_records = dns.getresources(@email_domain_block.domain, Resolv::DNS::Resource::IN::MX).to_a
end
@resolved_records = DomainResource.new(@email_domain_block.domain).mx
end
def resource_params

View File

@ -5,6 +5,8 @@ module Admin
before_action :set_instances, only: :index
before_action :set_instance, except: :index
LOGS_LIMIT = 5
def index
authorize :instance, :index?
preload_delivery_failures!
@ -13,7 +15,7 @@ module Admin
def show
authorize :instance, :show?
@time_period = (6.days.ago.to_date...Time.now.utc.to_date)
@action_logs = Admin::ActionLogFilter.new(target_domain: @instance.domain).results.limit(5)
@action_logs = Admin::ActionLogFilter.new(target_domain: @instance.domain).results.limit(LOGS_LIMIT)
end
def destroy

View File

@ -32,7 +32,7 @@ module Admin
def deactivate_all
authorize :invite, :deactivate_all?
Invite.available.in_batches.update_all(expires_at: Time.now.utc)
Invite.available.in_batches.touch_all(:expires_at)
redirect_to admin_invites_path
end

View File

@ -21,6 +21,7 @@ module Admin
@relay = Relay.new(resource_params)
if @relay.save
log_action :create, @relay
@relay.enable!
redirect_to admin_relays_path
else
@ -31,18 +32,21 @@ module Admin
def destroy
authorize :relay, :update?
@relay.destroy
log_action :destroy, @relay
redirect_to admin_relays_path
end
def enable
authorize :relay, :update?
@relay.enable!
log_action :enable, @relay
redirect_to admin_relays_path
end
def disable
authorize :relay, :update?
@relay.disable!
log_action :disable, @relay
redirect_to admin_relays_path
end

View File

@ -6,7 +6,7 @@ module Admin
def index
authorize :software_update, :index?
@software_updates = SoftwareUpdate.all.sort_by(&:gem_version)
@software_updates = SoftwareUpdate.by_version
end
private

View File

@ -16,6 +16,8 @@ module Admin
def show
authorize [:admin, @status], :show?
@status_batch_action = Admin::StatusBatchAction.new
end
def batch

View File

@ -0,0 +1,18 @@
# frozen_string_literal: true
class Admin::TermsOfService::DistributionsController < Admin::BaseController
before_action :set_terms_of_service
def create
authorize @terms_of_service, :distribute?
@terms_of_service.touch(:notification_sent_at)
Admin::DistributeTermsOfServiceNotificationWorker.perform_async(@terms_of_service.id)
redirect_to admin_terms_of_service_index_path
end
private
def set_terms_of_service
@terms_of_service = TermsOfService.find(params[:terms_of_service_id])
end
end

View File

@ -0,0 +1,36 @@
# frozen_string_literal: true
class Admin::TermsOfService::DraftsController < Admin::BaseController
before_action :set_terms_of_service
def show
authorize :terms_of_service, :create?
end
def update
authorize @terms_of_service, :update?
@terms_of_service.published_at = Time.now.utc if params[:action_type] == 'publish'
if @terms_of_service.update(resource_params)
log_action(:publish, @terms_of_service) if @terms_of_service.published?
redirect_to @terms_of_service.published? ? admin_terms_of_service_index_path : admin_terms_of_service_draft_path
else
render :show
end
end
private
def set_terms_of_service
@terms_of_service = TermsOfService.draft.first || TermsOfService.new(text: current_terms_of_service&.text)
end
def current_terms_of_service
TermsOfService.live.first
end
def resource_params
params.require(:terms_of_service).permit(:text, :changelog)
end
end

View File

@ -0,0 +1,37 @@
# frozen_string_literal: true
class Admin::TermsOfService::GeneratesController < Admin::BaseController
before_action :set_instance_presenter
def show
authorize :terms_of_service, :create?
@generator = TermsOfService::Generator.new(
domain: @instance_presenter.domain,
admin_email: @instance_presenter.contact.email
)
end
def create
authorize :terms_of_service, :create?
@generator = TermsOfService::Generator.new(resource_params)
if @generator.valid?
TermsOfService.create!(text: @generator.render)
redirect_to admin_terms_of_service_draft_path
else
render :show
end
end
private
def set_instance_presenter
@instance_presenter = InstancePresenter.new
end
def resource_params
params.require(:terms_of_service_generator).permit(*TermsOfService::Generator::VARIABLES)
end
end

View File

@ -0,0 +1,8 @@
# frozen_string_literal: true
class Admin::TermsOfService::HistoriesController < Admin::BaseController
def show
authorize :terms_of_service, :index?
@terms_of_service = TermsOfService.published.all
end
end

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
class Admin::TermsOfService::PreviewsController < Admin::BaseController
before_action :set_terms_of_service
def show
authorize @terms_of_service, :distribute?
@user_count = @terms_of_service.scope_for_notification.count
end
private
def set_terms_of_service
@terms_of_service = TermsOfService.find(params[:terms_of_service_id])
end
end

View File

@ -0,0 +1,17 @@
# frozen_string_literal: true
class Admin::TermsOfService::TestsController < Admin::BaseController
before_action :set_terms_of_service
def create
authorize @terms_of_service, :distribute?
UserMailer.terms_of_service_changed(current_user, @terms_of_service).deliver_later!
redirect_to admin_terms_of_service_preview_path(@terms_of_service)
end
private
def set_terms_of_service
@terms_of_service = TermsOfService.find(params[:terms_of_service_id])
end
end

View File

@ -0,0 +1,8 @@
# frozen_string_literal: true
class Admin::TermsOfServiceController < Admin::BaseController
def index
authorize :terms_of_service, :index?
@terms_of_service = TermsOfService.live.first
end
end

View File

@ -4,6 +4,7 @@ class Admin::Trends::Links::PreviewCardProvidersController < Admin::BaseControll
def index
authorize :preview_card_provider, :review?
@pending_preview_card_providers_count = PreviewCardProvider.unreviewed.async_count
@preview_card_providers = filtered_preview_card_providers.page(params[:page])
@form = Trends::PreviewCardProviderBatch.new
end

View File

@ -4,7 +4,7 @@ class Admin::Trends::LinksController < Admin::BaseController
def index
authorize :preview_card, :review?
@locales = PreviewCardTrend.pluck('distinct language')
@locales = PreviewCardTrend.locales
@preview_cards = filtered_preview_cards.page(params[:page])
@form = Trends::PreviewCardBatch.new
end

View File

@ -4,7 +4,7 @@ class Admin::Trends::StatusesController < Admin::BaseController
def index
authorize [:admin, :status], :review?
@locales = StatusTrend.pluck('distinct language')
@locales = StatusTrend.locales
@statuses = filtered_statuses.page(params[:page])
@form = Trends::StatusBatch.new
end

View File

@ -4,6 +4,7 @@ class Admin::Trends::TagsController < Admin::BaseController
def index
authorize :tag, :review?
@pending_tags_count = Tag.pending_review.async_count
@tags = filtered_tags.page(params[:page])
@form = Trends::TagBatch.new
end

View File

@ -12,7 +12,7 @@ class Api::V1::Accounts::FamiliarFollowersController < Api::BaseController
private
def set_accounts
@accounts = Account.without_suspended.where(id: account_ids).select('id, hide_collections')
@accounts = Account.without_suspended.where(id: account_ids).select(:id, :hide_collections)
end
def familiar_followers

View File

@ -16,6 +16,7 @@ class Api::V1::AccountsController < Api::BaseController
before_action :check_account_confirmation, except: [:index, :create]
before_action :check_enabled_registrations, only: [:create]
before_action :check_accounts_limit, only: [:index]
before_action :check_following_self, only: [:follow]
skip_before_action :require_authenticated_user!, only: :create
@ -101,8 +102,12 @@ class Api::V1::AccountsController < Api::BaseController
raise(Mastodon::ValidationError) if account_ids.size > DEFAULT_ACCOUNTS_LIMIT
end
def relationships(**options)
AccountRelationshipsPresenter.new([@account], current_user.account_id, **options)
def check_following_self
render json: { error: I18n.t('accounts.self_follow_error') }, status: 403 if current_user.account.id == @account.id
end
def relationships(**)
AccountRelationshipsPresenter.new([@account], current_user.account_id, **)
end
def account_ids

View File

@ -17,6 +17,17 @@ class Api::V1::AnnualReportsController < Api::BaseController
relationships: @relationships
end
def show
with_read_replica do
@presenter = AnnualReportsPresenter.new([@annual_report])
@relationships = StatusRelationshipsPresenter.new(@presenter.statuses, current_account.id)
end
render json: @presenter,
serializer: REST::AnnualReportsSerializer,
relationships: @relationships
end
def read
@annual_report.view!
render_empty

View File

@ -5,6 +5,8 @@ class Api::V1::FeaturedTags::SuggestionsController < Api::BaseController
before_action :require_user!
before_action :set_recently_used_tags, only: :index
RECENT_TAGS_LIMIT = 10
def index
render json: @recently_used_tags, each_serializer: REST::TagSerializer, relationships: TagRelationshipsPresenter.new(@recently_used_tags, current_user&.account_id)
end
@ -12,6 +14,6 @@ class Api::V1::FeaturedTags::SuggestionsController < Api::BaseController
private
def set_recently_used_tags
@recently_used_tags = Tag.suggestions_for_account(current_account).limit(10)
@recently_used_tags = Tag.suggestions_for_account(current_account).limit(RECENT_TAGS_LIMIT)
end
end

View File

@ -28,8 +28,8 @@ class Api::V1::FollowRequestsController < Api::BaseController
@account ||= Account.find(params[:id])
end
def relationships(**options)
AccountRelationshipsPresenter.new([account], current_user.account_id, **options)
def relationships(**)
AccountRelationshipsPresenter.new([account], current_user.account_id, **)
end
def load_accounts

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
class Api::V1::Instances::TermsOfServicesController < Api::V1::Instances::BaseController
before_action :set_terms_of_service
def show
cache_even_if_authenticated!
render json: @terms_of_service, serializer: REST::PrivacyPolicySerializer
end
private
def set_terms_of_service
@terms_of_service = TermsOfService.live.first!
end
end

View File

@ -15,17 +15,12 @@ class Api::V1::Lists::AccountsController < Api::BaseController
end
def create
ApplicationRecord.transaction do
list_accounts.each do |account|
@list.accounts << account
end
end
AddAccountsToListService.new.call(@list, Account.find(account_ids))
render_empty
end
def destroy
ListAccount.where(list: @list, account_id: account_ids).destroy_all
RemoveAccountsFromListService.new.call(@list, Account.where(id: account_ids))
render_empty
end
@ -43,10 +38,6 @@ class Api::V1::Lists::AccountsController < Api::BaseController
end
end
def list_accounts
Account.find(account_ids)
end
def account_ids
Array(resource_params[:account_ids])
end

View File

@ -52,7 +52,7 @@ class Api::V1::Notifications::RequestsController < Api::BaseController
private
def load_requests
requests = NotificationRequest.where(account: current_account).includes(:last_status, from_account: [:account_stat, :user]).to_a_paginated_by_id(
requests = NotificationRequest.where(account: current_account).without_suspended.includes(:last_status, from_account: [:account_stat, :user]).to_a_paginated_by_id(
limit_param(DEFAULT_ACCOUNTS_LIMIT),
params_slice(:max_id, :since_id, :min_id)
)

View File

@ -15,7 +15,7 @@ class Api::V1::Polls::VotesController < Api::BaseController
private
def set_poll
@poll = Poll.attached.find(params[:poll_id])
@poll = Poll.find(params[:poll_id])
authorize @poll.status, :show?
rescue Mastodon::NotPermittedError
not_found

View File

@ -15,7 +15,7 @@ class Api::V1::PollsController < Api::BaseController
private
def set_poll
@poll = Poll.attached.find(params[:id])
@poll = Poll.find(params[:id])
authorize @poll.status, :show?
rescue Mastodon::NotPermittedError
not_found

View File

@ -23,6 +23,6 @@ class Api::V1::Statuses::TranslationsController < Api::V1::Statuses::BaseControl
private
def set_translation
@translation = TranslateStatusService.new.call(@status, content_locale)
@translation = TranslateStatusService.new.call(@status, I18n.locale.to_s)
end
end

View File

@ -27,7 +27,9 @@ class Api::V1::Trends::TagsController < Api::BaseController
end
def tags_from_trends
Trends.tags.query.allowed
scope = Trends.tags.query.allowed.in_locale(content_locale)
scope = scope.filtered_for(current_account) if user_signed_in?
scope
end
def next_path

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true
class Api::Web::PushSubscriptionsController < Api::Web::BaseController
before_action :require_user!
before_action :require_user!, except: :destroy
before_action :set_push_subscription, only: :update
before_action :destroy_previous_subscriptions, only: :create, if: :prior_subscriptions?
after_action :update_session_with_subscription, only: :create
@ -17,6 +17,13 @@ class Api::Web::PushSubscriptionsController < Api::Web::BaseController
render json: @push_subscription, serializer: REST::WebPushSubscriptionSerializer
end
def destroy
push_subscription = ::Web::PushSubscription.find_by_token_for(:unsubscribe, params[:id])
push_subscription&.destroy
head 200
end
private
def active_session

View File

@ -22,7 +22,6 @@ class ApplicationController < ActionController::Base
helper_method :use_seamless_external_login?
helper_method :sso_account_settings
helper_method :limited_federation_mode?
helper_method :body_class_string
helper_method :skip_csrf_meta_tags?
rescue_from ActionController::ParameterMissing, Paperclip::AdapterRegistry::NoHandlerError, with: :bad_request
@ -32,7 +31,7 @@ class ApplicationController < ActionController::Base
rescue_from ActionController::InvalidAuthenticityToken, with: :unprocessable_entity
rescue_from Mastodon::RateLimitExceededError, with: :too_many_requests
rescue_from HTTP::Error, OpenSSL::SSL::SSLError, with: :internal_server_error
rescue_from(*Mastodon::HTTP_CONNECTION_ERRORS, with: :internal_server_error)
rescue_from Mastodon::RaceConditionError, Stoplight::Error::RedLight, ActiveRecord::SerializationFailure, with: :service_unavailable
rescue_from Seahorse::Client::NetworkingError do |e|
@ -71,7 +70,13 @@ class ApplicationController < ActionController::Base
end
def require_functional!
redirect_to edit_user_registration_path unless current_user.functional?
return if current_user.functional?
if current_user.confirmed?
redirect_to edit_user_registration_path
else
redirect_to auth_setup_path
end
end
def skip_csrf_meta_tags?
@ -158,10 +163,6 @@ class ApplicationController < ActionController::Base
current_user.setting_theme
end
def body_class_string
@body_classes || ''
end
def respond_with_error(code)
respond_to do |format|
format.any { render "errors/#{code}", layout: 'error', status: code, formats: [:html] }

View File

@ -142,4 +142,12 @@ class Auth::RegistrationsController < Devise::RegistrationsController
def set_cache_headers
response.cache_control.replace(private: true, no_store: true)
end
def is_flashing_format? # rubocop:disable Naming/PredicateName
if params[:action] == 'create'
false # Disable flash messages for sign-up
else
super
end
end
end

View File

@ -20,7 +20,7 @@ module Api::ErrorHandling
render json: { error: 'Record not found' }, status: 404
end
rescue_from HTTP::Error, Mastodon::UnexpectedResponseError do
rescue_from(*Mastodon::HTTP_CONNECTION_ERRORS, Mastodon::UnexpectedResponseError) do
render json: { error: 'Remote data could not be fetched' }, status: 503
end

View File

@ -10,7 +10,7 @@ module Auth::CaptchaConcern
end
def captcha_available?
ENV['HCAPTCHA_SECRET_KEY'].present? && ENV['HCAPTCHA_SITE_KEY'].present?
Rails.configuration.x.captcha.secret_key.present? && Rails.configuration.x.captcha.site_key.present?
end
def captcha_enabled?

View File

@ -28,7 +28,7 @@ module CacheConcern
def render_with_cache(**options)
raise ArgumentError, 'Only JSON render calls are supported' unless options.key?(:json) || block_given?
key = options.delete(:key) || [[params[:controller], params[:action]].join('/'), options[:json].respond_to?(:cache_key) ? options[:json].cache_key : nil, options[:fields].nil? ? nil : options[:fields].join(',')].compact.join(':')
key = options.delete(:key) || [[params[:controller], params[:action]].join('/'), options[:json].respond_to?(:cache_key) ? options[:json].cache_key : nil, options[:fields]&.join(',')].compact.join(':')
expires_in = options.delete(:expires_in) || 3.minutes
body = Rails.cache.read(key, raw: true)

View File

@ -25,7 +25,7 @@ module Localized
end
def available_locale_or_nil(locale_name)
locale_name.to_sym if locale_name.present? && I18n.available_locales.include?(locale_name.to_sym)
locale_name.to_sym if locale_name.respond_to?(:to_sym) && I18n.available_locales.include?(locale_name.to_sym)
end
def content_locale

View File

@ -80,7 +80,7 @@ module SignatureVerification
fail_with! "Verification failed for #{actor.to_log_human_identifier} #{actor.uri} using rsa-sha256 (RSASSA-PKCS1-v1_5 with SHA-256)", signed_string: compare_signed_string, signature: signature_params['signature']
rescue SignatureVerificationError => e
fail_with! e.message
rescue HTTP::Error, OpenSSL::SSL::SSLError => e
rescue *Mastodon::HTTP_CONNECTION_ERRORS => e
fail_with! "Failed to fetch remote data: #{e.message}"
rescue Mastodon::UnexpectedResponseError
fail_with! 'Failed to fetch remote data (got unexpected reply from server)'

View File

@ -7,13 +7,13 @@ module WebAppControllerConcern
vary_by 'Accept, Accept-Language, Cookie'
before_action :redirect_unauthenticated_to_permalinks!
before_action :set_app_body_class
before_action :set_referer_header
content_security_policy do |p|
policy = ContentSecurityPolicy.new
if policy.sso_host.present?
p.form_action policy.sso_host
p.form_action policy.sso_host, -> { "https://#{request.host}/auth/auth/" }
else
p.form_action :none
end
@ -24,10 +24,6 @@ module WebAppControllerConcern
!(ENV['ONE_CLICK_SSO_LOGIN'] == 'true' && ENV['OMNIAUTH_ONLY'] == 'true' && Devise.omniauth_providers.length == 1) && current_user.nil?
end
def set_app_body_class
@body_classes = 'app-body'
end
def redirect_unauthenticated_to_permalinks!
return if user_signed_in? && current_account.moved_to_account_id.nil?
@ -46,4 +42,10 @@ module WebAppControllerConcern
end
end
end
protected
def set_referer_header
response.set_header('Referrer-Policy', Setting.allow_referrer_origin ? 'origin' : 'same-origin')
end
end

View File

@ -1,10 +1,8 @@
# frozen_string_literal: true
class CustomCssController < ActionController::Base # rubocop:disable Rails/ApplicationController
before_action :set_user_roles
def show
expires_in 3.minutes, public: true
expires_in 1.month, public: true
render content_type: 'text/css'
end
@ -14,8 +12,4 @@ class CustomCssController < ActionController::Base # rubocop:disable Rails/Appli
Setting.custom_css
end
helper_method :custom_css_styles
def set_user_roles
@user_roles = UserRole.providing_styles
end
end

View File

@ -13,7 +13,7 @@ class MediaProxyController < ApplicationController
rescue_from ActiveRecord::RecordInvalid, with: :not_found
rescue_from Mastodon::UnexpectedResponseError, with: :not_found
rescue_from Mastodon::NotPermittedError, with: :not_found
rescue_from HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError, with: :internal_server_error
rescue_from(*Mastodon::HTTP_CONNECTION_ERRORS, with: :internal_server_error)
def show
with_redis_lock("media_download:#{params[:id]}") do

View File

@ -35,12 +35,6 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio
end
def set_last_used_at_by_app
@last_used_at_by_app = Doorkeeper::AccessToken
.select('DISTINCT ON (application_id) application_id, last_used_at')
.where(resource_owner_id: current_resource_owner.id)
.where.not(last_used_at: nil)
.order(application_id: :desc, last_used_at: :desc)
.pluck(:application_id, :last_used_at)
.to_h
@last_used_at_by_app = current_resource_owner.applications_last_used
end
end

View File

@ -0,0 +1,11 @@
# frozen_string_literal: true
class Oauth::UserinfoController < Api::BaseController
before_action -> { doorkeeper_authorize! :profile }, only: [:show]
before_action :require_user!
def show
@account = current_account
render json: @account, serializer: OauthUserinfoSerializer
end
end

View File

@ -9,7 +9,7 @@ class Settings::ExportsController < Settings::BaseController
skip_before_action :require_functional!
def show
@export = Export.new(current_account)
@export_summary = ExportSummary.new(preloaded_account)
@backups = current_user.backups
end
@ -25,4 +25,15 @@ class Settings::ExportsController < Settings::BaseController
redirect_to settings_export_path
end
private
def preloaded_account
current_account.tap do |account|
ActiveRecord::Associations::Preloader.new(
records: [account],
associations: :account_stat
).call
end
end
end

View File

@ -5,6 +5,8 @@ class Settings::FeaturedTagsController < Settings::BaseController
before_action :set_featured_tag, except: [:index, :create]
before_action :set_recently_used_tags, only: :index
RECENT_TAGS_LIMIT = 10
def index
@featured_tag = FeaturedTag.new
end
@ -38,7 +40,7 @@ class Settings::FeaturedTagsController < Settings::BaseController
end
def set_recently_used_tags
@recently_used_tags = Tag.suggestions_for_account(current_account).limit(10)
@recently_used_tags = Tag.suggestions_for_account(current_account).limit(RECENT_TAGS_LIMIT)
end
def featured_tag_params

View File

@ -24,6 +24,8 @@ class Settings::ImportsController < Settings::BaseController
lists: false,
}.freeze
RECENT_IMPORTS_LIMIT = 10
def index
@import = Form::Import.new(current_account: current_account)
end
@ -96,6 +98,6 @@ class Settings::ImportsController < Settings::BaseController
end
def set_recent_imports
@recent_imports = current_account.bulk_imports.reorder(id: :desc).limit(10)
@recent_imports = current_account.bulk_imports.reorder(id: :desc).limit(RECENT_IMPORTS_LIMIT)
end
end

View File

@ -0,0 +1,11 @@
# frozen_string_literal: true
class TermsOfServiceController < ApplicationController
include WebAppControllerConcern
skip_before_action :require_functional!
def show
expires_in(15.seconds, public: true, stale_while_revalidate: 30.seconds, stale_if_error: 1.day) unless user_signed_in?
end
end

View File

@ -7,7 +7,23 @@ module WellKnown
def show
@webfinger_template = "#{webfinger_url}?resource={uri}"
expires_in 3.days, public: true
render content_type: 'application/xrd+xml', formats: [:xml]
respond_to do |format|
format.any do
render content_type: 'application/xrd+xml', formats: [:xml]
end
format.json do
render json: {
links: [
{
rel: 'lrdd',
template: @webfinger_template,
},
],
}
end
end
end
end
end

View File

@ -12,12 +12,12 @@ module Admin::AccountModerationNotesHelper
)
end
def admin_account_inline_link_to(account)
def admin_account_inline_link_to(account, path: nil)
return if account.nil?
link_to(
account_inline_text(account),
admin_account_path(account.id),
path || admin_account_path(account.id),
class: class_names('inline-name-tag', suspended: suspended_account?(account)),
title: account.acct
)

View File

@ -33,6 +33,15 @@ module Admin::ActionLogsHelper
else
I18n.t('admin.action_logs.deleted_account')
end
when 'Relay'
link_to log.human_identifier, admin_relays_path
end
end
def sorted_action_log_types
Admin::ActionLogFilter::ACTION_TYPE_MAP
.keys
.map { |key| [I18n.t("admin.action_logs.action_types.#{key}"), key] }
.sort_by(&:first)
end
end

View File

@ -2,7 +2,7 @@
module Admin::SettingsHelper
def captcha_available?
ENV['HCAPTCHA_SECRET_KEY'].present? && ENV['HCAPTCHA_SITE_KEY'].present?
Rails.configuration.x.captcha.secret_key.present? && Rails.configuration.x.captcha.site_key.present?
end
def login_activity_title(activity)

View File

@ -1,12 +1,6 @@
# frozen_string_literal: true
module ApplicationHelper
DANGEROUS_SCOPES = %w(
read
write
follow
).freeze
RTL_LOCALES = %i(
ar
ckb
@ -85,7 +79,7 @@ module ApplicationHelper
def html_title
safe_join(
[content_for(:page_title).to_s.chomp, title]
[content_for(:page_title), title]
.compact_blank,
' - '
)
@ -95,8 +89,11 @@ module ApplicationHelper
Rails.env.production? ? site_title : "#{site_title} (Dev)"
end
def class_for_scope(scope)
'scope-danger' if DANGEROUS_SCOPES.include?(scope.to_s)
def label_for_scope(scope)
safe_join [
tag.samp(scope, class: { 'scope-danger' => SessionActivation::DEFAULT_SCOPES.include?(scope.to_s) }),
tag.span(t("doorkeeper.scopes.#{scope}"), class: :hint),
]
end
def can?(action, record)
@ -123,18 +120,6 @@ module ApplicationHelper
inline_svg_tag 'check.svg'
end
def visibility_icon(status)
if status.public_visibility?
material_symbol('globe', title: I18n.t('statuses.visibilities.public'))
elsif status.unlisted_visibility?
material_symbol('lock_open', title: I18n.t('statuses.visibilities.unlisted'))
elsif status.private_visibility? || status.limited_visibility?
material_symbol('lock', title: I18n.t('statuses.visibilities.private'))
elsif status.direct_visibility?
material_symbol('alternate_email', title: I18n.t('statuses.visibilities.direct'))
end
end
def interrelationships_icon(relationships, account_id)
if relationships.following[account_id] && relationships.followed_by[account_id]
material_symbol('sync_alt', title: I18n.t('relationships.mutual'), class: 'active passive')
@ -158,10 +143,11 @@ module ApplicationHelper
end
def body_classes
output = body_class_string.split
output = []
output << content_for(:body_classes)
output << "theme-#{current_theme.parameterize}"
output << 'system-font' if current_account&.user&.setting_system_font_ui
output << 'custom-scrollbars' unless current_account&.user&.setting_system_scrollbars_ui
output << (current_account&.user&.setting_reduce_motion ? 'reduce-motion' : 'no-reduce-motion')
output << 'rtl' if locale_direction == 'rtl'
output.compact_blank.join(' ')
@ -243,6 +229,23 @@ module ApplicationHelper
full_asset_url(instance_presenter.mascot&.file&.url || frontend_asset_path('images/elephant_ui_plane.svg'))
end
def copyable_input(options = {})
tag.input(type: :text, maxlength: 999, spellcheck: false, readonly: true, **options)
end
def recent_tag_usage(tag)
people = tag.history.aggregate(2.days.ago.to_date..Time.zone.today).accounts
I18n.t 'user_mailer.welcome.hashtags_recent_count', people: number_with_delimiter(people), count: people
end
def app_store_url_ios
'https://apps.apple.com/app/mastodon-for-iphone-and-ipad/id1571998974'
end
def app_store_url_android
'https://play.google.com/store/apps/details?id=org.joinmastodon.android'
end
private
def storage_host_var

View File

@ -1,6 +1,14 @@
# frozen_string_literal: true
module FormattingHelper
SYNDICATED_EMOJI_STYLES = <<~CSS.squish
height: 1.1em;
margin: -.2ex .15em .2ex;
object-fit: contain;
vertical-align: middle;
width: 1.1em;
CSS
def html_aware_format(text, local, options = {})
HtmlAwareFormatter.new(text, local, options).to_s
end
@ -19,42 +27,33 @@ module FormattingHelper
module_function :extract_status_plain_text
def status_content_format(status)
html_aware_format(status.text, status.local?, preloaded_accounts: [status.account] + (status.respond_to?(:active_mentions) ? status.active_mentions.map(&:account) : []))
MastodonOTELTracer.in_span('HtmlAwareFormatter rendering') do |span|
span.add_attributes(
'app.formatter.content.type' => 'status',
'app.formatter.content.origin' => status.local? ? 'local' : 'remote'
)
html_aware_format(status.text, status.local?, preloaded_accounts: [status.account] + (status.respond_to?(:active_mentions) ? status.active_mentions.map(&:account) : []))
end
end
def rss_status_content_format(status)
html = status_content_format(status)
before_html = 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
end
after_html = 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
end
prerender_custom_emojis(
safe_join([before_html, html, after_html]),
wrapped_status_content_format(status),
status.emojis,
style: 'width: 1.1em; height: 1.1em; object-fit: contain; vertical-align: middle; margin: -.2ex .15em .2ex'
style: SYNDICATED_EMOJI_STYLES
).to_str
end
def account_bio_format(account)
html_aware_format(account.note, account.local?)
MastodonOTELTracer.in_span('HtmlAwareFormatter rendering') do |span|
span.add_attributes(
'app.formatter.content.type' => 'account_bio',
'app.formatter.content.origin' => account.local? ? 'local' : 'remote'
)
html_aware_format(account.note, account.local?)
end
end
def account_field_value_format(field, with_rel_me: true)
@ -64,4 +63,51 @@ module FormattingHelper
html_aware_format(field.value, field.account.local?, with_rel_me: with_rel_me, with_domains: true, multiline: false)
end
end
def markdown(text)
Redcarpet::Markdown.new(Redcarpet::Render::HTML, escape_html: true, no_images: true).render(text).html_safe # rubocop:disable Rails/OutputSafety
end
private
def wrapped_status_content_format(status)
safe_join [
rss_content_preroll(status),
status_content_format(status),
rss_content_postroll(status),
]
end
def rss_content_preroll(status)
if status.spoiler_text?
safe_join [
tag.p { spoiler_with_warning(status) },
tag.hr,
]
end
end
def spoiler_with_warning(status)
safe_join [
tag.strong { I18n.t('rss.content_warning', locale: available_locale_or_nil(status.language) || I18n.default_locale) },
status.spoiler_text,
]
end
def rss_content_postroll(status)
if status.preloadable_poll
tag.p do
poll_option_tags(status)
end
end
end
def poll_option_tags(status)
safe_join(
status.preloadable_poll.options.map do |option|
tag.send(status.preloadable_poll.multiple? ? 'checkbox' : 'radio', option, disabled: true)
end,
tag.br
)
end
end

View File

@ -162,7 +162,7 @@ module LanguagesHelper
th: ['Thai', 'ไทย'].freeze,
ti: ['Tigrinya', 'ትግርኛ'].freeze,
tk: ['Turkmen', 'Türkmen'].freeze,
tl: ['Tagalog', 'Wikang Tagalog'].freeze,
tl: ['Tagalog', 'Tagalog'].freeze,
tn: ['Tswana', 'Setswana'].freeze,
to: ['Tonga', 'faka Tonga'].freeze,
tr: ['Turkish', 'Türkçe'].freeze,
@ -193,6 +193,7 @@ module LanguagesHelper
ckb: ['Sorani (Kurdish)', 'سۆرانی'].freeze,
cnr: ['Montenegrin', 'crnogorski'].freeze,
csb: ['Kashubian', 'Kaszëbsczi'].freeze,
gsw: ['Swiss German', 'Schwiizertütsch'].freeze,
jbo: ['Lojban', 'la .lojban.'].freeze,
kab: ['Kabyle', 'Taqbaylit'].freeze,
ldn: ['Láadan', 'Láadan'].freeze,

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true
module MediaComponentHelper
def render_video_component(status, **options)
def render_video_component(status, **)
video = status.ordered_media_attachments.first
meta = video.file.meta || {}
@ -18,14 +18,14 @@ module MediaComponentHelper
media: [
serialize_media_attachment(video),
].as_json,
}.merge(**options)
}.merge(**)
react_component :video, component_params do
render partial: 'statuses/attachment_list', locals: { attachments: status.ordered_media_attachments }
end
end
def render_audio_component(status, **options)
def render_audio_component(status, **)
audio = status.ordered_media_attachments.first
meta = audio.file.meta || {}
@ -38,19 +38,19 @@ module MediaComponentHelper
foregroundColor: meta.dig('colors', 'foreground'),
accentColor: meta.dig('colors', 'accent'),
duration: meta.dig('original', 'duration'),
}.merge(**options)
}.merge(**)
react_component :audio, component_params do
render partial: 'statuses/attachment_list', locals: { attachments: status.ordered_media_attachments }
end
end
def render_media_gallery_component(status, **options)
def render_media_gallery_component(status, **)
component_params = {
sensitive: sensitive_viewer?(status, current_account),
autoplay: prefers_autoplay?,
media: status.ordered_media_attachments.map { |a| serialize_media_attachment(a).as_json },
}.merge(**options)
}.merge(**)
react_component :media_gallery, component_params do
render partial: 'statuses/attachment_list', locals: { attachments: status.ordered_media_attachments }

View File

@ -16,6 +16,6 @@ module RegistrationHelper
end
def ip_blocked?(remote_ip)
IpBlock.where(severity: :sign_up_block).exists?(['ip >>= ?', remote_ip.to_s])
IpBlock.severity_sign_up_block.containing(remote_ip.to_s).exists?
end
end

View File

@ -14,8 +14,8 @@ module RoutingHelper
end
end
def full_asset_url(source, **options)
source = ActionController::Base.helpers.asset_url(source, **options) unless use_storage?
def full_asset_url(source, **)
source = ActionController::Base.helpers.asset_url(source, **) unless use_storage?
URI.join(asset_host, source).to_s
end
@ -24,12 +24,12 @@ module RoutingHelper
Rails.configuration.action_controller.asset_host || root_url
end
def frontend_asset_path(source, **options)
asset_pack_path("media/#{source}", **options)
def frontend_asset_path(source, **)
asset_pack_path("media/#{source}", **)
end
def frontend_asset_url(source, **options)
full_asset_url(frontend_asset_path(source, **options))
def frontend_asset_url(source, **)
full_asset_url(frontend_asset_path(source, **))
end
def use_storage?

View File

@ -1,9 +1,11 @@
# frozen_string_literal: true
module SelfDestructHelper
VERIFY_PURPOSE = 'self-destruct'
def self.self_destruct?
value = ENV.fetch('SELF_DESTRUCT', nil)
value.present? && Rails.application.message_verifier('self-destruct').verify(value) == ENV['LOCAL_DOMAIN']
value = Rails.configuration.x.mastodon.self_destruct_value
value.present? && Rails.application.message_verifier(VERIFY_PURPOSE).verify(value) == ENV['LOCAL_DOMAIN']
rescue ActiveSupport::MessageVerifier::InvalidSignature
false
end

View File

@ -1,9 +1,6 @@
# frozen_string_literal: true
module StatusesHelper
EMBEDDED_CONTROLLER = 'statuses'
EMBEDDED_ACTION = 'embed'
VISIBLITY_ICONS = {
public: 'globe',
unlisted: 'lock_open',
@ -12,7 +9,7 @@ module StatusesHelper
}.freeze
def nothing_here(extra_classes = '')
content_tag(:div, class: "nothing-here #{extra_classes}") do
tag.div(class: ['nothing-here', extra_classes]) do
t('accounts.nothing_here')
end
end
@ -60,18 +57,10 @@ module StatusesHelper
components.compact_blank.join("\n\n")
end
def stream_link_target
embedded_view? ? '_blank' : nil
end
def visibility_icon(status)
VISIBLITY_ICONS[status.visibility.to_sym]
end
def embedded_view?
params[:controller] == EMBEDDED_CONTROLLER && params[:action] == EMBEDDED_ACTION
end
def prefers_autoplay?
ActiveModel::Type::Boolean.new.cast(params[:autoplay]) || current_user&.setting_auto_play_gif
end

View File

@ -23,8 +23,31 @@ module ThemeHelper
end
end
def custom_stylesheet
if active_custom_stylesheet.present?
stylesheet_link_tag(
custom_css_path(active_custom_stylesheet),
host: root_url,
media: :all,
skip_pipeline: true
)
end
end
private
def active_custom_stylesheet
if cached_custom_css_digest.present?
[:custom, cached_custom_css_digest.to_s.first(8)]
.compact_blank
.join('-')
end
end
def cached_custom_css_digest
Rails.cache.read(:setting_digest_custom_css)
end
def theme_color_for(theme)
theme == 'mastodon-light' ? Themes::THEME_COLORS[:light] : Themes::THEME_COLORS[:dark]
end

View File

@ -60,6 +60,10 @@ window.addEventListener('message', (e) => {
const data = e.data;
// Only set overflow to `hidden` once we got the expected `message` so the post can still be scrolled if
// embedded without parent Javascript support
document.body.style.overflow = 'hidden';
// We use a timeout to allow for the React page to render before calculating the height
afterInitialRender(() => {
window.parent.postMessage(

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