Compare commits

..

17 Commits

Author SHA1 Message Date
root
d34048ecd1 Modern theme update to latest version 2023-08-29 08:29:56 -04:00
root
7311c41239 Modern theme update 2023-08-23 14:15:47 -04:00
root
211a7143a7 fix Modern theme when split into separtate flavour 2023-08-14 10:43:30 -04:00
root
03d55b7804 Migrate Modern theme to separate Flavour 2023-08-12 18:30:18 -04:00
root
096e8248aa Migrate Modern theme to separate Flavour 2023-08-12 18:28:43 -04:00
root
d486b1527d Re-add Modern theme, with color variants 2023-08-12 16:17:40 -04:00
root
bf4ff204f7 merge fix 2023-08-10 15:15:39 -04:00
root
22eecd2de6 dev work 2023-08-10 15:03:08 -04:00
Tarrien
250b062a5e Merge branch '4.1.4-glitch' of https://git.gyro-tech.net/tarrien/Mastodon into 4.1.4-glitch-fix 2023-08-07 15:05:26 -04:00
Tarrien
641af1fda1 Block gpt via robots.txt 2023-08-07 15:05:00 -04:00
tarrien
97e9fd5aca Delete .env.production.old 2023-08-07 11:53:33 -04:00
tarrien
de0a71ad02 Cleanup 2023-08-07 11:53:18 -04:00
Tarrien
26e6a23636 Final save before migration 2023-08-07 10:35:45 -04:00
Tarrien
122d808fc2 Merge branch 'main' of https://github.com/glitch-soc/mastodon into 4.1.4-glitch-fix
Pulling update
2023-07-28 07:39:27 -04:00
Tarrien
ba0c1a1d99 Merge branch 'main' of https://github.com/glitch-soc/mastodon into 4.1.4-glitch-fix
Updating Glitch
2023-07-24 14:01:44 -04:00
Tarrien
ecff96db8b Fixing some customization tweaks 2023-07-24 14:00:51 -04:00
Tarrien
a5491eb02f Wobbl customizations on Glitch-SOC 2023-07-20 09:42:19 -04:00
850 changed files with 9616 additions and 19844 deletions

3
.bundler-audit.yml Normal file
View File

@ -0,0 +1,3 @@
---
ignore:
- CVE-2015-9284 # Mitigation following https://github.com/omniauth/omniauth/wiki/Resolving-CVE-2015-9284#mitigating-in-rails-applications

View File

@ -4,6 +4,10 @@ FROM mcr.microsoft.com/devcontainers/ruby:1-3.2-bullseye
# Install Rails # Install Rails
# RUN gem install rails webdrivers # RUN gem install rails webdrivers
# Default value to allow debug server to serve content over GitHub Codespace's port forwarding service
# The value is a comma-separated list of allowed domains
ENV RAILS_DEVELOPMENT_HOSTS=".githubpreview.dev,.preview.app.github.dev,.app.github.dev"
ARG NODE_VERSION="16" ARG NODE_VERSION="16"
RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1" RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"

View File

@ -1,49 +0,0 @@
{
"name": "Mastodon on GitHub Codespaces",
"dockerComposeFile": "../docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
"features": {
"ghcr.io/devcontainers/features/sshd:1": {}
},
"runServices": ["app", "db", "redis"],
"forwardPorts": [3000, 4000],
"portsAttributes": {
"3000": {
"label": "web",
"onAutoForward": "notify"
},
"4000": {
"label": "stream",
"onAutoForward": "silent"
}
},
"otherPortsAttributes": {
"onAutoForward": "silent"
},
"remoteEnv": {
"LOCAL_DOMAIN": "${localEnv:CODESPACE_NAME}-3000.app.github.dev",
"LOCAL_HTTPS": "true",
"STREAMING_API_BASE_URL": "https://${localEnv:CODESPACE_NAME}-4000.app.github.dev",
"DISABLE_FORGERY_REQUEST_PROTECTION": "true",
"ES_ENABLED": "",
"LIBRE_TRANSLATE_ENDPOINT": ""
},
"onCreateCommand": "git config --global --add safe.directory ${containerWorkspaceFolder}",
"postCreateCommand": ".devcontainer/post-create.sh",
"waitFor": "postCreateCommand",
"customizations": {
"vscode": {
"settings": {},
"extensions": ["EditorConfig.EditorConfig", "webben.browserslist"]
}
}
}

View File

@ -1,39 +1,31 @@
// For more details, see https://aka.ms/devcontainer.json.
{ {
"name": "Mastodon on local machine", "name": "Mastodon",
"dockerComposeFile": "docker-compose.yml", "dockerComposeFile": "docker-compose.yml",
"service": "app", "service": "app",
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}", "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
// Features to add to the dev container. More info: https://containers.dev/features.
"features": { "features": {
"ghcr.io/devcontainers/features/sshd:1": {} "ghcr.io/devcontainers/features/sshd:1": {}
}, },
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// This can be used to network with other containers or the host.
"forwardPorts": [3000, 4000], "forwardPorts": [3000, 4000],
"portsAttributes": { // Use 'postCreateCommand' to run commands after the container is created.
"3000": {
"label": "web",
"onAutoForward": "notify",
"requireLocalPort": true
},
"4000": {
"label": "stream",
"onAutoForward": "silent",
"requireLocalPort": true
}
},
"otherPortsAttributes": {
"onAutoForward": "silent"
},
"onCreateCommand": "git config --global --add safe.directory ${containerWorkspaceFolder}", "onCreateCommand": "git config --global --add safe.directory ${containerWorkspaceFolder}",
"postCreateCommand": ".devcontainer/post-create.sh", "postCreateCommand": ".devcontainer/post-create.sh",
"waitFor": "postCreateCommand", "waitFor": "postCreateCommand",
// Configure tool-specific properties.
"customizations": { "customizations": {
// Configure properties specific to VS Code.
"vscode": { "vscode": {
// Set *default* container specific settings.json values on container create.
"settings": {}, "settings": {},
// Add the IDs of extensions you want installed when the container is created.
"extensions": ["EditorConfig.EditorConfig", "webben.browserslist"] "extensions": ["EditorConfig.EditorConfig", "webben.browserslist"]
} }
} }

View File

@ -25,7 +25,6 @@ services:
command: sleep infinity command: sleep infinity
ports: ports:
- '127.0.0.1:3000:3000' - '127.0.0.1:3000:3000'
- '127.0.0.1:3035:3035'
- '127.0.0.1:4000:4000' - '127.0.0.1:4000:4000'
networks: networks:
- external_network - external_network

View File

@ -2,7 +2,3 @@ VAGRANT=true
LOCAL_DOMAIN=mastodon.local LOCAL_DOMAIN=mastodon.local
BIND=0.0.0.0 BIND=0.0.0.0
DB_HOST=/var/run/postgresql/ DB_HOST=/var/run/postgresql/
ES_ENABLED=true
ES_HOST=localhost
ES_PORT=9200

View File

@ -1,21 +1,20 @@
{ {
$schema: 'https://docs.renovatebot.com/renovate-schema.json', $schema: 'https://docs.renovatebot.com/renovate-schema.json',
extends: [ extends: [
'config:recommended', 'config:base',
':dependencyDashboard',
':labels(dependencies)', ':labels(dependencies)',
':maintainLockFilesMonthly', // update non-direct dependencies monthly ':maintainLockFilesMonthly', // update non-direct dependencies monthly
':prConcurrentLimitNone', // Remove limit for open PRs at any time. ':prConcurrentLimit10', // only 10 open PRs at the same time
':prHourlyLimit2', // Rate limit PR creation to a maximum of two per hour.
], ],
minimumReleaseAge: '3', // Wait 3 days after the package has been published before upgrading it stabilityDays: 3, // Wait 3 days after the package has been published before upgrading it
// packageRules order is important, they are applied from top to bottom and are merged, // packageRules order is important, they are applied from top to bottom and are merged,
// meaning the most important ones must be at the bottom, for example grouping rules // meaning the most important ones must be at the bottom, for example grouping rules
// If we do not want a package to be grouped with others, we need to set its groupName // If we do not want a package to be grouped with others, we need to set its groupName
// to `null` after any other rule set it to something. // to `null` after any other rule set it to something.
dependencyDashboardHeader: 'This issue lists Renovate updates and detected dependencies. Read the [Dependency Dashboard](https://docs.renovatebot.com/key-concepts/dashboard/) docs to learn more. Before approving any upgrade: read the description and comments in the [`renovate.json5` file](https://github.com/mastodon/mastodon/blob/main/.github/renovate.json5).',
packageRules: [ packageRules: [
{ {
// Require Dependency Dashboard Approval for major version bumps of these node packages // Ignore major version bumps for these node packages
matchManagers: ['npm'], matchManagers: ['npm'],
matchPackageNames: [ matchPackageNames: [
'tesseract.js', // Requires code changes 'tesseract.js', // Requires code changes
@ -42,10 +41,10 @@
'react-router-dom', 'react-router-dom',
], ],
matchUpdateTypes: ['major'], matchUpdateTypes: ['major'],
dependencyDashboardApproval: true, enabled: false,
}, },
{ {
// Require Dependency Dashboard Approval for major version bumps of these Ruby packages // Ignore major version bumps for these Ruby packages
matchManagers: ['bundler'], matchManagers: ['bundler'],
matchPackageNames: [ matchPackageNames: [
'rack', // Needs to be synced with Rails version 'rack', // Needs to be synced with Rails version
@ -56,7 +55,7 @@
'redis', // Requires manual upgrade and sync with Sidekiq version 'redis', // Requires manual upgrade and sync with Sidekiq version
], ],
matchUpdateTypes: ['major'], matchUpdateTypes: ['major'],
dependencyDashboardApproval: true, enabled: false,
}, },
{ {
// Update Github Actions and Docker images weekly // Update Github Actions and Docker images weekly
@ -64,25 +63,25 @@
extends: ['schedule:weekly'], extends: ['schedule:weekly'],
}, },
{ {
// Require Dependency Dashboard Approval for major & minor bumps for the ruby image, this needs to be synced with .ruby-version // Ignore major & minor bumps for the ruby image, this needs to be synced with .ruby-version
matchManagers: ['dockerfile'], matchManagers: ['dockerfile'],
matchPackageNames: ['moritzheiber/ruby-jemalloc'], matchPackageNames: ['moritzheiber/ruby-jemalloc'],
matchUpdateTypes: ['minor', 'major'], matchUpdateTypes: ['minor', 'major'],
dependencyDashboardApproval: true, enabled: false,
}, },
{ {
// Require Dependency Dashboard Approval for major bumps for the node image, this needs to be synced with .nvmrc // Ignore major bump for the node image, this needs to be synced with .nvmrc
matchManagers: ['dockerfile'], matchManagers: ['dockerfile'],
matchPackageNames: ['node'], matchPackageNames: ['node'],
matchUpdateTypes: ['major'], matchUpdateTypes: ['major'],
dependencyDashboardApproval: true, enabled: false,
}, },
{ {
// Require Dependency Dashboard Approval for major postgres bumps in the docker-compose file, as those break dev environments // Ignore major postgres bumps in the docker-compose file, as those break dev environments
matchManagers: ['docker-compose'], matchManagers: ['docker-compose'],
matchPackageNames: ['postgres'], matchPackageNames: ['postgres'],
matchUpdateTypes: ['major'], matchUpdateTypes: ['major'],
dependencyDashboardApproval: true, enabled: false,
}, },
{ {
// Update devDependencies every week, with one grouped PR // Update devDependencies every week, with one grouped PR

View File

@ -4,16 +4,11 @@ on:
platforms: platforms:
required: true required: true
type: string type: string
cache:
type: boolean
default: true
use_native_arm64_builder: use_native_arm64_builder:
type: boolean type: boolean
push_to_images: push_to_images:
type: string type: string
version_prerelease: version_suffix:
type: string
version_metadata:
type: string type: string
flavor: flavor:
type: string type: string
@ -27,7 +22,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- uses: docker/setup-qemu-action@v2 - uses: docker/setup-qemu-action@v2
if: contains(inputs.platforms, 'linux/arm64') && !inputs.use_native_arm64_builder if: contains(inputs.platforms, 'linux/arm64') && !inputs.use_native_arm64_builder
@ -79,6 +74,8 @@ jobs:
if: ${{ inputs.push_to_images != '' }} if: ${{ inputs.push_to_images != '' }}
with: with:
images: ${{ inputs.push_to_images }} images: ${{ inputs.push_to_images }}
# Only tag with latest when ran against the latest stable branch
# This needs to be updated after each minor version release
flavor: ${{ inputs.flavor }} flavor: ${{ inputs.flavor }}
tags: ${{ inputs.tags }} tags: ${{ inputs.tags }}
labels: ${{ inputs.labels }} labels: ${{ inputs.labels }}
@ -86,14 +83,12 @@ jobs:
- uses: docker/build-push-action@v4 - uses: docker/build-push-action@v4
with: with:
context: . context: .
build-args: | build-args: MASTODON_VERSION_SUFFIX=${{ inputs.version_suffix }}
MASTODON_VERSION_PRERELEASE=${{ inputs.version_prerelease }}
MASTODON_VERSION_METADATA=${{ inputs.version_metadata }}
platforms: ${{ inputs.platforms }} platforms: ${{ inputs.platforms }}
provenance: false provenance: false
builder: ${{ steps.buildx.outputs.name || steps.buildx-native.outputs.name }} builder: ${{ steps.buildx.outputs.name || steps.buildx-native.outputs.name }}
push: ${{ inputs.push_to_images != '' }} push: ${{ inputs.push_to_images != '' }}
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
cache-from: ${{ inputs.cache && 'type=gha' || '' }} cache-from: type=gha
cache-to: ${{ inputs.cache && 'type=gha,mode=max' || '' }} cache-to: type=gha,mode=max

View File

@ -16,9 +16,9 @@ jobs:
env: env:
TZ: Etc/UTC TZ: Etc/UTC
run: | run: |
echo mastodon_version_prerelease=nightly.$(date +'%Y-%m-%d')>> $GITHUB_OUTPUT echo mastodon_version_suffix=nightly-$(date +'%Y-%m-%d')>> $GITHUB_OUTPUT
outputs: outputs:
prerelease: ${{ steps.version_vars.outputs.mastodon_version_prerelease }} suffix: ${{ steps.version_vars.outputs.mastodon_version_suffix }}
build-image: build-image:
needs: compute-suffix needs: compute-suffix
@ -26,16 +26,16 @@ jobs:
with: with:
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
use_native_arm64_builder: false use_native_arm64_builder: false
cache: false
push_to_images: | push_to_images: |
ghcr.io/${{ github.repository_owner }}/mastodon ghcr.io/${{ github.repository_owner }}/mastodon
version_prerelease: ${{ needs.compute-suffix.outputs.prerelease }} # The `+` is important here, result will be v4.1.2+nightly-2022-03-05
version_suffix: +${{ needs.compute-suffix.outputs.suffix }}
labels: | labels: |
org.opencontainers.image.description=Nightly build image used for testing purposes org.opencontainers.image.description=Nightly build image used for testing purposes
flavor: | flavor: |
latest=true latest=auto
tags: | tags: |
type=raw,value=edge type=raw,value=edge
type=raw,value=nightly type=raw,value=nightly
type=schedule,pattern=${{ needs.compute-suffix.outputs.prerelease }} type=schedule,pattern=${{ needs.compute-suffix.outputs.suffix }}
secrets: inherit secrets: inherit

View File

@ -18,12 +18,12 @@ jobs:
steps: steps:
# Repository needs to be cloned so `git rev-parse` below works # Repository needs to be cloned so `git rev-parse` below works
- name: Clone repository - name: Clone repository
uses: actions/checkout@v4 uses: actions/checkout@v3
- id: version_vars - id: version_vars
run: | run: |
echo mastodon_version_metadata=pr-${{ github.event.pull_request.number }}-$(git rev-parse --short HEAD) >> $GITHUB_OUTPUT echo mastodon_version_suffix=+pr-${{ github.event.pull_request.number }}-$(git rev-parse --short HEAD) >> $GITHUB_OUTPUT
outputs: outputs:
metadata: ${{ steps.version_vars.outputs.mastodon_version_metadata }} suffix: ${{ steps.version_vars.outputs.mastodon_version_suffix }}
build-image: build-image:
needs: compute-suffix needs: compute-suffix
@ -33,7 +33,7 @@ jobs:
use_native_arm64_builder: false use_native_arm64_builder: false
push_to_images: | push_to_images: |
ghcr.io/${{ github.repository_owner }}/mastodon ghcr.io/${{ github.repository_owner }}/mastodon
version_metadata: ${{ needs.compute-suffix.outputs.metadata }} version_suffix: ${{ needs.compute-suffix.outputs.suffix }}
flavor: | flavor: |
latest=auto latest=auto
tags: | tags: |

View File

@ -16,12 +16,8 @@ jobs:
use_native_arm64_builder: false use_native_arm64_builder: false
push_to_images: | push_to_images: |
ghcr.io/${{ github.repository_owner }}/mastodon ghcr.io/${{ github.repository_owner }}/mastodon
# Do not use cache when building releases, so apt update is always ran and the release always contain the latest packages
cache: false
# Only tag with latest when ran against the latest stable branch
# This needs to be updated after each minor version release
flavor: | flavor: |
latest=${{ startsWith(github.ref, 'refs/tags/v4.2.') }} latest=${{ startsWith(github.ref, 'refs/tags/v4.1.') }}
tags: | tags: |
type=pep440,pattern={{raw}} type=pep440,pattern={{raw}}
type=pep440,pattern=v{{major}}.{{minor}} type=pep440,pattern=v{{major}}.{{minor}}

View File

@ -25,7 +25,7 @@ jobs:
steps: steps:
- name: Clone repository - name: Clone repository
uses: actions/checkout@v4 uses: actions/checkout@v3
- name: Install native Ruby dependencies - name: Install native Ruby dependencies
run: sudo apt-get install -y libicu-dev libidn11-dev run: sudo apt-get install -y libicu-dev libidn11-dev

View File

@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- name: Install system dependencies - name: Install system dependencies
run: | run: |

View File

@ -27,7 +27,7 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL

View File

@ -14,7 +14,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v3
- name: Increase Git http.postBuffer - name: Increase Git http.postBuffer
# This is needed due to a bug in Ubuntu's cURL version? # This is needed due to a bug in Ubuntu's cURL version?

View File

@ -20,7 +20,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v3
- name: crowdin action - name: crowdin action
uses: crowdin/github-action@v1 uses: crowdin/github-action@v1

View File

@ -33,7 +33,7 @@ jobs:
steps: steps:
- name: Clone repository - name: Clone repository
uses: actions/checkout@v4 uses: actions/checkout@v3
- name: Set up Node.js - name: Set up Node.js
uses: actions/setup-node@v3 uses: actions/setup-node@v3

View File

@ -28,7 +28,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Clone repository - name: Clone repository
uses: actions/checkout@v4 uses: actions/checkout@v3
- name: Install native Ruby dependencies - name: Install native Ruby dependencies
run: | run: |

View File

@ -37,7 +37,7 @@ jobs:
steps: steps:
- name: Clone repository - name: Clone repository
uses: actions/checkout@v4 uses: actions/checkout@v3
- name: Set up Node.js - name: Set up Node.js
uses: actions/setup-node@v3 uses: actions/setup-node@v3

View File

@ -29,7 +29,7 @@ jobs:
steps: steps:
- name: Clone repository - name: Clone repository
uses: actions/checkout@v4 uses: actions/checkout@v3
- name: Set up Node.js - name: Set up Node.js
uses: actions/setup-node@v3 uses: actions/setup-node@v3

View File

@ -29,7 +29,7 @@ jobs:
steps: steps:
- name: Clone repository - name: Clone repository
uses: actions/checkout@v4 uses: actions/checkout@v3
- name: Set up Node.js - name: Set up Node.js
uses: actions/setup-node@v3 uses: actions/setup-node@v3

View File

@ -29,7 +29,7 @@ jobs:
steps: steps:
- name: Clone repository - name: Clone repository
uses: actions/checkout@v4 uses: actions/checkout@v3
- name: Install native Ruby dependencies - name: Install native Ruby dependencies
run: sudo apt-get install -y libicu-dev libidn11-dev run: sudo apt-get install -y libicu-dev libidn11-dev

View File

@ -31,7 +31,7 @@ jobs:
steps: steps:
- name: Clone repository - name: Clone repository
uses: actions/checkout@v4 uses: actions/checkout@v3
- name: Set up Node.js - name: Set up Node.js
uses: actions/setup-node@v3 uses: actions/setup-node@v3

View File

@ -33,7 +33,7 @@ jobs:
steps: steps:
- name: Clone repository - name: Clone repository
uses: actions/checkout@v4 uses: actions/checkout@v3
- name: Set up Node.js - name: Set up Node.js
uses: actions/setup-node@v3 uses: actions/setup-node@v3

View File

@ -70,7 +70,7 @@ jobs:
BUNDLE_RETRY: 3 BUNDLE_RETRY: 3
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- name: Install native Ruby dependencies - name: Install native Ruby dependencies
run: | run: |

View File

@ -69,7 +69,7 @@ jobs:
BUNDLE_RETRY: 3 BUNDLE_RETRY: 3
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- name: Install native Ruby dependencies - name: Install native Ruby dependencies
run: | run: |

View File

@ -32,7 +32,7 @@ jobs:
SECRET_KEY_BASE: precompile_placeholder SECRET_KEY_BASE: precompile_placeholder
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- name: Set up Node.js - name: Set up Node.js
uses: actions/setup-node@v3 uses: actions/setup-node@v3
@ -127,7 +127,7 @@ jobs:
- 3 - 3
- 4 - 4
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- uses: actions/download-artifact@v3 - uses: actions/download-artifact@v3
with: with:
@ -153,213 +153,3 @@ jobs:
run: './bin/rails db:create db:schema:load db:seed' run: './bin/rails db:create db:schema:load db:seed'
- run: bundle exec rake rspec_chunked - run: bundle exec rake rspec_chunked
test-e2e:
name: End to End testing
runs-on: ubuntu-latest
needs:
- build
services:
postgres:
image: postgres:14-alpine
env:
POSTGRES_PASSWORD: postgres
POSTGRES_USER: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
redis:
image: redis:7-alpine
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 6379:6379
env:
DB_HOST: localhost
DB_USER: postgres
DB_PASS: postgres
DISABLE_SIMPLECOV: true
RAILS_ENV: test
BUNDLE_WITH: test
strategy:
fail-fast: false
matrix:
ruby-version:
- '3.0'
- '3.1'
- '.ruby-version'
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v3
with:
path: './public'
name: ${{ github.sha }}
- name: Update package index
run: sudo apt-get update
- name: Set up Node.js
uses: actions/setup-node@v3
with:
cache: yarn
node-version-file: '.nvmrc'
- name: Install native Ruby dependencies
run: sudo apt-get install -y libicu-dev libidn11-dev
- name: Install additional system dependencies
run: sudo apt-get install -y ffmpeg imagemagick
- name: Set up bundler cache
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby-version}}
bundler-cache: true
- run: yarn --frozen-lockfile
- name: Load database schema
run: './bin/rails db:create db:schema:load db:seed'
- run: bundle exec rake spec:system
- name: Archive logs
uses: actions/upload-artifact@v3
if: failure()
with:
name: e2e-logs-${{ matrix.ruby-version }}
path: log/
- name: Archive test screenshots
uses: actions/upload-artifact@v3
if: failure()
with:
name: e2e-screenshots
path: tmp/screenshots/
test-search:
name: Testing search
runs-on: ubuntu-latest
needs:
- build
services:
postgres:
image: postgres:14-alpine
env:
POSTGRES_PASSWORD: postgres
POSTGRES_USER: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
redis:
image: redis:7-alpine
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 6379:6379
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:7.17.13
env:
discovery.type: single-node
xpack.security.enabled: false
options: >-
--health-cmd "curl http://localhost:9200/_cluster/health"
--health-interval 10s
--health-timeout 5s
--health-retries 10
ports:
- 9200:9200
env:
DB_HOST: localhost
DB_USER: postgres
DB_PASS: postgres
DISABLE_SIMPLECOV: true
RAILS_ENV: test
BUNDLE_WITH: test
ES_ENABLED: true
ES_HOST: localhost
ES_PORT: 9200
strategy:
fail-fast: false
matrix:
ruby-version:
- '3.0'
- '3.1'
- '.ruby-version'
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v3
with:
path: './public'
name: ${{ github.sha }}
- name: Update package index
run: sudo apt-get update
- name: Set up Node.js
uses: actions/setup-node@v3
with:
cache: yarn
node-version-file: '.nvmrc'
- name: Install native Ruby dependencies
run: sudo apt-get install -y libicu-dev libidn11-dev
- name: Install additional system dependencies
run: sudo apt-get install -y ffmpeg imagemagick
- name: Set up bundler cache
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby-version}}
bundler-cache: true
- run: yarn --frozen-lockfile
- name: Load database schema
run: './bin/rails db:create db:schema:load db:seed'
- run: bundle exec rake spec:search
- name: Archive logs
uses: actions/upload-artifact@v3
if: failure()
with:
name: test-search-logs-${{ matrix.ruby-version }}
path: log/
- name: Archive test screenshots
uses: actions/upload-artifact@v3
if: failure()
with:
name: test-search-screenshots
path: tmp/screenshots/

2
.nvmrc
View File

@ -1 +1 @@
20.7 16.20

View File

@ -38,7 +38,14 @@ Layout/FirstHashElementIndentation:
# Reason: Currently disabled in .rubocop_todo.yml # Reason: Currently disabled in .rubocop_todo.yml
# https://docs.rubocop.org/rubocop/cops_layout.html#layoutlinelength # https://docs.rubocop.org/rubocop/cops_layout.html#layoutlinelength
Layout/LineLength: Layout/LineLength:
Max: 320 # Default of 120 causes a duplicate entry in generated todo file AllowedPatterns:
# Allow comments to be long lines
- !ruby/regexp / \# .*$/
- !ruby/regexp /^\# .*$/
Exclude:
- 'lib/mastodon/cli/*.rb'
- db/*migrate/**/*
- db/seeds/**/*
# Reason: # Reason:
# https://docs.rubocop.org/rubocop/cops_lint.html#lintuselessaccessmodifier # https://docs.rubocop.org/rubocop/cops_lint.html#lintuselessaccessmodifier

View File

@ -1,6 +1,6 @@
# This configuration was generated by # This configuration was generated by
# `rubocop --auto-gen-config --auto-gen-only-exclude --no-exclude-limit --no-offense-counts --no-auto-gen-timestamp` # `rubocop --auto-gen-config --auto-gen-only-exclude --no-exclude-limit --no-offense-counts --no-auto-gen-timestamp`
# using RuboCop version 1.56.1. # using RuboCop version 1.54.2.
# The point is for the user to remove these configuration records # The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base. # one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new # Note that changes in the inspected code, or installation of new
@ -37,14 +37,7 @@ Layout/HashAlignment:
Layout/LeadingCommentSpace: Layout/LeadingCommentSpace:
Exclude: Exclude:
- 'config/application.rb' - 'config/application.rb'
- 'config/initializers/3_omniauth.rb' - 'config/initializers/omniauth.rb'
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: Max, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns.
# URISchemes: http, https
Layout/LineLength:
Exclude:
- 'app/models/account.rb'
# This cop supports safe autocorrection (--autocorrect). # This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle. # Configuration parameters: EnforcedStyle.
@ -61,8 +54,38 @@ Lint/EmptyBlock:
- 'spec/fabricators/access_token_fabricator.rb' - 'spec/fabricators/access_token_fabricator.rb'
- 'spec/fabricators/conversation_fabricator.rb' - 'spec/fabricators/conversation_fabricator.rb'
- 'spec/fabricators/system_key_fabricator.rb' - 'spec/fabricators/system_key_fabricator.rb'
- 'spec/helpers/admin/action_logs_helper_spec.rb'
- 'spec/lib/activitypub/adapter_spec.rb' - 'spec/lib/activitypub/adapter_spec.rb'
- 'spec/models/account_alias_spec.rb'
- 'spec/models/account_deletion_request_spec.rb'
- 'spec/models/account_moderation_note_spec.rb'
- 'spec/models/announcement_mute_spec.rb'
- 'spec/models/announcement_reaction_spec.rb'
- 'spec/models/announcement_spec.rb'
- 'spec/models/backup_spec.rb'
- 'spec/models/conversation_mute_spec.rb'
- 'spec/models/custom_filter_keyword_spec.rb'
- 'spec/models/custom_filter_spec.rb'
- 'spec/models/device_spec.rb'
- 'spec/models/encrypted_message_spec.rb'
- 'spec/models/featured_tag_spec.rb'
- 'spec/models/follow_recommendation_suppression_spec.rb'
- 'spec/models/list_account_spec.rb'
- 'spec/models/list_spec.rb'
- 'spec/models/login_activity_spec.rb'
- 'spec/models/mute_spec.rb'
- 'spec/models/preview_card_spec.rb'
- 'spec/models/preview_card_trend_spec.rb'
- 'spec/models/relay_spec.rb'
- 'spec/models/scheduled_status_spec.rb'
- 'spec/models/status_stat_spec.rb'
- 'spec/models/status_trend_spec.rb'
- 'spec/models/system_key_spec.rb'
- 'spec/models/tag_follow_spec.rb'
- 'spec/models/unavailable_domain_spec.rb'
- 'spec/models/user_invite_request_spec.rb'
- 'spec/models/user_role_spec.rb' - 'spec/models/user_role_spec.rb'
- 'spec/models/web/setting_spec.rb'
Lint/NonLocalExitFromIterator: Lint/NonLocalExitFromIterator:
Exclude: Exclude:
@ -86,9 +109,10 @@ Lint/UnusedBlockArgument:
Lint/UselessAssignment: Lint/UselessAssignment:
Exclude: Exclude:
- 'app/services/activitypub/process_status_update_service.rb' - 'app/services/activitypub/process_status_update_service.rb'
- 'config/initializers/3_omniauth.rb' - 'config/initializers/omniauth.rb'
- 'db/migrate/20190511134027_add_silenced_at_suspended_at_to_accounts.rb' - 'db/migrate/20190511134027_add_silenced_at_suspended_at_to_accounts.rb'
- 'db/post_migrate/20190511152737_remove_suspended_silenced_account_fields.rb' - 'db/post_migrate/20190511152737_remove_suspended_silenced_account_fields.rb'
- 'spec/controllers/api/v1/bookmarks_controller_spec.rb'
- 'spec/controllers/api/v1/favourites_controller_spec.rb' - 'spec/controllers/api/v1/favourites_controller_spec.rb'
- 'spec/controllers/concerns/account_controller_concern_spec.rb' - 'spec/controllers/concerns/account_controller_concern_spec.rb'
- 'spec/helpers/jsonld_helper_spec.rb' - 'spec/helpers/jsonld_helper_spec.rb'
@ -105,7 +129,7 @@ Lint/UselessAssignment:
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes. # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
Metrics/AbcSize: Metrics/AbcSize:
Max: 144 Max: 150
Exclude: Exclude:
- 'app/serializers/initial_state_serializer.rb' - 'app/serializers/initial_state_serializer.rb'
@ -137,17 +161,12 @@ Naming/VariableNumber:
- 'spec/models/user_spec.rb' - 'spec/models/user_spec.rb'
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: SafeMultiline. Performance/UnfreezeString:
Performance/DeletePrefix:
Exclude: Exclude:
- 'app/models/featured_tag.rb' - 'app/lib/rss/builder.rb'
- 'app/lib/text_formatter.rb'
Performance/MapMethodChain: - 'app/validators/status_length_validator.rb'
Exclude: - 'lib/tasks/mastodon.rake'
- 'app/models/feed.rb'
- 'lib/mastodon/cli/maintenance.rb'
- 'spec/services/bulk_import_service_spec.rb'
- 'spec/services/import_service_spec.rb'
RSpec/AnyInstance: RSpec/AnyInstance:
Exclude: Exclude:
@ -168,6 +187,41 @@ RSpec/AnyInstance:
- 'spec/workers/activitypub/delivery_worker_spec.rb' - 'spec/workers/activitypub/delivery_worker_spec.rb'
- 'spec/workers/web/push_notification_worker_spec.rb' - 'spec/workers/web/push_notification_worker_spec.rb'
# This cop supports unsafe autocorrection (--autocorrect-all).
RSpec/EmptyExampleGroup:
Exclude:
- 'spec/helpers/admin/action_logs_helper_spec.rb'
- 'spec/models/account_alias_spec.rb'
- 'spec/models/account_deletion_request_spec.rb'
- 'spec/models/account_moderation_note_spec.rb'
- 'spec/models/announcement_mute_spec.rb'
- 'spec/models/announcement_reaction_spec.rb'
- 'spec/models/announcement_spec.rb'
- 'spec/models/backup_spec.rb'
- 'spec/models/conversation_mute_spec.rb'
- 'spec/models/custom_filter_keyword_spec.rb'
- 'spec/models/custom_filter_spec.rb'
- 'spec/models/device_spec.rb'
- 'spec/models/encrypted_message_spec.rb'
- 'spec/models/featured_tag_spec.rb'
- 'spec/models/follow_recommendation_suppression_spec.rb'
- 'spec/models/list_account_spec.rb'
- 'spec/models/list_spec.rb'
- 'spec/models/login_activity_spec.rb'
- 'spec/models/mute_spec.rb'
- 'spec/models/preview_card_spec.rb'
- 'spec/models/preview_card_trend_spec.rb'
- 'spec/models/relay_spec.rb'
- 'spec/models/scheduled_status_spec.rb'
- 'spec/models/status_stat_spec.rb'
- 'spec/models/status_trend_spec.rb'
- 'spec/models/system_key_spec.rb'
- 'spec/models/tag_follow_spec.rb'
- 'spec/models/unavailable_domain_spec.rb'
- 'spec/models/user_invite_request_spec.rb'
- 'spec/models/web/setting_spec.rb'
- 'spec/services/unmute_service_spec.rb'
# Configuration parameters: CountAsOne. # Configuration parameters: CountAsOne.
RSpec/ExampleLength: RSpec/ExampleLength:
Max: 22 Max: 22
@ -300,6 +354,43 @@ Rails/ApplicationController:
Exclude: Exclude:
- 'app/controllers/health_controller.rb' - 'app/controllers/health_controller.rb'
# Configuration parameters: Database, Include.
# SupportedDatabases: mysql, postgresql
# Include: db/**/*.rb
Rails/BulkChangeTable:
Exclude:
- 'db/migrate/20160222143943_add_profile_fields_to_accounts.rb'
- 'db/migrate/20160223162837_add_metadata_to_statuses.rb'
- 'db/migrate/20160305115639_add_devise_to_users.rb'
- 'db/migrate/20160314164231_add_owner_to_application.rb'
- 'db/migrate/20160926213048_remove_owner_from_application.rb'
- 'db/migrate/20161003142332_add_confirmable_to_users.rb'
- 'db/migrate/20170112154826_migrate_settings.rb'
- 'db/migrate/20170127165745_add_devise_two_factor_to_users.rb'
- 'db/migrate/20170322143850_change_primary_key_to_bigint_on_statuses.rb'
- 'db/migrate/20170330021336_add_counter_caches.rb'
- 'db/migrate/20170425202925_add_oembed_to_preview_cards.rb'
- 'db/migrate/20170427011934_re_add_owner_to_application.rb'
- 'db/migrate/20170520145338_change_language_filter_to_opt_out.rb'
- 'db/migrate/20170624134742_add_description_to_session_activations.rb'
- 'db/migrate/20170718211102_add_activitypub_to_accounts.rb'
- 'db/migrate/20171006142024_add_uri_to_custom_emojis.rb'
- 'db/migrate/20180812123222_change_relays_enabled.rb'
- 'db/migrate/20190511134027_add_silenced_at_suspended_at_to_accounts.rb'
- 'db/migrate/20190805123746_add_capabilities_to_tags.rb'
- 'db/migrate/20190807135426_add_comments_to_domain_blocks.rb'
- 'db/migrate/20190815225426_add_last_status_at_to_tags.rb'
- 'db/migrate/20190901035623_add_max_score_to_tags.rb'
- 'db/migrate/20200417125749_add_storage_schema_version.rb'
- 'db/migrate/20200608113046_add_sign_in_token_to_users.rb'
- 'db/migrate/20211112011713_add_language_to_preview_cards.rb'
- 'db/migrate/20211231080958_add_category_to_reports.rb'
- 'db/migrate/20220202200743_add_trendable_to_accounts.rb'
- 'db/migrate/20220224010024_add_ips_to_email_domain_blocks.rb'
- 'db/migrate/20220227041951_add_last_used_at_to_oauth_access_tokens.rb'
- 'db/migrate/20220303000827_add_ordered_media_attachment_ids_to_status_edits.rb'
- 'db/migrate/20220824164433_add_human_identifier_to_admin_action_logs.rb'
# Configuration parameters: Include. # Configuration parameters: Include.
# Include: db/**/*.rb # Include: db/**/*.rb
Rails/CreateTableWithTimestamps: Rails/CreateTableWithTimestamps:
@ -575,12 +666,12 @@ Style/FetchEnvVar:
- 'app/lib/translation_service.rb' - 'app/lib/translation_service.rb'
- 'config/environments/development.rb' - 'config/environments/development.rb'
- 'config/environments/production.rb' - 'config/environments/production.rb'
- 'config/initializers/2_limited_federation_mode.rb' - 'config/initializers/2_whitelist_mode.rb'
- 'config/initializers/3_omniauth.rb'
- 'config/initializers/blacklists.rb' - 'config/initializers/blacklists.rb'
- 'config/initializers/cache_buster.rb' - 'config/initializers/cache_buster.rb'
- 'config/initializers/content_security_policy.rb' - 'config/initializers/content_security_policy.rb'
- 'config/initializers/devise.rb' - 'config/initializers/devise.rb'
- 'config/initializers/omniauth.rb'
- 'config/initializers/paperclip.rb' - 'config/initializers/paperclip.rb'
- 'config/initializers/vapid.rb' - 'config/initializers/vapid.rb'
- 'lib/mastodon/premailer_webpack_strategy.rb' - 'lib/mastodon/premailer_webpack_strategy.rb'
@ -748,15 +839,6 @@ Style/RedundantFetchBlock:
- 'config/initializers/paperclip.rb' - 'config/initializers/paperclip.rb'
- 'config/puma.rb' - 'config/puma.rb'
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AllowMultipleReturnValues.
Style/RedundantReturn:
Exclude:
- 'app/controllers/api/v1/directories_controller.rb'
- 'app/controllers/auth/confirmations_controller.rb'
- 'app/lib/ostatus/tag_manager.rb'
- 'app/models/form/import.rb'
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods, MaxChainLength. # Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods, MaxChainLength.
# AllowedMethods: present?, blank?, presence, try, try! # AllowedMethods: present?, blank?, presence, try, try!
@ -814,7 +896,7 @@ Style/StringLiterals:
# AllowedMethods: define_method, mail, respond_to # AllowedMethods: define_method, mail, respond_to
Style/SymbolProc: Style/SymbolProc:
Exclude: Exclude:
- 'config/initializers/3_omniauth.rb' - 'config/initializers/omniauth.rb'
# This cop supports safe autocorrection (--autocorrect). # This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle, AllowSafeAssignment. # Configuration parameters: EnforcedStyle, AllowSafeAssignment.
@ -847,3 +929,9 @@ Style/WordArray:
- 'config/initializers/cors.rb' - 'config/initializers/cors.rb'
- 'spec/controllers/settings/imports_controller_spec.rb' - 'spec/controllers/settings/imports_controller_spec.rb'
- 'spec/models/form/import_spec.rb' - 'spec/models/form/import_spec.rb'
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns.
# URISchemes: http, https
Layout/LineLength:
Max: 701

1676
AUTHORS.md

File diff suppressed because it is too large Load Diff

View File

@ -2,334 +2,6 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
## [4.2.0] - 2023-09-21
The following changelog entries focus on changes visible to users, administrators, client developers or federated software developers, but there has also been a lot of code modernization, refactoring, and tooling work, in particular by [@danielmbrasil](https://github.com/danielmbrasil), [@mjankowski](https://github.com/mjankowski), [@nschonni](https://github.com/nschonni), [@renchap](https://github.com/renchap), and [@takayamaki](https://github.com/takayamaki).
### Added
- **Add full-text search of opted-in public posts and rework search operators** ([Gargron](https://github.com/mastodon/mastodon/pull/26485), [jsgoldstein](https://github.com/mastodon/mastodon/pull/26344), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26657), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26650), [jsgoldstein](https://github.com/mastodon/mastodon/pull/26659), [Gargron](https://github.com/mastodon/mastodon/pull/26660), [Gargron](https://github.com/mastodon/mastodon/pull/26663), [Gargron](https://github.com/mastodon/mastodon/pull/26688), [Gargron](https://github.com/mastodon/mastodon/pull/26689), [Gargron](https://github.com/mastodon/mastodon/pull/26686), [Gargron](https://github.com/mastodon/mastodon/pull/26687), [Gargron](https://github.com/mastodon/mastodon/pull/26692), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26697), [Gargron](https://github.com/mastodon/mastodon/pull/26699), [Gargron](https://github.com/mastodon/mastodon/pull/26701), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26710), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26739), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26754), [Gargron](https://github.com/mastodon/mastodon/pull/26662), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26755), [Gargron](https://github.com/mastodon/mastodon/pull/26781), [Gargron](https://github.com/mastodon/mastodon/pull/26782), [Gargron](https://github.com/mastodon/mastodon/pull/26760), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26756), [Gargron](https://github.com/mastodon/mastodon/pull/26784), [Gargron](https://github.com/mastodon/mastodon/pull/26807), [Gargron](https://github.com/mastodon/mastodon/pull/26835), [Gargron](https://github.com/mastodon/mastodon/pull/26847), [Gargron](https://github.com/mastodon/mastodon/pull/26834), [arbolitoloco1](https://github.com/mastodon/mastodon/pull/26893), [tribela](https://github.com/mastodon/mastodon/pull/26896), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26927), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26959), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/27014))
This introduces a new `public_statuses` Elasticsearch index for public posts by users who have opted in to their posts being searchable (`toot#indexable` flag).
This also revisits the other indexes to provide more useful indexing, and adds new search operators such as `from:me`, `before:2022-11-01`, `after:2022-11-01`, `during:2022-11-01`, `language:fr`, `has:poll`, or `in:library` (for searching only in posts you have written or interacted with).
Results are now ordered chronologically.
- **Add admin notifications for new Mastodon versions** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26582))
This is done by querying `https://api.joinmastodon.org/update-check` every 30 minutes in a background job.
That URL can be changed using the `UPDATE_CHECK_URL` environment variable, and the feature outright disabled by setting that variable to an empty string (`UPDATE_CHECK_URL=`).
- **Add “Privacy and reach” tab in profile settings** ([Gargron](https://github.com/mastodon/mastodon/pull/26484), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26508))
This reorganized scattered privacy and reach settings to a single place, as well as improve their wording.
- **Add display of out-of-band hashtags in the web interface** ([Gargron](https://github.com/mastodon/mastodon/pull/26492), [arbolitoloco1](https://github.com/mastodon/mastodon/pull/26497), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26506), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26525), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26606), [Gargron](https://github.com/mastodon/mastodon/pull/26666), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26960))
- **Add role badges to the web interface** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25649), [Gargron](https://github.com/mastodon/mastodon/pull/26281))
- **Add ability to pick domains to forward reports to using the `forward_to_domains` parameter in `POST /api/v1/reports`** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25866), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26636))
The `forward_to_domains` REST API parameter is a list of strings. If it is empty or omitted, the previous behavior is maintained.
The `forward` parameter still needs to be set for `forward_to_domains` to be taken into account.
The forwarded-to domains can only include that of the original author and people being replied to.
- **Add forwarding of reported replies to servers being replied to** ([Gargron](https://github.com/mastodon/mastodon/pull/25341), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26189))
- Add `ONE_CLICK_SSO_LOGIN` environment variable to directly link to the Single-Sign On provider if there is only one sign up method available ([CSDUMMI](https://github.com/mastodon/mastodon/pull/26083), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26368), [CSDUMMI](https://github.com/mastodon/mastodon/pull/26857), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26901))
- **Add webhook templating** ([Gargron](https://github.com/mastodon/mastodon/pull/23289))
- **Add webhooks for local `status.created`, `status.updated`, `account.updated` and `report.updated`** ([VyrCossont](https://github.com/mastodon/mastodon/pull/24133), [VyrCossont](https://github.com/mastodon/mastodon/pull/24243), [VyrCossont](https://github.com/mastodon/mastodon/pull/24211))
- **Add exclusive lists** ([dariusk, necropolina](https://github.com/mastodon/mastodon/pull/22048), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25324))
- **Add a confirmation screen when suspending a domain** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25144), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25603))
- **Add support for importing lists** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25203), [mgmn](https://github.com/mastodon/mastodon/pull/26120), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26372))
- **Add optional hCaptcha support** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25019), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25057), [Gargron](https://github.com/mastodon/mastodon/pull/25395), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26388))
- **Add lines to threads in web UI** ([Gargron](https://github.com/mastodon/mastodon/pull/24549), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24677), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24696), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24711), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24714), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24713), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24715), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24800), [teeerevor](https://github.com/mastodon/mastodon/pull/25706), [renchap](https://github.com/mastodon/mastodon/pull/25807))
- **Add new onboarding flow to web UI** ([Gargron](https://github.com/mastodon/mastodon/pull/24619), [Gargron](https://github.com/mastodon/mastodon/pull/24646), [Gargron](https://github.com/mastodon/mastodon/pull/24705), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24872), [ThisIsMissEm](https://github.com/mastodon/mastodon/pull/24883), [Gargron](https://github.com/mastodon/mastodon/pull/24954), [stevenjlm](https://github.com/mastodon/mastodon/pull/24959), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25010), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25275), [Gargron](https://github.com/mastodon/mastodon/pull/25559), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25561))
- **Add auto-refresh of accounts we get new messages/edits of** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26510))
- **Add Elasticsearch cluster health check and indexes mismatch check to dashboard** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26448), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26605), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26658))
- Add `hide_collections`, `discoverable` and `indexable` attributes to credentials API ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26998))
- Add `S3_ENABLE_CHECKSUM_MODE` environment variable to enable checksum verification on compatible S3-providers ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26435))
- Add admin API for managing tags ([rrgeorge](https://github.com/mastodon/mastodon/pull/26872))
- Add a link to hashtag timelines from the Trending hashtags moderation interface ([gunchleoc](https://github.com/mastodon/mastodon/pull/26724))
- Add timezone to datetimes in e-mails ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26822))
- Add `authorized_fetch` server setting in addition to env var ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25798), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26958))
- Add avatar image to webfinger responses ([tvler](https://github.com/mastodon/mastodon/pull/26558))
- Add debug logging on signature verification failure ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26637), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26812))
- Add explicit error messages when DeepL quota is exceeded ([lutoma](https://github.com/mastodon/mastodon/pull/26704))
- Add Elasticsearch/OpenSearch version to “Software” in admin dashboard ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26652))
- Add `data-nosnippet` attribute to remote posts and local posts with `noindex` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26648))
- Add support for federating `memorial` attribute ([rrgeorge](https://github.com/mastodon/mastodon/pull/26583))
- Add Cherokee and Kalmyk to languages dropdown ([gunchleoc](https://github.com/mastodon/mastodon/pull/26012), [gunchleoc](https://github.com/mastodon/mastodon/pull/26013))
- Add `DELETE /api/v1/profile/avatar` and `DELETE /api/v1/profile/header` to the REST API ([danielmbrasil](https://github.com/mastodon/mastodon/pull/25124), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26573))
- Add `ES_PRESET` option to customize numbers of shards and replicas ([Gargron](https://github.com/mastodon/mastodon/pull/26483), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26489))
This can have a value of `single_node_cluster` (default), `small_cluster` (uses one replica) or `large_cluster` (uses one replica and a higher number of shards).
- Add `CACHE_BUSTER_HTTP_METHOD` environment variable ([renchap](https://github.com/mastodon/mastodon/pull/26528), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26542))
- Add support for `DB_PASS` when using `DATABASE_URL` ([ThisIsMissEm](https://github.com/mastodon/mastodon/pull/26295))
- Add `GET /api/v1/instance/languages` to REST API ([danielmbrasil](https://github.com/mastodon/mastodon/pull/24443))
- Add primary key to `preview_cards_statuses` join table ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25243), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26384), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26447), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26737), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26979))
- Add client-side timeout on resend confirmation button ([Gargron](https://github.com/mastodon/mastodon/pull/26300))
- Add published date and author to news on the explore screen in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/26155))
- Add `lang` attribute to various UI components ([c960657](https://github.com/mastodon/mastodon/pull/23869), [c960657](https://github.com/mastodon/mastodon/pull/23891), [c960657](https://github.com/mastodon/mastodon/pull/26111), [c960657](https://github.com/mastodon/mastodon/pull/26149))
- Add stricter protocol fields validation for accounts ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25937))
- Add support for Azure blob storage ([mistydemeo](https://github.com/mastodon/mastodon/pull/23607), [mistydemeo](https://github.com/mastodon/mastodon/pull/26080))
- Add toast with option to open post after publishing in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/25564), [Signez](https://github.com/mastodon/mastodon/pull/25919), [Gargron](https://github.com/mastodon/mastodon/pull/26664))
- Add canonical link tags in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/25715))
- Add button to see results for polls in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/25726))
- Add at-symbol prepended to mention span title ([forsamori](https://github.com/mastodon/mastodon/pull/25684))
- Add users index on `unconfirmed_email` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25672), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25702))
- Add superapp index on `oauth_applications` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25670))
- Add index to backups on `user_id` column ([mjankowski](https://github.com/mastodon/mastodon/pull/25647))
- Add onboarding prompt when home feed too slow in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/25267), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25556), [Gargron](https://github.com/mastodon/mastodon/pull/25579), [renchap](https://github.com/mastodon/mastodon/pull/25580), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25581), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25617), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25917), [Gargron](https://github.com/mastodon/mastodon/pull/26829), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26935))
- Add `POST /api/v1/conversations/:id/unread` API endpoint to mark a conversation as unread ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25509))
- Add `translate="no"` to outgoing mentions and links ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25524))
- Add unsubscribe link and headers to e-mails ([Gargron](https://github.com/mastodon/mastodon/pull/25378), [c960657](https://github.com/mastodon/mastodon/pull/26085))
- Add logging of websocket send errors ([ThisIsMissEm](https://github.com/mastodon/mastodon/pull/25280))
- Add time zone preference ([Gargron](https://github.com/mastodon/mastodon/pull/25342), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26025))
- Add `legal` as report category ([Gargron](https://github.com/mastodon/mastodon/pull/23941), [renchap](https://github.com/mastodon/mastodon/pull/25400), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26509))
- Add `data-nosnippet` so Google doesn't use trending posts in snippets for `/` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25279))
- Add card with who invited you to join when displaying rules on sign-up ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23475))
- Add missing primary keys to `accounts_tags` and `statuses_tags` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25210))
- Add support for custom sign-up URLs ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25014), [renchap](https://github.com/mastodon/mastodon/pull/25108), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25190), [mgmn](https://github.com/mastodon/mastodon/pull/25531))
This is set using `SSO_ACCOUNT_SIGN_UP` and reflected in the REST API by adding `registrations.sign_up_url` to the `/api/v2/instance` endpoint.
- Add polling and automatic redirection to `/start` on email confirmation ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25013))
- Add ability to block sign-ups from IP using the CLI ([danielmbrasil](https://github.com/mastodon/mastodon/pull/24870))
- Add ALT badges to media that has alternative text in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/24782), [c960657](https://github.com/mastodon/mastodon/pull/26166)
- Add ability to include accounts with pending follow requests in lists ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19727), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24810))
- Add trend management to admin API ([rrgeorge](https://github.com/mastodon/mastodon/pull/24257))
- `POST /api/v1/admin/trends/statuses/:id/approve`
- `POST /api/v1/admin/trends/statuses/:id/reject`
- `POST /api/v1/admin/trends/links/:id/approve`
- `POST /api/v1/admin/trends/links/:id/reject`
- `POST /api/v1/admin/trends/tags/:id/approve`
- `POST /api/v1/admin/trends/tags/:id/reject`
- `GET /api/v1/admin/trends/links/publishers`
- `POST /api/v1/admin/trends/links/publishers/:id/approve`
- `POST /api/v1/admin/trends/links/publishers/:id/reject`
- Add user handle to notification mail recipient address ([HeitorMC](https://github.com/mastodon/mastodon/pull/24240))
- Add progress indicator to sign-up flow ([Gargron](https://github.com/mastodon/mastodon/pull/24545))
- Add client-side validation for taken username in sign-up form ([Gargron](https://github.com/mastodon/mastodon/pull/24546))
- Add `--approve` option to `tootctl accounts create` ([danielmbrasil](https://github.com/mastodon/mastodon/pull/24533))
- Add “In Memoriam” banner back to profiles ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23591), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/23614))
This adds the `memorial` attribute to the `Account` REST API entity.
- Add colour to follow button when hashtag is being followed ([c960657](https://github.com/mastodon/mastodon/pull/24361))
- Add further explanations to the profile link verification instructions ([drzax](https://github.com/mastodon/mastodon/pull/19723))
- Add a link to Identity provider's account settings from the account settings ([CSDUMMI](https://github.com/mastodon/mastodon/pull/24100), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24628))
- Add support for streaming server to connect to postgres with self-signed certs through the `sslmode` URL parameter ([ramuuns](https://github.com/mastodon/mastodon/pull/21431))
- Add support for specifying S3 storage classes through the `S3_STORAGE_CLASS` environment variable ([hyl](https://github.com/mastodon/mastodon/pull/22480))
- Add support for incoming rich text ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23913))
- Add support for Ruby 3.2 ([tenderlove](https://github.com/mastodon/mastodon/pull/22928), [casperisfine](https://github.com/mastodon/mastodon/pull/24142), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24202), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26934))
- Add API parameter to safeguard unexpected mentions in new posts ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18350))
### Changed
- **Change hashtags to be displayed separately when they are the last line of a post** ([renchap](https://github.com/mastodon/mastodon/pull/26499), [renchap](https://github.com/mastodon/mastodon/pull/26614), [renchap](https://github.com/mastodon/mastodon/pull/26615))
- **Change reblogs to be excluded from "Posts and replies" tab in web UI** ([Gargron](https://github.com/mastodon/mastodon/pull/26302))
- **Change interaction modal in web interface** ([Gargron, ClearlyClaire](https://github.com/mastodon/mastodon/pull/26075), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26269), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26268), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26267), [mgmn](https://github.com/mastodon/mastodon/pull/26459), [tribela](https://github.com/mastodon/mastodon/pull/26461), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26593), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26795))
- **Change design of link previews in web UI** ([Gargron](https://github.com/mastodon/mastodon/pull/26136), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26151), [Gargron](https://github.com/mastodon/mastodon/pull/26153), [Gargron](https://github.com/mastodon/mastodon/pull/26250), [Gargron](https://github.com/mastodon/mastodon/pull/26287), [Gargron](https://github.com/mastodon/mastodon/pull/26286), [c960657](https://github.com/mastodon/mastodon/pull/26184))
- **Change "direct message" nomenclature to "private mention" in web UI** ([Gargron](https://github.com/mastodon/mastodon/pull/24248))
- **Change translation feature to cover Content Warnings, poll options and media descriptions** ([c960657](https://github.com/mastodon/mastodon/pull/24175), [S-H-GAMELINKS](https://github.com/mastodon/mastodon/pull/25251), [c960657](https://github.com/mastodon/mastodon/pull/26168), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26452))
- **Change account search to match by text when opted-in** ([jsgoldstein](https://github.com/mastodon/mastodon/pull/25599), [Gargron](https://github.com/mastodon/mastodon/pull/26378))
- **Change import feature to be clearer, less error-prone and more reliable** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/21054), [mgmn](https://github.com/mastodon/mastodon/pull/24874))
- **Change local and federated timelines to be tabs of a single “Live feeds” column** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25641), [Gargron](https://github.com/mastodon/mastodon/pull/25683), [mgmn](https://github.com/mastodon/mastodon/pull/25694), [Plastikmensch](https://github.com/mastodon/mastodon/pull/26247), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26633))
- **Change user archive export to be faster and more reliable, and export `.zip` archives instead of `.tar.gz` ones** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23360), [TheEssem](https://github.com/mastodon/mastodon/pull/25034))
- **Change `mastodon-streaming` systemd unit files to be templated** ([e-nomem](https://github.com/mastodon/mastodon/pull/24751))
- **Change `statsd` integration to disable sidekiq metrics by default** ([mjankowski](https://github.com/mastodon/mastodon/pull/25265), [mjankowski](https://github.com/mastodon/mastodon/pull/25336), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26310))
This deprecates `statsd` support and disables the sidekiq integration unless `STATSD_SIDEKIQ` is set to `true`.
This is because the `nsa` gem is unmaintained, and its sidekiq integration is known to add very significant overhead.
Later versions of Mastodon will have other ways to get the same metrics.
- **Change replica support to native Rails adapter** ([krainboltgreene](https://github.com/mastodon/mastodon/pull/25693), [Gargron](https://github.com/mastodon/mastodon/pull/25849), [Gargron](https://github.com/mastodon/mastodon/pull/25874), [Gargron](https://github.com/mastodon/mastodon/pull/25851), [Gargron](https://github.com/mastodon/mastodon/pull/25977), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26074), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26326), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26386), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26856))
This is a breaking change, dropping `makara` support, and requiring you to update your database configuration if you are using replicas.
To tell Mastodon to use a read replica, you can either set the `REPLICA_DB_NAME` environment variable (along with `REPLICA_DB_USER`, `REPLICA_DB_PASS`, `REPLICA_DB_HOST`, and `REPLICA_DB_PORT`, if they differ from the primary database), or the `REPLICA_DATABASE_URL` environment variable if your configuration is based on `DATABASE_URL`.
- Change DCT method used for JPEG encoding to float ([electroCutie](https://github.com/mastodon/mastodon/pull/26675))
- Change from `node-redis` to `ioredis` for streaming ([gmemstr](https://github.com/mastodon/mastodon/pull/26581))
- Change private statuses index to index without crutches ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26713))
- Change video compression parameters ([Gargron](https://github.com/mastodon/mastodon/pull/26631), [Gargron](https://github.com/mastodon/mastodon/pull/26745), [Gargron](https://github.com/mastodon/mastodon/pull/26766), [Gargron](https://github.com/mastodon/mastodon/pull/26970))
- Change admin e-mail notification settings to be their own settings group ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26596))
- Change opacity of the delete icon in the search field to be more visible ([AntoninDelFabbro](https://github.com/mastodon/mastodon/pull/26449))
- Change Account Search to prioritize username over display name ([jsgoldstein](https://github.com/mastodon/mastodon/pull/26623))
- Change follow recommendation materialized view to be faster in most cases ([renchap, ClearlyClaire](https://github.com/mastodon/mastodon/pull/26545))
- Change `robots.txt` to block GPTBot ([Foritus](https://github.com/mastodon/mastodon/pull/26396))
- Change header of hashtag timelines in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/26362), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26416))
- Change streaming `/metrics` to include additional metrics ([ThisIsMissEm](https://github.com/mastodon/mastodon/pull/26299), [ThisIsMissEm](https://github.com/mastodon/mastodon/pull/26945))
- Change indexing frequency from 5 minutes to 1 minute, add locks to schedulers ([Gargron](https://github.com/mastodon/mastodon/pull/26304))
- Change column link to add a better keyboard focus indicator ([teeerevor](https://github.com/mastodon/mastodon/pull/26278))
- Change poll form element colors to fit with the rest of the ui ([teeerevor](https://github.com/mastodon/mastodon/pull/26139), [teeerevor](https://github.com/mastodon/mastodon/pull/26162), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26164))
- Change 'favourite' to 'favorite' for American English ([marekr](https://github.com/mastodon/mastodon/pull/24667), [gunchleoc](https://github.com/mastodon/mastodon/pull/26009), [nabijaczleweli](https://github.com/mastodon/mastodon/pull/26109))
- Change ActivityStreams representation of suspended accounts to not use a blank `name` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25276))
- Change focus UI for keyboard only input ([teeerevor](https://github.com/mastodon/mastodon/pull/25935), [Gargron](https://github.com/mastodon/mastodon/pull/26125), [Gargron](https://github.com/mastodon/mastodon/pull/26767))
- Change thread view to scroll to the selected post rather than the post being replied to ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/24685))
- Change links in multi-column mode so tabs are open in single-column mode ([Signez](https://github.com/mastodon/mastodon/pull/25893), [Signez](https://github.com/mastodon/mastodon/pull/26070), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25973), [Signez](https://github.com/mastodon/mastodon/pull/26019), [Signez](https://github.com/mastodon/mastodon/pull/26759))
- Change searching with `#` to include account index ([jsgoldstein](https://github.com/mastodon/mastodon/pull/25638))
- Change label and design of sensitive and unavailable media in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/25712), [Gargron](https://github.com/mastodon/mastodon/pull/26135), [Gargron](https://github.com/mastodon/mastodon/pull/26330))
- Change button colors to increase hover/focus contrast and consistency ([teeerevor](https://github.com/mastodon/mastodon/pull/25677), [Gargron](https://github.com/mastodon/mastodon/pull/25679))
- Change dropdown icon above compose form from ellipsis to bars in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/25661))
- Change header backgrounds to use fewer different colors in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/25577))
- Change files to be deleted in batches instead of one-by-one ([Gargron](https://github.com/mastodon/mastodon/pull/23302), [S-H-GAMELINKS](https://github.com/mastodon/mastodon/pull/25586), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25587))
- Change emoji picker icon ([iparr](https://github.com/mastodon/mastodon/pull/25479))
- Change edit profile page ([Gargron](https://github.com/mastodon/mastodon/pull/25413), [c960657](https://github.com/mastodon/mastodon/pull/26538))
- Change "bot" label to "automated" ([Gargron](https://github.com/mastodon/mastodon/pull/25356))
- Change design of dropdowns in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/25107))
- Change wording of “Content cache retention period” setting to highlight destructive implications ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23261))
- Change autolinking to allow carets in URL search params ([renchap](https://github.com/mastodon/mastodon/pull/25216))
- Change share action from being in action bar to being in dropdown in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/25105))
- Change sessions to be ordered from most-recent to least-recently updated ([frankieroberto](https://github.com/mastodon/mastodon/pull/25005))
- Change vacuum scheduler to also delete expired tokens and unused application records ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/24868), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24871))
- Change "Sign in" to "Login" ([Gargron](https://github.com/mastodon/mastodon/pull/24942))
- Change domain suspensions to also be checked before trying to fetch unknown remote resources ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/24535))
- Change media components to use aspect-ratio rather than compute height themselves ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/24686), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24943), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26801))
- Change logo version in header based on screen size in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/24707))
- Change label from "For you" to "People" on explore screen in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/24706))
- Change logged-out WebUI HTML pages to be cached for a few seconds ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/24708))
- Change unauthenticated responses to be cached in REST API ([Gargron](https://github.com/mastodon/mastodon/pull/24348), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24662), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24665))
- Change HTTP caching logic ([Gargron](https://github.com/mastodon/mastodon/pull/24347), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24604))
- Change hashtags and mentions in bios to open in-app in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/24643))
- Change styling of the recommended accounts to allow bio to be more visible ([chike00](https://github.com/mastodon/mastodon/pull/24480))
- Change account search in moderation interface to allow searching by username including the leading `@` ([HeitorMC](https://github.com/mastodon/mastodon/pull/24242))
- Change all components to use the same error page in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/24512))
- Change search pop-out in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/24305))
- Change user settings to be stored in a more optimal way ([Gargron](https://github.com/mastodon/mastodon/pull/23630), [c960657](https://github.com/mastodon/mastodon/pull/24321), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24453), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24460), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24558), [Gargron](https://github.com/mastodon/mastodon/pull/24761), [Gargron](https://github.com/mastodon/mastodon/pull/24783), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25508), [jsgoldstein](https://github.com/mastodon/mastodon/pull/25340), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26884), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/27012))
- Change media upload limits and remove client-side resizing ([Gargron](https://github.com/mastodon/mastodon/pull/23726))
- Change design of account rows in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/24247), [Gargron](https://github.com/mastodon/mastodon/pull/24343), [Gargron](https://github.com/mastodon/mastodon/pull/24956), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25131))
- Change log-out to use Single Logout when using external log-in through OIDC ([CSDUMMI](https://github.com/mastodon/mastodon/pull/24020))
- Change sidekiq-bulk's batch size from 10,000 to 1,000 jobs in one Redis call ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/24034))
- Change translation to only be offered for supported languages ([c960657](https://github.com/mastodon/mastodon/pull/23879), [c960657](https://github.com/mastodon/mastodon/pull/24037))
This adds the `/api/v1/instance/translation_languages` REST API endpoint that returns an object with the supported translation language pairs in the form:
```json
{
"fr": ["en", "de"]
}
```
(where `fr` is a supported source language and `en` and `de` or supported output language when translating a `fr` string)
- Change compose form checkbox to native input with `appearance: none` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/22949))
- Change posts' clickable area to be larger ([c960657](https://github.com/mastodon/mastodon/pull/23621))
- Change `followed_by` link to `location=all` if account is local on /admin/accounts/:id page ([tribela](https://github.com/mastodon/mastodon/pull/23467))
### Removed
- **Remove support for Node.js 14** ([renchap](https://github.com/mastodon/mastodon/pull/25198))
- **Remove support for Ruby 2.7** ([nschonni](https://github.com/mastodon/mastodon/pull/24237))
- **Remove clustering from streaming API** ([ThisIsMissEm](https://github.com/mastodon/mastodon/pull/24655))
- **Remove anonymous access to the streaming API** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23989))
- Remove obfuscation of reply count in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/26768))
- Remove `kmr` from language selection, as it was a duplicate for `ku` ([gunchleoc](https://github.com/mastodon/mastodon/pull/26014), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26787))
- Remove 16:9 cropping from web UI ([Gargron](https://github.com/mastodon/mastodon/pull/26132))
- Remove back button from bookmarks, favourites and lists screens in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/26126))
- Remove display name input from sign-up form ([Gargron](https://github.com/mastodon/mastodon/pull/24704))
- Remove `tai` locale ([c960657](https://github.com/mastodon/mastodon/pull/23880))
- Remove empty Kushubian (csb) local files ([nschonni](https://github.com/mastodon/mastodon/pull/24151))
- Remove `Permissions-Policy` header from all responses ([Gargron](https://github.com/mastodon/mastodon/pull/24124))
### Fixed
- **Fix filters not being applying in the explore page** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25887))
- **Fix being unable to load past a full page of filtered posts in Home timeline** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/24930))
- **Fix log-in flow when involving both OAuth and external authentication** ([CSDUMMI](https://github.com/mastodon/mastodon/pull/24073))
- **Fix broken links in account gallery** ([c960657](https://github.com/mastodon/mastodon/pull/24218))
- **Fix migration handler not updating lists** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/24808))
- Fix crash when viewing a moderation appeal and the moderator account has been deleted ([xrobau](https://github.com/mastodon/mastodon/pull/25900))
- Fix error in Web UI when server rules cannot be fetched ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26957))
- Fix paragraph margins resulting in irregular read-more cut-off in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/26828))
- Fix notification permissions being requested immediately after login ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26472))
- Fix performances of profile directory ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26840), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26842))
- Fix mute button and volume slider feeling disconnected in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/26827), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26860))
- Fix “Scoped order is ignored, it's forced to be batch order.” warnings ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26793))
- Fix blocked domain appearing in account feeds ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26823))
- Fix invalid `Content-Type` header for WebP images ([c960657](https://github.com/mastodon/mastodon/pull/26773))
- Fix minor inefficiencies in `tootctl search deploy` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26721))
- Fix filter form in profiles directory overflowing instead of wrapping ([arbolitoloco1](https://github.com/mastodon/mastodon/pull/26682))
- Fix sign up steps progress layout in right-to-left locales ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26728))
- Fix bug with “favorited by” and “reblogged by“ view on posts only showing up to 40 items ([timothyjrogers](https://github.com/mastodon/mastodon/pull/26577), [timothyjrogers](https://github.com/mastodon/mastodon/pull/26574))
- Fix bad search type heuristic ([Gargron](https://github.com/mastodon/mastodon/pull/26673))
- Fix not being able to negate prefix clauses in search ([Gargron](https://github.com/mastodon/mastodon/pull/26672))
- Fix timeout on invalid set of exclusionary parameters in `/api/v1/timelines/public` ([danielmbrasil](https://github.com/mastodon/mastodon/pull/26239))
- Fix adding column with default value taking longer on Postgres >= 11 ([Gargron](https://github.com/mastodon/mastodon/pull/26375))
- Fix light theme select option for hashtags ([teeerevor](https://github.com/mastodon/mastodon/pull/26311))
- Fix AVIF attachments ([c960657](https://github.com/mastodon/mastodon/pull/26264))
- Fix incorrect URL normalization when fetching remote resources ([c960657](https://github.com/mastodon/mastodon/pull/26219), [c960657](https://github.com/mastodon/mastodon/pull/26285))
- Fix being unable to filter posts for individual Chinese languages ([gunchleoc](https://github.com/mastodon/mastodon/pull/26066))
- Fix preview card sometimes linking to 4xx error pages ([c960657](https://github.com/mastodon/mastodon/pull/26200))
- Fix emoji picker button scrolling with textarea content in single-column view ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25304))
- Fix missing border on error screen in light theme in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/26152))
- Fix UI overlap with the loupe icon in the Explore Tab ([gol-cha](https://github.com/mastodon/mastodon/pull/26113))
- Fix unexpected redirection to `/explore` after sign-in ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26143))
- Fix `/api/v1/statuses/:id/unfavourite` and `/api/v1/statuses/:id/unreblog` returning non-updated counts ([c960657](https://github.com/mastodon/mastodon/pull/24365))
- Fix clicking the “Back” button sometimes leading out of Mastodon ([c960657](https://github.com/mastodon/mastodon/pull/23953), [CSFlorin](https://github.com/mastodon/mastodon/pull/24835), [S-H-GAMELINKS](https://github.com/mastodon/mastodon/pull/24867), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25281))
- Fix processing of `null` ActivityPub activities ([tribela](https://github.com/mastodon/mastodon/pull/26021))
- Fix hashtag posts not being removed from home feed on hashtag unfollow ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26028))
- Fix for "follows you" indicator in light web UI not readable ([vmstan](https://github.com/mastodon/mastodon/pull/25993))
- Fix incorrect line break between icon and number of reposts & favourites ([edent](https://github.com/mastodon/mastodon/pull/26004))
- Fix sounds not being loaded from assets host ([Signez](https://github.com/mastodon/mastodon/pull/25931))
- Fix buttons showing inconsistent styles ([teeerevor](https://github.com/mastodon/mastodon/pull/25903), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25965), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26341), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/26482))
- Fix trend calculation working on too many items at a time ([Gargron](https://github.com/mastodon/mastodon/pull/25835))
- Fix dropdowns being disabled for logged out users in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/25714), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25964))
- Fix explore page being inaccessible when opted-out of trends in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/25716))
- Fix re-activated accounts possibly getting deleted by `AccountDeletionWorker` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25711))
- Fix `/api/v2/search` not working with following query param ([danielmbrasil](https://github.com/mastodon/mastodon/pull/25681))
- Fix inefficient query when requesting a new confirmation email from a logged-in account ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25669))
- Fix unnecessary concurrent calls to `/api/*/instance` in web UI ([mgmn](https://github.com/mastodon/mastodon/pull/25663))
- Fix resolving local URL for remote content ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25637))
- Fix search not being easily findable on smaller screens in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/25576), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/25631))
- Fix j/k keyboard shortcuts on some status lists ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25554))
- Fix missing validation on `default_privacy` setting ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25513))
- Fix incorrect pagination headers in `/api/v2/admin/accounts` ([danielmbrasil](https://github.com/mastodon/mastodon/pull/25477))
- Fix non-interactive upload container being given a `button` role and tabIndex ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25462))
- Fix always redirecting to onboarding in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/25396))
- Fix inconsistent use of middle dot (·) instead of bullet (•) to separate items ([j-f1](https://github.com/mastodon/mastodon/pull/25248))
- Fix spacing of middle dots in the detailed status meta section ([j-f1](https://github.com/mastodon/mastodon/pull/25247))
- Fix prev/next buttons color in media viewer ([renchap](https://github.com/mastodon/mastodon/pull/25231))
- Fix email addresses not being properly updated in `tootctl maintenance fix-duplicates` ([mjankowski](https://github.com/mastodon/mastodon/pull/25118))
- Fix unicode surrogate pairs sometimes being broken in page title ([eai04191](https://github.com/mastodon/mastodon/pull/25148))
- Fix various inefficient queries against account domains ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25126))
- Fix video player offering to expand in a lightbox when it's in an `iframe` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25067))
- Fix post embed previews ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25071))
- Fix inadequate error handling in several API controllers when given invalid parameters ([danielmbrasil](https://github.com/mastodon/mastodon/pull/24947), [danielmbrasil](https://github.com/mastodon/mastodon/pull/24958), [danielmbrasil](https://github.com/mastodon/mastodon/pull/25063), [danielmbrasil](https://github.com/mastodon/mastodon/pull/25072), [danielmbrasil](https://github.com/mastodon/mastodon/pull/25386), [danielmbrasil](https://github.com/mastodon/mastodon/pull/25595))
- Fix uncaught `ActiveRecord::StatementInvalid` in Mastodon::IpBlocksCLI ([danielmbrasil](https://github.com/mastodon/mastodon/pull/24861))
- Fix various edge cases with local moves ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/24812))
- Fix `tootctl accounts cull` crashing when encountering a domain resolving to a private address ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23378))
- Fix `tootctl accounts approve --number N` not aproving the N earliest registrations ([danielmbrasil](https://github.com/mastodon/mastodon/pull/24605))
- Fix being unable to clear media description when editing posts ([c960657](https://github.com/mastodon/mastodon/pull/24720))
- Fix unavailable translations not falling back to English ([mgmn](https://github.com/mastodon/mastodon/pull/24727))
- Fix anonymous visitors getting a session cookie on first visit ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/24584), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24650), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24664))
- Fix cutting off first letter of hashtag links sometimes in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/24623))
- Fix crash in `tootctl accounts create --reattach --force` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/24557), [danielmbrasil](https://github.com/mastodon/mastodon/pull/24680))
- Fix characters being emojified even when using Variation Selector 15 (text) ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/20949), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/24615))
- Fix uncaught ActiveRecord::StatementInvalid exception in `Mastodon::AccountsCLI#approve` ([danielmbrasil](https://github.com/mastodon/mastodon/pull/24590))
- Fix email confirmation skip option in `tootctl accounts modify USERNAME --email EMAIL --confirm` ([danielmbrasil](https://github.com/mastodon/mastodon/pull/24578))
- Fix tooltip for dates without time ([c960657](https://github.com/mastodon/mastodon/pull/24244))
- Fix missing loading spinner and loading more on scroll in Private Mentions column ([c960657](https://github.com/mastodon/mastodon/pull/24446))
- Fix account header image missing from `/settings/profile` on narrow screens ([c960657](https://github.com/mastodon/mastodon/pull/24433))
- Fix height of announcements not being updated when using reduced animations ([c960657](https://github.com/mastodon/mastodon/pull/24354))
- Fix inconsistent radius in advanced interface drawer ([thislight](https://github.com/mastodon/mastodon/pull/24407))
- Fix loading more trending posts on scroll in the advanced interface ([OmmyZhang](https://github.com/mastodon/mastodon/pull/24314))
- Fix poll ending notification for edited polls ([c960657](https://github.com/mastodon/mastodon/pull/24311))
- Fix max width of media in `/about` and `/privacy-policy` ([mgmn](https://github.com/mastodon/mastodon/pull/24180))
- Fix streaming API not being usable without `DATABASE_URL` ([Gargron](https://github.com/mastodon/mastodon/pull/23960))
- Fix external authentication not running onboarding code for new users ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/23458))
## [4.1.8] - 2023-09-19
### Fixed
- Fix post edits not being forwarded as expected ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26936))
- Fix moderator rights inconsistencies ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26729))
- Fix crash when encountering invalid URL ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26814))
- Fix cached posts including stale stats ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26409))
- Fix uploading of video files for which `ffprobe` reports `0/0` average framerate ([NicolaiSoeborg](https://github.com/mastodon/mastodon/pull/26500))
- Fix unexpected audio stream transcoding when uploaded video is eligible to passthrough ([yufushiro](https://github.com/mastodon/mastodon/pull/26608))
### Security
- Fix missing HTML sanitization in translation API (CVE-2023-42452, [GHSA-2693-xr3m-jhqr](https://github.com/mastodon/mastodon/security/advisories/GHSA-2693-xr3m-jhqr))
- Fix incorrect domain name normalization (CVE-2023-42451, [GHSA-v3xf-c9qf-j667](https://github.com/mastodon/mastodon/security/advisories/GHSA-v3xf-c9qf-j667))
## [4.1.7] - 2023-09-05
### Changed
- Change remote report processing to accept reports with long comments, but truncate them ([ThisIsMissEm](https://github.com/mastodon/mastodon/pull/25028))
### Fixed
- **Fix blocking subdomains of an already-blocked domain** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26392))
- Fix `/api/v1/timelines/tag/:hashtag` allowing for unauthenticated access when public preview is disabled ([danielmbrasil](https://github.com/mastodon/mastodon/pull/26237))
- Fix inefficiencies in `PlainTextFormatter` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26727))
## [4.1.6] - 2023-07-31
### Fixed
- Fix memory leak in streaming server ([ThisIsMissEm](https://github.com/mastodon/mastodon/pull/26228))
- Fix wrong filters sometimes applying in streaming ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26159), [ThisIsMissEm](https://github.com/mastodon/mastodon/pull/26213), [renchap](https://github.com/mastodon/mastodon/pull/26233))
- Fix incorrect connect timeout in outgoing requests ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26116))
## [4.1.5] - 2023-07-21 ## [4.1.5] - 2023-07-21
### Added ### Added

View File

@ -1,6 +1,6 @@
# syntax=docker/dockerfile:1.4 # syntax=docker/dockerfile:1.4
# This needs to be bookworm-slim because the Ruby image is built on bookworm-slim # This needs to be bullseye-slim because the Ruby image is built on bullseye-slim
ARG NODE_VERSION="20.6-bookworm-slim" ARG NODE_VERSION="16.20-bullseye-slim"
FROM ghcr.io/moritzheiber/ruby-jemalloc:3.2.2-slim as ruby FROM ghcr.io/moritzheiber/ruby-jemalloc:3.2.2-slim as ruby
FROM node:${NODE_VERSION} as build FROM node:${NODE_VERSION} as build
@ -17,11 +17,10 @@ COPY Gemfile* package.json yarn.lock /opt/mastodon/
# hadolint ignore=DL3008 # hadolint ignore=DL3008
RUN apt-get update && \ RUN apt-get update && \
apt-get -yq dist-upgrade && \
apt-get install -y --no-install-recommends build-essential \ apt-get install -y --no-install-recommends build-essential \
git \ git \
libicu-dev \ libicu-dev \
libidn-dev \ libidn11-dev \
libpq-dev \ libpq-dev \
libjemalloc-dev \ libjemalloc-dev \
zlib1g-dev \ zlib1g-dev \
@ -43,8 +42,8 @@ RUN apt-get update && \
FROM node:${NODE_VERSION} FROM node:${NODE_VERSION}
# Use those args to specify your own version flags & suffixes # Use those args to specify your own version flags & suffixes
ARG MASTODON_VERSION_PRERELEASE="" ARG MASTODON_VERSION_FLAGS=""
ARG MASTODON_VERSION_METADATA="" ARG MASTODON_VERSION_SUFFIX=""
ARG UID="991" ARG UID="991"
ARG GID="991" ARG GID="991"
@ -65,13 +64,13 @@ RUN apt-get update && \
apt-get -y --no-install-recommends install whois \ apt-get -y --no-install-recommends install whois \
wget \ wget \
procps \ procps \
libssl3 \ libssl1.1 \
libpq5 \ libpq5 \
imagemagick \ imagemagick \
ffmpeg \ ffmpeg \
libjemalloc2 \ libjemalloc2 \
libicu72 \ libicu67 \
libidn12 \ libidn11 \
libyaml-0-2 \ libyaml-0-2 \
file \ file \
ca-certificates \ ca-certificates \
@ -90,8 +89,8 @@ ENV RAILS_ENV="production" \
NODE_ENV="production" \ NODE_ENV="production" \
RAILS_SERVE_STATIC_FILES="true" \ RAILS_SERVE_STATIC_FILES="true" \
BIND="0.0.0.0" \ BIND="0.0.0.0" \
MASTODON_VERSION_PRERELEASE="${MASTODON_VERSION_PRERELEASE}" \ MASTODON_VERSION_FLAGS="${MASTODON_VERSION_FLAGS}" \
MASTODON_VERSION_METADATA="${MASTODON_VERSION_METADATA}" MASTODON_VERSION_SUFFIX="${MASTODON_VERSION_SUFFIX}"
# Set the run user # Set the run user
USER mastodon USER mastodon

View File

@ -27,5 +27,4 @@ More information on HTTP Signatures, as well as examples, can be found here: htt
- Linked-Data Signatures: https://docs.joinmastodon.org/spec/security/#ld - Linked-Data Signatures: https://docs.joinmastodon.org/spec/security/#ld
- Bearcaps: https://docs.joinmastodon.org/spec/bearcaps/ - Bearcaps: https://docs.joinmastodon.org/spec/bearcaps/
- Followers collection synchronization: https://codeberg.org/fediverse/fep/src/branch/main/fep/8fcf/fep-8fcf.md - Followers collection synchronization: https://git.activitypub.dev/ActivityPubDev/Fediverse-Enhancement-Proposals/src/branch/main/feps/fep-8fcf.md
- Search indexing consent for actors: https://codeberg.org/fediverse/fep/src/branch/main/fep/5feb/fep-5feb.md

30
Gemfile
View File

@ -35,14 +35,11 @@ group :pam_authentication, optional: true do
end end
gem 'net-ldap', '~> 0.18' gem 'net-ldap', '~> 0.18'
gem 'omniauth-cas', '~> 2.0'
# TODO: Point back at released omniauth-cas gem when PR merged gem 'omniauth-saml', '~> 1.10'
# https://github.com/dlindahl/omniauth-cas/pull/68
gem 'omniauth-cas', github: 'stanhu/omniauth-cas', ref: '4211e6d05941b4a981f9a36b49ec166cecd0e271'
gem 'omniauth-saml', '~> 2.0'
gem 'omniauth_openid_connect', '~> 0.6.1' gem 'omniauth_openid_connect', '~> 0.6.1'
gem 'omniauth', '~> 2.0' gem 'omniauth', '~> 1.9'
gem 'omniauth-rails_csrf_protection', '~> 1.0' gem 'omniauth-rails_csrf_protection', '~> 0.1'
gem 'color_diff', '~> 0.1' gem 'color_diff', '~> 0.1'
gem 'discard', '~> 1.2' gem 'discard', '~> 1.2'
@ -59,9 +56,8 @@ gem 'httplog', '~> 1.6.2'
gem 'idn-ruby', require: 'idn' gem 'idn-ruby', require: 'idn'
gem 'kaminari', '~> 1.2' gem 'kaminari', '~> 1.2'
gem 'link_header', '~> 0.0' gem 'link_header', '~> 0.0'
gem 'mime-types', '~> 3.5.0', require: 'mime/types/columnar' gem 'mime-types', '~> 3.4.1', require: 'mime/types/columnar'
gem 'nokogiri', '~> 1.15' gem 'nokogiri', '~> 1.15'
gem 'nsa', github: 'jhawthorn/nsa', ref: 'e020fcc3a54d993ab45b7194d89ab720296c111b'
gem 'oj', '~> 3.14' gem 'oj', '~> 3.14'
gem 'ox', '~> 2.14' gem 'ox', '~> 2.14'
gem 'parslet' gem 'parslet'
@ -103,6 +99,9 @@ gem 'rdf-normalize', '~> 0.5'
gem 'private_address_check', '~> 0.5' gem 'private_address_check', '~> 0.5'
group :test do group :test do
# RSpec runner for rails
gem 'rspec-rails', '~> 6.0'
# Used to split testing into chunks in CI # Used to split testing into chunks in CI
gem 'rspec_chunked', '~> 0.6' gem 'rspec_chunked', '~> 0.6'
@ -110,14 +109,10 @@ group :test do
gem 'fuubar', '~> 2.5' gem 'fuubar', '~> 2.5'
# Extra RSpec extenion methods and helpers for sidekiq # Extra RSpec extenion methods and helpers for sidekiq
gem 'rspec-sidekiq', '~> 4.0' gem 'rspec-sidekiq', '~> 3.1'
# Browser integration testing # Browser integration testing
gem 'capybara', '~> 3.39' gem 'capybara', '~> 3.39'
gem 'selenium-webdriver'
# Used to reset the database between system tests
gem 'database_cleaner-active_record'
# Used to mock environment variables # Used to mock environment variables
gem 'climate_control', '~> 0.2' gem 'climate_control', '~> 0.2'
@ -178,17 +173,10 @@ group :development do
# Validate missing i18n keys # Validate missing i18n keys
gem 'i18n-tasks', '~> 1.0', require: false gem 'i18n-tasks', '~> 1.0', require: false
end
group :development, :test do
# Profiling tools # Profiling tools
gem 'memory_profiler', require: false gem 'memory_profiler', require: false
gem 'ruby-prof', require: false
gem 'stackprof', require: false gem 'stackprof', require: false
gem 'test-prof'
# RSpec runner for rails
gem 'rspec-rails', '~> 6.0'
end end
group :production do group :production do

View File

@ -7,17 +7,6 @@ GIT
hkdf (~> 0.2) hkdf (~> 0.2)
jwt (~> 2.0) jwt (~> 2.0)
GIT
remote: https://github.com/jhawthorn/nsa.git
revision: e020fcc3a54d993ab45b7194d89ab720296c111b
ref: e020fcc3a54d993ab45b7194d89ab720296c111b
specs:
nsa (0.2.8)
activesupport (>= 4.2, < 7.2)
concurrent-ruby (~> 1.0, >= 1.0.2)
sidekiq (>= 3.5)
statsd-ruby (~> 1.4, >= 1.4.0)
GIT GIT
remote: https://github.com/mastodon/rails-settings-cached.git remote: https://github.com/mastodon/rails-settings-cached.git
revision: 86328ef0bd04ce21cc0504ff5e334591e8c2ccab revision: 86328ef0bd04ce21cc0504ff5e334591e8c2ccab
@ -26,60 +15,50 @@ GIT
rails-settings-cached (0.6.6) rails-settings-cached (0.6.6)
rails (>= 4.2.0) rails (>= 4.2.0)
GIT
remote: https://github.com/stanhu/omniauth-cas.git
revision: 4211e6d05941b4a981f9a36b49ec166cecd0e271
ref: 4211e6d05941b4a981f9a36b49ec166cecd0e271
specs:
omniauth-cas (2.0.0)
addressable (~> 2.3)
nokogiri (~> 1.5)
omniauth (>= 1.2, < 3)
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
actioncable (7.0.8) actioncable (7.0.6)
actionpack (= 7.0.8) actionpack (= 7.0.6)
activesupport (= 7.0.8) activesupport (= 7.0.6)
nio4r (~> 2.0) nio4r (~> 2.0)
websocket-driver (>= 0.6.1) websocket-driver (>= 0.6.1)
actionmailbox (7.0.8) actionmailbox (7.0.6)
actionpack (= 7.0.8) actionpack (= 7.0.6)
activejob (= 7.0.8) activejob (= 7.0.6)
activerecord (= 7.0.8) activerecord (= 7.0.6)
activestorage (= 7.0.8) activestorage (= 7.0.6)
activesupport (= 7.0.8) activesupport (= 7.0.6)
mail (>= 2.7.1) mail (>= 2.7.1)
net-imap net-imap
net-pop net-pop
net-smtp net-smtp
actionmailer (7.0.8) actionmailer (7.0.6)
actionpack (= 7.0.8) actionpack (= 7.0.6)
actionview (= 7.0.8) actionview (= 7.0.6)
activejob (= 7.0.8) activejob (= 7.0.6)
activesupport (= 7.0.8) activesupport (= 7.0.6)
mail (~> 2.5, >= 2.5.4) mail (~> 2.5, >= 2.5.4)
net-imap net-imap
net-pop net-pop
net-smtp net-smtp
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
actionpack (7.0.8) actionpack (7.0.6)
actionview (= 7.0.8) actionview (= 7.0.6)
activesupport (= 7.0.8) activesupport (= 7.0.6)
rack (~> 2.0, >= 2.2.4) rack (~> 2.0, >= 2.2.4)
rack-test (>= 0.6.3) rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0)
actiontext (7.0.8) actiontext (7.0.6)
actionpack (= 7.0.8) actionpack (= 7.0.6)
activerecord (= 7.0.8) activerecord (= 7.0.6)
activestorage (= 7.0.8) activestorage (= 7.0.6)
activesupport (= 7.0.8) activesupport (= 7.0.6)
globalid (>= 0.6.0) globalid (>= 0.6.0)
nokogiri (>= 1.8.5) nokogiri (>= 1.8.5)
actionview (7.0.8) actionview (7.0.6)
activesupport (= 7.0.8) activesupport (= 7.0.6)
builder (~> 3.1) builder (~> 3.1)
erubi (~> 1.4) erubi (~> 1.4)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
@ -89,27 +68,27 @@ GEM
activemodel (>= 4.1, < 7.1) activemodel (>= 4.1, < 7.1)
case_transform (>= 0.2) case_transform (>= 0.2)
jsonapi-renderer (>= 0.1.1.beta1, < 0.3) jsonapi-renderer (>= 0.1.1.beta1, < 0.3)
activejob (7.0.8) activejob (7.0.6)
activesupport (= 7.0.8) activesupport (= 7.0.6)
globalid (>= 0.3.6) globalid (>= 0.3.6)
activemodel (7.0.8) activemodel (7.0.6)
activesupport (= 7.0.8) activesupport (= 7.0.6)
activerecord (7.0.8) activerecord (7.0.6)
activemodel (= 7.0.8) activemodel (= 7.0.6)
activesupport (= 7.0.8) activesupport (= 7.0.6)
activestorage (7.0.8) activestorage (7.0.6)
actionpack (= 7.0.8) actionpack (= 7.0.6)
activejob (= 7.0.8) activejob (= 7.0.6)
activerecord (= 7.0.8) activerecord (= 7.0.6)
activesupport (= 7.0.8) activesupport (= 7.0.6)
marcel (~> 1.0) marcel (~> 1.0)
mini_mime (>= 1.1.0) mini_mime (>= 1.1.0)
activesupport (7.0.8) activesupport (7.0.6)
concurrent-ruby (~> 1.0, >= 1.0.2) concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2) i18n (>= 1.6, < 2)
minitest (>= 5.1) minitest (>= 5.1)
tzinfo (~> 2.0) tzinfo (~> 2.0)
addressable (2.8.5) addressable (2.8.4)
public_suffix (>= 2.0.2, < 6.0) public_suffix (>= 2.0.2, < 6.0)
aes_key_wrap (1.1.0) aes_key_wrap (1.1.0)
airbrussh (1.4.1) airbrussh (1.4.1)
@ -124,8 +103,8 @@ GEM
attr_required (1.0.1) attr_required (1.0.1)
awrence (1.2.1) awrence (1.2.1)
aws-eventstream (1.2.0) aws-eventstream (1.2.0)
aws-partitions (1.809.0) aws-partitions (1.791.0)
aws-sdk-core (3.181.0) aws-sdk-core (3.178.0)
aws-eventstream (~> 1, >= 1.0.2) aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.651.0) aws-partitions (~> 1, >= 1.651.0)
aws-sigv4 (~> 1.5) aws-sigv4 (~> 1.5)
@ -133,8 +112,8 @@ GEM
aws-sdk-kms (1.71.0) aws-sdk-kms (1.71.0)
aws-sdk-core (~> 3, >= 3.177.0) aws-sdk-core (~> 3, >= 3.177.0)
aws-sigv4 (~> 1.1) aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.133.0) aws-sdk-s3 (1.131.0)
aws-sdk-core (~> 3, >= 3.181.0) aws-sdk-core (~> 3, >= 3.177.0)
aws-sdk-kms (~> 1) aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.6) aws-sigv4 (~> 1.6)
aws-sigv4 (1.6.0) aws-sigv4 (1.6.0)
@ -147,7 +126,6 @@ GEM
faraday_middleware (~> 1.0, >= 1.0.0.rc1) faraday_middleware (~> 1.0, >= 1.0.0.rc1)
net-http-persistent (~> 4.0) net-http-persistent (~> 4.0)
nokogiri (~> 1, >= 1.10.8) nokogiri (~> 1, >= 1.10.8)
base64 (0.1.1)
bcrypt (3.1.18) bcrypt (3.1.18)
better_errors (2.10.1) better_errors (2.10.1)
erubi (>= 1.0.0) erubi (>= 1.0.0)
@ -203,7 +181,7 @@ GEM
activesupport activesupport
cbor (0.5.9.6) cbor (0.5.9.6)
charlock_holmes (0.7.7) charlock_holmes (0.7.7)
chewy (7.3.4) chewy (7.3.3)
activesupport (>= 5.2) activesupport (>= 5.2)
elasticsearch (>= 7.12.0, < 7.14.0) elasticsearch (>= 7.12.0, < 7.14.0)
elasticsearch-dsl elasticsearch-dsl
@ -221,10 +199,6 @@ GEM
crass (1.0.6) crass (1.0.6)
css_parser (1.14.0) css_parser (1.14.0)
addressable addressable
database_cleaner-active_record (2.1.0)
activerecord (>= 5.a)
database_cleaner-core (~> 2.0.0)
database_cleaner-core (2.0.1)
date (3.3.3) date (3.3.3)
debug_inspector (1.1.0) debug_inspector (1.1.0)
devise (4.9.2) devise (4.9.2)
@ -270,7 +244,7 @@ GEM
tzinfo tzinfo
excon (0.100.0) excon (0.100.0)
fabrication (2.30.0) fabrication (2.30.0)
faker (3.2.1) faker (3.2.0)
i18n (>= 1.8.11, < 2) i18n (>= 1.8.11, < 2)
faraday (1.10.3) faraday (1.10.3)
faraday-em_http (~> 1.0) faraday-em_http (~> 1.0)
@ -324,7 +298,7 @@ GEM
ruby-progressbar (~> 1.4) ruby-progressbar (~> 1.4)
globalid (1.1.0) globalid (1.1.0)
activesupport (>= 5.0) activesupport (>= 5.0)
haml (6.1.2) haml (6.1.1)
temple (>= 0.8.2) temple (>= 0.8.2)
thor thor
tilt tilt
@ -333,7 +307,7 @@ GEM
activesupport (>= 5.1) activesupport (>= 5.1)
haml (>= 4.0.6) haml (>= 4.0.6)
railties (>= 5.1) railties (>= 5.1)
haml_lint (0.50.0) haml_lint (0.49.2)
haml (>= 4.0, < 6.2) haml (>= 4.0, < 6.2)
parallel (~> 1.10) parallel (~> 1.10)
rainbow rainbow
@ -409,7 +383,7 @@ GEM
activerecord activerecord
kaminari-core (= 1.2.2) kaminari-core (= 1.2.2)
kaminari-core (1.2.2) kaminari-core (1.2.2)
kt-paperclip (7.2.1) kt-paperclip (7.2.0)
activemodel (>= 4.2.0) activemodel (>= 4.2.0)
activesupport (>= 4.2.0) activesupport (>= 4.2.0)
marcel (~> 1.0.1) marcel (~> 1.0.1)
@ -429,7 +403,7 @@ GEM
llhttp-ffi (0.4.0) llhttp-ffi (0.4.0)
ffi-compiler (~> 1.0) ffi-compiler (~> 1.0)
rake (~> 13.0) rake (~> 13.0)
lograge (0.13.0) lograge (0.12.0)
actionpack (>= 4) actionpack (>= 4)
activesupport (>= 4) activesupport (>= 4)
railties (>= 4) railties (>= 4)
@ -452,12 +426,12 @@ GEM
hashie (~> 5.0) hashie (~> 5.0)
memory_profiler (1.0.1) memory_profiler (1.0.1)
method_source (1.0.0) method_source (1.0.0)
mime-types (3.5.1) mime-types (3.4.1)
mime-types-data (~> 3.2015) mime-types-data (~> 3.2015)
mime-types-data (3.2023.0808) mime-types-data (3.2023.0218.1)
mini_mime (1.1.5) mini_mime (1.1.2)
mini_portile2 (2.8.4) mini_portile2 (2.8.2)
minitest (5.19.0) minitest (5.18.1)
msgpack (1.7.1) msgpack (1.7.1)
multi_json (1.15.0) multi_json (1.15.0)
multipart-post (2.3.0) multipart-post (2.3.0)
@ -465,7 +439,7 @@ GEM
uri uri
net-http-persistent (4.0.2) net-http-persistent (4.0.2)
connection_pool (~> 2.2) connection_pool (~> 2.2)
net-imap (0.3.7) net-imap (0.3.6)
date date
net-protocol net-protocol
net-ldap (0.18.0) net-ldap (0.18.0)
@ -479,20 +453,23 @@ GEM
net-protocol net-protocol
net-ssh (7.1.0) net-ssh (7.1.0)
nio4r (2.5.9) nio4r (2.5.9)
nokogiri (1.15.4) nokogiri (1.15.3)
mini_portile2 (~> 2.8.2) mini_portile2 (~> 2.8.2)
racc (~> 1.4) racc (~> 1.4)
oj (3.16.1) oj (3.15.0)
omniauth (2.1.1) omniauth (1.9.2)
hashie (>= 3.4.6) hashie (>= 3.4.6)
rack (>= 2.2.3) rack (>= 1.6.2, < 3)
rack-protection omniauth-cas (2.0.0)
omniauth-rails_csrf_protection (1.0.1) addressable (~> 2.3)
nokogiri (~> 1.5)
omniauth (~> 1.2)
omniauth-rails_csrf_protection (0.1.2)
actionpack (>= 4.2) actionpack (>= 4.2)
omniauth (~> 2.0) omniauth (>= 1.3.1)
omniauth-saml (2.1.0) omniauth-saml (1.10.3)
omniauth (~> 2.0) omniauth (~> 1.3, >= 1.3.2)
ruby-saml (~> 1.12) ruby-saml (~> 1.9)
omniauth_openid_connect (0.6.1) omniauth_openid_connect (0.6.1)
omniauth (>= 1.9, < 3) omniauth (>= 1.9, < 3)
openid_connect (~> 1.1) openid_connect (~> 1.1)
@ -519,8 +496,8 @@ GEM
parslet (2.0.0) parslet (2.0.0)
pastel (0.8.0) pastel (0.8.0)
tty-color (~> 0.5) tty-color (~> 0.5)
pg (1.5.4) pg (1.5.3)
pghero (3.3.4) pghero (3.3.3)
activerecord (>= 6) activerecord (>= 6)
posix-spawn (0.3.15) posix-spawn (0.3.15)
premailer (1.21.0) premailer (1.21.0)
@ -533,15 +510,15 @@ GEM
premailer (~> 1.7, >= 1.7.9) premailer (~> 1.7, >= 1.7.9)
private_address_check (0.5.0) private_address_check (0.5.0)
public_suffix (5.0.3) public_suffix (5.0.3)
puma (6.3.1) puma (6.3.0)
nio4r (~> 2.0) nio4r (~> 2.0)
pundit (2.3.0) pundit (2.3.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
raabro (1.4.0) raabro (1.4.0)
racc (1.7.1) racc (1.7.1)
rack (2.2.8) rack (2.2.7)
rack-attack (6.7.0) rack-attack (6.6.1)
rack (>= 1.0, < 4) rack (>= 1.0, < 3)
rack-cors (2.0.1) rack-cors (2.0.1)
rack (>= 2.0.0) rack (>= 2.0.0)
rack-oauth2 (1.21.3) rack-oauth2 (1.21.3)
@ -550,33 +527,30 @@ GEM
httpclient httpclient
json-jwt (>= 1.11.0) json-jwt (>= 1.11.0)
rack (>= 2.1.0) rack (>= 2.1.0)
rack-protection (3.0.5)
rack
rack-proxy (0.7.6) rack-proxy (0.7.6)
rack rack
rack-test (2.1.0) rack-test (2.1.0)
rack (>= 1.3) rack (>= 1.3)
rails (7.0.8) rails (7.0.6)
actioncable (= 7.0.8) actioncable (= 7.0.6)
actionmailbox (= 7.0.8) actionmailbox (= 7.0.6)
actionmailer (= 7.0.8) actionmailer (= 7.0.6)
actionpack (= 7.0.8) actionpack (= 7.0.6)
actiontext (= 7.0.8) actiontext (= 7.0.6)
actionview (= 7.0.8) actionview (= 7.0.6)
activejob (= 7.0.8) activejob (= 7.0.6)
activemodel (= 7.0.8) activemodel (= 7.0.6)
activerecord (= 7.0.8) activerecord (= 7.0.6)
activestorage (= 7.0.8) activestorage (= 7.0.6)
activesupport (= 7.0.8) activesupport (= 7.0.6)
bundler (>= 1.15.0) bundler (>= 1.15.0)
railties (= 7.0.8) railties (= 7.0.6)
rails-controller-testing (1.0.5) rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1) actionpack (>= 5.0.1.rc1)
actionview (>= 5.0.1.rc1) actionview (>= 5.0.1.rc1)
activesupport (>= 5.0.1.rc1) activesupport (>= 5.0.1.rc1)
rails-dom-testing (2.1.1) rails-dom-testing (2.0.3)
activesupport (>= 5.0.0) activesupport (>= 4.2.0)
minitest
nokogiri (>= 1.6) nokogiri (>= 1.6)
rails-html-sanitizer (1.6.0) rails-html-sanitizer (1.6.0)
loofah (~> 2.21) loofah (~> 2.21)
@ -584,9 +558,9 @@ GEM
rails-i18n (7.0.7) rails-i18n (7.0.7)
i18n (>= 0.7, < 2) i18n (>= 0.7, < 2)
railties (>= 6.0.0, < 8) railties (>= 6.0.0, < 8)
railties (7.0.8) railties (7.0.6)
actionpack (= 7.0.8) actionpack (= 7.0.6)
activesupport (= 7.0.8) activesupport (= 7.0.6)
method_source method_source
rake (>= 12.2) rake (>= 12.2)
thor (~> 1.0) thor (~> 1.0)
@ -633,15 +607,12 @@ GEM
rspec-expectations (~> 3.12) rspec-expectations (~> 3.12)
rspec-mocks (~> 3.12) rspec-mocks (~> 3.12)
rspec-support (~> 3.12) rspec-support (~> 3.12)
rspec-sidekiq (4.0.1) rspec-sidekiq (3.1.0)
rspec-core (~> 3.0) rspec-core (~> 3.0, >= 3.0.0)
rspec-expectations (~> 3.0) sidekiq (>= 2.4.0)
rspec-mocks (~> 3.0) rspec-support (3.12.0)
sidekiq (>= 5, < 8)
rspec-support (3.12.1)
rspec_chunked (0.6) rspec_chunked (0.6)
rubocop (1.56.3) rubocop (1.54.2)
base64 (~> 0.1.1)
json (~> 2.3) json (~> 2.3)
language_server-protocol (>= 3.17.0) language_server-protocol (>= 3.17.0)
parallel (~> 1.10) parallel (~> 1.10)
@ -649,7 +620,7 @@ GEM
rainbow (>= 2.2.2, < 4.0) rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0) regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0) rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.28.1, < 2.0) rubocop-ast (>= 1.28.0, < 2.0)
ruby-progressbar (~> 1.7) ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0) unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.29.0) rubocop-ast (1.29.0)
@ -658,18 +629,17 @@ GEM
rubocop (~> 1.41) rubocop (~> 1.41)
rubocop-factory_bot (2.23.1) rubocop-factory_bot (2.23.1)
rubocop (~> 1.33) rubocop (~> 1.33)
rubocop-performance (1.19.0) rubocop-performance (1.18.0)
rubocop (>= 1.7.0, < 2.0) rubocop (>= 1.7.0, < 2.0)
rubocop-ast (>= 0.4.0) rubocop-ast (>= 0.4.0)
rubocop-rails (2.20.2) rubocop-rails (2.20.2)
activesupport (>= 4.2.0) activesupport (>= 4.2.0)
rack (>= 1.1) rack (>= 1.1)
rubocop (>= 1.33.0, < 2.0) rubocop (>= 1.33.0, < 2.0)
rubocop-rspec (2.23.2) rubocop-rspec (2.22.0)
rubocop (~> 1.33) rubocop (~> 1.33)
rubocop-capybara (~> 2.17) rubocop-capybara (~> 2.17)
rubocop-factory_bot (~> 2.22) rubocop-factory_bot (~> 2.22)
ruby-prof (1.6.3)
ruby-progressbar (1.13.0) ruby-progressbar (1.13.0)
ruby-saml (1.15.0) ruby-saml (1.15.0)
nokogiri (>= 1.13.10) nokogiri (>= 1.13.10)
@ -686,10 +656,6 @@ GEM
scenic (1.7.0) scenic (1.7.0)
activerecord (>= 4.0.0) activerecord (>= 4.0.0)
railties (>= 4.0.0) railties (>= 4.0.0)
selenium-webdriver (4.11.0)
rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 3.0)
websocket (~> 1.0)
semantic_range (3.0.0) semantic_range (3.0.0)
sidekiq (6.5.9) sidekiq (6.5.9)
connection_pool (>= 2.2.5, < 3) connection_pool (>= 2.2.5, < 3)
@ -730,8 +696,7 @@ GEM
net-scp (>= 1.1.2) net-scp (>= 1.1.2)
net-ssh (>= 2.8.0) net-ssh (>= 2.8.0)
stackprof (0.2.25) stackprof (0.2.25)
statsd-ruby (1.5.0) stoplight (3.0.1)
stoplight (3.0.2)
redlock (~> 1.0) redlock (~> 1.0)
strong_migrations (0.8.0) strong_migrations (0.8.0)
activerecord (>= 5.2) activerecord (>= 5.2)
@ -745,7 +710,6 @@ GEM
unicode-display_width (>= 1.1.1, < 3) unicode-display_width (>= 1.1.1, < 3)
terrapin (0.6.0) terrapin (0.6.0)
climate_control (>= 0.0.3, < 1.0) climate_control (>= 0.0.3, < 1.0)
test-prof (1.2.3)
thor (1.2.2) thor (1.2.2)
tilt (2.2.0) tilt (2.2.0)
timeout (0.4.0) timeout (0.4.0)
@ -795,7 +759,7 @@ GEM
webfinger (1.2.0) webfinger (1.2.0)
activesupport activesupport
httpclient (>= 2.4) httpclient (>= 2.4)
webmock (3.19.1) webmock (3.18.1)
addressable (>= 2.8.0) addressable (>= 2.8.0)
crack (>= 0.3.2) crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0) hashdiff (>= 0.4.0, < 2.0.0)
@ -804,15 +768,14 @@ GEM
rack-proxy (>= 0.6.1) rack-proxy (>= 0.6.1)
railties (>= 5.2) railties (>= 5.2)
semantic_range (>= 2.3.0) semantic_range (>= 2.3.0)
websocket (1.2.9) websocket-driver (0.7.5)
websocket-driver (0.7.6)
websocket-extensions (>= 0.1.0) websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5) websocket-extensions (0.1.5)
wisper (2.0.1) wisper (2.0.1)
xorcist (1.1.3) xorcist (1.1.3)
xpath (3.2.0) xpath (3.2.0)
nokogiri (~> 1.8) nokogiri (~> 1.8)
zeitwerk (2.6.11) zeitwerk (2.6.8)
PLATFORMS PLATFORMS
ruby ruby
@ -841,7 +804,6 @@ DEPENDENCIES
color_diff (~> 0.1) color_diff (~> 0.1)
concurrent-ruby concurrent-ruby
connection_pool connection_pool
database_cleaner-active_record
devise (~> 4.9) devise (~> 4.9)
devise-two-factor (~> 4.1) devise-two-factor (~> 4.1)
devise_pam_authenticatable2 (~> 9.2) devise_pam_authenticatable2 (~> 9.2)
@ -878,16 +840,15 @@ DEPENDENCIES
mario-redis-lock (~> 1.2) mario-redis-lock (~> 1.2)
md-paperclip-azure (~> 2.2) md-paperclip-azure (~> 2.2)
memory_profiler memory_profiler
mime-types (~> 3.5.0) mime-types (~> 3.4.1)
net-http (~> 0.3.2) net-http (~> 0.3.2)
net-ldap (~> 0.18) net-ldap (~> 0.18)
nokogiri (~> 1.15) nokogiri (~> 1.15)
nsa!
oj (~> 3.14) oj (~> 3.14)
omniauth (~> 2.0) omniauth (~> 1.9)
omniauth-cas! omniauth-cas (~> 2.0)
omniauth-rails_csrf_protection (~> 1.0) omniauth-rails_csrf_protection (~> 0.1)
omniauth-saml (~> 2.0) omniauth-saml (~> 1.10)
omniauth_openid_connect (~> 0.6.1) omniauth_openid_connect (~> 0.6.1)
ox (~> 2.14) ox (~> 2.14)
parslet parslet
@ -913,19 +874,17 @@ DEPENDENCIES
redis-namespace (~> 1.10) redis-namespace (~> 1.10)
rqrcode (~> 2.2) rqrcode (~> 2.2)
rspec-rails (~> 6.0) rspec-rails (~> 6.0)
rspec-sidekiq (~> 4.0) rspec-sidekiq (~> 3.1)
rspec_chunked (~> 0.6) rspec_chunked (~> 0.6)
rubocop rubocop
rubocop-capybara rubocop-capybara
rubocop-performance rubocop-performance
rubocop-rails rubocop-rails
rubocop-rspec rubocop-rspec
ruby-prof
ruby-progressbar (~> 1.13) ruby-progressbar (~> 1.13)
rubyzip (~> 2.3) rubyzip (~> 2.3)
sanitize (~> 6.0) sanitize (~> 6.0)
scenic (~> 1.7) scenic (~> 1.7)
selenium-webdriver
sidekiq (~> 6.5) sidekiq (~> 6.5)
sidekiq-bulk (~> 0.2.0) sidekiq-bulk (~> 0.2.0)
sidekiq-scheduler (~> 5.0) sidekiq-scheduler (~> 5.0)
@ -938,7 +897,6 @@ DEPENDENCIES
stackprof stackprof
stoplight (~> 3.0.1) stoplight (~> 3.0.1)
strong_migrations (~> 0.8) strong_migrations (~> 0.8)
test-prof
thor (~> 1.2) thor (~> 1.2)
tty-prompt (~> 0.23) tty-prompt (~> 0.23)
twitter-text (~> 3.1.0) twitter-text (~> 3.1.0)

View File

@ -1,4 +1,4 @@
web: env PORT=3000 RAILS_ENV=development bundle exec puma -C config/puma.rb web: env PORT=3000 RAILS_ENV=development bundle exec puma -C config/puma.rb
sidekiq: env PORT=3000 RAILS_ENV=development bundle exec sidekiq sidekiq: env PORT=3000 RAILS_ENV=development bundle exec sidekiq
stream: env PORT=4000 yarn run start stream: env PORT=4000 yarn run start
webpack: bin/webpack-dev-server webpack: ./bin/webpack-dev-server --listen-host 0.0.0.0

View File

@ -1,11 +1,8 @@
# Security Policy # Security Policy
If you believe you've identified a security vulnerability in Mastodon (a bug that allows something to happen that shouldn't be possible), you can either: If you believe you've identified a security vulnerability in Mastodon (a bug that allows something to happen that shouldn't be possible), you can reach us at <security@joinmastodon.org>.
- open a [Github security issue on the Mastodon project](https://github.com/mastodon/mastodon/security/advisories/new) You should _not_ report such issues on GitHub or in other public spaces to give us time to publish a fix for the issue without exposing Mastodon's users to increased risk.
- reach us at <security@joinmastodon.org>
You should _not_ report such issues on public GitHub issues or in other public spaces to give us time to publish a fix for the issue without exposing Mastodon's users to increased risk.
## Scope ## Scope
@ -13,9 +10,9 @@ A "vulnerability in Mastodon" is a vulnerability in the code distributed through
## Supported Versions ## Supported Versions
| Version | Supported | | Version | Supported |
| ------- | ---------------- | | ------- | --------- |
| 4.1.x | Yes | | 4.1.x | Yes |
| 4.0.x | Until 2023-10-31 | | 4.0.x | Yes |
| 3.5.x | Until 2023-12-31 | | 3.5.x | Yes |
| < 3.5 | No | | < 3.5 | No |

44
Vagrantfile vendored
View File

@ -60,38 +60,6 @@ sudo usermod -a -G rvm $USER
SCRIPT SCRIPT
$provisionElasticsearch = <<SCRIPT
# Install Elastic Search
sudo apt install openjdk-17-jre-headless -y
sudo wget -O /usr/share/keyrings/elasticsearch.asc https://artifacts.elastic.co/GPG-KEY-elasticsearch
sudo sh -c 'echo "deb [signed-by=/usr/share/keyrings/elasticsearch.asc] https://artifacts.elastic.co/packages/7.x/apt stable main" > /etc/apt/sources.list.d/elastic-7.x.list'
sudo apt update
sudo apt install elasticsearch -y
sudo systemctl daemon-reload
sudo systemctl enable --now elasticsearch
echo 'path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
network.host: 0.0.0.0
http.port: 9200
discovery.seed_hosts: ["localhost"]
cluster.initial_master_nodes: ["node-1"]
xpack.security.enabled: false' > /etc/elasticsearch/elasticsearch.yml
sudo systemctl restart elasticsearch
# Install Kibana
sudo apt install kibana -y
sudo systemctl enable --now kibana
echo 'server.host: "0.0.0.0"
elasticsearch.hosts: ["http://localhost:9200"]' > /etc/kibana/kibana.yml
sudo systemctl restart kibana
SCRIPT
$provisionB = <<SCRIPT $provisionB = <<SCRIPT
source "/etc/profile.d/rvm.sh" source "/etc/profile.d/rvm.sh"
@ -134,8 +102,10 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.provider :virtualbox do |vb| config.vm.provider :virtualbox do |vb|
vb.name = "mastodon" vb.name = "mastodon"
vb.customize ["modifyvm", :id, "--memory", "8192"] vb.customize ["modifyvm", :id, "--memory", "4096"]
vb.customize ["modifyvm", :id, "--cpus", "3"] # Increase the number of CPUs. Uncomment and adjust to
# increase performance
# vb.customize ["modifyvm", :id, "--cpus", "3"]
# Disable VirtualBox DNS proxy to skip long-delay IPv6 resolutions. # Disable VirtualBox DNS proxy to skip long-delay IPv6 resolutions.
# https://github.com/mitchellh/vagrant/issues/1172 # https://github.com/mitchellh/vagrant/issues/1172
@ -171,15 +141,9 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.network :forwarded_port, guest: 3000, host: 3000 config.vm.network :forwarded_port, guest: 3000, host: 3000
config.vm.network :forwarded_port, guest: 4000, host: 4000 config.vm.network :forwarded_port, guest: 4000, host: 4000
config.vm.network :forwarded_port, guest: 8080, host: 8080 config.vm.network :forwarded_port, guest: 8080, host: 8080
config.vm.network :forwarded_port, guest: 9200, host: 9200
config.vm.network :forwarded_port, guest: 9300, host: 9300
config.vm.network :forwarded_port, guest: 9243, host: 9243
config.vm.network :forwarded_port, guest: 5601, host: 5601
# Full provisioning script, only runs on first 'vagrant up' or with 'vagrant provision' # Full provisioning script, only runs on first 'vagrant up' or with 'vagrant provision'
config.vm.provision :shell, inline: $provisionA, privileged: false, reset: true config.vm.provision :shell, inline: $provisionA, privileged: false, reset: true
# Run with elevated privileges for Elasticsearch installation
config.vm.provision :shell, inline: $provisionElasticsearch, privileged: true
config.vm.provision :shell, inline: $provisionB, privileged: false config.vm.provision :shell, inline: $provisionB, privileged: false
config.vm.post_up_message = <<MESSAGE config.vm.post_up_message = <<MESSAGE

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
class AccountsIndex < Chewy::Index class AccountsIndex < Chewy::Index
settings index: index_preset(refresh_interval: '30s'), analysis: { settings index: { refresh_interval: '30s' }, analysis: {
filter: { filter: {
english_stop: { english_stop: {
type: 'stop', type: 'stop',
@ -21,20 +21,19 @@ class AccountsIndex < Chewy::Index
analyzer: { analyzer: {
natural: { natural: {
tokenizer: 'standard', tokenizer: 'uax_url_email',
filter: %w( filter: %w(
english_possessive_stemmer
lowercase lowercase
asciifolding asciifolding
cjk_width cjk_width
elision
english_possessive_stemmer
english_stop english_stop
english_stemmer english_stemmer
), ),
}, },
verbatim: { verbatim: {
tokenizer: 'standard', tokenizer: 'whitespace',
filter: %w(lowercase asciifolding cjk_width), filter: %w(lowercase asciifolding cjk_width),
}, },
@ -63,6 +62,6 @@ class AccountsIndex < Chewy::Index
field(:last_status_at, type: 'date', value: ->(account) { account.last_status_at || account.created_at }) field(:last_status_at, type: 'date', value: ->(account) { account.last_status_at || account.created_at })
field(:display_name, type: 'text', analyzer: 'verbatim') { field :edge_ngram, type: 'text', analyzer: 'edge_ngram', search_analyzer: 'verbatim' } field(:display_name, type: 'text', analyzer: 'verbatim') { field :edge_ngram, type: 'text', analyzer: 'edge_ngram', search_analyzer: 'verbatim' }
field(:username, type: 'text', analyzer: 'verbatim', value: ->(account) { [account.username, account.domain].compact.join('@') }) { field :edge_ngram, type: 'text', analyzer: 'edge_ngram', search_analyzer: 'verbatim' } field(:username, type: 'text', analyzer: 'verbatim', value: ->(account) { [account.username, account.domain].compact.join('@') }) { field :edge_ngram, type: 'text', analyzer: 'edge_ngram', search_analyzer: 'verbatim' }
field(:text, type: 'text', analyzer: 'verbatim', value: ->(account) { account.searchable_text }) { field :stemmed, type: 'text', analyzer: 'natural' } field(:text, type: 'text', value: ->(account) { account.searchable_text }) { field :stemmed, type: 'text', analyzer: 'natural' }
end end
end end

View File

@ -1,12 +1,12 @@
# frozen_string_literal: true # frozen_string_literal: true
class InstancesIndex < Chewy::Index class InstancesIndex < Chewy::Index
settings index: index_preset(refresh_interval: '30s') settings index: { refresh_interval: '30s' }
index_scope ::Instance.searchable index_scope ::Instance.searchable
root date_detection: false do root date_detection: false do
field :domain, type: 'text', index_prefixes: { min_chars: 1, max_chars: 5 } field :domain, type: 'text', index_prefixes: { min_chars: 1 }
field :accounts_count, type: 'long' field :accounts_count, type: 'long'
end end
end end

View File

@ -1,67 +0,0 @@
# frozen_string_literal: true
class PublicStatusesIndex < Chewy::Index
settings index: index_preset(refresh_interval: '30s', number_of_shards: 5), analysis: {
filter: {
english_stop: {
type: 'stop',
stopwords: '_english_',
},
english_stemmer: {
type: 'stemmer',
language: 'english',
},
english_possessive_stemmer: {
type: 'stemmer',
language: 'possessive_english',
},
},
analyzer: {
verbatim: {
tokenizer: 'uax_url_email',
filter: %w(lowercase),
},
content: {
tokenizer: 'standard',
filter: %w(
lowercase
asciifolding
cjk_width
elision
english_possessive_stemmer
english_stop
english_stemmer
),
},
hashtag: {
tokenizer: 'keyword',
filter: %w(
word_delimiter_graph
lowercase
asciifolding
cjk_width
),
},
},
}
index_scope ::Status.unscoped
.kept
.indexable
.includes(:media_attachments, :preloadable_poll, :preview_cards, :tags)
root date_detection: false do
field(:id, type: 'long')
field(:account_id, type: 'long')
field(:text, type: 'text', analyzer: 'verbatim', value: ->(status) { status.searchable_text }) { field(:stemmed, type: 'text', analyzer: 'content') }
field(:tags, type: 'text', analyzer: 'hashtag', value: ->(status) { status.tags.map(&:display_name) })
field(:language, type: 'keyword')
field(:properties, type: 'keyword', value: ->(status) { status.searchable_properties })
field(:created_at, type: 'date')
end
end

View File

@ -1,65 +1,75 @@
# frozen_string_literal: true # frozen_string_literal: true
class StatusesIndex < Chewy::Index class StatusesIndex < Chewy::Index
settings index: index_preset(refresh_interval: '30s', number_of_shards: 5), analysis: { include FormattingHelper
settings index: { refresh_interval: '30s' }, analysis: {
filter: { filter: {
english_stop: { english_stop: {
type: 'stop', type: 'stop',
stopwords: '_english_', stopwords: '_english_',
}, },
english_stemmer: { english_stemmer: {
type: 'stemmer', type: 'stemmer',
language: 'english', language: 'english',
}, },
english_possessive_stemmer: { english_possessive_stemmer: {
type: 'stemmer', type: 'stemmer',
language: 'possessive_english', language: 'possessive_english',
}, },
}, },
analyzer: { analyzer: {
verbatim: {
tokenizer: 'uax_url_email',
filter: %w(lowercase),
},
content: { content: {
tokenizer: 'standard', tokenizer: 'uax_url_email',
filter: %w( filter: %w(
english_possessive_stemmer
lowercase lowercase
asciifolding asciifolding
cjk_width cjk_width
elision
english_possessive_stemmer
english_stop english_stop
english_stemmer english_stemmer
), ),
}, },
hashtag: {
tokenizer: 'keyword',
filter: %w(
word_delimiter_graph
lowercase
asciifolding
cjk_width
),
},
}, },
} }
index_scope ::Status.unscoped.kept.without_reblogs.includes(:media_attachments, :preview_cards, :local_mentioned, :local_favorited, :local_reblogged, :local_bookmarked, :tags, preloadable_poll: :local_voters), delete_if: ->(status) { status.searchable_by.empty? } # We do not use delete_if option here because it would call a method that we
# expect to be called with crutches without crutches, causing n+1 queries
index_scope ::Status.unscoped.kept.without_reblogs.includes(:media_attachments, :preloadable_poll)
crutch :mentions do |collection|
data = ::Mention.where(status_id: collection.map(&:id)).where(account: Account.local, silent: false).pluck(:status_id, :account_id)
data.each.with_object({}) { |(id, name), result| (result[id] ||= []).push(name) }
end
crutch :favourites do |collection|
data = ::Favourite.where(status_id: collection.map(&:id)).where(account: Account.local).pluck(:status_id, :account_id)
data.each.with_object({}) { |(id, name), result| (result[id] ||= []).push(name) }
end
crutch :reblogs do |collection|
data = ::Status.where(reblog_of_id: collection.map(&:id)).where(account: Account.local).pluck(:reblog_of_id, :account_id)
data.each.with_object({}) { |(id, name), result| (result[id] ||= []).push(name) }
end
crutch :bookmarks do |collection|
data = ::Bookmark.where(status_id: collection.map(&:id)).where(account: Account.local).pluck(:status_id, :account_id)
data.each.with_object({}) { |(id, name), result| (result[id] ||= []).push(name) }
end
crutch :votes do |collection|
data = ::PollVote.joins(:poll).where(poll: { status_id: collection.map(&:id) }).where(account: Account.local).pluck(:status_id, :account_id)
data.each.with_object({}) { |(id, name), result| (result[id] ||= []).push(name) }
end
root date_detection: false do root date_detection: false do
field(:id, type: 'long') field :id, type: 'long'
field(:account_id, type: 'long') field :account_id, type: 'long'
field(:text, type: 'text', analyzer: 'verbatim', value: ->(status) { status.searchable_text }) { field(:stemmed, type: 'text', analyzer: 'content') }
field(:tags, type: 'text', analyzer: 'hashtag', value: ->(status) { status.tags.map(&:display_name) }) field :text, type: 'text', value: ->(status) { status.searchable_text } do
field(:searchable_by, type: 'long', value: ->(status) { status.searchable_by }) field :stemmed, type: 'text', analyzer: 'content'
field(:language, type: 'keyword') end
field(:properties, type: 'keyword', value: ->(status) { status.searchable_properties })
field(:created_at, type: 'date') field :searchable_by, type: 'long', value: ->(status, crutches) { status.searchable_by(crutches) }
end end
end end

View File

@ -1,25 +1,16 @@
# frozen_string_literal: true # frozen_string_literal: true
class TagsIndex < Chewy::Index class TagsIndex < Chewy::Index
settings index: index_preset(refresh_interval: '30s'), analysis: { settings index: { refresh_interval: '30s' }, analysis: {
analyzer: { analyzer: {
content: { content: {
tokenizer: 'keyword', tokenizer: 'keyword',
filter: %w( filter: %w(lowercase asciifolding cjk_width),
word_delimiter_graph
lowercase
asciifolding
cjk_width
),
}, },
edge_ngram: { edge_ngram: {
tokenizer: 'edge_ngram', tokenizer: 'edge_ngram',
filter: %w( filter: %w(lowercase asciifolding cjk_width),
lowercase
asciifolding
cjk_width
),
}, },
}, },
@ -39,9 +30,12 @@ class TagsIndex < Chewy::Index
end end
root date_detection: false do root date_detection: false do
field(:name, type: 'text', analyzer: 'content', value: :display_name) { field(:edge_ngram, type: 'text', analyzer: 'edge_ngram', search_analyzer: 'content') } field :name, type: 'text', analyzer: 'content' do
field(:reviewed, type: 'boolean', value: ->(tag) { tag.reviewed? }) field :edge_ngram, type: 'text', analyzer: 'edge_ngram', search_analyzer: 'content'
field(:usage, type: 'long', value: ->(tag, crutches) { tag.history.aggregate(crutches.time_period).accounts }) end
field(:last_status_at, type: 'date', value: ->(tag) { tag.last_status_at || tag.created_at })
field :reviewed, type: 'boolean', value: ->(tag) { tag.reviewed? }
field :usage, type: 'long', value: ->(tag, crutches) { tag.history.aggregate(crutches.time_period).accounts }
field :last_status_at, type: 'date', value: ->(tag) { tag.last_status_at || tag.created_at }
end end
end end

View File

@ -12,7 +12,7 @@ class AccountsController < ApplicationController
before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? } before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
skip_around_action :set_locale, if: -> { [:json, :rss].include?(request.format&.to_sym) } skip_around_action :set_locale, if: -> { [:json, :rss].include?(request.format&.to_sym) }
skip_before_action :require_functional!, unless: :limited_federation_mode? skip_before_action :require_functional!, unless: :whitelist_mode?
def show def show
respond_to do |format| respond_to do |format|

View File

@ -40,7 +40,7 @@ module Admin
end end
# Allow transparently upgrading a domain block # Allow transparently upgrading a domain block
if existing_domain_block.present? && existing_domain_block.domain == TagManager.instance.normalize_domain(@domain_block.domain.strip) if existing_domain_block.present?
@domain_block = existing_domain_block @domain_block = existing_domain_block
@domain_block.assign_attributes(resource_params) @domain_block.assign_attributes(resource_params)
end end

View File

@ -65,7 +65,7 @@ module Admin
end end
def filtered_instances def filtered_instances
InstanceFilter.new(limited_federation_mode? ? { allowed: true } : filter_params).results InstanceFilter.new(whitelist_mode? ? { allowed: true } : filter_params).results
end end
def filter_params def filter_params

View File

@ -1,18 +0,0 @@
# frozen_string_literal: true
module Admin
class SoftwareUpdatesController < BaseController
before_action :check_enabled!
def index
authorize :software_update, :index?
@software_updates = SoftwareUpdate.all.sort_by(&:gem_version)
end
private
def check_enabled!
not_found unless SoftwareUpdate.check_enabled?
end
end
end

View File

@ -8,7 +8,7 @@ class Api::BaseController < ApplicationController
include AccessTokenTrackingConcern include AccessTokenTrackingConcern
include ApiCachingConcern include ApiCachingConcern
skip_before_action :require_functional!, unless: :limited_federation_mode? skip_before_action :require_functional!, unless: :whitelist_mode?
before_action :require_authenticated_user!, if: :disallow_unauthenticated_api_access? before_action :require_authenticated_user!, if: :disallow_unauthenticated_api_access?
before_action :require_not_suspended! before_action :require_not_suspended!
@ -150,7 +150,7 @@ class Api::BaseController < ApplicationController
end end
def disallow_unauthenticated_api_access? def disallow_unauthenticated_api_access?
ENV['DISALLOW_UNAUTHENTICATED_API_ACCESS'] == 'true' || Rails.configuration.x.limited_federation_mode ENV['DISALLOW_UNAUTHENTICATED_API_ACCESS'] == 'true' || Rails.configuration.x.whitelist_mode
end end
private private

View File

@ -30,7 +30,6 @@ class Api::V1::Accounts::CredentialsController < Api::BaseController
:bot, :bot,
:discoverable, :discoverable,
:hide_collections, :hide_collections,
:indexable,
fields_attributes: [:name, :value] fields_attributes: [:name, :value]
) )
end end

View File

@ -1,74 +0,0 @@
# frozen_string_literal: true
class Api::V1::Admin::TagsController < Api::BaseController
include Authorization
before_action -> { authorize_if_got_token! :'admin:read' }, only: [:index, :show]
before_action -> { authorize_if_got_token! :'admin:write' }, only: :update
before_action :set_tags, only: :index
before_action :set_tag, except: :index
after_action :insert_pagination_headers, only: :index
after_action :verify_authorized
LIMIT = 100
PAGINATION_PARAMS = %i(limit).freeze
def index
authorize :tag, :index?
render json: @tags, each_serializer: REST::Admin::TagSerializer
end
def show
authorize @tag, :show?
render json: @tag, serializer: REST::Admin::TagSerializer
end
def update
authorize @tag, :update?
@tag.update!(tag_params.merge(reviewed_at: Time.now.utc))
render json: @tag, serializer: REST::Admin::TagSerializer
end
private
def set_tag
@tag = Tag.find(params[:id])
end
def set_tags
@tags = Tag.all.to_a_paginated_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id))
end
def tag_params
params.permit(:display_name, :trendable, :usable, :listable)
end
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def next_path
api_v1_admin_tags_url(pagination_params(max_id: pagination_max_id)) if records_continue?
end
def prev_path
api_v1_admin_tags_url(pagination_params(min_id: pagination_since_id)) unless @tags.empty?
end
def pagination_max_id
@tags.last.id
end
def pagination_since_id
@tags.first.id
end
def records_continue?
@tags.size == limit_param(LIMIT)
end
def pagination_params(core_params)
params.slice(*PAGINATION_PARAMS).permit(*PAGINATION_PARAMS).merge(core_params)
end
end

View File

@ -16,9 +16,7 @@ class Api::V1::DirectoriesController < Api::BaseController
end end
def set_accounts def set_accounts
with_read_replica do @accounts = accounts_scope.offset(params[:offset]).limit(limit_param(DEFAULT_ACCOUNTS_LIMIT))
@accounts = accounts_scope.offset(params[:offset]).limit(limit_param(DEFAULT_ACCOUNTS_LIMIT))
end
end end
def accounts_scope def accounts_scope

View File

@ -3,7 +3,7 @@
class Api::V1::Instances::ActivityController < Api::BaseController class Api::V1::Instances::ActivityController < Api::BaseController
before_action :require_enabled_api! before_action :require_enabled_api!
skip_before_action :require_authenticated_user!, unless: :limited_federation_mode? skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
vary_by '' vary_by ''
@ -33,6 +33,6 @@ class Api::V1::Instances::ActivityController < Api::BaseController
end end
def require_enabled_api! def require_enabled_api!
head 404 unless Setting.activity_api_enabled && !limited_federation_mode? head 404 unless Setting.activity_api_enabled && !whitelist_mode?
end end
end end

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::Instances::DomainBlocksController < Api::BaseController class Api::V1::Instances::DomainBlocksController < Api::BaseController
skip_before_action :require_authenticated_user!, unless: :limited_federation_mode? skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
before_action :require_enabled_api! before_action :require_enabled_api!
before_action :set_domain_blocks before_action :set_domain_blocks

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::Instances::ExtendedDescriptionsController < Api::BaseController class Api::V1::Instances::ExtendedDescriptionsController < Api::BaseController
skip_before_action :require_authenticated_user!, unless: :limited_federation_mode? skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
skip_around_action :set_locale skip_around_action :set_locale
before_action :set_extended_description before_action :set_extended_description
@ -10,7 +10,7 @@ class Api::V1::Instances::ExtendedDescriptionsController < Api::BaseController
# Override `current_user` to avoid reading session cookies unless in whitelist mode # Override `current_user` to avoid reading session cookies unless in whitelist mode
def current_user def current_user
super if limited_federation_mode? super if whitelist_mode?
end end
def show def show

View File

@ -1,21 +0,0 @@
# frozen_string_literal: true
class Api::V1::Instances::LanguagesController < Api::BaseController
skip_before_action :require_authenticated_user!, unless: :limited_federation_mode?
skip_around_action :set_locale
before_action :set_languages
vary_by ''
def show
cache_even_if_authenticated!
render json: @languages, each_serializer: REST::LanguageSerializer
end
private
def set_languages
@languages = LanguagesHelper::SUPPORTED_LOCALES.keys.map { |code| LanguagePresenter.new(code) }
end
end

View File

@ -3,14 +3,14 @@
class Api::V1::Instances::PeersController < Api::BaseController class Api::V1::Instances::PeersController < Api::BaseController
before_action :require_enabled_api! before_action :require_enabled_api!
skip_before_action :require_authenticated_user!, unless: :limited_federation_mode? skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
skip_around_action :set_locale skip_around_action :set_locale
vary_by '' vary_by ''
# Override `current_user` to avoid reading session cookies unless in whitelist mode # Override `current_user` to avoid reading session cookies unless in whitelist mode
def current_user def current_user
super if limited_federation_mode? super if whitelist_mode?
end end
def index def index
@ -21,6 +21,6 @@ class Api::V1::Instances::PeersController < Api::BaseController
private private
def require_enabled_api! def require_enabled_api!
head 404 unless Setting.peers_api_enabled && !limited_federation_mode? head 404 unless Setting.peers_api_enabled && !whitelist_mode?
end end
end end

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::Instances::PrivacyPoliciesController < Api::BaseController class Api::V1::Instances::PrivacyPoliciesController < Api::BaseController
skip_before_action :require_authenticated_user!, unless: :limited_federation_mode? skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
before_action :set_privacy_policy before_action :set_privacy_policy

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::Instances::RulesController < Api::BaseController class Api::V1::Instances::RulesController < Api::BaseController
skip_before_action :require_authenticated_user!, unless: :limited_federation_mode? skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
skip_around_action :set_locale skip_around_action :set_locale
before_action :set_rules before_action :set_rules
@ -10,7 +10,7 @@ class Api::V1::Instances::RulesController < Api::BaseController
# Override `current_user` to avoid reading session cookies unless in whitelist mode # Override `current_user` to avoid reading session cookies unless in whitelist mode
def current_user def current_user
super if limited_federation_mode? super if whitelist_mode?
end end
def index def index

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::Instances::TranslationLanguagesController < Api::BaseController class Api::V1::Instances::TranslationLanguagesController < Api::BaseController
skip_before_action :require_authenticated_user!, unless: :limited_federation_mode? skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
before_action :set_languages before_action :set_languages

View File

@ -1,14 +1,14 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::InstancesController < Api::BaseController class Api::V1::InstancesController < Api::BaseController
skip_before_action :require_authenticated_user!, unless: :limited_federation_mode? skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
skip_around_action :set_locale skip_around_action :set_locale
vary_by '' vary_by ''
# Override `current_user` to avoid reading session cookies unless in whitelist mode # Override `current_user` to avoid reading session cookies unless in whitelist mode
def current_user def current_user
super if limited_federation_mode? super if whitelist_mode?
end end
def show def show

View File

@ -4,7 +4,7 @@ class Api::V1::Peers::SearchController < Api::BaseController
before_action :require_enabled_api! before_action :require_enabled_api!
before_action :set_domains before_action :set_domains
skip_before_action :require_authenticated_user!, unless: :limited_federation_mode? skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
skip_around_action :set_locale skip_around_action :set_locale
vary_by '' vary_by ''
@ -17,7 +17,7 @@ class Api::V1::Peers::SearchController < Api::BaseController
private private
def require_enabled_api! def require_enabled_api!
head 404 unless Setting.peers_api_enabled && !limited_federation_mode? head 404 unless Setting.peers_api_enabled && !whitelist_mode?
end end
def set_domains def set_domains
@ -27,7 +27,7 @@ class Api::V1::Peers::SearchController < Api::BaseController
@domains = InstancesIndex.query(function_score: { @domains = InstancesIndex.query(function_score: {
query: { query: {
prefix: { prefix: {
domain: TagManager.instance.normalize_domain(params[:q].strip), domain: params[:q],
}, },
}, },
@ -41,7 +41,5 @@ class Api::V1::Peers::SearchController < Api::BaseController
domain = TagManager.instance.normalize_domain(domain) domain = TagManager.instance.normalize_domain(domain)
@domains = Instance.searchable.where(Instance.arel_table[:domain].matches("#{Instance.sanitize_sql_like(domain)}%", false, true)).limit(10).pluck(:domain) @domains = Instance.searchable.where(Instance.arel_table[:domain].matches("#{Instance.sanitize_sql_like(domain)}%", false, true)).limit(10).pluck(:domain)
end end
rescue Addressable::URI::InvalidURIError
@domains = []
end end
end end

View File

@ -1,13 +0,0 @@
# frozen_string_literal: true
class Api::V1::Profile::AvatarsController < Api::BaseController
before_action -> { doorkeeper_authorize! :write, :'write:accounts' }
before_action :require_user!
def destroy
@account = current_account
UpdateAccountService.new.call(@account, { avatar: nil }, raise_error: true)
ActivityPub::UpdateDistributionWorker.perform_async(@account.id)
render json: @account, serializer: REST::CredentialAccountSerializer
end
end

View File

@ -1,13 +0,0 @@
# frozen_string_literal: true
class Api::V1::Profile::HeadersController < Api::BaseController
before_action -> { doorkeeper_authorize! :write, :'write:accounts' }
before_action :require_user!
def destroy
@account = current_account
UpdateAccountService.new.call(@account, { header: nil }, raise_error: true)
ActivityPub::UpdateDistributionWorker.perform_async(@account.id)
render json: @account, serializer: REST::CredentialAccountSerializer
end
end

View File

@ -8,15 +8,7 @@ class Api::V1::Statuses::TranslationsController < Api::BaseController
before_action :set_translation before_action :set_translation
rescue_from TranslationService::NotConfiguredError, with: :not_found rescue_from TranslationService::NotConfiguredError, with: :not_found
rescue_from TranslationService::UnexpectedResponseError, with: :service_unavailable rescue_from TranslationService::UnexpectedResponseError, TranslationService::QuotaExceededError, TranslationService::TooManyRequestsError, with: :service_unavailable
rescue_from TranslationService::QuotaExceededError do
render json: { error: I18n.t('translation.errors.quota_exceeded') }, status: 503
end
rescue_from TranslationService::TooManyRequestsError do
render json: { error: I18n.t('translation.errors.too_many_requests') }, status: 503
end
def create def create
render json: @translation, serializer: REST::TranslationSerializer render json: @translation, serializer: REST::TranslationSerializer

View File

@ -1,7 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::Timelines::TagController < Api::BaseController class Api::V1::Timelines::TagController < Api::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:statuses' }, only: :show, if: :require_auth?
before_action :load_tag before_action :load_tag
after_action :insert_pagination_headers, unless: -> { @statuses.empty? } after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
@ -13,10 +12,6 @@ class Api::V1::Timelines::TagController < Api::BaseController
private private
def require_auth?
!Setting.timeline_preview
end
def load_tag def load_tag
@tag = Tag.find_normalized(params[:id]) @tag = Tag.find_normalized(params[:id])
end end

View File

@ -12,7 +12,6 @@ class ApplicationController < ActionController::Base
include DomainControlHelper include DomainControlHelper
include ThemingConcern include ThemingConcern
include DatabaseHelper include DatabaseHelper
include AuthorizedFetchHelper
helper_method :current_account helper_method :current_account
helper_method :current_session helper_method :current_session
@ -22,7 +21,7 @@ class ApplicationController < ActionController::Base
helper_method :use_seamless_external_login? helper_method :use_seamless_external_login?
helper_method :omniauth_only? helper_method :omniauth_only?
helper_method :sso_account_settings helper_method :sso_account_settings
helper_method :limited_federation_mode? helper_method :whitelist_mode?
helper_method :body_class_string helper_method :body_class_string
helper_method :skip_csrf_meta_tags? helper_method :skip_csrf_meta_tags?
@ -54,6 +53,10 @@ class ApplicationController < ActionController::Base
private private
def authorized_fetch_mode?
ENV['AUTHORIZED_FETCH'] == 'true' || Rails.configuration.x.whitelist_mode
end
def public_fetch_mode? def public_fetch_mode?
!authorized_fetch_mode? !authorized_fetch_mode?
end end

View File

@ -4,7 +4,7 @@ module AccountOwnedConcern
extend ActiveSupport::Concern extend ActiveSupport::Concern
included do included do
before_action :authenticate_user!, if: -> { limited_federation_mode? && request.format != :json } before_action :authenticate_user!, if: -> { whitelist_mode? && request.format != :json }
before_action :set_account, if: :account_required? before_action :set_account, if: :account_required?
before_action :check_account_approval, if: :account_required? before_action :check_account_approval, if: :account_required?
before_action :check_account_suspension, if: :account_required? before_action :check_account_suspension, if: :account_required?

View File

@ -8,6 +8,6 @@ module ApiCachingConcern
end end
def cache_even_if_authenticated! def cache_even_if_authenticated!
expires_in(5.minutes, public: true, stale_while_revalidate: 30.seconds, stale_if_error: 1.day) unless limited_federation_mode? expires_in(5.minutes, public: true, stale_while_revalidate: 30.seconds, stale_if_error: 1.day) unless whitelist_mode?
end end
end end

View File

@ -42,7 +42,7 @@ module CaptchaConcern
end end
def extend_csp_for_captcha! def extend_csp_for_captcha!
policy = request.content_security_policy&.clone policy = request.content_security_policy
return unless captcha_required? && policy.present? return unless captcha_required? && policy.present?
@ -54,8 +54,6 @@ module CaptchaConcern
policy.send(directive, *values) policy.send(directive, *values)
end end
request.content_security_policy = policy
end end
def render_captcha def render_captcha

View File

@ -119,8 +119,6 @@ module SignatureVerification
private private
def fail_with!(message, **options) def fail_with!(message, **options)
Rails.logger.debug { "Signature verification failed: #{message}" }
@signature_verification_failure_reason = { error: message }.merge(options) @signature_verification_failure_reason = { error: message }.merge(options)
@signed_request_actor = nil @signed_request_actor = nil
end end

View File

@ -12,7 +12,7 @@ module WebAppControllerConcern
end end
def skip_csrf_meta_tags? def skip_csrf_meta_tags?
!(ENV['ONE_CLICK_SSO_LOGIN'] == 'true' && ENV['OMNIAUTH_ONLY'] == 'true' && Devise.omniauth_providers.length == 1) && current_user.nil? current_user.nil?
end end
def set_app_body_class def set_app_body_class

View File

@ -10,7 +10,7 @@ class FollowerAccountsController < ApplicationController
before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? } before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
skip_around_action :set_locale, if: -> { request.format == :json } skip_around_action :set_locale, if: -> { request.format == :json }
skip_before_action :require_functional!, unless: :limited_federation_mode? skip_before_action :require_functional!, unless: :whitelist_mode?
def index def index
respond_to do |format| respond_to do |format|

View File

@ -10,7 +10,7 @@ class FollowingAccountsController < ApplicationController
before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? } before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
skip_around_action :set_locale, if: -> { request.format == :json } skip_around_action :set_locale, if: -> { request.format == :json }
skip_before_action :require_functional!, unless: :limited_federation_mode? skip_before_action :require_functional!, unless: :whitelist_mode?
def index def index
respond_to do |format| respond_to do |format|

View File

@ -9,8 +9,6 @@ class MailSubscriptionsController < ApplicationController
before_action :set_user before_action :set_user
before_action :set_type before_action :set_type
protect_from_forgery with: :null_session
def show; end def show; end
def create def create
@ -22,7 +20,6 @@ class MailSubscriptionsController < ApplicationController
def set_user def set_user
@user = GlobalID::Locator.locate_signed(params[:token], for: 'unsubscribe') @user = GlobalID::Locator.locate_signed(params[:token], for: 'unsubscribe')
not_found unless @user
end end
def set_body_classes def set_body_classes
@ -38,7 +35,7 @@ class MailSubscriptionsController < ApplicationController
when 'follow', 'reblog', 'favourite', 'mention', 'follow_request' when 'follow', 'reblog', 'favourite', 'mention', 'follow_request'
"notification_emails.#{params[:type]}" "notification_emails.#{params[:type]}"
else else
not_found raise ArgumentError
end end
end end
end end

View File

@ -3,9 +3,9 @@
class MediaController < ApplicationController class MediaController < ApplicationController
include Authorization include Authorization
skip_before_action :require_functional!, unless: :limited_federation_mode? skip_before_action :require_functional!, unless: :whitelist_mode?
before_action :authenticate_user!, if: :limited_federation_mode? before_action :authenticate_user!, if: :whitelist_mode?
before_action :set_media_attachment before_action :set_media_attachment
before_action :verify_permitted_status! before_action :verify_permitted_status!
before_action :check_playable, only: :player before_action :check_playable, only: :player

View File

@ -8,7 +8,7 @@ class MediaProxyController < ApplicationController
skip_before_action :require_functional! skip_before_action :require_functional!
before_action :authenticate_user!, if: :limited_federation_mode? before_action :authenticate_user!, if: :whitelist_mode?
rescue_from ActiveRecord::RecordInvalid, with: :not_found rescue_from ActiveRecord::RecordInvalid, with: :not_found
rescue_from Mastodon::UnexpectedResponseError, with: :not_found rescue_from Mastodon::UnexpectedResponseError, with: :not_found

View File

@ -1,27 +0,0 @@
# frozen_string_literal: true
class Settings::PrivacyController < Settings::BaseController
before_action :set_account
def show; end
def update
if UpdateAccountService.new.call(@account, account_params.except(:settings))
current_user.update!(settings_attributes: account_params[:settings])
ActivityPub::UpdateDistributionWorker.perform_async(@account.id)
redirect_to settings_privacy_path, notice: I18n.t('generic.changes_saved_msg')
else
render :show
end
end
private
def account_params
params.require(:account).permit(:discoverable, :unlocked, :indexable, :show_collections, settings: UserSettings.keys)
end
def set_account
@account = current_account
end
end

View File

@ -20,7 +20,7 @@ class Settings::ProfilesController < Settings::BaseController
private private
def account_params def account_params
params.require(:account).permit(:display_name, :note, :avatar, :header, :bot, fields_attributes: [:name, :value]) params.require(:account).permit(:display_name, :note, :avatar, :header, :locked, :bot, :discoverable, :hide_collections, fields_attributes: [:name, :value])
end end
def set_account def set_account

View File

@ -17,7 +17,7 @@ class StatusesController < ApplicationController
after_action :set_link_headers after_action :set_link_headers
skip_around_action :set_locale, if: -> { request.format == :json } skip_around_action :set_locale, if: -> { request.format == :json }
skip_before_action :require_functional!, only: [:show, :embed], unless: :limited_federation_mode? skip_before_action :require_functional!, only: [:show, :embed], unless: :whitelist_mode?
content_security_policy only: :embed do |policy| content_security_policy only: :embed do |policy|
policy.frame_ancestors(false) policy.frame_ancestors(false)

View File

@ -10,13 +10,13 @@ class TagsController < ApplicationController
vary_by -> { public_fetch_mode? ? 'Accept, Accept-Language, Cookie' : 'Accept, Accept-Language, Cookie, Signature' } vary_by -> { public_fetch_mode? ? 'Accept, Accept-Language, Cookie' : 'Accept, Accept-Language, Cookie, Signature' }
before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? } before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
before_action :authenticate_user!, if: :limited_federation_mode? before_action :authenticate_user!, if: :whitelist_mode?
before_action :set_local before_action :set_local
before_action :set_tag before_action :set_tag
before_action :set_statuses, if: -> { request.format == :rss } before_action :set_statuses, if: -> { request.format == :rss }
before_action :set_instance_presenter before_action :set_instance_presenter
skip_before_action :require_functional!, unless: :limited_federation_mode? skip_before_action :require_functional!, unless: :whitelist_mode?
def show def show
respond_to do |format| respond_to do |format|

View File

@ -1,11 +0,0 @@
# frozen_string_literal: true
module AuthorizedFetchHelper
def authorized_fetch_mode?
ENV.fetch('AUTHORIZED_FETCH') { Setting.authorized_fetch && 'true' } == 'true' || Rails.configuration.x.limited_federation_mode
end
def authorized_fetch_overridden?
ENV.key?('AUTHORIZED_FETCH') || Rails.configuration.x.limited_federation_mode
end
end

View File

@ -21,8 +21,6 @@ module ContextHelper
focal_point: { 'toot' => 'http://joinmastodon.org/ns#', 'focalPoint' => { '@container' => '@list', '@id' => 'toot:focalPoint' } }, focal_point: { 'toot' => 'http://joinmastodon.org/ns#', 'focalPoint' => { '@container' => '@list', '@id' => 'toot:focalPoint' } },
blurhash: { 'toot' => 'http://joinmastodon.org/ns#', 'blurhash' => 'toot:blurhash' }, blurhash: { 'toot' => 'http://joinmastodon.org/ns#', 'blurhash' => 'toot:blurhash' },
discoverable: { 'toot' => 'http://joinmastodon.org/ns#', 'discoverable' => 'toot:discoverable' }, discoverable: { 'toot' => 'http://joinmastodon.org/ns#', 'discoverable' => 'toot:discoverable' },
indexable: { 'toot' => 'http://joinmastodon.org/ns#', 'indexable' => 'toot:indexable' },
memorial: { 'toot' => 'http://joinmastodon.org/ns#', 'memorial' => 'toot:memorial' },
voters_count: { 'toot' => 'http://joinmastodon.org/ns#', 'votersCount' => 'toot:votersCount' }, voters_count: { 'toot' => 'http://joinmastodon.org/ns#', 'votersCount' => 'toot:votersCount' },
olm: { olm: {
'toot' => 'http://joinmastodon.org/ns#', 'Device' => 'toot:Device', 'Ed25519Signature' => 'toot:Ed25519Signature', 'Ed25519Key' => 'toot:Ed25519Key', 'Curve25519Key' => 'toot:Curve25519Key', 'EncryptedMessage' => 'toot:EncryptedMessage', 'publicKeyBase64' => 'toot:publicKeyBase64', 'deviceId' => 'toot:deviceId', 'toot' => 'http://joinmastodon.org/ns#', 'Device' => 'toot:Device', 'Ed25519Signature' => 'toot:Ed25519Signature', 'Ed25519Key' => 'toot:Ed25519Key', 'Curve25519Key' => 'toot:Curve25519Key', 'EncryptedMessage' => 'toot:EncryptedMessage', 'publicKeyBase64' => 'toot:publicKeyBase64', 'deviceId' => 'toot:deviceId',

View File

@ -10,14 +10,14 @@ module DomainControlHelper
uri_or_domain uri_or_domain
end end
if limited_federation_mode? if whitelist_mode?
!DomainAllow.allowed?(domain) !DomainAllow.allowed?(domain)
else else
DomainBlock.blocked?(domain) DomainBlock.blocked?(domain)
end end
end end
def limited_federation_mode? def whitelist_mode?
Rails.configuration.x.limited_federation_mode Rails.configuration.x.whitelist_mode
end end
end end

View File

@ -188,11 +188,11 @@ module LanguagesHelper
ISO_639_3 = { ISO_639_3 = {
ast: ['Asturian', 'Asturianu'].freeze, ast: ['Asturian', 'Asturianu'].freeze,
chr: ['Cherokee', 'ᏣᎳᎩ ᎦᏬᏂᎯᏍᏗ'].freeze,
ckb: ['Sorani (Kurdish)', 'سۆرانی'].freeze, ckb: ['Sorani (Kurdish)', 'سۆرانی'].freeze,
cnr: ['Montenegrin', 'crnogorski'].freeze, cnr: ['Montenegrin', 'crnogorski'].freeze,
jbo: ['Lojban', 'la .lojban.'].freeze, jbo: ['Lojban', 'la .lojban.'].freeze,
kab: ['Kabyle', 'Taqbaylit'].freeze, kab: ['Kabyle', 'Taqbaylit'].freeze,
kmr: ['Kurmanji (Kurdish)', 'Kurmancî'].freeze,
ldn: ['Láadan', 'Láadan'].freeze, ldn: ['Láadan', 'Láadan'].freeze,
lfn: ['Lingua Franca Nova', 'lingua franca nova'].freeze, lfn: ['Lingua Franca Nova', 'lingua franca nova'].freeze,
sco: ['Scots', 'Scots'].freeze, sco: ['Scots', 'Scots'].freeze,
@ -200,22 +200,11 @@ module LanguagesHelper
smj: ['Lule Sami', 'Julevsámegiella'].freeze, smj: ['Lule Sami', 'Julevsámegiella'].freeze,
szl: ['Silesian', 'ślůnsko godka'].freeze, szl: ['Silesian', 'ślůnsko godka'].freeze,
tok: ['Toki Pona', 'toki pona'].freeze, tok: ['Toki Pona', 'toki pona'].freeze,
xal: ['Kalmyk', 'Хальмг келн'].freeze,
zba: ['Balaibalan', 'باليبلن'].freeze, zba: ['Balaibalan', 'باليبلن'].freeze,
zgh: ['Standard Moroccan Tamazight', 'ⵜⴰⵎⴰⵣⵉⵖⵜ'].freeze, zgh: ['Standard Moroccan Tamazight', 'ⵜⴰⵎⴰⵣⵉⵖⵜ'].freeze,
}.freeze }.freeze
# e.g. For Chinese, which is not a language, SUPPORTED_LOCALES = {}.merge(ISO_639_1).merge(ISO_639_3).freeze
# but a language family in spite of sharing the main locale code
# We need to be able to filter these
ISO_639_1_REGIONAL = {
'zh-CN': ['Chinese (China)', '简体中文'].freeze,
'zh-HK': ['Chinese (Hong Kong)', '繁體中文(香港)'].freeze,
'zh-TW': ['Chinese (Taiwan)', '繁體中文(臺灣)'].freeze,
'zh-YUE': ['Cantonese', '廣東話'].freeze,
}.freeze
SUPPORTED_LOCALES = {}.merge(ISO_639_1).merge(ISO_639_1_REGIONAL).merge(ISO_639_3).freeze
# For ISO-639-1 and ISO-639-3 language codes, we have their official # For ISO-639-1 and ISO-639-3 language codes, we have their official
# names, but for some translations, we need the names of the # names, but for some translations, we need the names of the
@ -228,6 +217,9 @@ module LanguagesHelper
'pt-BR': 'Português (Brasil)', 'pt-BR': 'Português (Brasil)',
'pt-PT': 'Português (Portugal)', 'pt-PT': 'Português (Portugal)',
'sr-Latn': 'Srpski (latinica)', 'sr-Latn': 'Srpski (latinica)',
'zh-CN': '简体中文',
'zh-HK': '繁體中文(香港)',
'zh-TW': '繁體中文(臺灣)',
}.freeze }.freeze
def native_locale_name(locale) def native_locale_name(locale)

View File

@ -14,7 +14,6 @@ module MediaComponentHelper
blurhash: video.blurhash, blurhash: video.blurhash,
frameRate: meta.dig('original', 'frame_rate'), frameRate: meta.dig('original', 'frame_rate'),
inline: true, inline: true,
aspectRatio: "#{meta.dig('original', 'width')} / #{meta.dig('original', 'height')}",
media: [ media: [
serialize_media_attachment(video), serialize_media_attachment(video),
].as_json, ].as_json,

View File

@ -0,0 +1,28 @@
// This file will be loaded on public pages, regardless of theme.
import 'packs/public-path';
import { delegate } from '@rails/ujs';
const getProfileAvatarAnimationHandler = (swapTo) => {
//animate avatar gifs on the profile page when moused over
return ({ target }) => {
const swapSrc = target.getAttribute(swapTo);
//only change the img source if autoplay is off and the image src is actually different
if(target.getAttribute('data-autoplay') !== 'true' && target.src !== swapSrc) {
target.src = swapSrc;
}
};
};
delegate(document, 'img#profile_page_avatar', 'mouseover', getProfileAvatarAnimationHandler('data-original'));
delegate(document, 'img#profile_page_avatar', 'mouseout', getProfileAvatarAnimationHandler('data-static'));
delegate(document, '#account_header', 'change', ({ target }) => {
const header = document.querySelector('.card .card__img img');
const [file] = target.files || [];
const url = file ? URL.createObjectURL(file) : header.dataset.originalSrc;
header.src = url;
});

View File

@ -140,9 +140,7 @@ const fromAcct = (acct: string) => {
}; };
const fetchInteractionURL = (uri_or_domain: string) => { const fetchInteractionURL = (uri_or_domain: string) => {
if (uri_or_domain === '') { if (/^https?:\/\//.test(uri_or_domain)) {
fetchInteractionURLFailure();
} else if (/^https?:\/\//.test(uri_or_domain)) {
fromURL(uri_or_domain); fromURL(uri_or_domain);
} else if (uri_or_domain.includes('@')) { } else if (uri_or_domain.includes('@')) {
fromAcct(uri_or_domain); fromAcct(uri_or_domain);

View File

@ -2,15 +2,50 @@
import 'packs/public-path'; import 'packs/public-path';
import { delegate } from '@rails/ujs'; import { delegate } from '@rails/ujs';
import escapeTextContentForBrowser from 'escape-html';
delegate(document, '#edit_profile input[type=file]', 'change', ({ target }) => {
const avatar = document.getElementById(target.id + '-preview'); import emojify from '../mastodon/features/emoji/emoji';
delegate(document, '#account_display_name', 'input', ({ target }) => {
const name = document.querySelector('.card .display-name strong');
if (name) {
if (target.value) {
name.innerHTML = emojify(escapeTextContentForBrowser(target.value));
} else {
name.textContent = name.textContent = target.dataset.default;
}
}
});
delegate(document, '#account_avatar', 'change', ({ target }) => {
const avatar = document.querySelector('.card .avatar img');
const [file] = target.files || []; const [file] = target.files || [];
const url = file ? URL.createObjectURL(file) : avatar.dataset.originalSrc; const url = file ? URL.createObjectURL(file) : avatar.dataset.originalSrc;
avatar.src = url; avatar.src = url;
}); });
delegate(document, '#account_header', 'change', ({ target }) => {
const header = document.querySelector('.card .card__img img');
const [file] = target.files || [];
const url = file ? URL.createObjectURL(file) : header.dataset.originalSrc;
header.src = url;
});
delegate(document, '#account_locked', 'change', ({ target }) => {
const lock = document.querySelector('.card .display-name i');
if (lock) {
if (target.checked) {
delete lock.dataset.hidden;
} else {
lock.dataset.hidden = 'true';
}
}
});
delegate(document, '.input-copy input', 'click', ({ target }) => { delegate(document, '.input-copy input', 'click', ({ target }) => {
target.focus(); target.focus();
target.select(); target.select();

View File

@ -13,8 +13,8 @@ pack:
mailer: mailer:
filename: mailer.js filename: mailer.js
stylesheet: true stylesheet: true
modal: modal: public.js
public: public: public.js
settings: settings.js settings: settings.js
sign_up: sign_up:
share: share:

View File

@ -75,10 +75,7 @@ export function normalizeStatus(status, normalOldStatus, settings) {
normalStatus.contentHtml = normalOldStatus.get('contentHtml'); normalStatus.contentHtml = normalOldStatus.get('contentHtml');
normalStatus.spoilerHtml = normalOldStatus.get('spoilerHtml'); normalStatus.spoilerHtml = normalOldStatus.get('spoilerHtml');
normalStatus.hidden = normalOldStatus.get('hidden'); normalStatus.hidden = normalOldStatus.get('hidden');
normalStatus.translation = normalOldStatus.get('translation');
if (normalOldStatus.get('translation')) {
normalStatus.translation = normalOldStatus.get('translation');
}
} else { } else {
const spoilerText = normalStatus.spoiler_text || ''; const spoilerText = normalStatus.spoiler_text || '';
const searchContent = ([spoilerText, status.content].concat((status.poll && status.poll.options) ? status.poll.options.map(option => option.title) : [])).concat(status.media_attachments.map(att => att.description)).join('\n\n').replace(/<br\s*\/?>/g, '\n').replace(/<\/p><p>/g, '\n\n'); const searchContent = ([spoilerText, status.content].concat((status.poll && status.poll.options) ? status.poll.options.map(option => option.title) : [])).concat(status.media_attachments.map(att => att.description)).join('\n\n').replace(/<br\s*\/?>/g, '\n').replace(/<\/p><p>/g, '\n\n');

View File

@ -1,16 +1,11 @@
import api, { getLinks } from '../api'; import api from '../api';
import { fetchRelationships } from './accounts';
import { importFetchedAccounts, importFetchedStatus } from './importer'; import { importFetchedAccounts, importFetchedStatus } from './importer';
export const REBLOG_REQUEST = 'REBLOG_REQUEST'; export const REBLOG_REQUEST = 'REBLOG_REQUEST';
export const REBLOG_SUCCESS = 'REBLOG_SUCCESS'; export const REBLOG_SUCCESS = 'REBLOG_SUCCESS';
export const REBLOG_FAIL = 'REBLOG_FAIL'; export const REBLOG_FAIL = 'REBLOG_FAIL';
export const REBLOGS_EXPAND_REQUEST = 'REBLOGS_EXPAND_REQUEST';
export const REBLOGS_EXPAND_SUCCESS = 'REBLOGS_EXPAND_SUCCESS';
export const REBLOGS_EXPAND_FAIL = 'REBLOGS_EXPAND_FAIL';
export const FAVOURITE_REQUEST = 'FAVOURITE_REQUEST'; export const FAVOURITE_REQUEST = 'FAVOURITE_REQUEST';
export const FAVOURITE_SUCCESS = 'FAVOURITE_SUCCESS'; export const FAVOURITE_SUCCESS = 'FAVOURITE_SUCCESS';
export const FAVOURITE_FAIL = 'FAVOURITE_FAIL'; export const FAVOURITE_FAIL = 'FAVOURITE_FAIL';
@ -31,10 +26,6 @@ export const FAVOURITES_FETCH_REQUEST = 'FAVOURITES_FETCH_REQUEST';
export const FAVOURITES_FETCH_SUCCESS = 'FAVOURITES_FETCH_SUCCESS'; export const FAVOURITES_FETCH_SUCCESS = 'FAVOURITES_FETCH_SUCCESS';
export const FAVOURITES_FETCH_FAIL = 'FAVOURITES_FETCH_FAIL'; export const FAVOURITES_FETCH_FAIL = 'FAVOURITES_FETCH_FAIL';
export const FAVOURITES_EXPAND_REQUEST = 'FAVOURITES_EXPAND_REQUEST';
export const FAVOURITES_EXPAND_SUCCESS = 'FAVOURITES_EXPAND_SUCCESS';
export const FAVOURITES_EXPAND_FAIL = 'FAVOURITES_EXPAND_FAIL';
export const PIN_REQUEST = 'PIN_REQUEST'; export const PIN_REQUEST = 'PIN_REQUEST';
export const PIN_SUCCESS = 'PIN_SUCCESS'; export const PIN_SUCCESS = 'PIN_SUCCESS';
export const PIN_FAIL = 'PIN_FAIL'; export const PIN_FAIL = 'PIN_FAIL';
@ -268,10 +259,8 @@ export function fetchReblogs(id) {
dispatch(fetchReblogsRequest(id)); dispatch(fetchReblogsRequest(id));
api(getState).get(`/api/v1/statuses/${id}/reblogged_by`).then(response => { api(getState).get(`/api/v1/statuses/${id}/reblogged_by`).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts(response.data)); dispatch(importFetchedAccounts(response.data));
dispatch(fetchReblogsSuccess(id, response.data, next ? next.uri : null)); dispatch(fetchReblogsSuccess(id, response.data));
dispatch(fetchRelationships(response.data.map(item => item.id)));
}).catch(error => { }).catch(error => {
dispatch(fetchReblogsFail(id, error)); dispatch(fetchReblogsFail(id, error));
}); });
@ -285,62 +274,17 @@ export function fetchReblogsRequest(id) {
}; };
} }
export function fetchReblogsSuccess(id, accounts, next) { export function fetchReblogsSuccess(id, accounts) {
return { return {
type: REBLOGS_FETCH_SUCCESS, type: REBLOGS_FETCH_SUCCESS,
id, id,
accounts, accounts,
next,
}; };
} }
export function fetchReblogsFail(id, error) { export function fetchReblogsFail(id, error) {
return { return {
type: REBLOGS_FETCH_FAIL, type: REBLOGS_FETCH_FAIL,
id,
error,
};
}
export function expandReblogs(id) {
return (dispatch, getState) => {
const url = getState().getIn(['user_lists', 'reblogged_by', id, 'next']);
if (url === null) {
return;
}
dispatch(expandReblogsRequest(id));
api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts(response.data));
dispatch(expandReblogsSuccess(id, response.data, next ? next.uri : null));
dispatch(fetchRelationships(response.data.map(item => item.id)));
}).catch(error => dispatch(expandReblogsFail(id, error)));
};
}
export function expandReblogsRequest(id) {
return {
type: REBLOGS_EXPAND_REQUEST,
id,
};
}
export function expandReblogsSuccess(id, accounts, next) {
return {
type: REBLOGS_EXPAND_SUCCESS,
id,
accounts,
next,
};
}
export function expandReblogsFail(id, error) {
return {
type: REBLOGS_EXPAND_FAIL,
id,
error, error,
}; };
} }
@ -350,10 +294,8 @@ export function fetchFavourites(id) {
dispatch(fetchFavouritesRequest(id)); dispatch(fetchFavouritesRequest(id));
api(getState).get(`/api/v1/statuses/${id}/favourited_by`).then(response => { api(getState).get(`/api/v1/statuses/${id}/favourited_by`).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts(response.data)); dispatch(importFetchedAccounts(response.data));
dispatch(fetchFavouritesSuccess(id, response.data, next ? next.uri : null)); dispatch(fetchFavouritesSuccess(id, response.data));
dispatch(fetchRelationships(response.data.map(item => item.id)));
}).catch(error => { }).catch(error => {
dispatch(fetchFavouritesFail(id, error)); dispatch(fetchFavouritesFail(id, error));
}); });
@ -367,62 +309,17 @@ export function fetchFavouritesRequest(id) {
}; };
} }
export function fetchFavouritesSuccess(id, accounts, next) { export function fetchFavouritesSuccess(id, accounts) {
return { return {
type: FAVOURITES_FETCH_SUCCESS, type: FAVOURITES_FETCH_SUCCESS,
id, id,
accounts, accounts,
next,
}; };
} }
export function fetchFavouritesFail(id, error) { export function fetchFavouritesFail(id, error) {
return { return {
type: FAVOURITES_FETCH_FAIL, type: FAVOURITES_FETCH_FAIL,
id,
error,
};
}
export function expandFavourites(id) {
return (dispatch, getState) => {
const url = getState().getIn(['user_lists', 'favourited_by', id, 'next']);
if (url === null) {
return;
}
dispatch(expandFavouritesRequest(id));
api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts(response.data));
dispatch(expandFavouritesSuccess(id, response.data, next ? next.uri : null));
dispatch(fetchRelationships(response.data.map(item => item.id)));
}).catch(error => dispatch(expandFavouritesFail(id, error)));
};
}
export function expandFavouritesRequest(id) {
return {
type: FAVOURITES_EXPAND_REQUEST,
id,
};
}
export function expandFavouritesSuccess(id, accounts, next) {
return {
type: FAVOURITES_EXPAND_SUCCESS,
id,
accounts,
next,
};
}
export function expandFavouritesFail(id, error) {
return {
type: FAVOURITES_EXPAND_FAIL,
id,
error, error,
}; };
} }

View File

@ -18,7 +18,6 @@ import {
importFetchedStatuses, importFetchedStatuses,
} from './importer'; } from './importer';
import { submitMarkers } from './markers'; import { submitMarkers } from './markers';
import { register as registerPushNotifications } from './push_notifications';
import { saveSettings } from './settings'; import { saveSettings } from './settings';
@ -385,10 +384,6 @@ export function requestBrowserPermission(callback = noOp) {
requestNotificationPermission((permission) => { requestNotificationPermission((permission) => {
dispatch(setBrowserPermission(permission)); dispatch(setBrowserPermission(permission));
callback(permission); callback(permission);
if (permission === 'granted') {
dispatch(registerPushNotifications());
}
}); });
}; };
} }

View File

@ -1,7 +1,3 @@
import { fromJS } from 'immutable';
import { searchHistory } from 'flavours/glitch/settings';
import api from '../api'; import api from '../api';
import { fetchRelationships } from './accounts'; import { fetchRelationships } from './accounts';
@ -19,7 +15,8 @@ export const SEARCH_EXPAND_REQUEST = 'SEARCH_EXPAND_REQUEST';
export const SEARCH_EXPAND_SUCCESS = 'SEARCH_EXPAND_SUCCESS'; export const SEARCH_EXPAND_SUCCESS = 'SEARCH_EXPAND_SUCCESS';
export const SEARCH_EXPAND_FAIL = 'SEARCH_EXPAND_FAIL'; export const SEARCH_EXPAND_FAIL = 'SEARCH_EXPAND_FAIL';
export const SEARCH_HISTORY_UPDATE = 'SEARCH_HISTORY_UPDATE'; export const SEARCH_RESULT_CLICK = 'SEARCH_RESULT_CLICK';
export const SEARCH_RESULT_FORGET = 'SEARCH_RESULT_FORGET';
export function changeSearch(value) { export function changeSearch(value) {
return { return {
@ -40,17 +37,17 @@ export function submitSearch(type) {
const signedIn = !!getState().getIn(['meta', 'me']); const signedIn = !!getState().getIn(['meta', 'me']);
if (value.length === 0) { if (value.length === 0) {
dispatch(fetchSearchSuccess({ accounts: [], statuses: [], hashtags: [] }, '', type)); dispatch(fetchSearchSuccess({ accounts: [], statuses: [], hashtags: [] }, ''));
return; return;
} }
dispatch(fetchSearchRequest(type)); dispatch(fetchSearchRequest());
api(getState).get('/api/v2/search', { api(getState).get('/api/v2/search', {
params: { params: {
q: value, q: value,
resolve: signedIn, resolve: signedIn,
limit: 11, limit: 10,
type, type,
}, },
}).then(response => { }).then(response => {
@ -62,7 +59,7 @@ export function submitSearch(type) {
dispatch(importFetchedStatuses(response.data.statuses)); dispatch(importFetchedStatuses(response.data.statuses));
} }
dispatch(fetchSearchSuccess(response.data, value, type)); dispatch(fetchSearchSuccess(response.data, value));
dispatch(fetchRelationships(response.data.accounts.map(item => item.id))); dispatch(fetchRelationships(response.data.accounts.map(item => item.id)));
}).catch(error => { }).catch(error => {
dispatch(fetchSearchFail(error)); dispatch(fetchSearchFail(error));
@ -70,18 +67,16 @@ export function submitSearch(type) {
}; };
} }
export function fetchSearchRequest(searchType) { export function fetchSearchRequest() {
return { return {
type: SEARCH_FETCH_REQUEST, type: SEARCH_FETCH_REQUEST,
searchType,
}; };
} }
export function fetchSearchSuccess(results, searchTerm, searchType) { export function fetchSearchSuccess(results, searchTerm) {
return { return {
type: SEARCH_FETCH_SUCCESS, type: SEARCH_FETCH_SUCCESS,
results, results,
searchType,
searchTerm, searchTerm,
}; };
} }
@ -95,16 +90,15 @@ export function fetchSearchFail(error) {
export const expandSearch = type => (dispatch, getState) => { export const expandSearch = type => (dispatch, getState) => {
const value = getState().getIn(['search', 'value']); const value = getState().getIn(['search', 'value']);
const offset = getState().getIn(['search', 'results', type]).size - 1; const offset = getState().getIn(['search', 'results', type]).size;
dispatch(expandSearchRequest(type)); dispatch(expandSearchRequest());
api(getState).get('/api/v2/search', { api(getState).get('/api/v2/search', {
params: { params: {
q: value, q: value,
type, type,
offset, offset,
limit: 11,
}, },
}).then(({ data }) => { }).then(({ data }) => {
if (data.accounts) { if (data.accounts) {
@ -122,9 +116,8 @@ export const expandSearch = type => (dispatch, getState) => {
}); });
}; };
export const expandSearchRequest = (searchType) => ({ export const expandSearchRequest = () => ({
type: SEARCH_EXPAND_REQUEST, type: SEARCH_EXPAND_REQUEST,
searchType,
}); });
export const expandSearchSuccess = (results, searchTerm, searchType) => ({ export const expandSearchSuccess = (results, searchTerm, searchType) => ({
@ -168,34 +161,16 @@ export const openURL = routerHistory => (dispatch, getState) => {
}); });
}; };
export const clickSearchResult = (q, type) => (dispatch, getState) => { export const clickSearchResult = (q, type) => ({
const previous = getState().getIn(['search', 'recent']); type: SEARCH_RESULT_CLICK,
const me = getState().getIn(['meta', 'me']);
const current = previous.add(fromJS({ type, q })).takeLast(4);
searchHistory.set(me, current.toJS()); result: {
dispatch(updateSearchHistory(current)); type,
}; q,
},
export const forgetSearchResult = q => (dispatch, getState) => {
const previous = getState().getIn(['search', 'recent']);
const me = getState().getIn(['meta', 'me']);
const current = previous.filterNot(result => result.get('q') === q);
searchHistory.set(me, current.toJS());
dispatch(updateSearchHistory(current));
};
export const updateSearchHistory = recent => ({
type: SEARCH_HISTORY_UPDATE,
recent,
}); });
export const hydrateSearch = () => (dispatch, getState) => { export const forgetSearchResult = q => ({
const me = getState().getIn(['meta', 'me']); type: SEARCH_RESULT_FORGET,
const history = searchHistory.get(me); q,
});
if (history !== null) {
dispatch(updateSearchHistory(history));
}
};

View File

@ -2,7 +2,6 @@ import { Iterable, fromJS } from 'immutable';
import { hydrateCompose } from './compose'; import { hydrateCompose } from './compose';
import { importFetchedAccounts } from './importer'; import { importFetchedAccounts } from './importer';
import { hydrateSearch } from './search';
import { saveSettings } from './settings'; import { saveSettings } from './settings';
export const STORE_HYDRATE = 'STORE_HYDRATE'; export const STORE_HYDRATE = 'STORE_HYDRATE';
@ -35,7 +34,6 @@ export function hydrateStore(rawState) {
}); });
dispatch(hydrateCompose()); dispatch(hydrateCompose());
dispatch(hydrateSearch());
dispatch(importFetchedAccounts(Object.values(rawState.accounts))); dispatch(importFetchedAccounts(Object.values(rawState.accounts)));
dispatch(saveSettings()); dispatch(saveSettings());
}; };

View File

@ -157,7 +157,7 @@ export const expandHomeTimeline = ({ maxId } = {}, done = noOp) => ex
export const expandPublicTimeline = ({ maxId, onlyMedia, onlyRemote, allowLocalOnly } = {}, done = noOp) => expandTimeline(`public${onlyRemote ? ':remote' : (allowLocalOnly ? ':allow_local_only' : '')}${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { remote: !!onlyRemote, allow_local_only: !!allowLocalOnly, max_id: maxId, only_media: !!onlyMedia }, done); export const expandPublicTimeline = ({ maxId, onlyMedia, onlyRemote, allowLocalOnly } = {}, done = noOp) => expandTimeline(`public${onlyRemote ? ':remote' : (allowLocalOnly ? ':allow_local_only' : '')}${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { remote: !!onlyRemote, allow_local_only: !!allowLocalOnly, max_id: maxId, only_media: !!onlyMedia }, done);
export const expandCommunityTimeline = ({ maxId, onlyMedia } = {}, done = noOp) => expandTimeline(`community${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { local: true, max_id: maxId, only_media: !!onlyMedia }, done); export const expandCommunityTimeline = ({ maxId, onlyMedia } = {}, done = noOp) => expandTimeline(`community${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { local: true, max_id: maxId, only_media: !!onlyMedia }, done);
export const expandDirectTimeline = ({ maxId } = {}, done = noOp) => expandTimeline('direct', '/api/v1/timelines/direct', { max_id: maxId }, done); export const expandDirectTimeline = ({ maxId } = {}, done = noOp) => expandTimeline('direct', '/api/v1/timelines/direct', { max_id: maxId }, done);
export const expandAccountTimeline = (accountId, { maxId, withReplies, tagged } = {}) => expandTimeline(`account:${accountId}${withReplies ? ':with_replies' : ''}${tagged ? `:${tagged}` : ''}`, `/api/v1/accounts/${accountId}/statuses`, { exclude_replies: !withReplies, exclude_reblogs: withReplies, tagged, max_id: maxId }); export const expandAccountTimeline = (accountId, { maxId, withReplies, tagged } = {}) => expandTimeline(`account:${accountId}${withReplies ? ':with_replies' : ''}${tagged ? `:${tagged}` : ''}`, `/api/v1/accounts/${accountId}/statuses`, { exclude_replies: !withReplies, tagged, max_id: maxId });
export const expandAccountFeaturedTimeline = (accountId, { tagged } = {}) => expandTimeline(`account:${accountId}:pinned`, `/api/v1/accounts/${accountId}/statuses`, { pinned: true, tagged }); export const expandAccountFeaturedTimeline = (accountId, { tagged } = {}) => expandTimeline(`account:${accountId}:pinned`, `/api/v1/accounts/${accountId}/statuses`, { pinned: true, tagged });
export const expandAccountMediaTimeline = (accountId, { maxId } = {}) => expandTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { max_id: maxId, only_media: true, limit: 40 }); export const expandAccountMediaTimeline = (accountId, { maxId } = {}) => expandTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { max_id: maxId, only_media: true, limit: 40 });
export const expandListTimeline = (id, { maxId } = {}, done = noOp) => expandTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`, { max_id: maxId }, done); export const expandListTimeline = (id, { maxId } = {}, done = noOp) => expandTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`, { max_id: maxId }, done);

View File

@ -8,7 +8,6 @@ import classNames from 'classnames';
import api from 'flavours/glitch/api'; import api from 'flavours/glitch/api';
const messages = defineMessages({ const messages = defineMessages({
legal: { id: 'report.categories.legal', defaultMessage: 'Legal' },
other: { id: 'report.categories.other', defaultMessage: 'Other' }, other: { id: 'report.categories.other', defaultMessage: 'Other' },
spam: { id: 'report.categories.spam', defaultMessage: 'Spam' }, spam: { id: 'report.categories.spam', defaultMessage: 'Spam' },
violation: { id: 'report.categories.violation', defaultMessage: 'Content violates one or more server rules' }, violation: { id: 'report.categories.violation', defaultMessage: 'Content violates one or more server rules' },
@ -151,7 +150,6 @@ class ReportReasonSelector extends PureComponent {
return ( return (
<div className='report-reason-selector'> <div className='report-reason-selector'>
<Category id='other' text={intl.formatMessage(messages.other)} selected={category === 'other'} onSelect={this.handleSelect} disabled={disabled} /> <Category id='other' text={intl.formatMessage(messages.other)} selected={category === 'other'} onSelect={this.handleSelect} disabled={disabled} />
<Category id='legal' text={intl.formatMessage(messages.legal)} selected={category === 'legal'} onSelect={this.handleSelect} disabled={disabled} />
<Category id='spam' text={intl.formatMessage(messages.spam)} selected={category === 'spam'} onSelect={this.handleSelect} disabled={disabled} /> <Category id='spam' text={intl.formatMessage(messages.spam)} selected={category === 'spam'} onSelect={this.handleSelect} disabled={disabled} />
<Category id='violation' text={intl.formatMessage(messages.violation)} selected={category === 'violation'} onSelect={this.handleSelect} disabled={disabled}> <Category id='violation' text={intl.formatMessage(messages.violation)} selected={category === 'violation'} onSelect={this.handleSelect} disabled={disabled}>
{rules.map(rule => <Rule key={rule.id} id={rule.id} text={rule.text} selected={rule_ids.includes(rule.id)} onToggle={this.handleToggle} disabled={disabled} />)} {rules.map(rule => <Rule key={rule.id} id={rule.id} text={rule.text} selected={rule_ids.includes(rule.id)} onToggle={this.handleToggle} disabled={disabled} />)}

View File

@ -18,19 +18,7 @@ export default class Column extends PureComponent {
}; };
scrollTop () { scrollTop () {
let scrollable = null; const scrollable = this.props.bindToDocument ? document.scrollingElement : this.node.querySelector('.scrollable');
if (this.props.bindToDocument) {
scrollable = document.scrollingElement;
} else {
scrollable = this.node.querySelector('.scrollable');
// Some columns have nested `.scrollable` containers, with the outer one
// being a wrapper while the actual scrollable content is deeper.
if (scrollable.classList.contains('scrollable--flex')) {
scrollable = scrollable?.querySelector('.scrollable') || scrollable;
}
}
if (!scrollable) { if (!scrollable) {
return; return;

View File

@ -33,6 +33,8 @@ export const DismissableBanner: React.FC<PropsWithChildren<Props>> = ({
return ( return (
<div className='dismissable-banner'> <div className='dismissable-banner'>
<div className='dismissable-banner__message'>{children}</div>
<div className='dismissable-banner__action'> <div className='dismissable-banner__action'>
<IconButton <IconButton
icon='times' icon='times'
@ -40,8 +42,6 @@ export const DismissableBanner: React.FC<PropsWithChildren<Props>> = ({
onClick={handleDismiss} onClick={handleDismiss}
/> />
</div> </div>
<div className='dismissable-banner__message'>{children}</div>
</div> </div>
); );
}; };

View File

@ -792,7 +792,6 @@ class Status extends ImmutablePureComponent {
tabIndex={0} tabIndex={0}
data-featured={featured ? 'true' : null} data-featured={featured ? 'true' : null}
aria-label={textForScreenReader(intl, status, rebloggedByText, !status.get('hidden'))} aria-label={textForScreenReader(intl, status, rebloggedByText, !status.get('hidden'))}
data-nosnippet={status.getIn(['account', 'noindex'], true) || undefined}
> >
{!muted && prepend} {!muted && prepend}

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