diff --git a/.devcontainer/compose.yaml b/.devcontainer/compose.yaml index 705d26e0a..4d5ed0f25 100644 --- a/.devcontainer/compose.yaml +++ b/.devcontainer/compose.yaml @@ -10,6 +10,7 @@ services: RAILS_ENV: development NODE_ENV: development BIND: 0.0.0.0 + BOOTSNAP_CACHE_DIR: /tmp REDIS_HOST: redis REDIS_PORT: '6379' DB_HOST: db diff --git a/.env.production.sample b/.env.production.sample index 3dd66abae..1faaf5b57 100644 --- a/.env.production.sample +++ b/.env.production.sample @@ -50,7 +50,7 @@ OTP_SECRET= # 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 +# 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= diff --git a/.github/workflows/build-container-image.yml b/.github/workflows/build-container-image.yml index 6204319a6..260730004 100644 --- a/.github/workflows/build-container-image.yml +++ b/.github/workflows/build-container-image.yml @@ -1,14 +1,9 @@ on: workflow_call: inputs: - platforms: - required: true - type: string cache: type: boolean default: true - use_native_arm64_builder: - type: boolean push_to_images: type: string version_prerelease: @@ -24,42 +19,36 @@ on: file_to_build: type: string +# This builds multiple images with one runner each, allowing us to build for multiple architectures +# using Github's runners. +# The two-step process is adapted form: +# https://docs.docker.com/build/ci/github-actions/multi-platform/#distribute-build-across-multiple-runners jobs: + # Build each (amd64 and arm64) image separately build-image: - runs-on: ubuntu-latest + runs-on: ${{ startsWith(matrix.platform, 'linux/arm') && 'ubuntu-24.04-arm' || 'ubuntu-24.04' }} + strategy: + fail-fast: false + matrix: + platform: + - linux/amd64 + - linux/arm64 steps: - uses: actions/checkout@v4 - - uses: docker/setup-qemu-action@v3 - if: contains(inputs.platforms, 'linux/arm64') && !inputs.use_native_arm64_builder + - name: Prepare + env: + PUSH_TO_IMAGES: ${{ inputs.push_to_images }} + run: | + platform=${{ matrix.platform }} + echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV + # Transform multi-line variable into comma-separated variable + image_names=${PUSH_TO_IMAGES//$'\n'/,} + echo "IMAGE_NAMES=${image_names%,}" >> $GITHUB_ENV - uses: docker/setup-buildx-action@v3 id: buildx - if: ${{ !(inputs.use_native_arm64_builder && contains(inputs.platforms, 'linux/arm64')) }} - - - name: Start a local Docker Builder - if: inputs.use_native_arm64_builder && contains(inputs.platforms, 'linux/arm64') - run: | - docker run --rm -d --name buildkitd -p 1234:1234 --privileged moby/buildkit:latest --addr tcp://0.0.0.0:1234 - - - uses: docker/setup-buildx-action@v3 - id: buildx-native - if: inputs.use_native_arm64_builder && contains(inputs.platforms, 'linux/arm64') - with: - driver: remote - endpoint: tcp://localhost:1234 - platforms: linux/amd64 - append: | - - endpoint: tcp://${{ vars.DOCKER_BUILDER_HETZNER_ARM64_01_HOST }}:13865 - platforms: linux/arm64 - name: mastodon-docker-builder-arm64-01 - driver-opts: - - servername=mastodon-docker-builder-arm64-01 - env: - BUILDER_NODE_1_AUTH_TLS_CACERT: ${{ secrets.DOCKER_BUILDER_HETZNER_ARM64_01_CACERT }} - BUILDER_NODE_1_AUTH_TLS_CERT: ${{ secrets.DOCKER_BUILDER_HETZNER_ARM64_01_CERT }} - BUILDER_NODE_1_AUTH_TLS_KEY: ${{ secrets.DOCKER_BUILDER_HETZNER_ARM64_01_KEY }} - name: Log in to Docker Hub if: contains(inputs.push_to_images, 'tootsuite') @@ -76,16 +65,18 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - uses: docker/metadata-action@v5 + - name: Docker meta id: meta + uses: docker/metadata-action@v5 if: ${{ inputs.push_to_images != '' }} with: images: ${{ inputs.push_to_images }} flavor: ${{ inputs.flavor }} - tags: ${{ inputs.tags }} labels: ${{ inputs.labels }} - - uses: docker/build-push-action@v6 + - name: Build and push by digest + id: build + uses: docker/build-push-action@v6 with: context: . file: ${{ inputs.file_to_build }} @@ -93,11 +84,87 @@ jobs: MASTODON_VERSION_PRERELEASE=${{ inputs.version_prerelease }} MASTODON_VERSION_METADATA=${{ inputs.version_metadata }} SOURCE_COMMIT=${{ github.sha }} - platforms: ${{ inputs.platforms }} + platforms: ${{ matrix.platform }} provenance: false - builder: ${{ steps.buildx.outputs.name || steps.buildx-native.outputs.name }} push: ${{ inputs.push_to_images != '' }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} cache-from: ${{ inputs.cache && 'type=gha' || '' }} cache-to: ${{ inputs.cache && 'type=gha,mode=max' || '' }} + outputs: type=image,"name=${{ env.IMAGE_NAMES }}",push-by-digest=true,name-canonical=true,push=${{ inputs.push_to_images != '' }} + + - name: Export digest + if: ${{ inputs.push_to_images != '' }} + run: | + mkdir -p "${{ runner.temp }}/digests" + digest="${{ steps.build.outputs.digest }}" + touch "${{ runner.temp }}/digests/${digest#sha256:}" + + - name: Upload digest + if: ${{ inputs.push_to_images != '' }} + uses: actions/upload-artifact@v4 + with: + # `hashFiles` is used to disambiguate between streaming and non-streaming images + name: digests-${{ hashFiles(inputs.file_to_build) }}-${{ env.PLATFORM_PAIR }} + path: ${{ runner.temp }}/digests/* + if-no-files-found: error + retention-days: 1 + + # Then merge the docker images into a single one + merge-images: + if: ${{ inputs.push_to_images != '' }} + runs-on: ubuntu-24.04 + needs: + - build-image + + env: + PUSH_TO_IMAGES: ${{ inputs.push_to_images }} + + steps: + - uses: actions/checkout@v4 + + - name: Download digests + uses: actions/download-artifact@v4 + with: + path: ${{ runner.temp }}/digests + # `hashFiles` is used to disambiguate between streaming and non-streaming images + pattern: digests-${{ hashFiles(inputs.file_to_build) }}-* + merge-multiple: true + + - name: Log in to Docker Hub + if: contains(inputs.push_to_images, 'tootsuite') + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Log in to the GitHub Container registry + if: contains(inputs.push_to_images, 'ghcr.io') + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + if: ${{ inputs.push_to_images != '' }} + with: + images: ${{ inputs.push_to_images }} + flavor: ${{ inputs.flavor }} + tags: ${{ inputs.tags }} + labels: ${{ inputs.labels }} + + - name: Create manifest list and push + working-directory: ${{ runner.temp }}/digests + run: | + echo "$PUSH_TO_IMAGES" | xargs -I{} \ + docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ + $(printf '{}@sha256:%s ' *) + + - name: Inspect image + run: | + echo "$PUSH_TO_IMAGES" | xargs -i{} \ + docker buildx imagetools inspect {}:${{ steps.meta.outputs.version }} diff --git a/.github/workflows/build-nightly.yml b/.github/workflows/build-nightly.yml index 7c6f74b45..4a56f720e 100644 --- a/.github/workflows/build-nightly.yml +++ b/.github/workflows/build-nightly.yml @@ -26,8 +26,6 @@ jobs: uses: ./.github/workflows/build-container-image.yml with: file_to_build: Dockerfile - platforms: linux/amd64,linux/arm64 - use_native_arm64_builder: true cache: false push_to_images: | tootsuite/mastodon @@ -48,8 +46,6 @@ jobs: uses: ./.github/workflows/build-container-image.yml with: file_to_build: streaming/Dockerfile - platforms: linux/amd64,linux/arm64 - use_native_arm64_builder: true cache: false push_to_images: | tootsuite/mastodon-streaming diff --git a/.github/workflows/build-push-pr.yml b/.github/workflows/build-push-pr.yml index d3bc8e5df..418993475 100644 --- a/.github/workflows/build-push-pr.yml +++ b/.github/workflows/build-push-pr.yml @@ -32,8 +32,6 @@ jobs: uses: ./.github/workflows/build-container-image.yml with: file_to_build: Dockerfile - platforms: linux/amd64,linux/arm64 - use_native_arm64_builder: true push_to_images: | ghcr.io/mastodon/mastodon version_metadata: ${{ needs.compute-suffix.outputs.metadata }} @@ -49,8 +47,6 @@ jobs: uses: ./.github/workflows/build-container-image.yml with: file_to_build: streaming/Dockerfile - platforms: linux/amd64,linux/arm64 - use_native_arm64_builder: true push_to_images: | ghcr.io/mastodon/mastodon-streaming version_metadata: ${{ needs.compute-suffix.outputs.metadata }} diff --git a/.github/workflows/build-releases.yml b/.github/workflows/build-releases.yml index da9a45828..473718bd1 100644 --- a/.github/workflows/build-releases.yml +++ b/.github/workflows/build-releases.yml @@ -13,8 +13,6 @@ jobs: uses: ./.github/workflows/build-container-image.yml with: file_to_build: Dockerfile - platforms: linux/amd64,linux/arm64 - use_native_arm64_builder: true push_to_images: | tootsuite/mastodon ghcr.io/mastodon/mastodon @@ -34,8 +32,6 @@ jobs: uses: ./.github/workflows/build-container-image.yml with: file_to_build: streaming/Dockerfile - platforms: linux/amd64,linux/arm64 - use_native_arm64_builder: true push_to_images: | tootsuite/mastodon-streaming ghcr.io/mastodon/mastodon-streaming diff --git a/.github/workflows/build-security.yml b/.github/workflows/build-security.yml index 1e2455d3d..d3cb4e5e0 100644 --- a/.github/workflows/build-security.yml +++ b/.github/workflows/build-security.yml @@ -24,8 +24,6 @@ jobs: uses: ./.github/workflows/build-container-image.yml with: file_to_build: Dockerfile - platforms: linux/amd64,linux/arm64 - use_native_arm64_builder: true cache: false push_to_images: | tootsuite/mastodon @@ -46,8 +44,6 @@ jobs: uses: ./.github/workflows/build-container-image.yml with: file_to_build: streaming/Dockerfile - platforms: linux/amd64,linux/arm64 - use_native_arm64_builder: true cache: false push_to_images: | tootsuite/mastodon-streaming diff --git a/.github/workflows/lint-haml.yml b/.github/workflows/lint-haml.yml index 499be2010..936135807 100644 --- a/.github/workflows/lint-haml.yml +++ b/.github/workflows/lint-haml.yml @@ -43,4 +43,4 @@ jobs: - name: Run haml-lint run: | echo "::add-matcher::.github/workflows/haml-lint-problem-matcher.json" - bin/haml-lint --reporter github + bin/haml-lint --parallel --reporter github diff --git a/.github/workflows/test-image-build.yml b/.github/workflows/test-image-build.yml index 980e07189..bde40addd 100644 --- a/.github/workflows/test-image-build.yml +++ b/.github/workflows/test-image-build.yml @@ -20,7 +20,6 @@ jobs: uses: ./.github/workflows/build-container-image.yml with: file_to_build: Dockerfile - platforms: linux/amd64 # Testing only on native platform so it is performant cache: true build-image-streaming: @@ -31,5 +30,4 @@ jobs: uses: ./.github/workflows/build-container-image.yml with: file_to_build: streaming/Dockerfile - platforms: linux/amd64 # Testing only on native platform so it is performant cache: true diff --git a/.github/workflows/test-migrations.yml b/.github/workflows/test-migrations.yml index 306191fb8..733664b75 100644 --- a/.github/workflows/test-migrations.yml +++ b/.github/workflows/test-migrations.yml @@ -64,7 +64,6 @@ jobs: DB_HOST: localhost DB_USER: postgres DB_PASS: postgres - DISABLE_SIMPLECOV: true RAILS_ENV: test BUNDLE_CLEAN: true BUNDLE_FROZEN: true diff --git a/.github/workflows/test-ruby.yml b/.github/workflows/test-ruby.yml index 4deb08d32..1f7f8f93a 100644 --- a/.github/workflows/test-ruby.yml +++ b/.github/workflows/test-ruby.yml @@ -107,7 +107,7 @@ jobs: DB_HOST: localhost DB_USER: postgres DB_PASS: postgres - DISABLE_SIMPLECOV: ${{ matrix.ruby-version != '.ruby-version' }} + COVERAGE: ${{ matrix.ruby-version == '.ruby-version' }} RAILS_ENV: test ALLOW_NOPAM: true PAM_ENABLED: true @@ -208,7 +208,7 @@ jobs: DB_HOST: localhost DB_USER: postgres DB_PASS: postgres - DISABLE_SIMPLECOV: ${{ matrix.ruby-version != '.ruby-version' }} + COVERAGE: ${{ matrix.ruby-version == '.ruby-version' }} RAILS_ENV: test ALLOW_NOPAM: true PAM_ENABLED: true @@ -295,7 +295,6 @@ jobs: DB_HOST: localhost DB_USER: postgres DB_PASS: postgres - DISABLE_SIMPLECOV: true RAILS_ENV: test BUNDLE_WITH: test LOCAL_DOMAIN: localhost:3000 @@ -411,7 +410,6 @@ jobs: DB_HOST: localhost DB_USER: postgres DB_PASS: postgres - DISABLE_SIMPLECOV: true RAILS_ENV: test BUNDLE_WITH: test ES_ENABLED: true diff --git a/.nvmrc b/.nvmrc index fb0a13554..744ca17ec 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -22.13 +22.14 diff --git a/.rubocop.yml b/.rubocop.yml index ebeed6ea4..bba428285 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -26,9 +26,11 @@ inherit_mode: merge: - Exclude -require: +plugins: - rubocop-rails - rubocop-rspec - - rubocop-rspec_rails - rubocop-performance + +require: + - rubocop-rspec_rails - rubocop-capybara diff --git a/.rubocop/rails.yml b/.rubocop/rails.yml index ae31c1f26..bbd172e65 100644 --- a/.rubocop/rails.yml +++ b/.rubocop/rails.yml @@ -2,6 +2,9 @@ Rails/BulkChangeTable: Enabled: false # Conflicts with strong_migrations features +Rails/Delegate: + Enabled: false + Rails/FilePath: EnforcedStyle: arguments diff --git a/.rubocop/style.yml b/.rubocop/style.yml index df1da2ba3..f59340d45 100644 --- a/.rubocop/style.yml +++ b/.rubocop/style.yml @@ -58,3 +58,6 @@ Style/TrailingCommaInArrayLiteral: Style/TrailingCommaInHashLiteral: EnforcedStyleForMultiline: comma + +Style/WordArray: + MinSize: 3 # Override default of 2 diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 12ef0ad62..5cf43a3d5 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -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.69.2. +# using RuboCop version 1.72.2. # 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 @@ -69,15 +69,6 @@ Style/MapToHash: Exclude: - 'app/models/status.rb' -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: literals, strict -Style/MutableConstant: - Exclude: - - 'app/models/tag.rb' - - 'app/services/delete_account_service.rb' - - 'lib/mastodon/migration_warning.rb' - # Configuration parameters: AllowedMethods. # AllowedMethods: respond_to_missing? Style/OptionalBooleanParameter: @@ -103,10 +94,3 @@ Style/RedundantConstantBase: Exclude: - 'config/environments/production.rb' - 'config/initializers/sidekiq.rb' - -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: WordRegex. -# SupportedStyles: percent, brackets -Style/WordArray: - EnforcedStyle: percent - MinSize: 3 diff --git a/.ruby-version b/.ruby-version index 47b322c97..4d9d11cf5 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.4.1 +3.4.2 diff --git a/CHANGELOG.md b/CHANGELOG.md index ea18b3cb9..ef6a87ebb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,24 @@ All notable changes to this project will be documented in this file. +## [4.3.3] - 2025-01-16 + +### Security + +- Fix insufficient validation of account URIs ([GHSA-5wxh-3p65-r4g6](https://github.com/mastodon/mastodon/security/advisories/GHSA-5wxh-3p65-r4g6)) +- Update dependencies + +### Fixed + +- Fix `libyaml` missing from `Dockerfile` build stage (#33591 by @vmstan) +- Fix incorrect notification settings migration for non-followers (#33348 by @ClearlyClaire) +- Fix down clause for notification policy v2 migrations (#33340 by @jesseplusplus) +- Fix error decrementing status count when `FeaturedTags#last_status_at` is `nil` (#33320 by @ClearlyClaire) +- Fix last paginated notification group only including data on a single notification (#33271 by @ClearlyClaire) +- Fix processing of mentions for post edits with an existing corresponding silent mention (#33227 by @ClearlyClaire) +- Fix deletion of unconfirmed users with Webauthn set (#33186 by @ClearlyClaire) +- Fix empty authors preview card serialization (#33151, #33466 by @mjankowski and @ClearlyClaire) + ## [4.3.2] - 2024-12-03 ### Added diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4a3825484..6bdacab4a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,30 +9,51 @@ You can contribute in the following ways: - Contributing code to Mastodon by fixing bugs or implementing features - Improving the documentation -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 and the [DEVELOPMENT] guide for environment-specific details. -[contribution guidelines]: https://github.com/mastodon/.github/blob/main/CONTRIBUTING.md - ## API Changes and Additions -Please note that any changes or additions made to the API should have an accompanying pull request on [our documentation repository](https://github.com/mastodon/documentation). +Any changes or additions made to the API should have an accompanying pull +request on our [documentation repository]. -## Bug reports +## Bug Reports -Bug reports and feature suggestions must use descriptive and concise titles and be submitted to [GitHub Issues](https://github.com/mastodon/mastodon/issues). Please use the search function to make sure that you are not submitting duplicates, and that a similar report or request has not already been resolved or rejected. +Bug reports and feature suggestions must use descriptive and concise titles and +be submitted to [GitHub Issues]. Please use the search function to make sure +there are not duplicate bug reports or feature requests. ## Translations -You can submit translations via [Crowdin](https://crowdin.com/project/mastodon). They are periodically merged into the codebase. +Translations are community contributed via [Crowdin]. They are periodically +reviewed and merged into the codebase. [![Crowdin](https://d322cqt584bo4o.cloudfront.net/mastodon/localized.svg)](https://crowdin.com/project/mastodon) -## Pull requests +## Pull Requests -**Please use clean, concise titles for your pull requests.** Unless the pull request is about refactoring code, updating dependencies or other internal tasks, assume that the person reading the pull request title is not a programmer or Mastodon developer, but instead a Mastodon user or server administrator, and **try to describe your change or fix from their perspective**. We use commit squashing, so the final commit in the main branch will carry the title of the pull request, and commits from the main branch are fed into the changelog. The changelog is separated into [keepachangelog.com categories](https://keepachangelog.com/en/1.0.0/), and while that spec does not prescribe how the entries ought to be named, for easier sorting, start your pull request titles using one of the verbs "Add", "Change", "Deprecate", "Remove", or "Fix" (present tense). +### Size and Scope + +Our time is limited and PRs making large, unsolicited changes are unlikely to +get a response. Changes which link to an existing confirmed issue, or which come +from a "help wanted" issue or other request are more likely to be reviewed. + +The smaller and more narrowly focused the changes in a PR are, the easier they +are to review and potentially merge. If the change only makes sense in some +larger context of future ongoing work, note that in the description, but still +aim to keep each distinct PR to a "smallest viable change" chunk of work. + +### Description of Changes + +Unless the Pull Request is about refactoring code, updating dependencies or +other internal tasks, assume that the audience are not developers, but a +Mastodon user or server admin, and try to describe it from their perspective. + +The final commit in the main branch will carry the title from the PR. The main +branch is then fed into the changelog and ultimately into release notes. We try +to follow the [keepachangelog] spec, and while that does not prescribe how +exactly the entries ought to be named, starting titles using one of the verbs +"Add", "Change", "Deprecate", "Remove", or "Fix" (present tense) is helpful. Example: @@ -40,18 +61,25 @@ Example: | ------------------------------------ | ------------------------------------------------------------- | | Fixed NoMethodError in RemovalWorker | Fix nil error when removing statuses caused by race condition | -It is not always possible to phrase every change in such a manner, but it is desired. +### Technical Requirements -**The smaller the set of changes in the pull request is, the quicker it can be reviewed and merged.** Splitting tasks into multiple smaller pull requests is often preferable. - -**Pull requests that do not pass automated checks may not be reviewed**. In particular, you need to keep in mind: +Pull requests that do not pass automated checks on CI may not be reviewed. In +particular, please keep in mind: - Unit and integration tests (rspec, jest) - Code style rules (rubocop, eslint) - Normalization of locale files (i18n-tasks) +- Relevant accessibility or performance concerns ## 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). +The [Mastodon documentation] is a statically generated site that contains guides +and API docs. Improvements are made via PRs to the [documentation repository]. +[contribution guidelines]: https://github.com/mastodon/.github/blob/main/CONTRIBUTING.md +[Crowdin]: https://crowdin.com/project/mastodon [DEVELOPMENT]: docs/DEVELOPMENT.md +[documentation repository]: https://github.com/mastodon/documentation +[GitHub Issues]: https://github.com/mastodon/mastodon/issues +[keepachangelog]: https://keepachangelog.com/en/1.0.0/ +[Mastodon documentation]: https://docs.joinmastodon.org diff --git a/Dockerfile b/Dockerfile index d95dad6a2..b11ba0d3b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # 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 +# For a containerized local dev environment, see: https://github.com/mastodon/mastodon/blob/main/docs/DEVELOPMENT.md#docker # Please see https://docs.docker.com/engine/reference/builder for information about # the extended buildx capabilities used in this file. @@ -9,19 +9,20 @@ # See: https://docs.docker.com/build/building/multi-platform/ ARG TARGETPLATFORM=${TARGETPLATFORM} ARG BUILDPLATFORM=${BUILDPLATFORM} +ARG BASE_REGISTRY="docker.io" # 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.4.1" +ARG RUBY_VERSION="3.4.2" # # 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="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 +FROM ${BASE_REGISTRY}/node:${NODE_MAJOR_VERSION}-${DEBIAN_VERSION}-slim AS node # 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 +FROM ${BASE_REGISTRY}/ruby:${RUBY_VERSION}-slim-${DEBIAN_VERSION} AS ruby # Resulting version string is vX.X.X-MASTODON_VERSION_PRERELEASE+MASTODON_VERSION_METADATA # Example: v4.3.0-nightly.2023.11.09+pr-123456 @@ -153,6 +154,7 @@ RUN \ libpq-dev \ libssl-dev \ libtool \ + libyaml-dev \ meson \ nasm \ pkg-config \ diff --git a/Gemfile b/Gemfile index 8df00d8c0..9f8c69267 100644 --- a/Gemfile +++ b/Gemfile @@ -94,29 +94,31 @@ gem 'twitter-text', '~> 3.1.0' gem 'tzinfo-data', '~> 1.2023' gem 'webauthn', '~> 3.0' gem 'webpacker', '~> 5.4' -gem 'webpush', github: 'ClearlyClaire/webpush', ref: 'f14a4d52e201128b1b00245d11b6de80d6cfdcd9' +gem 'webpush', github: 'mastodon/webpush', ref: '9631ac63045cfabddacc69fc06e919b4c13eb913' gem 'json-ld' gem 'json-ld-preloaded', '~> 3.2' gem 'rdf-normalize', '~> 0.5' +gem 'prometheus_exporter', '~> 2.2', require: false + 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.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.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.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-instrumentation-active_job', '~> 0.8.0', require: false + gem 'opentelemetry-instrumentation-active_model_serializers', '~> 0.22.0', require: false + gem 'opentelemetry-instrumentation-concurrent_ruby', '~> 0.22.0', require: false + gem 'opentelemetry-instrumentation-excon', '~> 0.23.0', require: false + gem 'opentelemetry-instrumentation-faraday', '~> 0.26.0', require: false + gem 'opentelemetry-instrumentation-http', '~> 0.24.0', require: false + gem 'opentelemetry-instrumentation-http_client', '~> 0.23.0', require: false + gem 'opentelemetry-instrumentation-net_http', '~> 0.23.0', require: false + gem 'opentelemetry-instrumentation-pg', '~> 0.30.0', require: false + gem 'opentelemetry-instrumentation-rack', '~> 0.26.0', require: false + gem 'opentelemetry-instrumentation-rails', '~> 0.36.0', require: false + gem 'opentelemetry-instrumentation-redis', '~> 0.26.0', require: false + gem 'opentelemetry-instrumentation-sidekiq', '~> 0.26.0', require: false gem 'opentelemetry-sdk', '~> 1.4', require: false end @@ -125,7 +127,7 @@ group :test do gem 'flatware-rspec' # Adds RSpec Error/Warning annotations to GitHub PRs on the Files tab - gem 'rspec-github', '~> 2.4', require: false + gem 'rspec-github', '~> 3.0', require: false # RSpec helpers for email specs gem 'email_spec' @@ -143,9 +145,6 @@ group :test do # Used to mock environment variables gem 'climate_control' - # Add back helpers functions removed in Rails 5.1 - gem 'rails-controller-testing', '~> 1.0' - # Validate schemas in specs gem 'json-schema', '~> 5.0' @@ -154,7 +153,7 @@ group :test do gem 'shoulda-matchers' - # Coverage formatter for RSpec test if DISABLE_SIMPLECOV is false + # Coverage formatter for RSpec gem 'simplecov', '~> 0.22', require: false gem 'simplecov-lcov', '~> 0.8', require: false @@ -172,7 +171,7 @@ group :development do gem 'rubocop-rspec_rails', require: false # Annotates modules with schema - gem 'annotaterb', '~> 4.13' + gem 'annotaterb', '~> 4.13', require: false # Enhanced error message pages for development gem 'better_errors', '~> 2.9' @@ -195,7 +194,7 @@ end group :development, :test do # Interactive Debugging tools - gem 'debug', '~> 1.8' + gem 'debug', '~> 1.8', require: false # Generate fake data values gem 'faker', '~> 3.2' @@ -207,7 +206,7 @@ group :development, :test do gem 'memory_profiler', require: false gem 'ruby-prof', require: false gem 'stackprof', require: false - gem 'test-prof' + gem 'test-prof', require: false # RSpec runner for rails gem 'rspec-rails', '~> 7.0' diff --git a/Gemfile.lock b/Gemfile.lock index 36373bd33..b2b53c5ea 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,9 +1,9 @@ GIT - remote: https://github.com/ClearlyClaire/webpush.git - revision: f14a4d52e201128b1b00245d11b6de80d6cfdcd9 - ref: f14a4d52e201128b1b00245d11b6de80d6cfdcd9 + remote: https://github.com/mastodon/webpush.git + revision: 9631ac63045cfabddacc69fc06e919b4c13eb913 + ref: 9631ac63045cfabddacc69fc06e919b4c13eb913 specs: - webpush (0.3.8) + webpush (1.1.0) hkdf (~> 0.2) jwt (~> 2.0) @@ -90,7 +90,7 @@ GEM public_suffix (>= 2.0.2, < 7.0) aes_key_wrap (1.1.0) android_key_attestation (0.3.0) - annotaterb (4.13.0) + annotaterb (4.14.0) ast (2.4.2) attr_required (1.0.2) aws-eventstream (1.3.0) @@ -159,7 +159,7 @@ GEM climate_control (1.2.0) cocoon (1.2.15) color_diff (0.1) - concurrent-ruby (1.3.4) + concurrent-ruby (1.3.5) connection_pool (2.5.0) cose (1.3.1) cbor (~> 0.5.9) @@ -194,7 +194,7 @@ GEM devise_pam_authenticatable2 (9.2.0) devise (>= 4.0.0) rpam2 (~> 4.0) - diff-lcs (1.5.1) + diff-lcs (1.6.0) discard (1.4.0) activerecord (>= 4.2, < 9.0) docile (1.4.1) @@ -220,7 +220,7 @@ GEM erubi (1.13.1) et-orbi (1.2.11) tzinfo - excon (0.112.0) + excon (1.2.3) fabrication (2.31.0) faker (3.5.1) i18n (>= 1.8.11, < 2) @@ -244,15 +244,15 @@ GEM flatware-rspec (2.3.4) flatware (= 2.3.4) rspec (>= 3.6) - fog-core (2.5.0) + fog-core (2.6.0) builder - excon (~> 0.71) + excon (~> 1.0) formatador (>= 0.2, < 2.0) mime-types fog-json (1.2.0) fog-core multi_json (~> 1.10) - fog-openstack (1.1.3) + fog-openstack (1.1.4) fog-core (~> 2.1) fog-json (>= 1.0) formatador (1.1.0) @@ -273,7 +273,7 @@ GEM activesupport (>= 5.1) haml (>= 4.0.6) railties (>= 5.1) - haml_lint (0.59.0) + haml_lint (0.60.0) haml (>= 5.0) parallel (~> 1.10) rainbow @@ -283,7 +283,7 @@ GEM hashie (5.0.0) hcaptcha (7.1.0) json - highline (3.1.1) + highline (3.1.2) reline hiredis (0.6.3) hkdf (0.3.0) @@ -302,7 +302,7 @@ GEM httplog (1.7.0) rack (>= 2.0) rainbow (>= 2.0.0) - i18n (1.14.6) + i18n (1.14.7) concurrent-ruby (~> 1.0) i18n-tasks (1.0.14) activesupport (>= 4.0.2) @@ -319,7 +319,8 @@ GEM activesupport (>= 3.0) nokogiri (>= 1.6) io-console (0.8.0) - irb (1.14.3) + irb (1.15.1) + pp (>= 0.6.0) rdoc (>= 4.0.0) reline (>= 0.4.2) jd-paperclip-azure (3.0.0) @@ -327,7 +328,7 @@ GEM azure-blob (~> 0.5.2) hashie (~> 5.0) jmespath (1.6.2) - json (2.9.1) + json (2.10.1) json-canonicalization (1.0.0) json-jwt (1.15.3.1) activesupport (>= 4.2) @@ -349,7 +350,7 @@ GEM addressable (~> 2.8) bigdecimal (~> 3.1) jsonapi-renderer (0.2.2) - jwt (2.9.3) + jwt (2.10.1) base64 kaminari (1.2.2) activesupport (>= 4.1.0) @@ -369,10 +370,11 @@ GEM marcel (~> 1.0.1) mime-types terrapin (>= 0.6.0, < 2.0) - language_server-protocol (3.17.0.3) - launchy (3.0.1) + language_server-protocol (3.17.0.4) + launchy (3.1.0) addressable (~> 2.8) childprocess (~> 5.0) + logger (~> 1.6) letter_opener (1.10.0) launchy (>= 2.2, < 4) letter_opener_web (3.0.0) @@ -381,10 +383,11 @@ GEM railties (>= 6.1) rexml link_header (0.0.8) + lint_roller (1.1.0) llhttp-ffi (0.5.0) ffi-compiler (~> 1.0) rake (~> 13.0) - logger (1.6.4) + logger (1.6.6) lograge (0.14.0) actionpack (>= 4) activesupport (>= 4) @@ -406,16 +409,16 @@ GEM mime-types (3.6.0) logger mime-types-data (~> 3.2015) - mime-types-data (3.2024.1203) + mime-types-data (3.2025.0220) mini_mime (1.1.5) mini_portile2 (2.8.8) minitest (5.25.4) - msgpack (1.7.5) + msgpack (1.8.0) multi_json (1.15.0) mutex_m (0.3.0) net-http (0.6.0) uri - net-imap (0.5.4) + net-imap (0.5.6) date net-protocol net-ldap (0.19.0) @@ -423,10 +426,10 @@ GEM net-protocol net-protocol (0.2.2) timeout - net-smtp (0.5.0) + net-smtp (0.5.1) net-protocol nio4r (2.7.4) - nokogiri (1.18.1) + nokogiri (1.18.3) mini_portile2 (~> 2.8.2) racc (~> 1.4) oj (3.16.9) @@ -460,7 +463,7 @@ GEM validate_email validate_url webfinger (~> 1.2) - openssl (3.2.1) + openssl (3.3.0) openssl-signature_algorithm (1.3.0) openssl (> 2.0) opentelemetry-api (1.4.0) @@ -473,80 +476,86 @@ GEM opentelemetry-common (~> 0.20) opentelemetry-sdk (~> 1.2) opentelemetry-semantic_conventions - opentelemetry-helpers-sql-obfuscation (0.2.1) + opentelemetry-helpers-sql-obfuscation (0.3.0) opentelemetry-common (~> 0.21) - opentelemetry-instrumentation-action_mailer (0.3.0) + opentelemetry-instrumentation-action_mailer (0.4.0) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-active_support (~> 0.7) - opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-action_pack (0.10.0) + opentelemetry-instrumentation-base (~> 0.23.0) + opentelemetry-instrumentation-action_pack (0.12.0) opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-base (~> 0.22.1) + opentelemetry-instrumentation-base (~> 0.23.0) opentelemetry-instrumentation-rack (~> 0.21) - opentelemetry-instrumentation-action_view (0.8.0) + opentelemetry-instrumentation-action_view (0.9.0) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-active_support (~> 0.7) - opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-active_job (0.7.8) + opentelemetry-instrumentation-base (~> 0.23.0) + opentelemetry-instrumentation-active_job (0.8.0) opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-active_model_serializers (0.21.1) + opentelemetry-instrumentation-base (~> 0.23.0) + opentelemetry-instrumentation-active_model_serializers (0.22.0) 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-instrumentation-base (~> 0.23.0) + opentelemetry-instrumentation-active_record (0.9.0) opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-active_support (0.7.0) + opentelemetry-instrumentation-base (~> 0.23.0) + opentelemetry-instrumentation-active_storage (0.1.0) + opentelemetry-api (~> 1.4.0) + opentelemetry-instrumentation-active_support (~> 0.7) + opentelemetry-instrumentation-base (~> 0.23.0) + opentelemetry-instrumentation-active_support (0.8.0) opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-base (0.22.6) + opentelemetry-instrumentation-base (~> 0.23.0) + opentelemetry-instrumentation-base (0.23.0) opentelemetry-api (~> 1.0) opentelemetry-common (~> 0.21) opentelemetry-registry (~> 0.1) - opentelemetry-instrumentation-concurrent_ruby (0.21.4) + opentelemetry-instrumentation-concurrent_ruby (0.22.0) opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-excon (0.22.5) + opentelemetry-instrumentation-base (~> 0.23.0) + opentelemetry-instrumentation-excon (0.23.0) opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-faraday (0.25.0) + opentelemetry-instrumentation-base (~> 0.23.0) + opentelemetry-instrumentation-faraday (0.26.0) opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-http (0.23.5) + opentelemetry-instrumentation-base (~> 0.23.0) + opentelemetry-instrumentation-http (0.24.0) opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-http_client (0.22.8) + opentelemetry-instrumentation-base (~> 0.23.0) + opentelemetry-instrumentation-http_client (0.23.0) opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-net_http (0.22.8) + opentelemetry-instrumentation-base (~> 0.23.0) + opentelemetry-instrumentation-net_http (0.23.0) opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-pg (0.29.2) + opentelemetry-instrumentation-base (~> 0.23.0) + opentelemetry-instrumentation-pg (0.30.0) opentelemetry-api (~> 1.0) opentelemetry-helpers-sql-obfuscation - opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-rack (0.25.0) + opentelemetry-instrumentation-base (~> 0.23.0) + opentelemetry-instrumentation-rack (0.26.0) opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-rails (0.34.0) + opentelemetry-instrumentation-base (~> 0.23.0) + opentelemetry-instrumentation-rails (0.36.0) opentelemetry-api (~> 1.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.8.0) - opentelemetry-instrumentation-active_support (~> 0.7.0) - opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-redis (0.25.7) + opentelemetry-instrumentation-action_mailer (~> 0.4.0) + opentelemetry-instrumentation-action_pack (~> 0.12.0) + opentelemetry-instrumentation-action_view (~> 0.9.0) + opentelemetry-instrumentation-active_job (~> 0.8.0) + opentelemetry-instrumentation-active_record (~> 0.9.0) + opentelemetry-instrumentation-active_storage (~> 0.1.0) + opentelemetry-instrumentation-active_support (~> 0.8.0) + opentelemetry-instrumentation-base (~> 0.23.0) + opentelemetry-instrumentation-concurrent_ruby (~> 0.22.0) + opentelemetry-instrumentation-redis (0.26.1) opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-sidekiq (0.25.7) + opentelemetry-instrumentation-base (~> 0.23.0) + opentelemetry-instrumentation-sidekiq (0.26.0) opentelemetry-api (~> 1.0) - opentelemetry-instrumentation-base (~> 0.22.1) + opentelemetry-instrumentation-base (~> 0.23.0) opentelemetry-registry (0.3.1) opentelemetry-api (~> 1.1) - opentelemetry-sdk (1.6.0) + opentelemetry-sdk (1.7.0) opentelemetry-api (~> 1.1) opentelemetry-common (~> 0.20) opentelemetry-registry (~> 0.2) @@ -555,10 +564,10 @@ GEM opentelemetry-api (~> 1.0) orm_adapter (0.5.0) ostruct (0.6.1) - ox (2.14.19) + ox (2.14.22) bigdecimal (>= 3.0) parallel (1.26.3) - parser (3.3.6.0) + parser (3.3.7.1) ast (~> 2.4.1) racc parslet (2.0.0) @@ -567,6 +576,8 @@ GEM pg (1.5.9) pghero (3.6.1) activerecord (>= 6.1) + pp (0.6.2) + prettyprint premailer (1.27.0) addressable css_parser (>= 1.19.0) @@ -575,22 +586,25 @@ GEM actionmailer (>= 3) net-smtp premailer (~> 1.7, >= 1.7.9) + prettyprint (0.2.0) + prometheus_exporter (2.2.0) + webrick propshaft (1.1.0) actionpack (>= 7.0.0) activesupport (>= 7.0.0) rack railties (>= 7.0.0) - psych (5.2.2) + psych (5.2.3) date stringio public_suffix (6.0.1) - puma (6.5.0) + puma (6.6.0) nio4r (~> 2.0) pundit (2.4.0) activesupport (>= 3.0.0) raabro (1.4.0) racc (1.8.1) - rack (2.2.10) + rack (2.2.11) rack-attack (6.7.0) rack (>= 1.0, < 4) rack-cors (2.0.2) @@ -627,10 +641,6 @@ GEM activesupport (= 8.0.1) bundler (>= 1.15.0) railties (= 8.0.1) - rails-controller-testing (1.0.5) - actionpack (>= 5.0.1.rc1) - actionview (>= 5.0.1.rc1) - activesupport (>= 5.0.1.rc1) rails-dom-testing (2.2.0) activesupport (>= 5.0.0) minitest @@ -657,7 +667,7 @@ GEM link_header (~> 0.0, >= 0.0.8) rdf-normalize (0.7.0) rdf (~> 3.3) - rdoc (6.10.0) + rdoc (6.12.0) psych (>= 4.0.0) redcarpet (3.6.0) redis (4.8.1) @@ -673,7 +683,7 @@ GEM responders (3.1.1) actionpack (>= 5.2) railties (>= 5.2) - rexml (3.4.0) + rexml (3.4.1) rotp (6.3.0) rouge (4.5.1) rpam2 (4.0.2) @@ -685,17 +695,17 @@ GEM rspec-core (~> 3.13.0) rspec-expectations (~> 3.13.0) rspec-mocks (~> 3.13.0) - rspec-core (3.13.2) + rspec-core (3.13.3) rspec-support (~> 3.13.0) rspec-expectations (3.13.3) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) - rspec-github (2.4.0) + rspec-github (3.0.0) rspec-core (~> 3.0) rspec-mocks (3.13.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) - rspec-rails (7.1.0) + rspec-rails (7.1.1) actionpack (>= 7.0) activesupport (>= 7.0) railties (>= 7.0) @@ -709,30 +719,34 @@ GEM rspec-mocks (~> 3.0) sidekiq (>= 5, < 8) rspec-support (3.13.2) - rubocop (1.69.2) + rubocop (1.72.2) json (~> 2.3) - language_server-protocol (>= 3.17.0) + language_server-protocol (~> 3.17.0.2) + lint_roller (~> 1.1.0) parallel (~> 1.10) parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 2.9.3, < 3.0) - rubocop-ast (>= 1.36.2, < 2.0) + rubocop-ast (>= 1.38.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 4.0) - rubocop-ast (1.37.0) + rubocop-ast (1.38.0) parser (>= 3.3.1.0) rubocop-capybara (2.21.0) rubocop (~> 1.41) - rubocop-performance (1.23.1) - rubocop (>= 1.48.1, < 2.0) - rubocop-ast (>= 1.31.1, < 2.0) - rubocop-rails (2.28.0) + rubocop-performance (1.24.0) + lint_roller (~> 1.1) + rubocop (>= 1.72.1, < 2.0) + rubocop-ast (>= 1.38.0, < 2.0) + rubocop-rails (2.30.1) activesupport (>= 4.2.0) + lint_roller (~> 1.1) rack (>= 1.1) - rubocop (>= 1.52.0, < 2.0) - rubocop-ast (>= 1.31.1, < 2.0) - rubocop-rspec (3.3.0) - rubocop (~> 1.61) + rubocop (>= 1.72.1, < 2.0) + rubocop-ast (>= 1.38.0, < 2.0) + rubocop-rspec (3.5.0) + lint_roller (~> 1.1) + rubocop (~> 1.72, >= 1.72.1) rubocop-rspec_rails (2.30.0) rubocop (~> 1.61) rubocop-rspec (~> 3, >= 3.0.1) @@ -741,7 +755,7 @@ GEM ruby-saml (1.17.0) nokogiri (>= 1.13.10) rexml - ruby-vips (2.2.2) + ruby-vips (2.2.3) ffi (~> 1.12) logger rubyzip (2.4.1) @@ -756,7 +770,7 @@ GEM activerecord (>= 4.0.0) railties (>= 4.0.0) securerandom (0.4.1) - selenium-webdriver (4.27.0) + selenium-webdriver (4.29.1) base64 (~> 0.2) logger (~> 1.4) rexml (~> 3.2, >= 3.2.5) @@ -793,27 +807,27 @@ GEM simplecov-html (0.13.1) simplecov-lcov (0.8.0) simplecov_json_formatter (0.1.4) - stackprof (0.2.26) - stoplight (4.1.0) + stackprof (0.2.27) + stoplight (4.1.1) redlock (~> 1.0) - stringio (3.1.2) - strong_migrations (2.1.0) - activerecord (>= 6.1) + stringio (3.1.4) + strong_migrations (2.2.0) + activerecord (>= 7) swd (1.3.0) activesupport (>= 3) attr_required (>= 0.0.5) httpclient (>= 2.4) sysexits (1.2.0) temple (0.10.3) - terminal-table (3.0.2) - unicode-display_width (>= 1.1.1, < 3) + terminal-table (4.0.0) + unicode-display_width (>= 1.1.1, < 4) terrapin (1.0.1) climate_control test-prof (1.4.4) thor (1.3.2) - tilt (2.5.0) + tilt (2.6.0) timeout (0.4.3) - tpm-key_attestation (0.12.1) + tpm-key_attestation (0.14.0) bindata (~> 2.4) openssl (> 2.0) openssl-signature_algorithm (~> 1.0) @@ -832,12 +846,14 @@ GEM unf (~> 0.1.0) tzinfo (2.0.6) concurrent-ruby (~> 1.0) - tzinfo-data (1.2024.2) + tzinfo-data (1.2025.1) tzinfo (>= 1.0.0) unf (0.1.4) unf_ext unf_ext (0.0.9.1) - unicode-display_width (2.6.0) + unicode-display_width (3.1.4) + unicode-emoji (~> 4.0, >= 4.0.4) + unicode-emoji (4.0.4) uri (1.0.2) useragent (0.16.11) validate_email (0.1.6) @@ -848,18 +864,18 @@ GEM public_suffix warden (1.2.9) rack (>= 2.0.9) - webauthn (3.2.2) + webauthn (3.4.0) android_key_attestation (~> 0.3.0) bindata (~> 2.4) cbor (~> 0.5.9) cose (~> 1.1) openssl (>= 2.2) safety_net_attestation (~> 0.4.0) - tpm-key_attestation (~> 0.12.0) + tpm-key_attestation (~> 0.14.0) webfinger (1.2.0) activesupport httpclient (>= 2.4) - webmock (3.24.0) + webmock (3.25.0) addressable (>= 2.8.0) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) @@ -870,14 +886,15 @@ GEM semantic_range (>= 2.3.0) webrick (1.9.1) websocket (1.2.11) - websocket-driver (0.7.6) + websocket-driver (0.7.7) + base64 websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) wisper (2.0.1) xorcist (1.1.3) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.7.1) + zeitwerk (2.7.2) PLATFORMS ruby @@ -959,25 +976,26 @@ DEPENDENCIES omniauth_openid_connect (~> 0.6.1) opentelemetry-api (~> 1.4.0) opentelemetry-exporter-otlp (~> 0.29.0) - opentelemetry-instrumentation-active_job (~> 0.7.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.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.25.0) - opentelemetry-instrumentation-rails (~> 0.34.0) - opentelemetry-instrumentation-redis (~> 0.25.3) - opentelemetry-instrumentation-sidekiq (~> 0.25.2) + opentelemetry-instrumentation-active_job (~> 0.8.0) + opentelemetry-instrumentation-active_model_serializers (~> 0.22.0) + opentelemetry-instrumentation-concurrent_ruby (~> 0.22.0) + opentelemetry-instrumentation-excon (~> 0.23.0) + opentelemetry-instrumentation-faraday (~> 0.26.0) + opentelemetry-instrumentation-http (~> 0.24.0) + opentelemetry-instrumentation-http_client (~> 0.23.0) + opentelemetry-instrumentation-net_http (~> 0.23.0) + opentelemetry-instrumentation-pg (~> 0.30.0) + opentelemetry-instrumentation-rack (~> 0.26.0) + opentelemetry-instrumentation-rails (~> 0.36.0) + opentelemetry-instrumentation-redis (~> 0.26.0) + opentelemetry-instrumentation-sidekiq (~> 0.26.0) opentelemetry-sdk (~> 1.4) ox (~> 2.14) parslet pg (~> 1.5) pghero premailer-rails + prometheus_exporter (~> 2.2) propshaft public_suffix (~> 6.0) puma (~> 6.3) @@ -987,14 +1005,13 @@ DEPENDENCIES rack-cors (~> 2.0) rack-test (~> 2.1) rails (~> 8.0) - rails-controller-testing (~> 1.0) rails-i18n (~> 8.0) rdf-normalize (~> 0.5) redcarpet (~> 3.6) redis (~> 4.5) redis-namespace (~> 1.10) rqrcode (~> 2.2) - rspec-github (~> 2.4) + rspec-github (~> 3.0) rspec-rails (~> 7.0) rspec-sidekiq (~> 5.0) rubocop @@ -1037,4 +1054,4 @@ RUBY VERSION ruby 3.4.1p0 BUNDLED WITH - 2.6.2 + 2.6.5 diff --git a/app/controllers/activitypub/collections_controller.rb b/app/controllers/activitypub/collections_controller.rb index ab1b98e64..c80db3500 100644 --- a/app/controllers/activitypub/collections_controller.rb +++ b/app/controllers/activitypub/collections_controller.rb @@ -49,7 +49,7 @@ class ActivityPub::CollectionsController < ActivityPub::BaseController def collection_presenter ActivityPub::CollectionPresenter.new( - id: account_collection_url(@account, params[:id]), + id: ActivityPub::TagManager.instance.collection_uri_for(@account, params[:id]), type: @type, size: @size, items: @items diff --git a/app/controllers/activitypub/outboxes_controller.rb b/app/controllers/activitypub/outboxes_controller.rb index 0c995edbf..a9476b806 100644 --- a/app/controllers/activitypub/outboxes_controller.rb +++ b/app/controllers/activitypub/outboxes_controller.rb @@ -41,12 +41,8 @@ class ActivityPub::OutboxesController < ActivityPub::BaseController end end - def outbox_url(**) - if params[:account_username].present? - account_outbox_url(@account, **) - else - instance_actor_outbox_url(**) - end + def outbox_url(...) + ActivityPub::TagManager.instance.outbox_uri_for(@account, ...) end def next_page diff --git a/app/controllers/admin/account_actions_controller.rb b/app/controllers/admin/account_actions_controller.rb index e674bf55a..91849811e 100644 --- a/app/controllers/admin/account_actions_controller.rb +++ b/app/controllers/admin/account_actions_controller.rb @@ -34,7 +34,8 @@ module Admin end def resource_params - params.require(:admin_account_action).permit(:type, :report_id, :warning_preset_id, :text, :send_email_notification, :include_statuses) + params + .expect(admin_account_action: [:type, :report_id, :warning_preset_id, :text, :send_email_notification, :include_statuses]) end end end diff --git a/app/controllers/admin/account_moderation_notes_controller.rb b/app/controllers/admin/account_moderation_notes_controller.rb index a3c4adf59..7f65ced51 100644 --- a/app/controllers/admin/account_moderation_notes_controller.rb +++ b/app/controllers/admin/account_moderation_notes_controller.rb @@ -29,10 +29,8 @@ module Admin private def resource_params - params.require(:account_moderation_note).permit( - :content, - :target_account_id - ) + params + .expect(account_moderation_note: [:content, :target_account_id]) end def set_account_moderation_note diff --git a/app/controllers/admin/accounts_controller.rb b/app/controllers/admin/accounts_controller.rb index 7b169ba26..10391aa3e 100644 --- a/app/controllers/admin/accounts_controller.rb +++ b/app/controllers/admin/accounts_controller.rb @@ -158,7 +158,8 @@ module Admin end def form_account_batch_params - params.require(:form_account_batch).permit(:action, account_ids: []) + params + .expect(form_account_batch: [:action, account_ids: []]) end def action_from_button diff --git a/app/controllers/admin/announcements_controller.rb b/app/controllers/admin/announcements_controller.rb index 12230a650..eaf84aab2 100644 --- a/app/controllers/admin/announcements_controller.rb +++ b/app/controllers/admin/announcements_controller.rb @@ -84,6 +84,7 @@ class Admin::AnnouncementsController < Admin::BaseController end def resource_params - params.require(:announcement).permit(:text, :scheduled_at, :starts_at, :ends_at, :all_day) + params + .expect(announcement: [:text, :scheduled_at, :starts_at, :ends_at, :all_day]) end end diff --git a/app/controllers/admin/base_controller.rb b/app/controllers/admin/base_controller.rb index 3dca3a961..14338dd29 100644 --- a/app/controllers/admin/base_controller.rb +++ b/app/controllers/admin/base_controller.rb @@ -7,17 +7,12 @@ module Admin layout 'admin' - before_action :set_cache_headers before_action :set_referrer_policy_header after_action :verify_authorized private - def set_cache_headers - response.cache_control.replace(private: true, no_store: true) - end - def set_referrer_policy_header response.headers['Referrer-Policy'] = 'same-origin' end diff --git a/app/controllers/admin/change_emails_controller.rb b/app/controllers/admin/change_emails_controller.rb index a689d3a53..c923b94b1 100644 --- a/app/controllers/admin/change_emails_controller.rb +++ b/app/controllers/admin/change_emails_controller.rb @@ -41,9 +41,8 @@ module Admin end def resource_params - params.require(:user).permit( - :unconfirmed_email - ) + params + .expect(user: [:unconfirmed_email]) end end end diff --git a/app/controllers/admin/custom_emojis_controller.rb b/app/controllers/admin/custom_emojis_controller.rb index 00d069cdf..e3da834fc 100644 --- a/app/controllers/admin/custom_emojis_controller.rb +++ b/app/controllers/admin/custom_emojis_controller.rb @@ -44,7 +44,8 @@ module Admin private def resource_params - params.require(:custom_emoji).permit(:shortcode, :image, :visible_in_picker) + params + .expect(custom_emoji: [:shortcode, :image, :visible_in_picker]) end def filtered_custom_emojis @@ -74,7 +75,8 @@ module Admin end def form_custom_emoji_batch_params - params.require(:form_custom_emoji_batch).permit(:action, :category_id, :category_name, custom_emoji_ids: []) + params + .expect(form_custom_emoji_batch: [:action, :category_id, :category_name, custom_emoji_ids: []]) end end end diff --git a/app/controllers/admin/domain_allows_controller.rb b/app/controllers/admin/domain_allows_controller.rb index b0f139e3a..913c1a824 100644 --- a/app/controllers/admin/domain_allows_controller.rb +++ b/app/controllers/admin/domain_allows_controller.rb @@ -37,6 +37,7 @@ class Admin::DomainAllowsController < Admin::BaseController end def resource_params - params.require(:domain_allow).permit(:domain) + params + .expect(domain_allow: [:domain]) end end diff --git a/app/controllers/admin/domain_blocks_controller.rb b/app/controllers/admin/domain_blocks_controller.rb index 16a8cb9ee..c3443b707 100644 --- a/app/controllers/admin/domain_blocks_controller.rb +++ b/app/controllers/admin/domain_blocks_controller.rb @@ -25,7 +25,9 @@ module Admin rescue Mastodon::NotPermittedError flash[:alert] = I18n.t('admin.domain_blocks.not_permitted') else - redirect_to admin_instances_path(limited: '1'), notice: I18n.t('admin.domain_blocks.created_msg') + flash[:notice] = I18n.t('admin.domain_blocks.created_msg') + ensure + redirect_to admin_instances_path(limited: '1') end def new @@ -114,7 +116,12 @@ module Admin end def form_domain_block_batch_params - params.require(:form_domain_block_batch).permit(domain_blocks_attributes: [:enabled, :domain, :severity, :reject_media, :reject_reports, :private_comment, :public_comment, :obfuscate]) + params + .expect( + form_domain_block_batch: [ + domain_blocks_attributes: [[:enabled, :domain, :severity, :reject_media, :reject_reports, :private_comment, :public_comment, :obfuscate]], + ] + ) end def action_from_button diff --git a/app/controllers/admin/email_domain_blocks_controller.rb b/app/controllers/admin/email_domain_blocks_controller.rb index 9501ebd63..12f221164 100644 --- a/app/controllers/admin/email_domain_blocks_controller.rb +++ b/app/controllers/admin/email_domain_blocks_controller.rb @@ -62,11 +62,13 @@ module Admin end def resource_params - params.require(:email_domain_block).permit(:domain, :allow_with_approval, other_domains: []) + params + .expect(email_domain_block: [:domain, :allow_with_approval, other_domains: []]) end def form_email_domain_block_batch_params - params.require(:form_email_domain_block_batch).permit(email_domain_block_ids: []) + params + .expect(form_email_domain_block_batch: [email_domain_block_ids: []]) end def action_from_button diff --git a/app/controllers/admin/follow_recommendations_controller.rb b/app/controllers/admin/follow_recommendations_controller.rb index a54e41bd8..b060cfbe9 100644 --- a/app/controllers/admin/follow_recommendations_controller.rb +++ b/app/controllers/admin/follow_recommendations_controller.rb @@ -37,7 +37,8 @@ module Admin end def form_account_batch_params - params.require(:form_account_batch).permit(:action, account_ids: []) + params + .expect(form_account_batch: [:action, account_ids: []]) end def filter_params diff --git a/app/controllers/admin/invites_controller.rb b/app/controllers/admin/invites_controller.rb index 614e2a32d..ac4ee3527 100644 --- a/app/controllers/admin/invites_controller.rb +++ b/app/controllers/admin/invites_controller.rb @@ -39,7 +39,8 @@ module Admin private def resource_params - params.require(:invite).permit(:max_uses, :expires_in) + params + .expect(invite: [:max_uses, :expires_in]) end def filtered_invites diff --git a/app/controllers/admin/ip_blocks_controller.rb b/app/controllers/admin/ip_blocks_controller.rb index 1bd7ec805..afabda1b8 100644 --- a/app/controllers/admin/ip_blocks_controller.rb +++ b/app/controllers/admin/ip_blocks_controller.rb @@ -44,7 +44,8 @@ module Admin private def resource_params - params.require(:ip_block).permit(:ip, :severity, :comment, :expires_in) + params + .expect(ip_block: [:ip, :severity, :comment, :expires_in]) end def action_from_button @@ -52,7 +53,8 @@ module Admin end def form_ip_block_batch_params - params.require(:form_ip_block_batch).permit(ip_block_ids: []) + params + .expect(form_ip_block_batch: [ip_block_ids: []]) end end end diff --git a/app/controllers/admin/relays_controller.rb b/app/controllers/admin/relays_controller.rb index f05255adb..9a796949d 100644 --- a/app/controllers/admin/relays_controller.rb +++ b/app/controllers/admin/relays_controller.rb @@ -57,7 +57,8 @@ module Admin end def resource_params - params.require(:relay).permit(:inbox_url) + params + .expect(relay: [:inbox_url]) end def warn_signatures_not_enabled! diff --git a/app/controllers/admin/report_notes_controller.rb b/app/controllers/admin/report_notes_controller.rb index 6b16c29fc..10dbe846e 100644 --- a/app/controllers/admin/report_notes_controller.rb +++ b/app/controllers/admin/report_notes_controller.rb @@ -47,10 +47,8 @@ module Admin end def resource_params - params.require(:report_note).permit( - :content, - :report_id - ) + params + .expect(report_note: [:content, :report_id]) end def set_report_note diff --git a/app/controllers/admin/roles_controller.rb b/app/controllers/admin/roles_controller.rb index bcfc11159..2f9af8a6f 100644 --- a/app/controllers/admin/roles_controller.rb +++ b/app/controllers/admin/roles_controller.rb @@ -61,7 +61,8 @@ module Admin end def resource_params - params.require(:user_role).permit(:name, :color, :highlighted, :position, permissions_as_keys: []) + params + .expect(user_role: [:name, :color, :highlighted, :position, permissions_as_keys: []]) end end end diff --git a/app/controllers/admin/rules_controller.rb b/app/controllers/admin/rules_controller.rb index b8def22ba..289b6a98c 100644 --- a/app/controllers/admin/rules_controller.rb +++ b/app/controllers/admin/rules_controller.rb @@ -53,7 +53,8 @@ module Admin end def resource_params - params.require(:rule).permit(:text, :hint, :priority) + params + .expect(rule: [:text, :hint, :priority]) end end end diff --git a/app/controllers/admin/settings_controller.rb b/app/controllers/admin/settings_controller.rb index 338a3638c..2ae5ec825 100644 --- a/app/controllers/admin/settings_controller.rb +++ b/app/controllers/admin/settings_controller.rb @@ -28,7 +28,8 @@ module Admin end def settings_params - params.require(:form_admin_settings).permit(*Form::AdminSettings::KEYS) + params + .expect(form_admin_settings: [*Form::AdminSettings::KEYS]) end end end diff --git a/app/controllers/admin/software_updates_controller.rb b/app/controllers/admin/software_updates_controller.rb index d7b114a10..c9be97eb7 100644 --- a/app/controllers/admin/software_updates_controller.rb +++ b/app/controllers/admin/software_updates_controller.rb @@ -6,7 +6,7 @@ module Admin def index authorize :software_update, :index? - @software_updates = SoftwareUpdate.by_version + @software_updates = SoftwareUpdate.by_version.filter(&:pending?) end private diff --git a/app/controllers/admin/statuses_controller.rb b/app/controllers/admin/statuses_controller.rb index 40d1a481b..aeadb35e7 100644 --- a/app/controllers/admin/statuses_controller.rb +++ b/app/controllers/admin/statuses_controller.rb @@ -39,7 +39,8 @@ module Admin helper_method :batched_ordered_status_edits def admin_status_batch_action_params - params.require(:admin_status_batch_action).permit(status_ids: []) + params + .expect(admin_status_batch_action: [status_ids: []]) end def after_create_redirect_path diff --git a/app/controllers/admin/tags_controller.rb b/app/controllers/admin/tags_controller.rb index 4759d15bc..a7bfd6479 100644 --- a/app/controllers/admin/tags_controller.rb +++ b/app/controllers/admin/tags_controller.rb @@ -37,7 +37,8 @@ module Admin end def tag_params - params.require(:tag).permit(:name, :display_name, :trendable, :usable, :listable) + params + .expect(tag: [:name, :display_name, :trendable, :usable, :listable]) end def filtered_tags diff --git a/app/controllers/admin/terms_of_service/drafts_controller.rb b/app/controllers/admin/terms_of_service/drafts_controller.rb index 5d32c0bd8..02cb05946 100644 --- a/app/controllers/admin/terms_of_service/drafts_controller.rb +++ b/app/controllers/admin/terms_of_service/drafts_controller.rb @@ -31,6 +31,7 @@ class Admin::TermsOfService::DraftsController < Admin::BaseController end def resource_params - params.require(:terms_of_service).permit(:text, :changelog) + params + .expect(terms_of_service: [:text, :changelog]) end end diff --git a/app/controllers/admin/terms_of_service/generates_controller.rb b/app/controllers/admin/terms_of_service/generates_controller.rb index 28037674a..0edc87893 100644 --- a/app/controllers/admin/terms_of_service/generates_controller.rb +++ b/app/controllers/admin/terms_of_service/generates_controller.rb @@ -32,6 +32,7 @@ class Admin::TermsOfService::GeneratesController < Admin::BaseController end def resource_params - params.require(:terms_of_service_generator).permit(*TermsOfService::Generator::VARIABLES) + params + .expect(terms_of_service_generator: [*TermsOfService::Generator::VARIABLES]) end end diff --git a/app/controllers/admin/trends/links/preview_card_providers_controller.rb b/app/controllers/admin/trends/links/preview_card_providers_controller.rb index 5e4b4084f..5a650d5d8 100644 --- a/app/controllers/admin/trends/links/preview_card_providers_controller.rb +++ b/app/controllers/admin/trends/links/preview_card_providers_controller.rb @@ -31,7 +31,8 @@ class Admin::Trends::Links::PreviewCardProvidersController < Admin::BaseControll end def trends_preview_card_provider_batch_params - params.require(:trends_preview_card_provider_batch).permit(:action, preview_card_provider_ids: []) + params + .expect(trends_preview_card_provider_batch: [:action, preview_card_provider_ids: []]) end def action_from_button diff --git a/app/controllers/admin/trends/links_controller.rb b/app/controllers/admin/trends/links_controller.rb index 65eca11c7..68aa73c99 100644 --- a/app/controllers/admin/trends/links_controller.rb +++ b/app/controllers/admin/trends/links_controller.rb @@ -31,7 +31,8 @@ class Admin::Trends::LinksController < Admin::BaseController end def trends_preview_card_batch_params - params.require(:trends_preview_card_batch).permit(:action, preview_card_ids: []) + params + .expect(trends_preview_card_batch: [:action, preview_card_ids: []]) end def action_from_button diff --git a/app/controllers/admin/trends/statuses_controller.rb b/app/controllers/admin/trends/statuses_controller.rb index 682fe70bb..873d777fe 100644 --- a/app/controllers/admin/trends/statuses_controller.rb +++ b/app/controllers/admin/trends/statuses_controller.rb @@ -31,7 +31,8 @@ class Admin::Trends::StatusesController < Admin::BaseController end def trends_status_batch_params - params.require(:trends_status_batch).permit(:action, status_ids: []) + params + .expect(trends_status_batch: [:action, status_ids: []]) end def action_from_button diff --git a/app/controllers/admin/trends/tags_controller.rb b/app/controllers/admin/trends/tags_controller.rb index fcd23fbf6..1ccd74068 100644 --- a/app/controllers/admin/trends/tags_controller.rb +++ b/app/controllers/admin/trends/tags_controller.rb @@ -31,7 +31,8 @@ class Admin::Trends::TagsController < Admin::BaseController end def trends_tag_batch_params - params.require(:trends_tag_batch).permit(:action, tag_ids: []) + params + .expect(trends_tag_batch: [:action, tag_ids: []]) end def action_from_button diff --git a/app/controllers/admin/users/roles_controller.rb b/app/controllers/admin/users/roles_controller.rb index f5dfc643d..e8b58de50 100644 --- a/app/controllers/admin/users/roles_controller.rb +++ b/app/controllers/admin/users/roles_controller.rb @@ -28,7 +28,8 @@ module Admin end def resource_params - params.require(:user).permit(:role_id) + params + .expect(user: [:role_id]) end end end diff --git a/app/controllers/admin/warning_presets_controller.rb b/app/controllers/admin/warning_presets_controller.rb index efbf65b11..dcf88294e 100644 --- a/app/controllers/admin/warning_presets_controller.rb +++ b/app/controllers/admin/warning_presets_controller.rb @@ -52,7 +52,8 @@ module Admin end def warning_preset_params - params.require(:account_warning_preset).permit(:title, :text) + params + .expect(account_warning_preset: [:title, :text]) end end end diff --git a/app/controllers/admin/webhooks_controller.rb b/app/controllers/admin/webhooks_controller.rb index f1aad7c4b..31db36963 100644 --- a/app/controllers/admin/webhooks_controller.rb +++ b/app/controllers/admin/webhooks_controller.rb @@ -74,7 +74,8 @@ module Admin end def resource_params - params.require(:webhook).permit(:url, :template, events: []) + params + .expect(webhook: [:url, :template, events: []]) end end end diff --git a/app/controllers/api/v1/accounts/credentials_controller.rb b/app/controllers/api/v1/accounts/credentials_controller.rb index a37842518..1b64eb4ef 100644 --- a/app/controllers/api/v1/accounts/credentials_controller.rb +++ b/app/controllers/api/v1/accounts/credentials_controller.rb @@ -33,6 +33,7 @@ class Api::V1::Accounts::CredentialsController < Api::BaseController :discoverable, :hide_collections, :indexable, + attribution_domains: [], fields_attributes: [:name, :value] ) end diff --git a/app/controllers/api/v1/push/subscriptions_controller.rb b/app/controllers/api/v1/push/subscriptions_controller.rb index e1ad89ee3..f2c52f284 100644 --- a/app/controllers/api/v1/push/subscriptions_controller.rb +++ b/app/controllers/api/v1/push/subscriptions_controller.rb @@ -21,6 +21,7 @@ class Api::V1::Push::SubscriptionsController < Api::BaseController endpoint: subscription_params[:endpoint], key_p256dh: subscription_params[:keys][:p256dh], key_auth: subscription_params[:keys][:auth], + standard: subscription_params[:standard] || false, data: data_params, user_id: current_user.id, access_token_id: doorkeeper_token.id @@ -55,12 +56,12 @@ class Api::V1::Push::SubscriptionsController < Api::BaseController end def subscription_params - params.require(:subscription).permit(:endpoint, keys: [:auth, :p256dh]) + params.expect(subscription: [:endpoint, :standard, keys: [:auth, :p256dh]]) end def data_params return {} if params[:data].blank? - params.require(:data).permit(:policy, alerts: Notification::TYPES) + params.expect(data: [:policy, alerts: Notification::TYPES]) end end diff --git a/app/controllers/api/web/push_subscriptions_controller.rb b/app/controllers/api/web/push_subscriptions_controller.rb index f51596142..2711071b4 100644 --- a/app/controllers/api/web/push_subscriptions_controller.rb +++ b/app/controllers/api/web/push_subscriptions_controller.rb @@ -66,7 +66,7 @@ class Api::Web::PushSubscriptionsController < Api::Web::BaseController end def subscription_params - @subscription_params ||= params.require(:subscription).permit(:endpoint, keys: [:auth, :p256dh]) + @subscription_params ||= params.expect(subscription: [:standard, :endpoint, keys: [:auth, :p256dh]]) end def web_push_subscription_params @@ -76,11 +76,12 @@ class Api::Web::PushSubscriptionsController < Api::Web::BaseController endpoint: subscription_params[:endpoint], key_auth: subscription_params[:keys][:auth], key_p256dh: subscription_params[:keys][:p256dh], + standard: subscription_params[:standard] || false, user_id: active_session.user_id, } end def data_params - @data_params ||= params.require(:data).permit(:policy, alerts: Notification::TYPES) + @data_params ||= params.expect(data: [:policy, alerts: Notification::TYPES]) end end diff --git a/app/controllers/auth/registrations_controller.rb b/app/controllers/auth/registrations_controller.rb index 34c759955..6e34b6b62 100644 --- a/app/controllers/auth/registrations_controller.rb +++ b/app/controllers/auth/registrations_controller.rb @@ -12,7 +12,6 @@ class Auth::RegistrationsController < Devise::RegistrationsController before_action :set_sessions, only: [:edit, :update] before_action :set_strikes, only: [:edit, :update] before_action :require_not_suspended!, only: [:update] - before_action :set_cache_headers, only: [:edit, :update] before_action :set_rules, only: :new before_action :require_rules_acceptance!, only: :new before_action :set_registration_form_time, only: :new @@ -139,10 +138,6 @@ class Auth::RegistrationsController < Devise::RegistrationsController set_locale { render :rules } end - 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 diff --git a/app/controllers/auth/sessions_controller.rb b/app/controllers/auth/sessions_controller.rb index ecac4c5ba..250573fc7 100644 --- a/app/controllers/auth/sessions_controller.rb +++ b/app/controllers/auth/sessions_controller.rb @@ -73,7 +73,7 @@ class Auth::SessionsController < Devise::SessionsController end def user_params - params.require(:user).permit(:email, :password, :otp_attempt, credential: {}) + params.expect(user: [:email, :password, :otp_attempt, credential: {}]) end def after_sign_in_path_for(resource) diff --git a/app/controllers/auth/setup_controller.rb b/app/controllers/auth/setup_controller.rb index ad872dc60..5e7b14646 100644 --- a/app/controllers/auth/setup_controller.rb +++ b/app/controllers/auth/setup_controller.rb @@ -18,7 +18,7 @@ class Auth::SetupController < ApplicationController if @user.update(user_params) @user.resend_confirmation_instructions unless @user.confirmed? - redirect_to auth_setup_path, notice: I18n.t('auth.setup.new_confirmation_instructions_sent') + redirect_to auth_setup_path, notice: t('auth.setup.new_confirmation_instructions_sent') else render :show end @@ -35,6 +35,6 @@ class Auth::SetupController < ApplicationController end def user_params - params.require(:user).permit(:email) + params.expect(user: [:email]) end end diff --git a/app/controllers/concerns/admin/export_controller_concern.rb b/app/controllers/concerns/admin/export_controller_concern.rb index 6228ae67f..ce03b2a24 100644 --- a/app/controllers/concerns/admin/export_controller_concern.rb +++ b/app/controllers/concerns/admin/export_controller_concern.rb @@ -24,6 +24,6 @@ module Admin::ExportControllerConcern end def import_params - params.require(:admin_import).permit(:data) + params.expect(admin_import: [:data]) end end diff --git a/app/controllers/concerns/challengable_concern.rb b/app/controllers/concerns/challengable_concern.rb index c8d1a0bef..7fbc469bd 100644 --- a/app/controllers/concerns/challengable_concern.rb +++ b/app/controllers/concerns/challengable_concern.rb @@ -58,6 +58,6 @@ module ChallengableConcern end def challenge_params - params.require(:form_challenge).permit(:current_password, :return_to) + params.expect(form_challenge: [:current_password, :return_to]) end end diff --git a/app/controllers/concerns/signature_verification.rb b/app/controllers/concerns/signature_verification.rb index 4ae63632c..5f7ef8dd6 100644 --- a/app/controllers/concerns/signature_verification.rb +++ b/app/controllers/concerns/signature_verification.rb @@ -117,7 +117,7 @@ module SignatureVerification def verify_signature_strength! raise SignatureVerificationError, 'Mastodon requires the Date header or (created) pseudo-header to be signed' unless signed_headers.include?('date') || signed_headers.include?('(created)') - raise SignatureVerificationError, 'Mastodon requires the Digest header or (request-target) pseudo-header to be signed' unless signed_headers.include?(Request::REQUEST_TARGET) || signed_headers.include?('digest') + raise SignatureVerificationError, 'Mastodon requires the Digest header or (request-target) pseudo-header to be signed' unless signed_headers.include?(HttpSignatureDraft::REQUEST_TARGET) || signed_headers.include?('digest') raise SignatureVerificationError, 'Mastodon requires the Host header to be signed when doing a GET request' if request.get? && !signed_headers.include?('host') raise SignatureVerificationError, 'Mastodon requires the Digest header to be signed when doing a POST request' if request.post? && !signed_headers.include?('digest') end @@ -155,14 +155,14 @@ module SignatureVerification def build_signed_string(include_query_string: true) signed_headers.map do |signed_header| case signed_header - when Request::REQUEST_TARGET + when HttpSignatureDraft::REQUEST_TARGET if include_query_string - "#{Request::REQUEST_TARGET}: #{request.method.downcase} #{request.original_fullpath}" + "#{HttpSignatureDraft::REQUEST_TARGET}: #{request.method.downcase} #{request.original_fullpath}" else # Current versions of Mastodon incorrectly omit the query string from the (request-target) pseudo-header. # Therefore, temporarily support such incorrect signatures for compatibility. # TODO: remove eventually some time after release of the fixed version - "#{Request::REQUEST_TARGET}: #{request.method.downcase} #{request.path}" + "#{HttpSignatureDraft::REQUEST_TARGET}: #{request.method.downcase} #{request.path}" end when '(created)' raise SignatureVerificationError, 'Invalid pseudo-header (created) for rsa-sha256' unless signature_algorithm == 'hs2019' diff --git a/app/controllers/concerns/web_app_controller_concern.rb b/app/controllers/concerns/web_app_controller_concern.rb index 1d8ee4350..ec2256aa9 100644 --- a/app/controllers/concerns/web_app_controller_concern.rb +++ b/app/controllers/concerns/web_app_controller_concern.rb @@ -46,6 +46,6 @@ module WebAppControllerConcern protected def set_referer_header - response.set_header('Referrer-Policy', Setting.allow_referrer_origin ? 'origin' : 'same-origin') + response.set_header('Referrer-Policy', Setting.allow_referrer_origin ? 'strict-origin-when-cross-origin' : 'same-origin') end end diff --git a/app/controllers/disputes/appeals_controller.rb b/app/controllers/disputes/appeals_controller.rb index 98b58d211..797f31cf7 100644 --- a/app/controllers/disputes/appeals_controller.rb +++ b/app/controllers/disputes/appeals_controller.rb @@ -21,6 +21,6 @@ class Disputes::AppealsController < Disputes::BaseController end def appeal_params - params.require(:appeal).permit(:text) + params.expect(appeal: [:text]) end end diff --git a/app/controllers/disputes/base_controller.rb b/app/controllers/disputes/base_controller.rb index dd24a1b74..07677fd3f 100644 --- a/app/controllers/disputes/base_controller.rb +++ b/app/controllers/disputes/base_controller.rb @@ -8,11 +8,4 @@ class Disputes::BaseController < ApplicationController skip_before_action :require_functional! before_action :authenticate_user! - before_action :set_cache_headers - - private - - def set_cache_headers - response.cache_control.replace(private: true, no_store: true) - end end diff --git a/app/controllers/filters/statuses_controller.rb b/app/controllers/filters/statuses_controller.rb index 7ada13f68..d85b017aa 100644 --- a/app/controllers/filters/statuses_controller.rb +++ b/app/controllers/filters/statuses_controller.rb @@ -6,7 +6,6 @@ class Filters::StatusesController < ApplicationController before_action :authenticate_user! before_action :set_filter before_action :set_status_filters - before_action :set_cache_headers PER_PAGE = 20 @@ -34,14 +33,10 @@ class Filters::StatusesController < ApplicationController end def status_filter_batch_action_params - params.require(:form_status_filter_batch_action).permit(status_filter_ids: []) + params.expect(form_status_filter_batch_action: [status_filter_ids: []]) end def action_from_button 'remove' if params[:remove] end - - def set_cache_headers - response.cache_control.replace(private: true, no_store: true) - end end diff --git a/app/controllers/filters_controller.rb b/app/controllers/filters_controller.rb index 8c4e867e9..769aea2af 100644 --- a/app/controllers/filters_controller.rb +++ b/app/controllers/filters_controller.rb @@ -5,7 +5,6 @@ class FiltersController < ApplicationController before_action :authenticate_user! before_action :set_filter, only: [:edit, :update, :destroy] - before_action :set_cache_headers def index @filters = current_account.custom_filters.includes(:keywords, :statuses).order(:phrase) @@ -48,10 +47,6 @@ class FiltersController < ApplicationController end def resource_params - params.require(:custom_filter).permit(:title, :expires_in, :filter_action, context: [], keywords_attributes: [:id, :keyword, :whole_word, :_destroy]) - end - - def set_cache_headers - response.cache_control.replace(private: true, no_store: true) + params.expect(custom_filter: [:title, :expires_in, :filter_action, context: [], keywords_attributes: [[:id, :keyword, :whole_word, :_destroy]]]) end end diff --git a/app/controllers/follower_accounts_controller.rb b/app/controllers/follower_accounts_controller.rb index 5effd9495..f4c7b3708 100644 --- a/app/controllers/follower_accounts_controller.rb +++ b/app/controllers/follower_accounts_controller.rb @@ -46,7 +46,7 @@ class FollowerAccountsController < ApplicationController end def page_url(page) - account_followers_url(@account, page: page) unless page.nil? + ActivityPub::TagManager.instance.followers_uri_for(@account, page: page) unless page.nil? end def next_page_url diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb index 070852695..fc65333ac 100644 --- a/app/controllers/invites_controller.rb +++ b/app/controllers/invites_controller.rb @@ -6,7 +6,6 @@ class InvitesController < ApplicationController layout 'admin' before_action :authenticate_user! - before_action :set_cache_headers def index authorize :invite, :create? @@ -43,10 +42,6 @@ class InvitesController < ApplicationController end def resource_params - params.require(:invite).permit(:max_uses, :expires_in, :autofollow, :comment) - end - - def set_cache_headers - response.cache_control.replace(private: true, no_store: true) + params.expect(invite: [:max_uses, :expires_in, :autofollow, :comment]) end end diff --git a/app/controllers/oauth/authorizations_controller.rb b/app/controllers/oauth/authorizations_controller.rb index 66e774425..deafedeae 100644 --- a/app/controllers/oauth/authorizations_controller.rb +++ b/app/controllers/oauth/authorizations_controller.rb @@ -5,7 +5,6 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController before_action :store_current_location before_action :authenticate_resource_owner! - before_action :set_cache_headers content_security_policy do |p| p.form_action(false) @@ -32,8 +31,4 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController def truthy_param?(key) ActiveModel::Type::Boolean.new.cast(params[key]) end - - def set_cache_headers - response.cache_control.replace(private: true, no_store: true) - end end diff --git a/app/controllers/oauth/authorized_applications_controller.rb b/app/controllers/oauth/authorized_applications_controller.rb index 9e541e5e3..8b11a519e 100644 --- a/app/controllers/oauth/authorized_applications_controller.rb +++ b/app/controllers/oauth/authorized_applications_controller.rb @@ -6,7 +6,6 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio before_action :store_current_location before_action :authenticate_resource_owner! before_action :require_not_suspended!, only: :destroy - before_action :set_cache_headers before_action :set_last_used_at_by_app, only: :index, unless: -> { request.format == :json } @@ -30,10 +29,6 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio forbidden if current_account.unavailable? end - def set_cache_headers - response.cache_control.replace(private: true, no_store: true) - end - def set_last_used_at_by_app @last_used_at_by_app = current_resource_owner.applications_last_used end diff --git a/app/controllers/relationships_controller.rb b/app/controllers/relationships_controller.rb index d351afcfb..7e793fc73 100644 --- a/app/controllers/relationships_controller.rb +++ b/app/controllers/relationships_controller.rb @@ -6,7 +6,6 @@ class RelationshipsController < ApplicationController before_action :authenticate_user! before_action :set_accounts, only: :show before_action :set_relationships, only: :show - before_action :set_cache_headers helper_method :following_relationship?, :followed_by_relationship?, :mutual_relationship? @@ -36,7 +35,7 @@ class RelationshipsController < ApplicationController end def form_account_batch_params - params.require(:form_account_batch).permit(:action, account_ids: []) + params.expect(form_account_batch: [:action, account_ids: []]) end def following_relationship? @@ -66,8 +65,4 @@ class RelationshipsController < ApplicationController 'remove_domains_from_followers' end end - - def set_cache_headers - response.cache_control.replace(private: true, no_store: true) - end end diff --git a/app/controllers/settings/aliases_controller.rb b/app/controllers/settings/aliases_controller.rb index a421b8ede..c21d43eeb 100644 --- a/app/controllers/settings/aliases_controller.rb +++ b/app/controllers/settings/aliases_controller.rb @@ -30,7 +30,7 @@ class Settings::AliasesController < Settings::BaseController private def resource_params - params.require(:account_alias).permit(:acct) + params.expect(account_alias: [:acct]) end def set_alias diff --git a/app/controllers/settings/applications_controller.rb b/app/controllers/settings/applications_controller.rb index d6573f9b4..8e39741f8 100644 --- a/app/controllers/settings/applications_controller.rb +++ b/app/controllers/settings/applications_controller.rb @@ -2,7 +2,6 @@ class Settings::ApplicationsController < Settings::BaseController before_action :set_application, only: [:show, :update, :destroy, :regenerate] - before_action :prepare_scopes, only: [:create, :update] def index @applications = current_user.applications.order(id: :desc).page(params[:page]) @@ -60,16 +59,6 @@ class Settings::ApplicationsController < Settings::BaseController end def application_params - params.require(:doorkeeper_application).permit( - :name, - :redirect_uri, - :scopes, - :website - ) - end - - def prepare_scopes - scopes = params.fetch(:doorkeeper_application, {}).fetch(:scopes, nil) - params[:doorkeeper_application][:scopes] = scopes.join(' ') if scopes.is_a? Array + params.expect(doorkeeper_application: [:name, :redirect_uri, :website, scopes: []]) end end diff --git a/app/controllers/settings/base_controller.rb b/app/controllers/settings/base_controller.rb index 188334ac2..7f2279aa8 100644 --- a/app/controllers/settings/base_controller.rb +++ b/app/controllers/settings/base_controller.rb @@ -4,14 +4,9 @@ class Settings::BaseController < ApplicationController layout 'admin' before_action :authenticate_user! - before_action :set_cache_headers private - def set_cache_headers - response.cache_control.replace(private: true, no_store: true) - end - def require_not_suspended! forbidden if current_account.unavailable? end diff --git a/app/controllers/settings/deletes_controller.rb b/app/controllers/settings/deletes_controller.rb index 16c201b6b..815d95ad8 100644 --- a/app/controllers/settings/deletes_controller.rb +++ b/app/controllers/settings/deletes_controller.rb @@ -21,7 +21,7 @@ class Settings::DeletesController < Settings::BaseController private def resource_params - params.require(:form_delete_confirmation).permit(:password, :username) + params.expect(form_delete_confirmation: [:password, :username]) end def require_not_suspended! diff --git a/app/controllers/settings/featured_tags_controller.rb b/app/controllers/settings/featured_tags_controller.rb index 7e29dd1d2..0f352e191 100644 --- a/app/controllers/settings/featured_tags_controller.rb +++ b/app/controllers/settings/featured_tags_controller.rb @@ -44,6 +44,6 @@ class Settings::FeaturedTagsController < Settings::BaseController end def featured_tag_params - params.require(:featured_tag).permit(:name) + params.expect(featured_tag: [:name]) end end diff --git a/app/controllers/settings/imports_controller.rb b/app/controllers/settings/imports_controller.rb index 5346a448a..be1699315 100644 --- a/app/controllers/settings/imports_controller.rb +++ b/app/controllers/settings/imports_controller.rb @@ -90,7 +90,7 @@ class Settings::ImportsController < Settings::BaseController private def import_params - params.require(:form_import).permit(:data, :type, :mode) + params.expect(form_import: [:data, :type, :mode]) end def set_bulk_import diff --git a/app/controllers/settings/migration/redirects_controller.rb b/app/controllers/settings/migration/redirects_controller.rb index 6d469f384..d850e05e9 100644 --- a/app/controllers/settings/migration/redirects_controller.rb +++ b/app/controllers/settings/migration/redirects_controller.rb @@ -33,6 +33,6 @@ class Settings::Migration::RedirectsController < Settings::BaseController private def resource_params - params.require(:form_redirect).permit(:acct, :current_password, :current_username) + params.expect(form_redirect: [:acct, :current_password, :current_username]) end end diff --git a/app/controllers/settings/migrations_controller.rb b/app/controllers/settings/migrations_controller.rb index 62603aba8..92e3611fd 100644 --- a/app/controllers/settings/migrations_controller.rb +++ b/app/controllers/settings/migrations_controller.rb @@ -27,7 +27,7 @@ class Settings::MigrationsController < Settings::BaseController private def resource_params - params.require(:account_migration).permit(:acct, :current_password, :current_username) + params.expect(account_migration: [:acct, :current_password, :current_username]) end def set_migrations diff --git a/app/controllers/settings/preferences/base_controller.rb b/app/controllers/settings/preferences/base_controller.rb index c1f8b4989..d6d42b034 100644 --- a/app/controllers/settings/preferences/base_controller.rb +++ b/app/controllers/settings/preferences/base_controller.rb @@ -19,6 +19,6 @@ class Settings::Preferences::BaseController < Settings::BaseController end def user_params - params.require(:user).permit(:locale, :time_zone, chosen_languages: [], settings_attributes: UserSettings.keys) + params.expect(user: [:locale, :time_zone, chosen_languages: [], settings_attributes: UserSettings.keys]) end end diff --git a/app/controllers/settings/privacy_controller.rb b/app/controllers/settings/privacy_controller.rb index 1102c89fa..a5bb3b884 100644 --- a/app/controllers/settings/privacy_controller.rb +++ b/app/controllers/settings/privacy_controller.rb @@ -18,7 +18,7 @@ class Settings::PrivacyController < Settings::BaseController private def account_params - params.require(:account).permit(:discoverable, :unlocked, :indexable, :show_collections, settings: UserSettings.keys) + params.expect(account: [:discoverable, :unlocked, :indexable, :show_collections, settings: UserSettings.keys]) end def set_account diff --git a/app/controllers/settings/profiles_controller.rb b/app/controllers/settings/profiles_controller.rb index 8ae69b7fe..458f4148c 100644 --- a/app/controllers/settings/profiles_controller.rb +++ b/app/controllers/settings/profiles_controller.rb @@ -20,7 +20,7 @@ class Settings::ProfilesController < Settings::BaseController private def account_params - params.require(:account).permit(:display_name, :note, :avatar, :header, :bot, fields_attributes: [:name, :value]) + params.expect(account: [:display_name, :note, :avatar, :header, :bot, fields_attributes: [[:name, :value]]]) end def set_account diff --git a/app/controllers/settings/two_factor_authentication/confirmations_controller.rb b/app/controllers/settings/two_factor_authentication/confirmations_controller.rb index 1a0afe58b..eae990e79 100644 --- a/app/controllers/settings/two_factor_authentication/confirmations_controller.rb +++ b/app/controllers/settings/two_factor_authentication/confirmations_controller.rb @@ -38,7 +38,7 @@ module Settings private def confirmation_params - params.require(:form_two_factor_confirmation).permit(:otp_attempt) + params.expect(form_two_factor_confirmation: [:otp_attempt]) end def prepare_two_factor_form diff --git a/app/controllers/settings/verifications_controller.rb b/app/controllers/settings/verifications_controller.rb index 4e0663253..bed29dbee 100644 --- a/app/controllers/settings/verifications_controller.rb +++ b/app/controllers/settings/verifications_controller.rb @@ -18,7 +18,9 @@ class Settings::VerificationsController < Settings::BaseController private def account_params - params.require(:account).permit(:attribution_domains_as_text) + params.expect(account: [:attribution_domains]).tap do |params| + params[:attribution_domains] = params[:attribution_domains].split if params[:attribution_domains] + end end def set_account diff --git a/app/controllers/severed_relationships_controller.rb b/app/controllers/severed_relationships_controller.rb index 965753a26..817abebf6 100644 --- a/app/controllers/severed_relationships_controller.rb +++ b/app/controllers/severed_relationships_controller.rb @@ -4,7 +4,6 @@ class SeveredRelationshipsController < ApplicationController layout 'admin' before_action :authenticate_user! - before_action :set_cache_headers before_action :set_event, only: [:following, :followers] @@ -49,8 +48,4 @@ class SeveredRelationshipsController < ApplicationController def acct(account) account.local? ? account.local_username_and_domain : account.acct end - - def set_cache_headers - response.cache_control.replace(private: true, no_store: true) - end end diff --git a/app/controllers/statuses_cleanup_controller.rb b/app/controllers/statuses_cleanup_controller.rb index e517bf3ae..f4f49031a 100644 --- a/app/controllers/statuses_cleanup_controller.rb +++ b/app/controllers/statuses_cleanup_controller.rb @@ -5,7 +5,6 @@ class StatusesCleanupController < ApplicationController before_action :authenticate_user! before_action :set_policy - before_action :set_cache_headers def show; end @@ -15,8 +14,6 @@ class StatusesCleanupController < ApplicationController else render :show end - rescue ActionController::ParameterMissing - # Do nothing end def require_functional! @@ -30,10 +27,6 @@ class StatusesCleanupController < ApplicationController end def resource_params - params.require(:account_statuses_cleanup_policy).permit(:enabled, :min_status_age, :keep_direct, :keep_pinned, :keep_polls, :keep_media, :keep_self_fav, :keep_self_bookmark, :min_favs, :min_reblogs) - end - - def set_cache_headers - response.cache_control.replace(private: true, no_store: true) + params.expect(account_statuses_cleanup_policy: [:enabled, :min_status_age, :keep_direct, :keep_pinned, :keep_polls, :keep_media, :keep_self_fav, :keep_self_bookmark, :min_favs, :min_reblogs]) end end diff --git a/app/helpers/theme_helper.rb b/app/helpers/theme_helper.rb index 5dfb4a518..cda380b3b 100644 --- a/app/helpers/theme_helper.rb +++ b/app/helpers/theme_helper.rb @@ -45,7 +45,9 @@ module ThemeHelper end def cached_custom_css_digest - Rails.cache.read(:setting_digest_custom_css) + Rails.cache.fetch(:setting_digest_custom_css) do + Setting.custom_css&.then { |content| Digest::SHA256.hexdigest(content) } + end end def theme_color_for(theme) diff --git a/app/javascript/hooks/useSelectableClick.ts b/app/javascript/hooks/useSelectableClick.ts new file mode 100644 index 000000000..c8f16f0b0 --- /dev/null +++ b/app/javascript/hooks/useSelectableClick.ts @@ -0,0 +1,55 @@ +import { useRef, useCallback } from 'react'; + +type Position = [number, number]; + +export const useSelectableClick = ( + onClick: React.MouseEventHandler, + maxDelta = 5, +) => { + const clickPositionRef = useRef(null); + + const handleMouseDown = useCallback((e: React.MouseEvent) => { + clickPositionRef.current = [e.clientX, e.clientY]; + }, []); + + const handleMouseUp = useCallback( + (e: React.MouseEvent) => { + if (!clickPositionRef.current) { + return; + } + + const [startX, startY] = clickPositionRef.current; + const [deltaX, deltaY] = [ + Math.abs(e.clientX - startX), + Math.abs(e.clientY - startY), + ]; + + let element: EventTarget | null = e.target; + + while (element && element instanceof HTMLElement) { + if ( + element.localName === 'button' || + element.localName === 'a' || + element.localName === 'label' + ) { + return; + } + + element = element.parentNode; + } + + if ( + deltaX + deltaY < maxDelta && + (e.button === 0 || e.button === 1) && + e.detail >= 1 + ) { + onClick(e); + } + + clickPositionRef.current = null; + }, + [maxDelta, onClick], + ); + + return [handleMouseDown, handleMouseUp] as const; +}; diff --git a/app/javascript/images/archetypes/booster.png b/app/javascript/images/archetypes/booster.png index 18c92dfb7..df2a0226f 100755 Binary files a/app/javascript/images/archetypes/booster.png and b/app/javascript/images/archetypes/booster.png differ diff --git a/app/javascript/images/archetypes/lurker.png b/app/javascript/images/archetypes/lurker.png index 8e1d6451b..e37f98aab 100755 Binary files a/app/javascript/images/archetypes/lurker.png and b/app/javascript/images/archetypes/lurker.png differ diff --git a/app/javascript/images/archetypes/oracle.png b/app/javascript/images/archetypes/oracle.png index 2afd3c72e..9d4e2177c 100755 Binary files a/app/javascript/images/archetypes/oracle.png and b/app/javascript/images/archetypes/oracle.png differ diff --git a/app/javascript/images/archetypes/pollster.png b/app/javascript/images/archetypes/pollster.png index b838fccdd..9fe6281af 100755 Binary files a/app/javascript/images/archetypes/pollster.png and b/app/javascript/images/archetypes/pollster.png differ diff --git a/app/javascript/images/archetypes/replier.png b/app/javascript/images/archetypes/replier.png index b298d4221..6c6325b9f 100755 Binary files a/app/javascript/images/archetypes/replier.png and b/app/javascript/images/archetypes/replier.png differ diff --git a/app/javascript/images/reticle.png b/app/javascript/images/reticle.png deleted file mode 100644 index a724ac0bc..000000000 Binary files a/app/javascript/images/reticle.png and /dev/null differ diff --git a/app/javascript/mastodon/actions/compose.js b/app/javascript/mastodon/actions/compose.js index aa1c6de20..d70834cec 100644 --- a/app/javascript/mastodon/actions/compose.js +++ b/app/javascript/mastodon/actions/compose.js @@ -414,7 +414,7 @@ export function initMediaEditModal(id) { dispatch(openModal({ modalType: 'FOCAL_POINT', - modalProps: { id }, + modalProps: { mediaId: id }, })); }; } diff --git a/app/javascript/mastodon/actions/compose_typed.ts b/app/javascript/mastodon/actions/compose_typed.ts new file mode 100644 index 000000000..97f0d68c5 --- /dev/null +++ b/app/javascript/mastodon/actions/compose_typed.ts @@ -0,0 +1,70 @@ +import type { List as ImmutableList, Map as ImmutableMap } from 'immutable'; + +import { apiUpdateMedia } from 'mastodon/api/compose'; +import type { ApiMediaAttachmentJSON } from 'mastodon/api_types/media_attachments'; +import type { MediaAttachment } from 'mastodon/models/media_attachment'; +import { createDataLoadingThunk } from 'mastodon/store/typed_functions'; + +type SimulatedMediaAttachmentJSON = ApiMediaAttachmentJSON & { + unattached?: boolean; +}; + +const simulateModifiedApiResponse = ( + media: MediaAttachment, + params: { description?: string; focus?: string }, +): SimulatedMediaAttachmentJSON => { + const [x, y] = (params.focus ?? '').split(','); + + const data = { + ...media.toJS(), + ...params, + meta: { + focus: { + x: parseFloat(x ?? '0'), + y: parseFloat(y ?? '0'), + }, + }, + } as unknown as SimulatedMediaAttachmentJSON; + + return data; +}; + +export const changeUploadCompose = createDataLoadingThunk( + 'compose/changeUpload', + async ( + { + id, + ...params + }: { + id: string; + description: string; + focus: string; + }, + { getState }, + ) => { + const media = ( + (getState().compose as ImmutableMap).get( + 'media_attachments', + ) as ImmutableList + ).find((item) => item.get('id') === id); + + // Editing already-attached media is deferred to editing the post itself. + // For simplicity's sake, fake an API reply. + if (media && !media.get('unattached')) { + return new Promise((resolve) => { + resolve(simulateModifiedApiResponse(media, params)); + }); + } + + return apiUpdateMedia(id, params); + }, + (media: SimulatedMediaAttachmentJSON) => { + return { + media, + attached: typeof media.unattached !== 'undefined' && !media.unattached, + }; + }, + { + useLoadingBar: false, + }, +); diff --git a/app/javascript/mastodon/actions/modal.ts b/app/javascript/mastodon/actions/modal.ts index ab03e4676..49af176a1 100644 --- a/app/javascript/mastodon/actions/modal.ts +++ b/app/javascript/mastodon/actions/modal.ts @@ -9,6 +9,7 @@ export type ModalType = keyof typeof MODAL_COMPONENTS; interface OpenModalPayload { modalType: ModalType; modalProps: ModalProps; + previousModalProps?: ModalProps; } export const openModal = createAction('MODAL_OPEN'); diff --git a/app/javascript/mastodon/actions/push_notifications/registerer.js b/app/javascript/mastodon/actions/push_notifications/registerer.js index b3d3850e3..647a6bd9f 100644 --- a/app/javascript/mastodon/actions/push_notifications/registerer.js +++ b/app/javascript/mastodon/actions/push_notifications/registerer.js @@ -33,7 +33,7 @@ const unsubscribe = ({ registration, subscription }) => subscription ? subscription.unsubscribe().then(() => registration) : registration; const sendSubscriptionToBackend = (subscription) => { - const params = { subscription }; + const params = { subscription: { ...subscription.toJSON(), standard: true } }; if (me) { const data = pushNotificationsSetting.get(me); diff --git a/app/javascript/mastodon/api/compose.ts b/app/javascript/mastodon/api/compose.ts new file mode 100644 index 000000000..757e9961c --- /dev/null +++ b/app/javascript/mastodon/api/compose.ts @@ -0,0 +1,7 @@ +import { apiRequestPut } from 'mastodon/api'; +import type { ApiMediaAttachmentJSON } from 'mastodon/api_types/media_attachments'; + +export const apiUpdateMedia = ( + id: string, + params?: { description?: string; focus?: string }, +) => apiRequestPut(`v1/media/${id}`, params); diff --git a/app/javascript/mastodon/api_types/accounts.ts b/app/javascript/mastodon/api_types/accounts.ts index fdbd7523f..3f8b27497 100644 --- a/app/javascript/mastodon/api_types/accounts.ts +++ b/app/javascript/mastodon/api_types/accounts.ts @@ -19,7 +19,7 @@ export interface BaseApiAccountJSON { avatar_static: string; bot: boolean; created_at: string; - discoverable: boolean; + discoverable?: boolean; indexable: boolean; display_name: string; emojis: ApiCustomEmojiJSON[]; diff --git a/app/javascript/mastodon/components/alt_text_badge.tsx b/app/javascript/mastodon/components/alt_text_badge.tsx index 99bec1ee5..466c5cf1b 100644 --- a/app/javascript/mastodon/components/alt_text_badge.tsx +++ b/app/javascript/mastodon/components/alt_text_badge.tsx @@ -1,4 +1,4 @@ -import { useState, useCallback, useRef } from 'react'; +import { useState, useCallback, useRef, useId } from 'react'; import { FormattedMessage } from 'react-intl'; @@ -8,12 +8,15 @@ import type { UsePopperOptions, } from 'react-overlays/esm/usePopper'; +import { useSelectableClick } from '@/hooks/useSelectableClick'; + const offset = [0, 4] as OffsetValue; const popperConfig = { strategy: 'fixed' } as UsePopperOptions; export const AltTextBadge: React.FC<{ description: string; }> = ({ description }) => { + const accessibilityId = useId(); const anchorRef = useRef(null); const [open, setOpen] = useState(false); @@ -25,12 +28,16 @@ export const AltTextBadge: React.FC<{ setOpen(false); }, [setOpen]); + const [handleMouseDown, handleMouseUp] = useSelectableClick(handleClose); + return ( <> @@ -47,9 +54,12 @@ export const AltTextBadge: React.FC<{ > {({ props }) => (
- - ); -}; +GIFV.displayName = 'GIFV'; diff --git a/app/javascript/mastodon/components/load_gap.tsx b/app/javascript/mastodon/components/load_gap.tsx index 544b5e146..6cbdee6ce 100644 --- a/app/javascript/mastodon/components/load_gap.tsx +++ b/app/javascript/mastodon/components/load_gap.tsx @@ -1,9 +1,10 @@ -import { useCallback } from 'react'; +import { useCallback, useState } from 'react'; import { useIntl, defineMessages } from 'react-intl'; import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react'; import { Icon } from 'mastodon/components/icon'; +import { LoadingIndicator } from 'mastodon/components/loading_indicator'; const messages = defineMessages({ load_more: { id: 'status.load_more', defaultMessage: 'Load more' }, @@ -17,10 +18,12 @@ interface Props { export const LoadGap = ({ disabled, param, onClick }: Props) => { const intl = useIntl(); + const [loading, setLoading] = useState(false); const handleClick = useCallback(() => { + setLoading(true); onClick(param); - }, [param, onClick]); + }, [setLoading, param, onClick]); return ( ); }; diff --git a/app/javascript/mastodon/components/media_gallery.jsx b/app/javascript/mastodon/components/media_gallery.jsx index 95b06abc5..513231660 100644 --- a/app/javascript/mastodon/components/media_gallery.jsx +++ b/app/javascript/mastodon/components/media_gallery.jsx @@ -145,7 +145,6 @@ class Item extends PureComponent { srcSet={srcSet} sizes={sizes} alt={description} - title={description} lang={lang} style={{ objectPosition: `${x}% ${y}%` }} onLoad={this.handleImageLoad} @@ -167,7 +166,6 @@ class Item extends PureComponent {