Merge branch 'main' into media-display-options

# Conflicts:
#	app/views/settings/preferences/appearance/show.html.haml
This commit is contained in:
Christian Schmidt 2024-02-03 13:43:12 +01:00
commit 9c442c0047
2341 changed files with 76596 additions and 45064 deletions

6
.bundler-audit.yml Normal file
View File

@ -0,0 +1,6 @@
---
ignore:
# devise-two-factor advisory about brute-forcing TOTP
# We have rate-limits on authentication endpoints in place (including second
# factor verification) since Mastodon v3.2.0
- CVE-2024-0227

View File

@ -4,11 +4,7 @@ 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 ARG NODE_VERSION="20"
# 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"
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"
# [Optional] Uncomment this section to install additional OS packages. # [Optional] Uncomment this section to install additional OS packages.
@ -19,6 +15,6 @@ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
RUN gem install foreman RUN gem install foreman
# [Optional] Uncomment this line to install global node packages. # [Optional] Uncomment this line to install global node packages.
RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g yarn" 2>&1 RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && corepack enable" 2>&1
COPY welcome-message.txt /usr/local/etc/vscode-dev-containers/first-run-notice.txt COPY welcome-message.txt /usr/local/etc/vscode-dev-containers/first-run-notice.txt

View File

@ -0,0 +1,49 @@
{
"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,32 +1,40 @@
// For more details, see https://aka.ms/devcontainer.json.
{ {
"name": "Mastodon", "name": "Mastodon on local machine",
"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],
// Use 'postCreateCommand' to run commands after the container is created. "portsAttributes": {
"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,6 +25,7 @@ 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
@ -69,7 +70,7 @@ services:
hard: -1 hard: -1
libretranslate: libretranslate:
image: libretranslate/libretranslate:v1.3.11 image: libretranslate/libretranslate:v1.5.4
restart: unless-stopped restart: unless-stopped
volumes: volumes:
- lt-data:/home/libretranslate/.local - lt-data:/home/libretranslate/.local

View File

@ -11,7 +11,8 @@ bundle install
git checkout -- Gemfile.lock git checkout -- Gemfile.lock
# Fetch Javascript dependencies # Fetch Javascript dependencies
yarn --frozen-lockfile corepack prepare
yarn install --immutable
# [re]create, migrate, and seed the test database # [re]create, migrate, and seed the test database
RAILS_ENV=test ./bin/rails db:setup RAILS_ENV=test ./bin/rails db:setup
@ -23,4 +24,4 @@ RAILS_ENV=development ./bin/rails db:setup
RAILS_ENV=development ./bin/rails assets:precompile RAILS_ENV=development ./bin/rails assets:precompile
# Precompile assets for test # Precompile assets for test
RAILS_ENV=test NODE_ENV=tests ./bin/rails assets:precompile RAILS_ENV=test ./bin/rails assets:precompile

View File

@ -8,6 +8,7 @@
public/system public/system
public/assets public/assets
public/packs public/packs
public/packs-test
node_modules node_modules
neo4j neo4j
vendor/bundle vendor/bundle

View File

@ -1,5 +1,5 @@
# Node.js # In test, compile the NodeJS code as if we are in production
NODE_ENV=tests NODE_ENV=production
# Federation # Federation
LOCAL_DOMAIN=cb6e6126.ngrok.io LOCAL_DOMAIN=cb6e6126.ngrok.io
LOCAL_HTTPS=true LOCAL_HTTPS=true

View File

@ -2,3 +2,7 @@ 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,4 +1,7 @@
module.exports = { // @ts-check
const { defineConfig } = require('eslint-define-config');
module.exports = defineConfig({
root: true, root: true,
extends: [ extends: [
@ -9,7 +12,6 @@ module.exports = {
'plugin:import/recommended', 'plugin:import/recommended',
'plugin:promise/recommended', 'plugin:promise/recommended',
'plugin:jsdoc/recommended', 'plugin:jsdoc/recommended',
'plugin:prettier/recommended',
], ],
env: { env: {
@ -63,7 +65,9 @@ module.exports = {
'consistent-return': 'error', 'consistent-return': 'error',
'dot-notation': 'error', 'dot-notation': 'error',
eqeqeq: ['error', 'always', { 'null': 'ignore' }], eqeqeq: ['error', 'always', { 'null': 'ignore' }],
'indent': ['error', 2],
'jsx-quotes': ['error', 'prefer-single'], 'jsx-quotes': ['error', 'prefer-single'],
'semi': ['error', 'always'],
'no-case-declarations': 'off', 'no-case-declarations': 'off',
'no-catch-shadow': 'error', 'no-catch-shadow': 'error',
'no-console': [ 'no-console': [
@ -116,7 +120,6 @@ module.exports = {
'react/jsx-uses-react': 'off', // not needed with new JSX transform 'react/jsx-uses-react': 'off', // not needed with new JSX transform
'react/jsx-wrap-multilines': 'error', 'react/jsx-wrap-multilines': 'error',
'react/no-deprecated': 'off', 'react/no-deprecated': 'off',
'react/no-unknown-property': 'off',
'react/react-in-jsx-scope': 'off', // not needed with new JSX transform 'react/react-in-jsx-scope': 'off', // not needed with new JSX transform
'react/self-closing-comp': 'error', 'react/self-closing-comp': 'error',
@ -162,7 +165,7 @@ module.exports = {
// }, // },
// ], // ],
'jsx-a11y/no-noninteractive-tabindex': 'off', 'jsx-a11y/no-noninteractive-tabindex': 'off',
'jsx-a11y/no-onchange': 'warn', 'jsx-a11y/no-onchange': 'off',
// recommended is full 'error' // recommended is full 'error'
'jsx-a11y/no-static-element-interactions': [ 'jsx-a11y/no-static-element-interactions': [
'warn', 'warn',
@ -192,6 +195,7 @@ module.exports = {
'error', 'error',
{ {
devDependencies: [ devDependencies: [
'.eslintrc.js',
'config/webpack/**', 'config/webpack/**',
'app/javascript/mastodon/performance.js', 'app/javascript/mastodon/performance.js',
'app/javascript/mastodon/test_setup.js', 'app/javascript/mastodon/test_setup.js',
@ -235,13 +239,13 @@ module.exports = {
}, },
// Common React utilities // Common React utilities
{ {
pattern: '{classnames,react-helmet,react-router-dom}', pattern: '{classnames,react-helmet,react-router,react-router-dom}',
group: 'external', group: 'external',
position: 'before', position: 'before',
}, },
// Immutable / Redux / data store // Immutable / Redux / data store
{ {
pattern: '{immutable,react-redux,react-immutable-proptypes,react-immutable-pure-component,reselect}', pattern: '{immutable,@reduxjs/toolkit,react-redux,react-immutable-proptypes,react-immutable-pure-component}',
group: 'external', group: 'external',
position: 'before', position: 'before',
}, },
@ -279,7 +283,6 @@ module.exports = {
'formatjs/no-id': 'off', // IDs are used for translation keys 'formatjs/no-id': 'off', // IDs are used for translation keys
'formatjs/no-invalid-icu': 'error', 'formatjs/no-invalid-icu': 'error',
'formatjs/no-literal-string-in-jsx': 'off', // Should be looked at, but mainly flagging punctuation outside of strings 'formatjs/no-literal-string-in-jsx': 'off', // Should be looked at, but mainly flagging punctuation outside of strings
'formatjs/no-multiple-plurals': 'off', // Only used by hashtag.jsx
'formatjs/no-multiple-whitespaces': 'error', 'formatjs/no-multiple-whitespaces': 'error',
'formatjs/no-offset': 'error', 'formatjs/no-offset': 'error',
'formatjs/no-useless-message': 'error', 'formatjs/no-useless-message': 'error',
@ -298,6 +301,7 @@ module.exports = {
overrides: [ overrides: [
{ {
files: [ files: [
'.eslintrc.js',
'*.config.js', '*.config.js',
'.*rc.js', '.*rc.js',
'ide-helper.js', 'ide-helper.js',
@ -348,8 +352,15 @@ module.exports = {
'@typescript-eslint/consistent-type-definitions': ['warn', 'interface'], '@typescript-eslint/consistent-type-definitions': ['warn', 'interface'],
'@typescript-eslint/consistent-type-exports': 'error', '@typescript-eslint/consistent-type-exports': 'error',
'@typescript-eslint/consistent-type-imports': 'error', '@typescript-eslint/consistent-type-imports': 'error',
"@typescript-eslint/prefer-nullish-coalescing": ['error', {ignorePrimitives: {boolean: true}}], "@typescript-eslint/prefer-nullish-coalescing": ['error', { ignorePrimitives: { boolean: true } }],
"@typescript-eslint/no-restricted-imports": [
"warn",
{
"name": "react-redux",
"importNames": ["useSelector", "useDispatch"],
"message": "Use typed hooks `useAppDispatch` and `useAppSelector` instead."
}
],
'jsdoc/require-jsdoc': 'off', 'jsdoc/require-jsdoc': 'off',
// Those rules set stricter rules for TS files // Those rules set stricter rules for TS files
@ -371,14 +382,6 @@ module.exports = {
env: { env: {
jest: true, jest: true,
}, },
}, }
{
files: [
'streaming/**/*',
],
rules: {
'import/no-commonjs': 'off',
},
},
], ],
}; });

3
.github/FUNDING.yml vendored
View File

@ -1,3 +0,0 @@
patreon: mastodon
open_collective: mastodon
custom: https://sponsor.joinmastodon.org

View File

@ -0,0 +1,42 @@
name: 'Setup Javascript'
description: 'Setup a Javascript environment ready to run the Mastodon code'
inputs:
onlyProduction:
description: Only install production dependencies
default: 'false'
runs:
using: 'composite'
steps:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
# The following is needed because we can not use `cache: true` for `setup-node`, as it does not support Corepack yet and mess up with the cache location if ran after Node is installed
- name: Enable corepack
shell: bash
run: corepack enable
- name: Get yarn cache directory path
id: yarn-cache-dir-path
shell: bash
run: echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT
- uses: actions/cache@v4
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install all yarn packages
shell: bash
run: yarn install --immutable
if: inputs.onlyProduction == 'false'
- name: Install all production yarn packages
shell: bash
run: yarn workspaces focus --production
if: inputs.onlyProduction != 'false'

23
.github/actions/setup-ruby/action.yml vendored Normal file
View File

@ -0,0 +1,23 @@
name: 'Setup RUby'
description: 'Setup a Ruby environment ready to run the Mastodon code'
inputs:
ruby-version:
description: The Ruby version to install
default: '.ruby-version'
additional-system-dependencies:
description: 'Additional packages to install'
runs:
using: 'composite'
steps:
- name: Install system dependencies
shell: bash
run: |
sudo apt-get update
sudo apt-get install -y libicu-dev libidn11-dev ${{ inputs.additional-system-dependencies }}
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ inputs.ruby-version }}
bundler-cache: true

13
.github/codecov.yml vendored Normal file
View File

@ -0,0 +1,13 @@
coverage:
status:
project:
default:
# Github status check is not blocking
informational: true
patch:
default:
# Github status check is not blocking
informational: true
comment:
# Only write a comment in PR if there are changes
require_changes: true

View File

@ -3,7 +3,6 @@
extends: [ extends: [
'config:recommended', 'config:recommended',
':labels(dependencies)', ':labels(dependencies)',
':maintainLockFilesMonthly', // update non-direct dependencies monthly
':prConcurrentLimitNone', // Remove limit for open PRs at any time. ':prConcurrentLimitNone', // Remove limit for open PRs at any time.
':prHourlyLimit2', // Rate limit PR creation to a maximum of two per hour. ':prHourlyLimit2', // Rate limit PR creation to a maximum of two per hour.
], ],
@ -13,6 +12,7 @@
// 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).', 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).',
postUpdateOptions: ['yarnDedupeHighest'],
packageRules: [ packageRules: [
{ {
// Require Dependency Dashboard Approval for major version bumps of these node packages // Require Dependency Dashboard Approval for major version bumps of these node packages
@ -22,6 +22,7 @@
'react-hotkeys', // Requires code changes 'react-hotkeys', // Requires code changes
// Requires Webpacker upgrade or replacement // Requires Webpacker upgrade or replacement
'@svgr/webpack',
'@types/webpack', '@types/webpack',
'babel-loader', 'babel-loader',
'compression-webpack-plugin', 'compression-webpack-plugin',
@ -49,7 +50,6 @@
matchManagers: ['bundler'], matchManagers: ['bundler'],
matchPackageNames: [ matchPackageNames: [
'rack', // Needs to be synced with Rails version 'rack', // Needs to be synced with Rails version
'sprockets', // Requires manual upgrade https://github.com/rails/sprockets/blob/master/UPGRADING.md#guide-to-upgrading-from-sprockets-3x-to-4x
'strong_migrations', // Requires manual upgrade 'strong_migrations', // Requires manual upgrade
'sidekiq', // Requires manual upgrade 'sidekiq', // Requires manual upgrade
'sidekiq-unique-jobs', // Requires manual upgrades and sync with Sidekiq version 'sidekiq-unique-jobs', // Requires manual upgrades and sync with Sidekiq version
@ -99,6 +99,16 @@
matchUpdateTypes: ['patch', 'minor'], matchUpdateTypes: ['patch', 'minor'],
groupName: 'eslint (non-major)', groupName: 'eslint (non-major)',
}, },
{
// Group actions/*-artifact in the same PR
matchManagers: ['github-actions'],
matchPackageNames: [
'actions/download-artifact',
'actions/upload-artifact',
],
matchUpdateTypes: ['major'],
groupName: 'artifact actions (major)',
},
{ {
// Update @types/* packages every week, with one grouped PR // Update @types/* packages every week, with one grouped PR
matchPackagePrefixes: '@types/', matchPackagePrefixes: '@types/',

View File

@ -4,11 +4,16 @@ 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_suffix: version_prerelease:
type: string
version_metadata:
type: string type: string
flavor: flavor:
type: string type: string
@ -16,18 +21,20 @@ on:
type: string type: string
labels: labels:
type: string type: string
file_to_build:
type: string
jobs: jobs:
build-image: build-image:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: docker/setup-qemu-action@v2 - uses: docker/setup-qemu-action@v3
if: contains(inputs.platforms, 'linux/arm64') && !inputs.use_native_arm64_builder if: contains(inputs.platforms, 'linux/arm64') && !inputs.use_native_arm64_builder
- uses: docker/setup-buildx-action@v2 - uses: docker/setup-buildx-action@v3
id: buildx id: buildx
if: ${{ !(inputs.use_native_arm64_builder && contains(inputs.platforms, 'linux/arm64')) }} if: ${{ !(inputs.use_native_arm64_builder && contains(inputs.platforms, 'linux/arm64')) }}
@ -36,7 +43,7 @@ jobs:
run: | run: |
docker run --rm -d --name buildkitd -p 1234:1234 --privileged moby/buildkit:latest --addr tcp://0.0.0.0:1234 docker run --rm -d --name buildkitd -p 1234:1234 --privileged moby/buildkit:latest --addr tcp://0.0.0.0:1234
- uses: docker/setup-buildx-action@v2 - uses: docker/setup-buildx-action@v3
id: buildx-native id: buildx-native
if: inputs.use_native_arm64_builder && contains(inputs.platforms, 'linux/arm64') if: inputs.use_native_arm64_builder && contains(inputs.platforms, 'linux/arm64')
with: with:
@ -56,39 +63,40 @@ jobs:
- name: Log in to Docker Hub - name: Log in to Docker Hub
if: contains(inputs.push_to_images, 'tootsuite') if: contains(inputs.push_to_images, 'tootsuite')
uses: docker/login-action@v2 uses: docker/login-action@v3
with: with:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Log in to the Github Container registry - name: Log in to the Github Container registry
if: contains(inputs.push_to_images, 'ghcr.io') if: contains(inputs.push_to_images, 'ghcr.io')
uses: docker/login-action@v2 uses: docker/login-action@v3
with: with:
registry: ghcr.io registry: ghcr.io
username: ${{ github.actor }} username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/metadata-action@v4 - uses: docker/metadata-action@v5
id: meta id: meta
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 }}
- uses: docker/build-push-action@v4 - uses: docker/build-push-action@v5
with: with:
context: . context: .
build-args: MASTODON_VERSION_SUFFIX=${{ inputs.version_suffix }} file: ${{ inputs.file_to_build }}
build-args: |
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: type=gha cache-from: ${{ inputs.cache && 'type=gha' || '' }}
cache-to: type=gha,mode=max cache-to: ${{ inputs.cache && 'type=gha,mode=max' || '' }}

View File

@ -11,26 +11,28 @@ permissions:
jobs: jobs:
compute-suffix: compute-suffix:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.repository == 'mastodon/mastodon'
steps: steps:
- id: version_vars - id: version_vars
env: env:
TZ: Etc/UTC TZ: Etc/UTC
run: | run: |
echo mastodon_version_suffix=nightly-$(date +'%Y-%m-%d')>> $GITHUB_OUTPUT echo mastodon_version_prerelease=nightly.$(date +'%Y-%m-%d')>> $GITHUB_OUTPUT
outputs: outputs:
suffix: ${{ steps.version_vars.outputs.mastodon_version_suffix }} prerelease: ${{ steps.version_vars.outputs.mastodon_version_prerelease }}
build-image: build-image:
needs: compute-suffix needs: compute-suffix
uses: ./.github/workflows/build-container-image.yml uses: ./.github/workflows/build-container-image.yml
with: with:
file_to_build: Dockerfile
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
use_native_arm64_builder: true use_native_arm64_builder: true
cache: false
push_to_images: | push_to_images: |
tootsuite/mastodon tootsuite/mastodon
ghcr.io/mastodon/mastodon ghcr.io/mastodon/mastodon
# The `+` is important here, result will be v4.1.2+nightly-2022-03-05 version_prerelease: ${{ needs.compute-suffix.outputs.prerelease }}
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: |
@ -38,5 +40,27 @@ jobs:
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.suffix }} type=schedule,pattern=${{ needs.compute-suffix.outputs.prerelease }}
secrets: inherit
build-image-streaming:
needs: compute-suffix
uses: ./.github/workflows/build-container-image.yml
with:
file_to_build: streaming/Dockerfile
platforms: linux/amd64,linux/arm64
use_native_arm64_builder: true
cache: false
push_to_images: |
tootsuite/mastodon-streaming
ghcr.io/mastodon/mastodon-streaming
version_prerelease: ${{ needs.compute-suffix.outputs.prerelease }}
labels: |
org.opencontainers.image.description=Nightly build image used for testing purposes
flavor: |
latest=auto
tags: |
type=raw,value=edge
type=raw,value=nightly
type=schedule,pattern=${{ needs.compute-suffix.outputs.prerelease }}
secrets: inherit secrets: inherit

View File

@ -18,22 +18,39 @@ 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@v3 uses: actions/checkout@v4
- id: version_vars - id: version_vars
run: | run: |
echo mastodon_version_suffix=+pr-${{ github.event.pull_request.number }}-$(git rev-parse --short HEAD) >> $GITHUB_OUTPUT echo mastodon_version_metadata=pr-${{ github.event.pull_request.number }}-$(git rev-parse --short HEAD) >> $GITHUB_OUTPUT
outputs: outputs:
suffix: ${{ steps.version_vars.outputs.mastodon_version_suffix }} metadata: ${{ steps.version_vars.outputs.mastodon_version_metadata }}
build-image: build-image:
needs: compute-suffix needs: compute-suffix
uses: ./.github/workflows/build-container-image.yml uses: ./.github/workflows/build-container-image.yml
with: with:
file_to_build: Dockerfile
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
use_native_arm64_builder: true use_native_arm64_builder: true
push_to_images: | push_to_images: |
ghcr.io/mastodon/mastodon ghcr.io/mastodon/mastodon
version_suffix: ${{ needs.compute-suffix.outputs.suffix }} version_metadata: ${{ needs.compute-suffix.outputs.metadata }}
flavor: |
latest=auto
tags: |
type=ref,event=pr
secrets: inherit
build-image-streaming:
needs: compute-suffix
uses: ./.github/workflows/build-container-image.yml
with:
file_to_build: streaming/Dockerfile
platforms: linux/amd64,linux/arm64
use_native_arm64_builder: true
push_to_images: |
ghcr.io/mastodon/mastodon-streaming
version_metadata: ${{ needs.compute-suffix.outputs.metadata }}
flavor: | flavor: |
latest=auto latest=auto
tags: | tags: |

View File

@ -12,13 +12,39 @@ jobs:
build-image: build-image:
uses: ./.github/workflows/build-container-image.yml uses: ./.github/workflows/build-container-image.yml
with: with:
file_to_build: Dockerfile
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
use_native_arm64_builder: true use_native_arm64_builder: true
push_to_images: | push_to_images: |
tootsuite/mastodon tootsuite/mastodon
ghcr.io/mastodon/mastodon ghcr.io/mastodon/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.1.') }} latest=${{ startsWith(github.ref, 'refs/tags/v4.2.') }}
tags: |
type=pep440,pattern={{raw}}
type=pep440,pattern=v{{major}}.{{minor}}
secrets: inherit
build-image-streaming:
if: startsWith(github.ref, 'refs/tags/v4.3.')
uses: ./.github/workflows/build-container-image.yml
with:
file_to_build: streaming/Dockerfile
platforms: linux/amd64,linux/arm64
use_native_arm64_builder: true
push_to_images: |
tootsuite/mastodon-streaming
ghcr.io/mastodon/mastodon-streaming
# 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: |
latest=${{ startsWith(github.ref, 'refs/tags/v4.3.') }}
tags: | tags: |
type=pep440,pattern={{raw}} type=pep440,pattern={{raw}}
type=pep440,pattern=v{{major}}.{{minor}} type=pep440,pattern=v{{major}}.{{minor}}

64
.github/workflows/build-security.yml vendored Normal file
View File

@ -0,0 +1,64 @@
name: Build security nightly container image
on:
workflow_dispatch:
permissions:
contents: read
packages: write
jobs:
compute-suffix:
runs-on: ubuntu-latest
if: github.repository == 'mastodon/mastodon'
steps:
- id: version_vars
env:
TZ: Etc/UTC
run: |
echo mastodon_version_prerelease=nightly.$(date --date='next day' +'%Y-%m-%d')-security>> $GITHUB_OUTPUT
outputs:
prerelease: ${{ steps.version_vars.outputs.mastodon_version_prerelease }}
build-image:
needs: compute-suffix
uses: ./.github/workflows/build-container-image.yml
with:
file_to_build: Dockerfile
platforms: linux/amd64,linux/arm64
use_native_arm64_builder: true
cache: false
push_to_images: |
tootsuite/mastodon
ghcr.io/mastodon/mastodon
version_prerelease: ${{ needs.compute-suffix.outputs.prerelease }}
labels: |
org.opencontainers.image.description=Nightly build image used for testing purposes
flavor: |
latest=auto
tags: |
type=raw,value=edge
type=raw,value=nightly
type=schedule,pattern=${{ needs.compute-suffix.outputs.prerelease }}
secrets: inherit
build-image-streaming:
needs: compute-suffix
uses: ./.github/workflows/build-container-image.yml
with:
file_to_build: streaming/Dockerfile
platforms: linux/amd64,linux/arm64
use_native_arm64_builder: true
cache: false
push_to_images: |
tootsuite/mastodon-streaming
ghcr.io/mastodon/mastodon-streaming
version_prerelease: ${{ needs.compute-suffix.outputs.prerelease }}
labels: |
org.opencontainers.image.description=Nightly build image used for testing purposes
flavor: |
latest=auto
tags: |
type=raw,value=edge
type=raw,value=nightly
type=schedule,pattern=${{ needs.compute-suffix.outputs.prerelease }}
secrets: inherit

View File

@ -25,16 +25,10 @@ jobs:
steps: steps:
- name: Clone repository - name: Clone repository
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Install native Ruby dependencies - name: Set up Ruby environment
run: sudo apt-get install -y libicu-dev libidn11-dev uses: ./.github/actions/setup-ruby
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: .ruby-version
bundler-cache: true
- name: Run bundler-audit - name: Run bundler-audit
run: bundle exec bundler-audit run: bundle exec bundler-audit

View File

@ -17,27 +17,13 @@ jobs:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Install system dependencies - name: Set up Ruby environment
run: | uses: ./.github/actions/setup-ruby
sudo apt-get update
sudo apt-get install -y libicu-dev libidn11-dev
- name: Set up Ruby - name: Set up Javascript environment
uses: ruby/setup-ruby@v1 uses: ./.github/actions/setup-javascript
with:
ruby-version: .ruby-version
bundler-cache: true
- name: Set up Node.js
uses: actions/setup-node@v3
with:
cache: yarn
node-version-file: '.nvmrc'
- name: Install all yarn packages
run: yarn --frozen-lockfile
- name: Check for missing strings in English JSON - name: Check for missing strings in English JSON
run: | run: |

View File

@ -27,11 +27,11 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v3 uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v2 uses: github/codeql-action/init@v3
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file. # If you wish to specify custom queries, you can do so here or in a config file.
@ -44,7 +44,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
# If this step fails, then you should remove it and run the build manually (see below) # If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@v2 uses: github/codeql-action/autobuild@v3
# Command-line programs to run using the OS shell. # Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
@ -57,6 +57,6 @@ jobs:
# ./location_of_script_within_repo/buildscript.sh # ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2 uses: github/codeql-action/analyze@v3
with: with:
category: '/language:${{matrix.language}}' category: '/language:${{matrix.language}}'

View File

@ -11,10 +11,11 @@ permissions:
jobs: jobs:
download-translations: download-translations:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.repository == 'mastodon/mastodon'
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
- 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?
@ -43,14 +44,8 @@ jobs:
run: sudo chown -R runner:docker . run: sudo chown -R runner:docker .
# This is needed to run the normalize step # This is needed to run the normalize step
- name: Install native Ruby dependencies - name: Set up Ruby environment
run: sudo apt-get install -y libicu-dev libidn11-dev uses: ./.github/actions/setup-ruby
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: .ruby-version
bundler-cache: true
- name: Run i18n normalize task - name: Run i18n normalize task
run: bundle exec i18n-tasks normalize run: bundle exec i18n-tasks normalize

View File

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

View File

@ -33,16 +33,10 @@ jobs:
steps: steps:
- name: Clone repository - name: Clone repository
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Set up Node.js - name: Set up Javascript environment
uses: actions/setup-node@v3 uses: ./.github/actions/setup-javascript
with:
cache: yarn
node-version-file: '.nvmrc'
- name: Install all yarn packages
run: yarn --frozen-lockfile
- uses: xt0rted/stylelint-problem-matcher@v1 - uses: xt0rted/stylelint-problem-matcher@v1

View File

@ -28,18 +28,10 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Clone repository - name: Clone repository
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Install native Ruby dependencies - name: Set up Ruby environment
run: | uses: ./.github/actions/setup-ruby
sudo apt-get update
sudo apt-get install -y libicu-dev libidn11-dev
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: .ruby-version
bundler-cache: true
- name: Run haml-lint - name: Run haml-lint
run: | run: |

View File

@ -37,16 +37,10 @@ jobs:
steps: steps:
- name: Clone repository - name: Clone repository
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Set up Node.js - name: Set up Javascript environment
uses: actions/setup-node@v3 uses: ./.github/actions/setup-javascript
with:
cache: yarn
node-version-file: '.nvmrc'
- name: Install all yarn packages
run: yarn --frozen-lockfile
- name: ESLint - name: ESLint
run: yarn lint:js --max-warnings 0 run: yarn lint:js --max-warnings 0

View File

@ -29,16 +29,10 @@ jobs:
steps: steps:
- name: Clone repository - name: Clone repository
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Set up Node.js - name: Set up Javascript environment
uses: actions/setup-node@v3 uses: ./.github/actions/setup-javascript
with:
cache: yarn
node-version-file: '.nvmrc'
- name: Install all yarn packages
run: yarn --frozen-lockfile
- name: Prettier - name: Prettier
run: yarn lint:json run: yarn lint:json

View File

@ -29,16 +29,10 @@ jobs:
steps: steps:
- name: Clone repository - name: Clone repository
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Set up Node.js - name: Set up Javascript environment
uses: actions/setup-node@v3 uses: ./.github/actions/setup-javascript
with:
cache: yarn
node-version-file: '.nvmrc'
- name: Install all yarn packages
run: yarn --frozen-lockfile
- name: Prettier - name: Prettier
run: yarn lint:md run: yarn lint:md

View File

@ -29,16 +29,10 @@ jobs:
steps: steps:
- name: Clone repository - name: Clone repository
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Install native Ruby dependencies - name: Set up Ruby environment
run: sudo apt-get install -y libicu-dev libidn11-dev uses: ./.github/actions/setup-ruby
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: .ruby-version
bundler-cache: true
- name: Set-up RuboCop Problem Matcher - name: Set-up RuboCop Problem Matcher
uses: r7kamura/rubocop-problem-matchers-action@v1 uses: r7kamura/rubocop-problem-matchers-action@v1

View File

@ -31,16 +31,10 @@ jobs:
steps: steps:
- name: Clone repository - name: Clone repository
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Set up Node.js - name: Set up Javascript environment
uses: actions/setup-node@v3 uses: ./.github/actions/setup-javascript
with:
cache: yarn
node-version-file: '.nvmrc'
- name: Install all yarn packages
run: yarn --frozen-lockfile
- name: Prettier - name: Prettier
run: yarn lint:yml run: yarn lint:yml

View File

@ -7,6 +7,7 @@ on:
- .github/workflows/build-releases.yml - .github/workflows/build-releases.yml
- .github/workflows/test-image-build.yml - .github/workflows/test-image-build.yml
- Dockerfile - Dockerfile
- streaming/Dockerfile
permissions: permissions:
contents: read contents: read
@ -18,4 +19,17 @@ jobs:
uses: ./.github/workflows/build-container-image.yml uses: ./.github/workflows/build-container-image.yml
with: with:
file_to_build: Dockerfile
platforms: linux/amd64 # Testing only on native platform so it is performant platforms: linux/amd64 # Testing only on native platform so it is performant
cache: true
build-image-streaming:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-streaming
cancel-in-progress: true
uses: ./.github/workflows/build-container-image.yml
with:
file_to_build: streaming/Dockerfile
platforms: linux/amd64 # Testing only on native platform so it is performant
cache: true

View File

@ -33,16 +33,10 @@ jobs:
steps: steps:
- name: Clone repository - name: Clone repository
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Set up Node.js - name: Set up Javascript environment
uses: actions/setup-node@v3 uses: ./.github/actions/setup-javascript
with:
cache: yarn
node-version-file: '.nvmrc'
- name: Install all yarn packages
run: yarn --frozen-lockfile
- name: Jest testing - name: Jest testing
run: yarn jest --reporters github-actions summary run: yarn jest --reporters github-actions summary

View File

@ -70,39 +70,16 @@ jobs:
BUNDLE_RETRY: 3 BUNDLE_RETRY: 3
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Install native Ruby dependencies - name: Set up Ruby environment
run: | uses: ./.github/actions/setup-ruby
sudo apt-get update
sudo apt-get install -y libicu-dev libidn11-dev
- name: Set up bundler cache
uses: ruby/setup-ruby@v1
with:
ruby-version: .ruby-version
bundler-cache: true
- name: Create database - name: Create database
run: './bin/rails db:create' run: './bin/rails db:create'
- name: Run migrations up to v2.0.0 - name: Run historical migrations with data population
run: './bin/rails db:migrate VERSION=20171010025614' run: './bin/rails tests:migrations:prepare_database'
- name: Populate database with test data
run: './bin/rails tests:migrations:populate_v2'
- name: Run migrations up to v2.4.0
run: './bin/rails db:migrate VERSION=20180514140000'
- name: Populate database with test data
run: './bin/rails tests:migrations:populate_v2_4'
- name: Run migrations up to v2.4.3
run: './bin/rails db:migrate VERSION=20180707154237'
- name: Populate database with test data
run: './bin/rails tests:migrations:populate_v2_4_3'
- name: Run all remaining migrations - name: Run all remaining migrations
run: './bin/rails db:migrate' run: './bin/rails db:migrate'

View File

@ -45,6 +45,7 @@ jobs:
--health-retries 5 --health-retries 5
ports: ports:
- 5432:5432 - 5432:5432
redis: redis:
image: redis:7-alpine image: redis:7-alpine
options: >- options: >-
@ -69,44 +70,19 @@ jobs:
BUNDLE_RETRY: 3 BUNDLE_RETRY: 3
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Install native Ruby dependencies - name: Set up Ruby environment
run: | uses: ./.github/actions/setup-ruby
sudo apt-get update
sudo apt-get install -y libicu-dev libidn11-dev
- name: Set up bundler cache
uses: ruby/setup-ruby@v1
with:
ruby-version: .ruby-version
bundler-cache: true
- name: Create database - name: Create database
run: './bin/rails db:create' run: './bin/rails db:create'
- name: Run migrations up to v2.0.0 - name: Run historical migrations with data population
run: './bin/rails db:migrate VERSION=20171010025614' run: './bin/rails tests:migrations:prepare_database'
- name: Populate database with test data
run: './bin/rails tests:migrations:populate_v2'
- name: Run pre-deployment migrations up to v2.4.0
run: './bin/rails db:migrate VERSION=20180514140000'
env: env:
SKIP_POST_DEPLOYMENT_MIGRATIONS: true SKIP_POST_DEPLOYMENT_MIGRATIONS: true
- name: Populate database with test data
run: './bin/rails tests:migrations:populate_v2_4'
- name: Run migrations up to v2.4.3
run: './bin/rails db:migrate VERSION=20180707154237'
env:
SKIP_POST_DEPLOYMENT_MIGRATIONS: true
- name: Populate database with test data
run: './bin/rails tests:migrations:populate_v2_4_3'
- name: Run all remaining pre-deployment migrations - name: Run all remaining pre-deployment migrations
run: './bin/rails db:migrate' run: './bin/rails db:migrate'
env: env:

View File

@ -32,38 +32,31 @@ jobs:
SECRET_KEY_BASE: precompile_placeholder SECRET_KEY_BASE: precompile_placeholder
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Set up Node.js - name: Set up Ruby environment
uses: actions/setup-node@v3 uses: ./.github/actions/setup-ruby
- name: Set up Javascript environment
uses: ./.github/actions/setup-javascript
with: with:
cache: yarn onlyProduction: 'true'
node-version-file: '.nvmrc'
- name: Install native Ruby dependencies
run: |
sudo apt-get update
sudo apt-get install -y libicu-dev libidn11-dev
- name: Set up bundler cache
uses: ruby/setup-ruby@v1
with:
ruby-version: .ruby-version
bundler-cache: true
- run: yarn --frozen-lockfile --production
- name: Precompile assets - name: Precompile assets
# Previously had set this, but it's not supported # Previously had set this, but it's not supported
# export NODE_OPTIONS=--openssl-legacy-provider # export NODE_OPTIONS=--openssl-legacy-provider
run: |- run: |-
./bin/rails assets:precompile ./bin/rails assets:precompile
- uses: actions/upload-artifact@v3 - name: Archive asset artifacts
run: |
tar --exclude={"*.br","*.gz"} -zcf artifacts.tar.gz public/assets public/packs*
- uses: actions/upload-artifact@v4
if: matrix.mode == 'test' if: matrix.mode == 'test'
with: with:
path: |- path: |-
./public/assets ./artifacts.tar.gz
./public/packs-test
name: ${{ github.sha }} name: ${{ github.sha }}
retention-days: 0 retention-days: 0
@ -101,7 +94,7 @@ jobs:
DB_HOST: localhost DB_HOST: localhost
DB_USER: postgres DB_USER: postgres
DB_PASS: postgres DB_PASS: postgres
DISABLE_SIMPLECOV: true DISABLE_SIMPLECOV: ${{ matrix.ruby-version != '.ruby-version' }}
RAILS_ENV: test RAILS_ENV: test
ALLOW_NOPAM: true ALLOW_NOPAM: true
PAM_ENABLED: true PAM_ENABLED: true
@ -112,7 +105,7 @@ jobs:
SAML_ENABLED: true SAML_ENABLED: true
CAS_ENABLED: true CAS_ENABLED: true
BUNDLE_WITH: 'pam_authentication test' BUNDLE_WITH: 'pam_authentication test'
CI_JOBS: ${{ matrix.ci_job }}/4 GITHUB_RSPEC: ${{ matrix.ruby-version == '.ruby-version' && github.event.pull_request && 'true' }}
strategy: strategy:
fail-fast: false fail-fast: false
@ -121,38 +114,34 @@ jobs:
- '3.0' - '3.0'
- '3.1' - '3.1'
- '.ruby-version' - '.ruby-version'
ci_job:
- 1
- 2
- 3
- 4
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions/download-artifact@v3 - uses: actions/download-artifact@v4
with: with:
path: './public' path: './'
name: ${{ github.sha }} name: ${{ github.sha }}
- name: Update package index - name: Expand archived asset artifacts
run: sudo apt-get update run: |
tar xvzf artifacts.tar.gz
- name: Install native Ruby dependencies - name: Set up Ruby environment
run: sudo apt-get install -y libicu-dev libidn11-dev uses: ./.github/actions/setup-ruby
- name: Install additional system dependencies
run: sudo apt-get install -y ffmpeg imagemagick libpam-dev
- name: Set up bundler cache
uses: ruby/setup-ruby@v1
with: with:
ruby-version: ${{ matrix.ruby-version}} ruby-version: ${{ matrix.ruby-version}}
bundler-cache: true additional-system-dependencies: ffmpeg imagemagick libpam-dev
- name: Load database schema - name: Load database schema
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: bin/rspec
- name: Upload coverage reports to Codecov
if: matrix.ruby-version == '.ruby-version'
uses: codecov/codecov-action@v3
with:
files: coverage/lcov/mastodon.lcov
test-e2e: test-e2e:
name: End to End testing name: End to End testing
@ -202,35 +191,21 @@ jobs:
- '.ruby-version' - '.ruby-version'
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions/download-artifact@v3 - uses: actions/download-artifact@v4
with: with:
path: './public' path: './public'
name: ${{ github.sha }} name: ${{ github.sha }}
- name: Update package index - name: Set up Ruby environment
run: sudo apt-get update uses: ./.github/actions/setup-ruby
- 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: with:
ruby-version: ${{ matrix.ruby-version}} ruby-version: ${{ matrix.ruby-version}}
bundler-cache: true additional-system-dependencies: ffmpeg imagemagick
- run: yarn --frozen-lockfile - name: Set up Javascript environment
uses: ./.github/actions/setup-javascript
- name: Load database schema - name: Load database schema
run: './bin/rails db:create db:schema:load db:seed' run: './bin/rails db:create db:schema:load db:seed'
@ -238,15 +213,119 @@ jobs:
- run: bundle exec rake spec:system - run: bundle exec rake spec:system
- name: Archive logs - name: Archive logs
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
if: failure() if: failure()
with: with:
name: e2e-logs-${{ matrix.ruby-version }} name: e2e-logs-${{ matrix.ruby-version }}
path: log/ path: log/
- name: Archive test screenshots - name: Archive test screenshots
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
if: failure() if: failure()
with: with:
name: e2e-screenshots name: e2e-screenshots
path: tmp/screenshots/ path: tmp/screenshots/
test-search:
name: Elastic Search integration 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
search:
image: ${{ matrix.search-image }}
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'
search-image:
- docker.elastic.co/elasticsearch/elasticsearch:7.17.13
include:
- ruby-version: '.ruby-version'
search-image: docker.elastic.co/elasticsearch/elasticsearch:8.10.2
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
path: './public'
name: ${{ github.sha }}
- name: Set up Ruby environment
uses: ./.github/actions/setup-ruby
with:
ruby-version: ${{ matrix.ruby-version}}
additional-system-dependencies: ffmpeg imagemagick
- name: Set up Javascript environment
uses: ./.github/actions/setup-javascript
- name: Load database schema
run: './bin/rails db:create db:schema:load db:seed'
- run: bin/rspec --tag search
- name: Archive logs
uses: actions/upload-artifact@v4
if: failure()
with:
name: test-search-logs-${{ matrix.ruby-version }}
path: log/
- name: Archive test screenshots
uses: actions/upload-artifact@v4
if: failure()
with:
name: test-search-screenshots
path: tmp/screenshots/

12
.gitignore vendored
View File

@ -31,9 +31,6 @@
# Ignore Vagrant files # Ignore Vagrant files
.vagrant/ .vagrant/
# Ignore Capistrano customizations
/config/deploy/*
# Ignore IDE files # Ignore IDE files
.vscode/ .vscode/
.idea/ .idea/
@ -58,6 +55,15 @@ npm-debug.log
yarn-error.log yarn-error.log
yarn-debug.log yarn-debug.log
# From https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
# Ignore vagrant log files # Ignore vagrant log files
*-cloudimg-console.log *-cloudimg-console.log

View File

@ -12,3 +12,5 @@ linters:
enabled: true enabled: true
MiddleDot: MiddleDot:
enabled: true enabled: true
LineLength:
max: 320

View File

@ -1,47 +1,13 @@
# This configuration was generated by # This configuration was generated by
# `haml-lint --auto-gen-config` # `haml-lint --auto-gen-config`
# on 2023-07-20 09:47:50 -0400 using Haml-Lint version 0.48.0. # on 2024-01-09 11:30:07 -0500 using Haml-Lint version 0.53.0.
# 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 lints are removed from the code base. # one by one as the lints 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
# versions of Haml-Lint, may require this file to be generated again. # versions of Haml-Lint, may require this file to be generated again.
linters: linters:
# Offense count: 951 # Offense count: 1
LineLength: LineLength:
enabled: false
# Offense count: 22
UnnecessaryStringOutput:
enabled: false
# Offense count: 57
RuboCop:
enabled: false
# Offense count: 3
ViewLength:
exclude: exclude:
- 'app/views/admin/accounts/show.html.haml'
- 'app/views/admin/reports/show.html.haml'
- 'app/views/disputes/strikes/show.html.haml'
# Offense count: 32
InstanceVariables:
exclude:
- 'app/views/admin/reports/_actions.html.haml'
- 'app/views/admin/roles/_form.html.haml' - 'app/views/admin/roles/_form.html.haml'
- 'app/views/admin/webhooks/_form.html.haml'
- 'app/views/auth/registrations/_status.html.haml'
- 'app/views/auth/sessions/two_factor/_otp_authentication_form.html.haml'
- 'app/views/authorize_interactions/_post_follow_actions.html.haml'
- 'app/views/invites/_form.html.haml'
- 'app/views/relationships/_account.html.haml'
- 'app/views/shared/_og.html.haml'
# Offense count: 3
IdNames:
exclude:
- 'app/views/authorize_interactions/error.html.haml'
- 'app/views/oauth/authorizations/error.html.haml'
- 'app/views/shared/_error_messages.html.haml'

2
.nvmrc
View File

@ -1 +1 @@
16.20 20.11

View File

@ -31,9 +31,6 @@
# Ignore Vagrant files # Ignore Vagrant files
.vagrant/ .vagrant/
# Ignore Capistrano customizations
/config/deploy/*
# Ignore IDE files # Ignore IDE files
.vscode/ .vscode/
.idea/ .idea/
@ -76,3 +73,5 @@ app/javascript/styles/mastodon/reset.scss
# Ignore the generated AUTHORS.md # Ignore the generated AUTHORS.md
AUTHORS.md AUTHORS.md
!lint-staged.config.js

View File

@ -27,7 +27,8 @@ AllCops:
- 'node_modules/**/*' - 'node_modules/**/*'
- 'Vagrantfile' - 'Vagrantfile'
- 'vendor/**/*' - 'vendor/**/*'
- 'lib/json_ld/*' # Generated files - 'config/initializers/json_ld*' # Generated files
- 'lib/mastodon/migration_helpers.rb' # Vendored from GitLab
- 'lib/templates/**/*' - 'lib/templates/**/*'
# Reason: Prefer Hashes without extreme indentation # Reason: Prefer Hashes without extreme indentation
@ -71,13 +72,6 @@ Metrics/ModuleLength:
# Reason: Currently disabled in .rubocop_todo.yml # Reason: Currently disabled in .rubocop_todo.yml
# https://docs.rubocop.org/rubocop/cops_metrics.html#metricsabcsize # https://docs.rubocop.org/rubocop/cops_metrics.html#metricsabcsize
Metrics/AbcSize: Metrics/AbcSize:
Exclude:
- 'lib/mastodon/cli/*.rb'
- db/*migrate/**/*
# Reason:
# https://docs.rubocop.org/rubocop/cops_metrics.html#metricsblocknesting
Metrics/BlockNesting:
Exclude: Exclude:
- 'lib/mastodon/cli/*.rb' - 'lib/mastodon/cli/*.rb'
@ -86,7 +80,6 @@ Metrics/BlockNesting:
Metrics/CyclomaticComplexity: Metrics/CyclomaticComplexity:
Exclude: Exclude:
- lib/mastodon/cli/*.rb - lib/mastodon/cli/*.rb
- db/*migrate/**/*
# Reason: # Reason:
# https://docs.rubocop.org/rubocop/cops_metrics.html#metricsparameterlists # https://docs.rubocop.org/rubocop/cops_metrics.html#metricsparameterlists
@ -103,27 +96,48 @@ Rails/FilePath:
Rails/HttpStatus: Rails/HttpStatus:
EnforcedStyle: numeric EnforcedStyle: numeric
# Reason: Allowed in `tootctl` CLI code and in boot ENV checker # Reason: Allowed in boot ENV checker
# https://docs.rubocop.org/rubocop-rails/cops_rails.html#railsexit # https://docs.rubocop.org/rubocop-rails/cops_rails.html#railsexit
Rails/Exit: Rails/Exit:
Exclude: Exclude:
- 'config/boot.rb' - 'config/boot.rb'
- 'lib/mastodon/cli/*.rb'
# Reason: Some single letter camel case files shouldn't be split # Reason: Conflicts with `Lint/UselessMethodDefinition` for inherited controller actions
# https://docs.rubocop.org/rubocop-rails/cops_rails.html#railslexicallyscopedactionfilter
Rails/LexicallyScopedActionFilter:
Exclude:
- 'app/controllers/auth/*'
# Reason: These tasks are doing local work which do not need full env loaded
# https://docs.rubocop.org/rubocop-rails/cops_rails.html#railsrakeenvironment
Rails/RakeEnvironment:
Exclude:
- 'lib/tasks/auto_annotate_models.rake'
- 'lib/tasks/emojis.rake'
- 'lib/tasks/mastodon.rake'
- 'lib/tasks/repo.rake'
- 'lib/tasks/statistics.rake'
# Reason: There are appropriate times to use these features
# https://docs.rubocop.org/rubocop-rails/cops_rails.html#railsskipsmodelvalidations
Rails/SkipsModelValidations:
Enabled: false
# Reason: We want to preserve the ability to migrate from arbitrary old versions,
# and cannot guarantee that every installation has run every migration as they upgrade.
# https://docs.rubocop.org/rubocop-rails/cops_rails.html#railsunusedignoredcolumns
Rails/UnusedIgnoredColumns:
Enabled: false
# Reason: Prevailing style choice
# https://docs.rubocop.org/rubocop-rails/cops_rails.html#railsnegateinclude
Rails/NegateInclude:
Enabled: false
# Reason: Deprecated cop, will be removed in 3.0, replaced by SpecFilePathFormat
# https://docs.rubocop.org/rubocop-rspec/cops_rspec.html#rspecfilepath # https://docs.rubocop.org/rubocop-rspec/cops_rspec.html#rspecfilepath
RSpec/FilePath: RSpec/FilePath:
CustomTransform: Enabled: false
ActivityPub: activitypub # Ignore the snake_case due to the amount of files to rename
DeepL: deepl
FetchOEmbedService: fetch_oembed_service
JsonLdHelper: jsonld_helper
OEmbedController: oembed_controller
OStatus: ostatus
NodeInfoController: nodeinfo_controller # NodeInfo isn't snake_cased for any of the instances
Exclude:
- 'spec/config/initializers/rack_attack_spec.rb' # namespaces usually have separate folder
- 'spec/lib/sanitize_config_spec.rb' # namespaces usually have separate folder
# Reason: # Reason:
# https://docs.rubocop.org/rubocop-rspec/cops_rspec.html#rspecnamedsubject # https://docs.rubocop.org/rubocop-rspec/cops_rspec.html#rspecnamedsubject
@ -140,6 +154,16 @@ RSpec/NotToNot:
RSpec/Rails/HttpStatus: RSpec/Rails/HttpStatus:
EnforcedStyle: numeric EnforcedStyle: numeric
# Reason: Match overrides from Rspec/FilePath rule above
# https://docs.rubocop.org/rubocop-rspec/cops_rspec.html#rspecspecfilepathformat
RSpec/SpecFilePathFormat:
CustomTransform:
ActivityPub: activitypub
DeepL: deepl
FetchOEmbedService: fetch_oembed_service
OEmbedController: oembed_controller
OStatus: ostatus
# Reason: # Reason:
# https://docs.rubocop.org/rubocop/cops_style.html#styleclassandmodulechildren # https://docs.rubocop.org/rubocop/cops_style.html#styleclassandmodulechildren
Style/ClassAndModuleChildren: Style/ClassAndModuleChildren:
@ -150,6 +174,15 @@ Style/ClassAndModuleChildren:
Style/Documentation: Style/Documentation:
Enabled: false Enabled: false
# Reason: Route redirects are not token-formatted and must be skipped
# https://docs.rubocop.org/rubocop/cops_style.html#styleformatstringtoken
Style/FormatStringToken:
inherit_mode:
merge:
- AllowedMethods # The rubocop-rails config adds `redirect`
AllowedMethods:
- redirect_with_vary
# Reason: Enforce modern Ruby style # Reason: Enforce modern Ruby style
# https://docs.rubocop.org/rubocop/cops_style.html#stylehashsyntax # https://docs.rubocop.org/rubocop/cops_style.html#stylehashsyntax
Style/HashSyntax: Style/HashSyntax:

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.54.2. # using RuboCop version 1.60.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
@ -13,129 +13,13 @@ Bundler/OrderedGems:
Exclude: Exclude:
- 'Gemfile' - 'Gemfile'
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: with_first_argument, with_fixed_indentation
Layout/ArgumentAlignment:
Exclude:
- 'config/initializers/cors.rb'
- 'config/initializers/session_store.rb'
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
# SupportedHashRocketStyles: key, separator, table
# SupportedColonStyles: key, separator, table
# SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit
Layout/HashAlignment:
Exclude:
- 'config/environments/production.rb'
- 'config/initializers/rack_attack.rb'
- 'config/routes.rb'
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AllowDoxygenCommentStyle, AllowGemfileRubyComment.
Layout/LeadingCommentSpace:
Exclude:
- 'config/application.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).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: require_no_space, require_space
Layout/SpaceInLambdaLiteral:
Exclude:
- 'config/environments/production.rb'
- 'config/initializers/content_security_policy.rb'
# Configuration parameters: AllowComments, AllowEmptyLambdas.
Lint/EmptyBlock:
Exclude:
- 'spec/controllers/api/v2/search_controller_spec.rb'
- 'spec/fabricators/access_token_fabricator.rb'
- 'spec/fabricators/conversation_fabricator.rb'
- 'spec/fabricators/system_key_fabricator.rb'
- 'spec/helpers/admin/action_logs_helper_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/web/setting_spec.rb'
Lint/NonLocalExitFromIterator: Lint/NonLocalExitFromIterator:
Exclude: Exclude:
- 'app/helpers/jsonld_helper.rb' - 'app/helpers/jsonld_helper.rb'
# This cop supports unsafe autocorrection (--autocorrect-all).
Lint/OrAssignmentToConstant:
Exclude:
- 'lib/sanitize_ext/sanitize_config.rb'
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: IgnoreEmptyBlocks, AllowUnusedKeywordArguments.
Lint/UnusedBlockArgument:
Exclude:
- 'config/initializers/content_security_policy.rb'
- 'config/initializers/doorkeeper.rb'
- 'config/initializers/paperclip.rb'
- 'config/initializers/simple_form.rb'
# This cop supports unsafe autocorrection (--autocorrect-all).
Lint/UselessAssignment:
Exclude:
- 'app/services/activitypub/process_status_update_service.rb'
- 'config/initializers/omniauth.rb'
- 'db/migrate/20190511134027_add_silenced_at_suspended_at_to_accounts.rb'
- 'db/post_migrate/20190511152737_remove_suspended_silenced_account_fields.rb'
- 'spec/controllers/api/v1/favourites_controller_spec.rb'
- 'spec/controllers/concerns/account_controller_concern_spec.rb'
- 'spec/helpers/jsonld_helper_spec.rb'
- 'spec/models/account_spec.rb'
- 'spec/models/domain_block_spec.rb'
- 'spec/models/status_spec.rb'
- 'spec/models/user_spec.rb'
- 'spec/models/webauthn_credentials_spec.rb'
- 'spec/services/account_search_service_spec.rb'
- 'spec/services/post_status_service_spec.rb'
- 'spec/services/precompute_feed_service_spec.rb'
- 'spec/services/resolve_url_service_spec.rb'
- 'spec/views/statuses/show.html.haml_spec.rb'
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes. # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
Metrics/AbcSize: Metrics/AbcSize:
Max: 146 Max: 82
# Configuration parameters: CountBlocks, Max. # Configuration parameters: CountBlocks, Max.
Metrics/BlockNesting: Metrics/BlockNesting:
@ -150,356 +34,33 @@ Metrics/CyclomaticComplexity:
Metrics/PerceivedComplexity: Metrics/PerceivedComplexity:
Max: 27 Max: 27
# Configuration parameters: EnforcedStyle, CheckMethodNames, CheckSymbols, AllowedIdentifiers, AllowedPatterns.
# SupportedStyles: snake_case, normalcase, non_integer
# AllowedIdentifiers: capture3, iso8601, rfc1123_date, rfc822, rfc2822, rfc3339, x86_64
Naming/VariableNumber:
Exclude:
- 'db/migrate/20180106000232_add_index_on_statuses_for_api_v1_accounts_account_id_statuses.rb'
- 'db/migrate/20180514140000_revert_index_change_on_statuses_for_api_v1_accounts_account_id_statuses.rb'
- 'db/migrate/20190820003045_update_statuses_index.rb'
- 'db/migrate/20190823221802_add_local_index_to_statuses.rb'
- 'db/migrate/20200119112504_add_public_index_to_statuses.rb'
- 'spec/models/account_spec.rb'
- 'spec/models/domain_block_spec.rb'
- 'spec/models/user_spec.rb'
RSpec/AnyInstance:
Exclude:
- 'spec/controllers/activitypub/inboxes_controller_spec.rb'
- 'spec/controllers/admin/accounts_controller_spec.rb'
- 'spec/controllers/admin/resets_controller_spec.rb'
- 'spec/controllers/admin/settings/branding_controller_spec.rb'
- 'spec/controllers/api/v1/media_controller_spec.rb'
- 'spec/controllers/auth/sessions_controller_spec.rb'
- 'spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb'
- 'spec/controllers/settings/two_factor_authentication/recovery_codes_controller_spec.rb'
- 'spec/lib/request_spec.rb'
- 'spec/lib/status_filter_spec.rb'
- 'spec/models/account_spec.rb'
- 'spec/models/setting_spec.rb'
- 'spec/services/activitypub/process_collection_service_spec.rb'
- 'spec/validators/follow_limit_validator_spec.rb'
- 'spec/workers/activitypub/delivery_worker_spec.rb'
- 'spec/workers/web/push_notification_worker_spec.rb'
# Configuration parameters: CountAsOne. # Configuration parameters: CountAsOne.
RSpec/ExampleLength: RSpec/ExampleLength:
Max: 22 Max: 22
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: implicit, each, example
RSpec/HookArgument:
Exclude:
- 'spec/controllers/api/v1/streaming_controller_spec.rb'
- 'spec/controllers/well_known/webfinger_controller_spec.rb'
- 'spec/helpers/instance_helper_spec.rb'
- 'spec/models/user_spec.rb'
- 'spec/rails_helper.rb'
- 'spec/serializers/activitypub/note_serializer_spec.rb'
- 'spec/serializers/activitypub/update_poll_serializer_spec.rb'
- 'spec/services/import_service_spec.rb'
# Configuration parameters: AssignmentOnly.
RSpec/InstanceVariable:
Exclude:
- 'spec/controllers/api/v1/streaming_controller_spec.rb'
- 'spec/controllers/auth/confirmations_controller_spec.rb'
- 'spec/controllers/auth/passwords_controller_spec.rb'
- 'spec/controllers/auth/sessions_controller_spec.rb'
- 'spec/controllers/concerns/export_controller_concern_spec.rb'
- 'spec/controllers/home_controller_spec.rb'
- 'spec/controllers/settings/two_factor_authentication/webauthn_credentials_controller_spec.rb'
- 'spec/controllers/statuses_cleanup_controller_spec.rb'
- 'spec/models/concerns/account_finder_concern_spec.rb'
- 'spec/models/concerns/account_interactions_spec.rb'
- 'spec/models/public_feed_spec.rb'
- 'spec/serializers/activitypub/note_serializer_spec.rb'
- 'spec/serializers/activitypub/update_poll_serializer_spec.rb'
- 'spec/services/remove_status_service_spec.rb'
- 'spec/services/search_service_spec.rb'
- 'spec/services/unblock_domain_service_spec.rb'
RSpec/LetSetup:
Exclude:
- 'spec/controllers/admin/accounts_controller_spec.rb'
- 'spec/controllers/admin/action_logs_controller_spec.rb'
- 'spec/controllers/admin/instances_controller_spec.rb'
- 'spec/controllers/admin/reports/actions_controller_spec.rb'
- 'spec/controllers/admin/statuses_controller_spec.rb'
- 'spec/controllers/api/v1/accounts/statuses_controller_spec.rb'
- 'spec/controllers/api/v1/admin/accounts_controller_spec.rb'
- 'spec/controllers/api/v1/filters_controller_spec.rb'
- 'spec/controllers/api/v1/followed_tags_controller_spec.rb'
- 'spec/controllers/api/v2/admin/accounts_controller_spec.rb'
- 'spec/controllers/api/v2/filters/keywords_controller_spec.rb'
- 'spec/controllers/api/v2/filters/statuses_controller_spec.rb'
- 'spec/controllers/auth/confirmations_controller_spec.rb'
- 'spec/controllers/auth/passwords_controller_spec.rb'
- 'spec/controllers/auth/sessions_controller_spec.rb'
- 'spec/controllers/follower_accounts_controller_spec.rb'
- 'spec/controllers/following_accounts_controller_spec.rb'
- 'spec/controllers/oauth/authorized_applications_controller_spec.rb'
- 'spec/controllers/oauth/tokens_controller_spec.rb'
- 'spec/controllers/settings/imports_controller_spec.rb'
- 'spec/lib/activitypub/activity/delete_spec.rb'
- 'spec/lib/vacuum/applications_vacuum_spec.rb'
- 'spec/lib/vacuum/preview_cards_vacuum_spec.rb'
- 'spec/models/account_spec.rb'
- 'spec/models/account_statuses_cleanup_policy_spec.rb'
- 'spec/models/canonical_email_block_spec.rb'
- 'spec/models/status_spec.rb'
- 'spec/models/user_spec.rb'
- 'spec/services/account_statuses_cleanup_service_spec.rb'
- 'spec/services/activitypub/fetch_featured_collection_service_spec.rb'
- 'spec/services/activitypub/fetch_remote_status_service_spec.rb'
- 'spec/services/activitypub/process_account_service_spec.rb'
- 'spec/services/activitypub/process_collection_service_spec.rb'
- 'spec/services/batched_remove_status_service_spec.rb'
- 'spec/services/block_domain_service_spec.rb'
- 'spec/services/bulk_import_service_spec.rb'
- 'spec/services/delete_account_service_spec.rb'
- 'spec/services/import_service_spec.rb'
- 'spec/services/notify_service_spec.rb'
- 'spec/services/remove_status_service_spec.rb'
- 'spec/services/report_service_spec.rb'
- 'spec/services/resolve_account_service_spec.rb'
- 'spec/services/suspend_account_service_spec.rb'
- 'spec/services/unallow_domain_service_spec.rb'
- 'spec/services/unsuspend_account_service_spec.rb'
- 'spec/workers/scheduler/user_cleanup_scheduler_spec.rb'
RSpec/MessageChain:
Exclude:
- 'spec/controllers/api/v1/media_controller_spec.rb'
- 'spec/models/concerns/remotable_spec.rb'
- 'spec/models/session_activation_spec.rb'
- 'spec/models/setting_spec.rb'
# Configuration parameters: EnforcedStyle.
# SupportedStyles: have_received, receive
RSpec/MessageSpies:
Exclude:
- 'spec/controllers/admin/accounts_controller_spec.rb'
- 'spec/helpers/admin/account_moderation_notes_helper_spec.rb'
- 'spec/lib/webfinger_resource_spec.rb'
- 'spec/models/admin/account_action_spec.rb'
- 'spec/models/concerns/remotable_spec.rb'
- 'spec/models/follow_request_spec.rb'
- 'spec/models/identity_spec.rb'
- 'spec/models/session_activation_spec.rb'
- 'spec/models/setting_spec.rb'
- 'spec/services/activitypub/fetch_replies_service_spec.rb'
- 'spec/services/activitypub/process_collection_service_spec.rb'
- 'spec/spec_helper.rb'
- 'spec/validators/status_length_validator_spec.rb'
RSpec/MultipleExpectations: RSpec/MultipleExpectations:
Max: 8 Max: 8
# Configuration parameters: AllowSubject. # Configuration parameters: AllowSubject.
RSpec/MultipleMemoizedHelpers: RSpec/MultipleMemoizedHelpers:
Max: 21 Max: 17
# Configuration parameters: AllowedGroups. # Configuration parameters: AllowedGroups.
RSpec/NestedGroups: RSpec/NestedGroups:
Max: 6 Max: 6
RSpec/PendingWithoutReason:
Exclude:
- 'spec/models/account_spec.rb'
# This cop supports unsafe autocorrection (--autocorrect-all).
Rails/ApplicationController:
Exclude:
- 'app/controllers/health_controller.rb'
# Configuration parameters: Include.
# Include: db/**/*.rb
Rails/CreateTableWithTimestamps:
Exclude:
- 'db/migrate/20170508230434_create_conversation_mutes.rb'
- 'db/migrate/20170823162448_create_status_pins.rb'
- 'db/migrate/20171116161857_create_list_accounts.rb'
- 'db/migrate/20180929222014_create_account_conversations.rb'
- 'db/migrate/20181007025445_create_pghero_space_stats.rb'
- 'db/migrate/20190103124649_create_scheduled_statuses.rb'
- 'db/migrate/20220824233535_create_status_trends.rb'
- 'db/migrate/20221006061337_create_preview_card_trends.rb'
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: Severity.
Rails/DuplicateAssociation:
Exclude:
- 'app/serializers/activitypub/collection_serializer.rb'
- 'app/serializers/activitypub/note_serializer.rb'
# Configuration parameters: Include. # Configuration parameters: Include.
# Include: app/models/**/*.rb # Include: app/models/**/*.rb
Rails/HasAndBelongsToMany: Rails/HasAndBelongsToMany:
Exclude: Exclude:
- 'app/models/concerns/account_associations.rb' - 'app/models/concerns/account/associations.rb'
- 'app/models/preview_card.rb'
- 'app/models/status.rb' - 'app/models/status.rb'
- 'app/models/tag.rb' - 'app/models/tag.rb'
# Configuration parameters: Include.
# Include: app/models/**/*.rb
Rails/HasManyOrHasOneDependent:
Exclude:
- 'app/models/concerns/account_counters.rb'
- 'app/models/conversation.rb'
- 'app/models/custom_emoji.rb'
- 'app/models/custom_emoji_category.rb'
- 'app/models/domain_block.rb'
- 'app/models/invite.rb'
- 'app/models/status.rb'
- 'app/models/user.rb'
- 'app/models/web/push_subscription.rb'
Rails/I18nLocaleTexts:
Exclude:
- 'lib/tasks/mastodon.rake'
- 'spec/helpers/flashes_helper_spec.rb'
# Configuration parameters: Include.
# Include: app/controllers/**/*.rb, app/mailers/**/*.rb
Rails/LexicallyScopedActionFilter:
Exclude:
- 'app/controllers/auth/passwords_controller.rb'
- 'app/controllers/auth/registrations_controller.rb'
- 'app/controllers/auth/sessions_controller.rb'
# This cop supports unsafe autocorrection (--autocorrect-all).
Rails/NegateInclude:
Exclude:
- 'app/controllers/concerns/signature_verification.rb'
- 'app/helpers/jsonld_helper.rb'
- 'app/lib/activitypub/activity/create.rb'
- 'app/lib/activitypub/activity/move.rb'
- 'app/lib/feed_manager.rb'
- 'app/lib/link_details_extractor.rb'
- 'app/models/concerns/attachmentable.rb'
- 'app/models/concerns/remotable.rb'
- 'app/models/custom_filter.rb'
- 'app/services/activitypub/process_status_update_service.rb'
- 'app/services/fetch_link_card_service.rb'
- 'app/services/search_service.rb'
- 'app/workers/web/push_notification_worker.rb'
- 'lib/paperclip/color_extractor.rb'
Rails/OutputSafety: Rails/OutputSafety:
Exclude: Exclude:
- 'config/initializers/simple_form.rb' - 'config/initializers/simple_form.rb'
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: Include.
# Include: **/Rakefile, **/*.rake
Rails/RakeEnvironment:
Exclude:
- 'lib/tasks/auto_annotate_models.rake'
- 'lib/tasks/db.rake'
- 'lib/tasks/emojis.rake'
- 'lib/tasks/mastodon.rake'
- 'lib/tasks/repo.rake'
- 'lib/tasks/statistics.rake'
# Configuration parameters: Include.
# Include: db/**/*.rb
Rails/ReversibleMigration:
Exclude:
- 'db/migrate/20160223164502_make_uris_nullable_in_statuses.rb'
- 'db/migrate/20161122163057_remove_unneeded_indexes.rb'
- 'db/migrate/20170205175257_remove_devices.rb'
- 'db/migrate/20170322143850_change_primary_key_to_bigint_on_statuses.rb'
- 'db/migrate/20170520145338_change_language_filter_to_opt_out.rb'
- 'db/migrate/20170609145826_remove_default_language_from_statuses.rb'
- 'db/migrate/20170711225116_fix_null_booleans.rb'
- 'db/migrate/20171129172043_add_index_on_stream_entries.rb'
- 'db/migrate/20171212195226_remove_duplicate_indexes_in_lists.rb'
- 'db/migrate/20171226094803_more_faster_index_on_notifications.rb'
- 'db/migrate/20180106000232_add_index_on_statuses_for_api_v1_accounts_account_id_statuses.rb'
- 'db/migrate/20180617162849_remove_unused_indexes.rb'
- 'db/migrate/20220827195229_change_canonical_email_blocks_nullable.rb'
# Configuration parameters: ForbiddenMethods, AllowedMethods.
# ForbiddenMethods: decrement!, decrement_counter, increment!, increment_counter, insert, insert!, insert_all, insert_all!, toggle!, touch, touch_all, update_all, update_attribute, update_column, update_columns, update_counters, upsert, upsert_all
Rails/SkipsModelValidations:
Exclude:
- 'app/controllers/admin/invites_controller.rb'
- 'app/controllers/concerns/session_tracking_concern.rb'
- 'app/models/concerns/account_merging.rb'
- 'app/models/concerns/expireable.rb'
- 'app/models/status.rb'
- 'app/models/trends/links.rb'
- 'app/models/trends/preview_card_batch.rb'
- 'app/models/trends/preview_card_provider_batch.rb'
- 'app/models/trends/status_batch.rb'
- 'app/models/trends/statuses.rb'
- 'app/models/trends/tag_batch.rb'
- 'app/models/trends/tags.rb'
- 'app/models/user.rb'
- 'app/services/activitypub/process_status_update_service.rb'
- 'app/services/approve_appeal_service.rb'
- 'app/services/block_domain_service.rb'
- 'app/services/delete_account_service.rb'
- 'app/services/process_mentions_service.rb'
- 'app/services/unallow_domain_service.rb'
- 'app/services/unblock_domain_service.rb'
- 'app/services/update_status_service.rb'
- 'app/workers/activitypub/post_upgrade_worker.rb'
- 'app/workers/move_worker.rb'
- 'app/workers/scheduler/ip_cleanup_scheduler.rb'
- 'app/workers/scheduler/scheduled_statuses_scheduler.rb'
- 'db/migrate/20161203164520_add_from_account_id_to_notifications.rb'
- 'db/migrate/20170105224407_add_shortcode_to_media_attachments.rb'
- 'db/migrate/20170209184350_add_reply_to_statuses.rb'
- 'db/migrate/20170304202101_add_type_to_media_attachments.rb'
- 'db/migrate/20180528141303_fix_accounts_unique_index.rb'
- 'db/migrate/20180609104432_migrate_web_push_subscriptions2.rb'
- 'db/migrate/20181207011115_downcase_custom_emoji_domains.rb'
- 'db/migrate/20190511134027_add_silenced_at_suspended_at_to_accounts.rb'
- 'db/migrate/20191007013357_update_pt_locales.rb'
- 'db/migrate/20220316233212_update_kurdish_locales.rb'
- 'db/post_migrate/20190511152737_remove_suspended_silenced_account_fields.rb'
- 'db/post_migrate/20200917193528_migrate_notifications_type.rb'
- 'db/post_migrate/20201017234926_fill_account_suspension_origin.rb'
- 'db/post_migrate/20220617202502_migrate_roles.rb'
- 'db/post_migrate/20221101190723_backfill_admin_action_logs.rb'
- 'db/post_migrate/20221206114142_backfill_admin_action_logs_again.rb'
- 'lib/mastodon/cli/accounts.rb'
- 'lib/mastodon/cli/main.rb'
- 'lib/mastodon/cli/maintenance.rb'
- 'spec/controllers/api/v1/admin/accounts_controller_spec.rb'
- 'spec/lib/activitypub/activity/follow_spec.rb'
- 'spec/services/follow_service_spec.rb'
- 'spec/services/update_account_service_spec.rb'
# Configuration parameters: Include.
# Include: db/**/*.rb
Rails/ThreeStateBooleanColumn:
Exclude:
- 'db/migrate/20160325130944_add_admin_to_users.rb'
- 'db/migrate/20161123093447_add_sensitive_to_statuses.rb'
- 'db/migrate/20170123203248_add_reject_media_to_domain_blocks.rb'
- 'db/migrate/20170127165745_add_devise_two_factor_to_users.rb'
- 'db/migrate/20170209184350_add_reply_to_statuses.rb'
- 'db/migrate/20170330163835_create_imports.rb'
- 'db/migrate/20170905165803_add_local_to_statuses.rb'
- 'db/migrate/20181203021853_add_discoverable_to_accounts.rb'
- 'db/migrate/20190509164208_add_by_moderator_to_tombstone.rb'
- 'db/migrate/20190805123746_add_capabilities_to_tags.rb'
- 'db/migrate/20191212163405_add_hide_collections_to_accounts.rb'
- 'db/migrate/20200309150742_add_forwarded_to_reports.rb'
- 'db/migrate/20210609202149_create_login_activities.rb'
- 'db/migrate/20210621221010_add_skip_sign_in_token_to_users.rb'
- 'db/migrate/20211031031021_create_preview_card_providers.rb'
- 'db/migrate/20211115032527_add_trendable_to_preview_cards.rb'
- 'db/migrate/20220202200743_add_trendable_to_accounts.rb'
- 'db/migrate/20220202200926_add_trendable_to_statuses.rb'
- 'db/migrate/20220303000827_add_ordered_media_attachment_ids_to_status_edits.rb'
# Configuration parameters: Include. # Configuration parameters: Include.
# Include: app/models/**/*.rb # Include: app/models/**/*.rb
Rails/UniqueValidationWithoutIndex: Rails/UniqueValidationWithoutIndex:
@ -509,61 +70,7 @@ Rails/UniqueValidationWithoutIndex:
- 'app/models/identity.rb' - 'app/models/identity.rb'
- 'app/models/webauthn_credential.rb' - 'app/models/webauthn_credential.rb'
# Configuration parameters: Include.
# Include: app/models/**/*.rb
Rails/UnusedIgnoredColumns:
Exclude:
- 'app/models/account.rb'
- 'app/models/account_stat.rb'
- 'app/models/admin/action_log.rb'
- 'app/models/custom_filter.rb'
- 'app/models/email_domain_block.rb'
- 'app/models/report.rb'
- 'app/models/status_edit.rb'
- 'app/models/user.rb'
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: exists, where
Rails/WhereExists:
Exclude:
- 'app/controllers/activitypub/inboxes_controller.rb'
- 'app/controllers/admin/email_domain_blocks_controller.rb'
- 'app/controllers/auth/registrations_controller.rb'
- 'app/lib/activitypub/activity/create.rb'
- 'app/lib/delivery_failure_tracker.rb'
- 'app/lib/feed_manager.rb'
- 'app/lib/status_cache_hydrator.rb'
- 'app/lib/suspicious_sign_in_detector.rb'
- 'app/models/concerns/account_interactions.rb'
- 'app/models/featured_tag.rb'
- 'app/models/poll.rb'
- 'app/models/session_activation.rb'
- 'app/models/status.rb'
- 'app/models/user.rb'
- 'app/policies/status_policy.rb'
- 'app/serializers/rest/announcement_serializer.rb'
- 'app/serializers/rest/tag_serializer.rb'
- 'app/services/activitypub/fetch_remote_status_service.rb'
- 'app/services/app_sign_up_service.rb'
- 'app/services/vote_service.rb'
- 'app/validators/reaction_validator.rb'
- 'app/validators/vote_validator.rb'
- 'app/workers/move_worker.rb'
- 'db/migrate/20190529143559_preserve_old_layout_for_existing_users.rb'
- 'lib/tasks/tests.rake'
- 'spec/models/account_spec.rb'
- 'spec/services/activitypub/process_collection_service_spec.rb'
- 'spec/services/purge_domain_service_spec.rb'
- 'spec/services/unallow_domain_service_spec.rb'
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AllowOnConstant, AllowOnSelfClass.
Style/CaseEquality:
Exclude:
- 'config/initializers/trusted_proxies.rb'
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AllowedMethods, AllowedPatterns. # Configuration parameters: AllowedMethods, AllowedPatterns.
# AllowedMethods: ==, equal?, eql? # AllowedMethods: ==, equal?, eql?
Style/ClassEqualityComparison: Style/ClassEqualityComparison:
@ -575,12 +82,6 @@ Style/ClassVars:
Exclude: Exclude:
- 'config/initializers/devise.rb' - 'config/initializers/devise.rb'
# This cop supports unsafe autocorrection (--autocorrect-all).
Style/CombinableLoops:
Exclude:
- 'app/models/form/custom_emoji_batch.rb'
- 'app/models/form/ip_block_batch.rb'
# This cop supports safe autocorrection (--autocorrect). # This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AllowedVars. # Configuration parameters: AllowedVars.
Style/FetchEnvVar: Style/FetchEnvVar:
@ -590,15 +91,14 @@ Style/FetchEnvVar:
- '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_limited_federation_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/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/redis_config.rb' - 'lib/mastodon/redis_config.rb'
- 'lib/premailer_webpack_strategy.rb'
- 'lib/tasks/repo.rake' - 'lib/tasks/repo.rake'
- 'spec/features/profile_spec.rb' - 'spec/features/profile_spec.rb'
@ -608,14 +108,12 @@ Style/FetchEnvVar:
# AllowedMethods: redirect # AllowedMethods: redirect
Style/FormatStringToken: Style/FormatStringToken:
Exclude: Exclude:
- 'app/models/privacy_policy.rb'
- 'config/initializers/devise.rb' - 'config/initializers/devise.rb'
- 'lib/paperclip/color_extractor.rb' - 'lib/paperclip/color_extractor.rb'
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
Style/GlobalStdStream: Style/GlobalStdStream:
Exclude: Exclude:
- 'config/boot.rb'
- 'config/environments/development.rb' - 'config/environments/development.rb'
- 'config/environments/production.rb' - 'config/environments/production.rb'
@ -623,17 +121,13 @@ Style/GlobalStdStream:
# Configuration parameters: MinBodyLength, AllowConsecutiveConditionals. # Configuration parameters: MinBodyLength, AllowConsecutiveConditionals.
Style/GuardClause: Style/GuardClause:
Exclude: Exclude:
- 'app/controllers/admin/confirmations_controller.rb'
- 'app/controllers/auth/confirmations_controller.rb'
- 'app/controllers/auth/passwords_controller.rb'
- 'app/controllers/settings/two_factor_authentication/webauthn_credentials_controller.rb'
- 'app/lib/activitypub/activity/block.rb' - 'app/lib/activitypub/activity/block.rb'
- 'app/lib/request.rb' - 'app/lib/request.rb'
- 'app/lib/request_pool.rb' - 'app/lib/request_pool.rb'
- 'app/lib/webfinger.rb' - 'app/lib/webfinger.rb'
- 'app/lib/webfinger_resource.rb' - 'app/lib/webfinger_resource.rb'
- 'app/models/concerns/account_counters.rb' - 'app/models/concerns/account/counters.rb'
- 'app/models/concerns/ldap_authenticable.rb' - 'app/models/concerns/user/ldap_authenticable.rb'
- 'app/models/tag.rb' - 'app/models/tag.rb'
- 'app/models/user.rb' - 'app/models/user.rb'
- 'app/services/fan_out_on_write_service.rb' - 'app/services/fan_out_on_write_service.rb'
@ -645,10 +139,8 @@ Style/GuardClause:
- 'app/workers/redownload_media_worker.rb' - 'app/workers/redownload_media_worker.rb'
- 'app/workers/remote_account_refresh_worker.rb' - 'app/workers/remote_account_refresh_worker.rb'
- 'config/initializers/devise.rb' - 'config/initializers/devise.rb'
- 'db/migrate/20170901141119_truncate_preview_cards.rb' - 'lib/devise/strategies/two_factor_ldap_authenticatable.rb'
- 'db/post_migrate/20220704024901_migrate_settings_to_user_roles.rb' - 'lib/devise/strategies/two_factor_pam_authenticatable.rb'
- 'lib/devise/two_factor_ldap_authenticatable.rb'
- 'lib/devise/two_factor_pam_authenticatable.rb'
- 'lib/mastodon/cli/accounts.rb' - 'lib/mastodon/cli/accounts.rb'
- 'lib/mastodon/cli/maintenance.rb' - 'lib/mastodon/cli/maintenance.rb'
- 'lib/mastodon/cli/media.rb' - 'lib/mastodon/cli/media.rb'
@ -662,12 +154,11 @@ Style/HashAsLastArrayItem:
Exclude: Exclude:
- 'app/controllers/admin/statuses_controller.rb' - 'app/controllers/admin/statuses_controller.rb'
- 'app/controllers/api/v1/statuses_controller.rb' - 'app/controllers/api/v1/statuses_controller.rb'
- 'app/models/concerns/account_counters.rb' - 'app/models/concerns/account/counters.rb'
- 'app/models/concerns/status_threading_concern.rb' - 'app/models/concerns/status/threading_concern.rb'
- 'app/models/status.rb' - 'app/models/status.rb'
- 'app/services/batched_remove_status_service.rb' - 'app/services/batched_remove_status_service.rb'
- 'app/services/notify_service.rb' - 'app/services/notify_service.rb'
- 'db/migrate/20181024224956_migrate_account_conversations.rb'
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
Style/HashTransformValues: Style/HashTransformValues:
@ -682,22 +173,6 @@ Style/IfUnlessModifier:
- 'config/initializers/devise.rb' - 'config/initializers/devise.rb'
- 'config/initializers/ffmpeg.rb' - 'config/initializers/ffmpeg.rb'
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: InverseMethods, InverseBlocks.
Style/InverseMethods:
Exclude:
- 'app/models/custom_filter.rb'
- 'app/services/update_account_service.rb'
- 'spec/controllers/activitypub/replies_controller_spec.rb'
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: line_count_dependent, lambda, literal
Style/Lambda:
Exclude:
- 'config/initializers/simple_form.rb'
- 'config/routes.rb'
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
Style/MapToHash: Style/MapToHash:
Exclude: Exclude:
@ -767,35 +242,21 @@ Style/RedundantFetchBlock:
# AllowedMethods: present?, blank?, presence, try, try! # AllowedMethods: present?, blank?, presence, try, try!
Style/SafeNavigation: Style/SafeNavigation:
Exclude: Exclude:
- 'app/models/concerns/account_finder_concern.rb' - 'app/models/concerns/account/finder_concern.rb'
- 'app/models/status.rb'
# This cop supports safe autocorrection (--autocorrect). # This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle. # Configuration parameters: EnforcedStyle.
# SupportedStyles: only_raise, only_fail, semantic # SupportedStyles: only_raise, only_fail, semantic
Style/SignalException: Style/SignalException:
Exclude: Exclude:
- 'lib/devise/two_factor_ldap_authenticatable.rb' - 'lib/devise/strategies/two_factor_ldap_authenticatable.rb'
- 'lib/devise/two_factor_pam_authenticatable.rb' - 'lib/devise/strategies/two_factor_pam_authenticatable.rb'
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
Style/SingleArgumentDig: Style/SingleArgumentDig:
Exclude: Exclude:
- 'lib/webpacker/manifest_extensions.rb' - 'lib/webpacker/manifest_extensions.rb'
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: require_parentheses, require_no_parentheses
Style/StabbyLambdaParentheses:
Exclude:
- 'config/environments/production.rb'
- 'config/initializers/content_security_policy.rb'
# This cop supports safe autocorrection (--autocorrect).
Style/StderrPuts:
Exclude:
- 'config/boot.rb'
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: Mode. # Configuration parameters: Mode.
Style/StringConcatenation: Style/StringConcatenation:
@ -814,20 +275,6 @@ Style/StringLiterals:
- 'config/initializers/webauthn.rb' - 'config/initializers/webauthn.rb'
- 'config/routes.rb' - 'config/routes.rb'
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: AllowMethodsWithArguments, AllowedMethods, AllowedPatterns, AllowComments.
# AllowedMethods: define_method, mail, respond_to
Style/SymbolProc:
Exclude:
- 'config/initializers/omniauth.rb'
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle, AllowSafeAssignment.
# SupportedStyles: require_parentheses, require_no_parentheses, require_parentheses_when_complex
Style/TernaryParentheses:
Exclude:
- 'config/environments/development.rb'
# This cop supports safe autocorrection (--autocorrect). # This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyleForMultiline. # Configuration parameters: EnforcedStyleForMultiline.
# SupportedStylesForMultiline: comma, consistent_comma, no_comma # SupportedStylesForMultiline: comma, consistent_comma, no_comma
@ -844,11 +291,8 @@ Style/TrailingCommaInHashLiteral:
- 'config/environments/test.rb' - 'config/environments/test.rb'
# This cop supports safe autocorrection (--autocorrect). # This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle, MinSize, WordRegex. # Configuration parameters: WordRegex.
# SupportedStyles: percent, brackets # SupportedStyles: percent, brackets
Style/WordArray: Style/WordArray:
Exclude: EnforcedStyle: percent
- 'app/helpers/languages_helper.rb' MinSize: 3
- 'config/initializers/cors.rb'
- 'spec/controllers/settings/imports_controller_spec.rb'
- 'spec/models/form/import_spec.rb'

View File

@ -1 +1 @@
3.2.2 3.2.3

22
.simplecov Normal file
View File

@ -0,0 +1,22 @@
# frozen_string_literal: true
if ENV['CI']
require 'simplecov-lcov'
SimpleCov::Formatter::LcovFormatter.config.report_with_single_file = true
SimpleCov.formatter = SimpleCov::Formatter::LcovFormatter
else
SimpleCov.formatter = SimpleCov::Formatter::HTMLFormatter
end
SimpleCov.start 'rails' do
enable_coverage :branch
add_filter 'lib/linter'
add_group 'Libraries', 'lib'
add_group 'Policies', 'app/policies'
add_group 'Presenters', 'app/presenters'
add_group 'Serializers', 'app/serializers'
add_group 'Services', 'app/services'
add_group 'Validators', 'app/validators'
end

3
.watchmanconfig Normal file
View File

@ -0,0 +1,3 @@
{
"ignore_dirs": ["node_modules/", "public/"]
}

0
.yarn/.gitkeep Normal file
View File

View File

@ -0,0 +1,13 @@
diff --git a/lib/index.js b/lib/index.js
index 16ed6be8be8f555cc99096c2ff60954b42dc313d..d009c069770d066ad0db7ad02de1ea473a29334e 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -99,7 +99,7 @@ function lodash(_ref) {
var node = _ref3;
- if ((0, _types.isModuleDeclaration)(node)) {
+ if ((0, _types.isImportDeclaration)(node) || (0, _types.isExportDeclaration)(node)) {
isModule = true;
break;
}

View File

@ -1,49 +0,0 @@
# test directories
__tests__
test
tests
powered-test
# asset directories
docs
doc
website
images
# assets
# examples
example
examples
# code coverage directories
coverage
.nyc_output
# build scripts
Makefile
Gulpfile.js
Gruntfile.js
# configs
.tern-project
.gitattributes
.editorconfig
.*ignore
.eslintrc
.jshintrc
.flowconfig
.documentup.json
.yarn-metadata.json
.*.yml
*.yml
# misc
*.gz
*.md
# for specific ignore
!.svgo.yml
!sass-lint/**/*.yml
# breaks lint-staged or generally anything using https://github.com/eemeli/yaml/issues/384
!**/yaml/dist/**/doc

1
.yarnrc.yml Normal file
View File

@ -0,0 +1 @@
nodeLinker: node-modules

1680
AUTHORS.md

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -11,6 +11,10 @@ You can contribute in the following ways:
If your contributions are accepted into Mastodon, you can request to be paid through [our OpenCollective](https://opencollective.com/mastodon). If your contributions are accepted into Mastodon, you can request to be paid through [our OpenCollective](https://opencollective.com/mastodon).
## API Changes and Additions
Please note that any changes or additions made to the API should have an accompanying pull request on [our documentation repository](https://github.com/mastodon/documentation).
## Bug reports ## Bug reports
Bug reports and feature suggestions must use descriptive and concise titles and be submitted to [GitHub Issues](https://github.com/mastodon/mastodon/issues). Please use the search function to make sure that you are not submitting duplicates, and that a similar report or request has not already been resolved or rejected. Bug reports and feature suggestions must use descriptive and concise titles and be submitted to [GitHub Issues](https://github.com/mastodon/mastodon/issues). Please use the search function to make sure that you are not submitting duplicates, and that a similar report or request has not already been resolved or rejected.

15
Capfile
View File

@ -1,15 +0,0 @@
# frozen_string_literal: true
require 'capistrano/setup'
require 'capistrano/deploy'
require 'capistrano/scm/git'
install_plugin Capistrano::SCM::Git
require 'capistrano/rbenv'
require 'capistrano/bundler'
require 'capistrano/yarn'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }

View File

@ -1,104 +1,260 @@
# syntax=docker/dockerfile:1.4 # syntax=docker/dockerfile:1.4
# This needs to be bullseye-slim because the Ruby image is built on bullseye-slim
ARG NODE_VERSION="16.20-bullseye-slim"
FROM ghcr.io/moritzheiber/ruby-jemalloc:3.2.2-slim as ruby # Please see https://docs.docker.com/engine/reference/builder for information about
FROM node:${NODE_VERSION} as build # the extended buildx capabilities used in this file.
# Make sure multiarch TARGETPLATFORM is available for interpolation
# See: https://docs.docker.com/build/building/multi-platform/
ARG TARGETPLATFORM=${TARGETPLATFORM}
ARG BUILDPLATFORM=${BUILDPLATFORM}
COPY --link --from=ruby /opt/ruby /opt/ruby # Ruby image to use for base image, change with [--build-arg RUBY_VERSION="3.2.3"]
ARG RUBY_VERSION="3.2.3"
# # Node version to use in base image, change with [--build-arg NODE_MAJOR_VERSION="20"]
ARG NODE_MAJOR_VERSION="20"
# Debian image to use for base image, change with [--build-arg DEBIAN_VERSION="bookworm"]
ARG DEBIAN_VERSION="bookworm"
# Node image to use for base image based on combined variables (ex: 20-bookworm-slim)
FROM docker.io/node:${NODE_MAJOR_VERSION}-${DEBIAN_VERSION}-slim as node
# Ruby image to use for base image based on combined variables (ex: 3.2.3-slim-bookworm)
FROM docker.io/ruby:${RUBY_VERSION}-slim-${DEBIAN_VERSION} as ruby
ENV DEBIAN_FRONTEND="noninteractive" \ # Resulting version string is vX.X.X-MASTODON_VERSION_PRERELEASE+MASTODON_VERSION_METADATA
PATH="${PATH}:/opt/ruby/bin" # Example: v4.2.0-nightly.2023.11.09+something
# Overwrite existance of 'alpha.0' in version.rb [--build-arg MASTODON_VERSION_PRERELEASE="nightly.2023.11.09"]
SHELL ["/bin/bash", "-o", "pipefail", "-c"] ARG MASTODON_VERSION_PRERELEASE=""
# Append build metadata or fork information to version.rb [--build-arg MASTODON_VERSION_METADATA="something"]
WORKDIR /opt/mastodon ARG MASTODON_VERSION_METADATA=""
COPY Gemfile* package.json yarn.lock /opt/mastodon/
# hadolint ignore=DL3008
RUN apt-get update && \
apt-get install -y --no-install-recommends build-essential \
git \
libicu-dev \
libidn11-dev \
libpq-dev \
libjemalloc-dev \
zlib1g-dev \
libgdbm-dev \
libgmp-dev \
libssl-dev \
libyaml-0-2 \
ca-certificates \
libreadline8 \
python3 \
shared-mime-info && \
bundle config set --local deployment 'true' && \
bundle config set --local without 'development test' && \
bundle config set silence_root_warning true && \
bundle install -j"$(nproc)" && \
yarn install --pure-lockfile --production --network-timeout 600000 && \
yarn cache clean
FROM node:${NODE_VERSION}
# Use those args to specify your own version flags & suffixes
ARG MASTODON_VERSION_FLAGS=""
ARG MASTODON_VERSION_SUFFIX=""
# Allow Ruby on Rails to serve static files
# See: https://docs.joinmastodon.org/admin/config/#rails_serve_static_files
ARG RAILS_SERVE_STATIC_FILES="true"
# Allow to use YJIT compiler
# See: https://github.com/ruby/ruby/blob/master/doc/yjit/yjit.md
ARG RUBY_YJIT_ENABLE="1"
# Timezone used by the Docker container and runtime, change with [--build-arg TZ=Europe/Berlin]
ARG TZ="Etc/UTC"
# Linux UID (user id) for the mastodon user, change with [--build-arg UID=1234]
ARG UID="991" ARG UID="991"
# Linux GID (group id) for the mastodon user, change with [--build-arg GID=1234]
ARG GID="991" ARG GID="991"
COPY --link --from=ruby /opt/ruby /opt/ruby # Apply Mastodon build options based on options above
ENV \
# Apply Mastodon version information
MASTODON_VERSION_PRERELEASE="${MASTODON_VERSION_PRERELEASE}" \
MASTODON_VERSION_METADATA="${MASTODON_VERSION_METADATA}" \
# Apply Mastodon static files and YJIT options
RAILS_SERVE_STATIC_FILES=${RAILS_SERVE_STATIC_FILES} \
RUBY_YJIT_ENABLE=${RUBY_YJIT_ENABLE} \
# Apply timezone
TZ=${TZ}
SHELL ["/bin/bash", "-o", "pipefail", "-c"] ENV \
# Configure the IP to bind Mastodon to when serving traffic
BIND="0.0.0.0" \
# Use production settings for Yarn, Node and related nodejs based tools
NODE_ENV="production" \
# Use production settings for Ruby on Rails
RAILS_ENV="production" \
# Add Ruby and Mastodon installation to the PATH
DEBIAN_FRONTEND="noninteractive" \
PATH="${PATH}:/opt/ruby/bin:/opt/mastodon/bin" \
# Optimize jemalloc 5.x performance
MALLOC_CONF="narenas:2,background_thread:true,thp:never,dirty_decay_ms:1000,muzzy_decay_ms:0"
ENV DEBIAN_FRONTEND="noninteractive" \ # Set default shell used for running commands
PATH="${PATH}:/opt/ruby/bin:/opt/mastodon/bin" SHELL ["/bin/bash", "-o", "pipefail", "-o", "errexit", "-c"]
# Ignoring these here since we don't want to pin any versions and the Debian image removes apt-get content after use ARG TARGETPLATFORM
# hadolint ignore=DL3008,DL3009
RUN apt-get update && \
echo "Etc/UTC" > /etc/localtime && \
groupadd -g "${GID}" mastodon && \
useradd -l -u "$UID" -g "${GID}" -m -d /opt/mastodon mastodon && \
apt-get -y --no-install-recommends install whois \
wget \
procps \
libssl1.1 \
libpq5 \
imagemagick \
ffmpeg \
libjemalloc2 \
libicu67 \
libidn11 \
libyaml-0-2 \
file \
ca-certificates \
tzdata \
libreadline8 \
tini && \
ln -s /opt/mastodon /mastodon
# Note: no, cleaning here since Debian does this automatically RUN echo "Target platform is $TARGETPLATFORM"
# See the file /etc/apt/apt.conf.d/docker-clean within the Docker image's filesystem
COPY --chown=mastodon:mastodon . /opt/mastodon RUN \
COPY --chown=mastodon:mastodon --from=build /opt/mastodon /opt/mastodon # Remove automatic apt cache Docker cleanup scripts
rm -f /etc/apt/apt.conf.d/docker-clean; \
# Sets timezone
echo "${TZ}" > /etc/localtime; \
# Creates mastodon user/group and sets home directory
groupadd -g "${GID}" mastodon; \
useradd -l -u "${UID}" -g "${GID}" -m -d /opt/mastodon mastodon; \
# Creates /mastodon symlink to /opt/mastodon
ln -s /opt/mastodon /mastodon;
ENV RAILS_ENV="production" \ # Set /opt/mastodon as working directory
NODE_ENV="production" \
RAILS_SERVE_STATIC_FILES="true" \
BIND="0.0.0.0" \
MASTODON_VERSION_FLAGS="${MASTODON_VERSION_FLAGS}" \
MASTODON_VERSION_SUFFIX="${MASTODON_VERSION_SUFFIX}"
# Set the run user
USER mastodon
WORKDIR /opt/mastodon WORKDIR /opt/mastodon
# Precompile assets # hadolint ignore=DL3008,DL3005
RUN OTP_SECRET=precompile_placeholder SECRET_KEY_BASE=precompile_placeholder rails assets:precompile RUN \
# Mount Apt cache and lib directories from Docker buildx caches
--mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \
--mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \
# Apt update & upgrade to check for security updates to Debian image
apt-get update; \
apt-get dist-upgrade -yq; \
# Install jemalloc, curl and other necessary components
apt-get install -y --no-install-recommends \
ca-certificates \
curl \
ffmpeg \
file \
imagemagick \
libjemalloc2 \
patchelf \
procps \
tini \
tzdata \
wget \
; \
# Patch Ruby to use jemalloc
patchelf --add-needed libjemalloc.so.2 /usr/local/bin/ruby; \
# Discard patchelf after use
apt-get purge -y \
patchelf \
;
# Set the work dir and the container entry point # Create temporary build layer from base image
ENTRYPOINT ["/usr/bin/tini", "--"] FROM ruby as build
EXPOSE 3000 4000
# Copy Node package configuration files into working directory
COPY package.json yarn.lock .yarnrc.yml /opt/mastodon/
COPY .yarn /opt/mastodon/.yarn
COPY --from=node /usr/local/bin /usr/local/bin
COPY --from=node /usr/local/lib /usr/local/lib
ARG TARGETPLATFORM
# hadolint ignore=DL3008
RUN \
# Mount Apt cache and lib directories from Docker buildx caches
--mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \
--mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \
# Install build tools and bundler dependencies from APT
apt-get install -y --no-install-recommends \
g++ \
gcc \
git \
libgdbm-dev \
libgmp-dev \
libicu-dev \
libidn-dev \
libpq-dev \
libssl-dev \
make \
shared-mime-info \
zlib1g-dev \
;
RUN \
# Configure Corepack
rm /usr/local/bin/yarn*; \
corepack enable; \
corepack prepare --activate;
# Create temporary bundler specific build layer from build layer
FROM build as bundler
ARG TARGETPLATFORM
# Copy Gemfile config into working directory
COPY Gemfile* /opt/mastodon/
RUN \
# Mount Ruby Gem caches
--mount=type=cache,id=gem-cache-${TARGETPLATFORM},target=/usr/local/bundle/cache/,sharing=locked \
# Configure bundle to prevent changes to Gemfile and Gemfile.lock
bundle config set --global frozen "true"; \
# Configure bundle to not cache downloaded Gems
bundle config set --global cache_all "false"; \
# Configure bundle to only process production Gems
bundle config set --local without "development test"; \
# Configure bundle to not warn about root user
bundle config set silence_root_warning "true"; \
# Download and install required Gems
bundle install -j"$(nproc)";
# Create temporary node specific build layer from build layer
FROM build as yarn
ARG TARGETPLATFORM
# Copy Node package configuration files into working directory
COPY package.json yarn.lock .yarnrc.yml /opt/mastodon/
COPY streaming/package.json /opt/mastodon/streaming/
COPY .yarn /opt/mastodon/.yarn
# hadolint ignore=DL3008
RUN \
--mount=type=cache,id=corepack-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/corepack,sharing=locked \
--mount=type=cache,id=yarn-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/yarn,sharing=locked \
# Install Node packages
yarn workspaces focus --production @mastodon/mastodon;
# Create temporary assets build layer from build layer
FROM build as precompiler
# Copy Mastodon sources into precompiler layer
COPY . /opt/mastodon/
# Copy bundler and node packages from build layer to container
COPY --from=yarn /opt/mastodon /opt/mastodon/
COPY --from=bundler /opt/mastodon /opt/mastodon/
COPY --from=bundler /usr/local/bundle/ /usr/local/bundle/
ARG TARGETPLATFORM
RUN \
# Use Ruby on Rails to create Mastodon assets
OTP_SECRET=precompile_placeholder SECRET_KEY_BASE=precompile_placeholder bundle exec rails assets:precompile; \
# Cleanup temporary files
rm -fr /opt/mastodon/tmp;
# Prep final Mastodon Ruby layer
FROM ruby as mastodon
ARG TARGETPLATFORM
# hadolint ignore=DL3008
RUN \
# Mount Apt cache and lib directories from Docker buildx caches
--mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \
--mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \
# Mount Corepack and Yarn caches from Docker buildx caches
--mount=type=cache,id=corepack-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/corepack,sharing=locked \
--mount=type=cache,id=yarn-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/yarn,sharing=locked \
# Apt update install non-dev versions of necessary components
apt-get install -y --no-install-recommends \
libssl3 \
libpq5 \
libicu72 \
libidn12 \
libreadline8 \
libyaml-0-2 \
;
# Copy Mastodon sources into final layer
COPY . /opt/mastodon/
# Copy compiled assets to layer
COPY --from=precompiler /opt/mastodon/public/packs /opt/mastodon/public/packs
COPY --from=precompiler /opt/mastodon/public/assets /opt/mastodon/public/assets
# Copy bundler components to layer
COPY --from=bundler /usr/local/bundle/ /usr/local/bundle/
RUN \
# Precompile bootsnap code for faster Rails startup
bundle exec bootsnap precompile --gemfile app/ lib/;
RUN \
# Pre-create and chown system volume to Mastodon user
mkdir -p /opt/mastodon/public/system; \
chown mastodon:mastodon /opt/mastodon/public/system; \
# Set Mastodon user as owner of tmp folder
chown -R mastodon:mastodon /opt/mastodon/tmp;
# Set the running user for resulting container
USER mastodon
# Expose default Puma ports
EXPOSE 3000
# Set container tini as default entry point
ENTRYPOINT ["/usr/bin/tini", "--"]

View File

@ -1,19 +1,35 @@
## ActivityPub federation in Mastodon # Federation
## Supported federation protocols and standards
- [ActivityPub](https://www.w3.org/TR/activitypub/) (Server-to-Server)
- [WebFinger](https://webfinger.net/)
- [Http Signatures](https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures)
- [NodeInfo](https://nodeinfo.diaspora.software/)
## Supported FEPs
- [FEP-67ff: FEDERATION.md](https://codeberg.org/fediverse/fep/src/branch/main/fep/67ff/fep-67ff.md)
- [FEP-f1d5: NodeInfo in Fediverse Software](https://codeberg.org/fediverse/fep/src/branch/main/fep/f1d5/fep-f1d5.md)
- [FEP-8fcf: Followers collection synchronization across servers](https://codeberg.org/fediverse/fep/src/branch/main/fep/8fcf/fep-8fcf.md)
- [FEP-5feb: Search indexing consent for actors](https://codeberg.org/fediverse/fep/src/branch/main/fep/5feb/fep-5feb.md)
## ActivityPub in Mastodon
Mastodon largely follows the ActivityPub server-to-server specification but it makes uses of some non-standard extensions, some of which are required for interacting with Mastodon at all. Mastodon largely follows the ActivityPub server-to-server specification but it makes uses of some non-standard extensions, some of which are required for interacting with Mastodon at all.
Supported vocabulary: https://docs.joinmastodon.org/spec/activitypub/ - [Supported ActivityPub vocabulary](https://docs.joinmastodon.org/spec/activitypub/)
### Required extensions ### Required extensions
#### Webfinger #### WebFinger
In Mastodon, users are identified by a `username` and `domain` pair (e.g., `Gargron@mastodon.social`). In Mastodon, users are identified by a `username` and `domain` pair (e.g., `Gargron@mastodon.social`).
This is used both for discovery and for unambiguously mentioning users across the fediverse. Furthermore, this is part of Mastodon's database design from its very beginnings. This is used both for discovery and for unambiguously mentioning users across the fediverse. Furthermore, this is part of Mastodon's database design from its very beginnings.
As a result, Mastodon requires that each ActivityPub actor uniquely maps back to an `acct:` URI that can be resolved via WebFinger. As a result, Mastodon requires that each ActivityPub actor uniquely maps back to an `acct:` URI that can be resolved via WebFinger.
More information and examples are available at: https://docs.joinmastodon.org/spec/webfinger/ - [WebFinger information and examples](https://docs.joinmastodon.org/spec/webfinger/)
#### HTTP Signatures #### HTTP Signatures
@ -21,10 +37,13 @@ In order to authenticate activities, Mastodon relies on HTTP Signatures, signing
Mastodon requires all `POST` requests to be signed, and MAY require `GET` requests to be signed, depending on the configuration of the Mastodon server. Mastodon requires all `POST` requests to be signed, and MAY require `GET` requests to be signed, depending on the configuration of the Mastodon server.
More information on HTTP Signatures, as well as examples, can be found here: https://docs.joinmastodon.org/spec/security/#http - [HTTP Signatures information and examples](https://docs.joinmastodon.org/spec/security/#http)
### Optional extensions ### Optional extensions
- 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://git.activitypub.dev/ActivityPubDev/Fediverse-Enhancement-Proposals/src/branch/main/feps/fep-8fcf.md
### Additional documentation
- [Mastodon documentation](https://docs.joinmastodon.org/)

55
Gemfile
View File

@ -4,11 +4,14 @@ source 'https://rubygems.org'
ruby '>= 3.0.0' ruby '>= 3.0.0'
gem 'puma', '~> 6.3' gem 'puma', '~> 6.3'
gem 'rails', '~> 7.0' gem 'rails', '~> 7.1.1'
gem 'sprockets', '~> 3.7.2' gem 'propshaft'
gem 'thor', '~> 1.2' gem 'thor', '~> 1.2'
gem 'rack', '~> 2.2.7' gem 'rack', '~> 2.2.7'
# For why irb is in the Gemfile, see: https://ruby.social/@st0012/111444685161478182
gem 'irb', '~> 1.8'
gem 'haml-rails', '~>2.0' gem 'haml-rails', '~>2.0'
gem 'pg', '~> 1.5' gem 'pg', '~> 1.5'
gem 'pghero' gem 'pghero'
@ -16,14 +19,14 @@ gem 'dotenv-rails', '~> 2.8'
gem 'aws-sdk-s3', '~> 1.123', require: false gem 'aws-sdk-s3', '~> 1.123', require: false
gem 'fog-core', '<= 2.4.0' gem 'fog-core', '<= 2.4.0'
gem 'fog-openstack', '~> 0.3', require: false gem 'fog-openstack', '~> 1.0', require: false
gem 'kt-paperclip', '~> 7.2' gem 'kt-paperclip', '~> 7.2'
gem 'md-paperclip-azure', '~> 2.2', require: false gem 'md-paperclip-azure', '~> 2.2', require: false
gem 'blurhash', '~> 0.1' gem 'blurhash', '~> 0.1'
gem 'active_model_serializers', '~> 0.10' gem 'active_model_serializers', '~> 0.10'
gem 'addressable', '~> 2.8' gem 'addressable', '~> 2.8'
gem 'bootsnap', '~> 1.16.0', require: false gem 'bootsnap', '~> 1.17.0', require: false
gem 'browser' gem 'browser'
gem 'charlock_holmes', '~> 0.7.7' gem 'charlock_holmes', '~> 0.7.7'
gem 'chewy', '~> 7.3' gem 'chewy', '~> 7.3'
@ -36,15 +39,14 @@ end
gem 'net-ldap', '~> 0.18' gem 'net-ldap', '~> 0.18'
# TODO: Point back at released omniauth-cas gem when PR merged gem 'omniauth-cas', '~> 3.0.0.beta.1'
# https://github.com/dlindahl/omniauth-cas/pull/68
gem 'omniauth-cas', github: 'stanhu/omniauth-cas', ref: '4211e6d05941b4a981f9a36b49ec166cecd0e271'
gem 'omniauth-saml', '~> 2.0' 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', '~> 2.0'
gem 'omniauth-rails_csrf_protection', '~> 1.0' gem 'omniauth-rails_csrf_protection', '~> 1.0'
gem 'color_diff', '~> 0.1' gem 'color_diff', '~> 0.1'
gem 'csv', '~> 3.2'
gem 'discard', '~> 1.2' gem 'discard', '~> 1.2'
gem 'doorkeeper', '~> 5.6' gem 'doorkeeper', '~> 5.6'
gem 'ed25519', '~> 1.3' gem 'ed25519', '~> 1.3'
@ -72,7 +74,6 @@ gem 'premailer-rails'
gem 'rack-attack', '~> 6.6' gem 'rack-attack', '~> 6.6'
gem 'rack-cors', '~> 2.0', require: 'rack/cors' gem 'rack-cors', '~> 2.0', require: 'rack/cors'
gem 'rails-i18n', '~> 7.0' gem 'rails-i18n', '~> 7.0'
gem 'rails-settings-cached', '~> 0.6', git: 'https://github.com/mastodon/rails-settings-cached.git', branch: 'v0.6.6-aliases-true'
gem 'redcarpet', '~> 3.6' gem 'redcarpet', '~> 3.6'
gem 'redis', '~> 4.5', require: ['redis', 'redis/connection/hiredis'] gem 'redis', '~> 4.5', require: ['redis', 'redis/connection/hiredis']
gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock' gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock'
@ -86,9 +87,8 @@ gem 'sidekiq-unique-jobs', '~> 7.1'
gem 'sidekiq-bulk', '~> 0.2.0' gem 'sidekiq-bulk', '~> 0.2.0'
gem 'simple-navigation', '~> 4.4' gem 'simple-navigation', '~> 4.4'
gem 'simple_form', '~> 5.2' gem 'simple_form', '~> 5.2'
gem 'sprockets-rails', '~> 3.4', require: 'sprockets/railtie'
gem 'stoplight', '~> 3.0.1' gem 'stoplight', '~> 3.0.1'
gem 'strong_migrations', '~> 0.8' gem 'strong_migrations', '1.7.0'
gem 'tty-prompt', '~> 0.23', require: false gem 'tty-prompt', '~> 0.23', require: false
gem 'twitter-text', '~> 3.1.0' gem 'twitter-text', '~> 3.1.0'
gem 'tzinfo-data', '~> 1.2023' gem 'tzinfo-data', '~> 1.2023'
@ -103,14 +103,17 @@ gem 'rdf-normalize', '~> 0.5'
gem 'private_address_check', '~> 0.5' gem 'private_address_check', '~> 0.5'
group :test do group :test do
# Used to split testing into chunks in CI # Adds RSpec Error/Warning annotations to GitHub PRs on the Files tab
gem 'rspec_chunked', '~> 0.6' gem 'rspec-github', '~> 2.4', require: false
# RSpec progress bar formatter # RSpec progress bar formatter
gem 'fuubar', '~> 2.5' gem 'fuubar', '~> 2.5'
# RSpec helpers for email specs
gem 'email_spec'
# Extra RSpec extenion methods and helpers for sidekiq # Extra RSpec extenion methods and helpers for sidekiq
gem 'rspec-sidekiq', '~> 3.1' gem 'rspec-sidekiq', '~> 4.0'
# Browser integration testing # Browser integration testing
gem 'capybara', '~> 3.39' gem 'capybara', '~> 3.39'
@ -120,13 +123,7 @@ group :test do
gem 'database_cleaner-active_record' gem 'database_cleaner-active_record'
# Used to mock environment variables # Used to mock environment variables
gem 'climate_control', '~> 0.2' gem 'climate_control'
# Generating fake data for specs
gem 'faker', '~> 3.2'
# Generate test objects for specs
gem 'fabrication', '~> 2.30'
# Add back helpers functions removed in Rails 5.1 # Add back helpers functions removed in Rails 5.1
gem 'rails-controller-testing', '~> 1.0' gem 'rails-controller-testing', '~> 1.0'
@ -139,6 +136,7 @@ group :test do
# Coverage formatter for RSpec test if DISABLE_SIMPLECOV is false # Coverage formatter for RSpec test if DISABLE_SIMPLECOV is false
gem 'simplecov', '~> 0.22', require: false gem 'simplecov', '~> 0.22', require: false
gem 'simplecov-lcov', '~> 0.8', require: false
# Stub web requests for specs # Stub web requests for specs
gem 'webmock', '~> 3.18' gem 'webmock', '~> 3.18'
@ -170,17 +168,20 @@ group :development do
# Linter CLI for HAML files # Linter CLI for HAML files
gem 'haml_lint', require: false gem 'haml_lint', require: false
# Deployment automation
gem 'capistrano', '~> 3.17'
gem 'capistrano-rails', '~> 1.6'
gem 'capistrano-rbenv', '~> 2.2'
gem 'capistrano-yarn', '~> 2.0'
# Validate missing i18n keys # Validate missing i18n keys
gem 'i18n-tasks', '~> 1.0', require: false gem 'i18n-tasks', '~> 1.0', require: false
end end
group :development, :test do group :development, :test do
# Interactive Debugging tools
gem 'debug', '~> 1.8'
# Generate fake data values
gem 'faker', '~> 3.2'
# Generate factory objects
gem 'fabrication', '~> 2.30'
# Profiling tools # Profiling tools
gem 'memory_profiler', require: false gem 'memory_profiler', require: false
gem 'ruby-prof', require: false gem 'ruby-prof', require: false
@ -200,7 +201,7 @@ gem 'connection_pool', require: false
gem 'xorcist', '~> 1.1' gem 'xorcist', '~> 1.1'
gem 'cocoon', '~> 1.2' gem 'cocoon', '~> 1.2'
gem 'net-http', '~> 0.3.2' gem 'net-http', '~> 0.4.0'
gem 'rubyzip', '~> 2.3' gem 'rubyzip', '~> 2.3'
gem 'hcaptcha', '~> 7.1' gem 'hcaptcha', '~> 7.1'

File diff suppressed because it is too large Load Diff

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 workspace @mastodon/streaming start
webpack: ./bin/webpack-dev-server --listen-host 0.0.0.0 webpack: bin/webpack-dev-server

View File

@ -59,21 +59,25 @@ Mastodon acts as an OAuth2 provider, so 3rd party apps can use the REST and Stre
## Deployment ## Deployment
### Tech stack: ### Tech stack
- **Ruby on Rails** powers the REST API and other web pages - **Ruby on Rails** powers the REST API and other web pages
- **React.js** and Redux are used for the dynamic parts of the interface - **React.js** and Redux are used for the dynamic parts of the interface
- **Node.js** powers the streaming API - **Node.js** powers the streaming API
### Requirements: ### Requirements
- **PostgreSQL** 9.5+ - **PostgreSQL** 12+
- **Redis** 4+ - **Redis** 4+
- **Ruby** 2.7+ - **Ruby** 2.7+
- **Node.js** 14+ - **Node.js** 16+
The repository includes deployment configurations for **Docker and docker-compose** as well as specific platforms like **Heroku**, **Scalingo**, and **Nanobox**. For Helm charts, reference the [mastodon/chart repository](https://github.com/mastodon/chart). The [**standalone** installation guide](https://docs.joinmastodon.org/admin/install/) is available in the documentation. The repository includes deployment configurations for **Docker and docker-compose** as well as specific platforms like **Heroku**, **Scalingo**, and **Nanobox**. For Helm charts, reference the [mastodon/chart repository](https://github.com/mastodon/chart). The [**standalone** installation guide](https://docs.joinmastodon.org/admin/install/) is available in the documentation.
## Development
### Vagrant
A **Vagrant** configuration is included for development purposes. To use it, complete the following steps: A **Vagrant** configuration is included for development purposes. To use it, complete the following steps:
- Install Vagrant and Virtualbox - Install Vagrant and Virtualbox
@ -82,27 +86,42 @@ A **Vagrant** configuration is included for development purposes. To use it, com
- Run `vagrant ssh -c "cd /vagrant && foreman start"` - Run `vagrant ssh -c "cd /vagrant && foreman start"`
- Open `http://mastodon.local` in your browser - Open `http://mastodon.local` in your browser
### MacOS
To set up **MacOS** for native development, complete the following steps: To set up **MacOS** for native development, complete the following steps:
- Install the latest stable Ruby version (use a ruby version manager for easy installation and management of ruby versions) - Install the latest stable Ruby version (use a Ruby version manager for easy installation and management of Ruby versions)
- Run `brew install postgresql@14` - Run `brew install postgresql@14`
- Run `brew install redis` - Run `brew install redis`
- Run `brew install imagemagick` - Run `brew install imagemagick`
- Run `brew install libidn`
- Install Foreman or a similar tool (such as [overmind](https://github.com/DarthSim/overmind)) to handle multiple process launching. - Install Foreman or a similar tool (such as [overmind](https://github.com/DarthSim/overmind)) to handle multiple process launching.
- Navigate to Mastodon's root directory and run `brew install nvm` then `nvm use` to use the version from .nvmrc - Navigate to Mastodon's root directory and run `brew install nvm` then `nvm use` to use the version from .nvmrc
- Run `corepack enable && yarn set version classic` - Run `corepack enable && corepack prepare`
- Run `bundle exec rails db:setup` (optionally prepend `RAILS_ENV=development` to target the dev environment) - Run `bundle exec rails db:setup` (optionally prepend `RAILS_ENV=development` to target the dev environment)
- Finally, run `overmind start -f Procfile.dev` - Finally, run `overmind start -f Procfile.dev`
### Getting Started with GitHub Codespaces ### Docker
To get started, create a codespace for this repository by clicking this 👇 For development with **Docker**, complete the following steps:
[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://github.com/codespaces/new?hide_repo_select=true&ref=main&repo=52281283) - Install Docker Desktop
- Run `docker compose -f .devcontainer/docker-compose.yml up -d`
- Run `docker compose -f .devcontainer/docker-compose.yml exec app .devcontainer/post-create.sh`
- Finally, run `docker compose -f .devcontainer/docker-compose.yml exec app foreman start -f Procfile.dev`
A codespace will open in a web-based version of Visual Studio Code. The [dev container](.devcontainer/devcontainer.json) is fully configured with the software needed for this project. If you are using an IDE with [support for the Development Container specification](https://containers.dev/supporting), it will run the above `docker compose` commands automatically. For **Visual Studio Code** this requires the [Dev Container extension](https://containers.dev/supporting#dev-containers).
**Note**: Dev containers are an open spec that is supported by [GitHub Codespaces](https://github.com/codespaces) and [other tools](https://containers.dev/supporting). ### GitHub Codespaces
To get you coding in just a few minutes, GitHub Codespaces provides a web-based version of Visual Studio Code and a cloud-hosted development environment fully configured with the software needed for this project..
- Click this button to create a new codespace:<br>
[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://github.com/codespaces/new?hide_repo_select=true&ref=main&repo=52281283&devcontainer_path=.devcontainer%2Fcodespaces%2Fdevcontainer.json)
- Wait for the environment to build. This will take a few minutes.
- When the editor is ready, run `foreman start -f Procfile.dev` in the terminal.
- After a few seconds, a popup will appear with a button labeled _Open in Browser_. This will open Mastodon.
- On the _Ports_ tab, right click on the “stream” row and select _Port visibility__Public_.
## Contributing ## Contributing
@ -114,7 +133,7 @@ You can open issues for bugs you've found or features you think are missing. You
## License ## License
Copyright (C) 2016-2022 Eugen Rochko & other Mastodon contributors (see [AUTHORS.md](AUTHORS.md)) Copyright (C) 2016-2024 Eugen Rochko & other Mastodon contributors (see [AUTHORS.md](AUTHORS.md))
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

View File

@ -1,8 +1,11 @@
# 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 reach us at <security@joinmastodon.org>. If you believe you've identified a security vulnerability in Mastodon (a bug that allows something to happen that shouldn't be possible), you can either:
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. - open a [Github security issue on the Mastodon project](https://github.com/mastodon/mastodon/security/advisories/new)
- 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
@ -12,7 +15,6 @@ A "vulnerability in Mastodon" is a vulnerability in the code distributed through
| Version | Supported | | Version | Supported |
| ------- | --------- | | ------- | --------- |
| 4.2.x | Yes |
| 4.1.x | Yes | | 4.1.x | Yes |
| 4.0.x | Yes | | < 4.1 | No |
| 3.5.x | Yes |
| < 3.5 | No |

54
Vagrantfile vendored
View File

@ -10,7 +10,11 @@ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
sudo apt-add-repository 'deb https://dl.yarnpkg.com/debian/ stable main' sudo apt-add-repository 'deb https://dl.yarnpkg.com/debian/ stable main'
# Add repo for NodeJS # Add repo for NodeJS
curl -sL https://deb.nodesource.com/setup_16.x | sudo bash - sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
NODE_MAJOR=20
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list
sudo apt-get update
# Add firewall rule to redirect 80 to PORT and save # Add firewall rule to redirect 80 to PORT and save
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port #{ENV["PORT"]} sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port #{ENV["PORT"]}
@ -60,6 +64,38 @@ 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"
@ -80,11 +116,11 @@ bundle install
# Install node modules # Install node modules
sudo corepack enable sudo corepack enable
yarn set version classic corepack prepare
yarn install yarn install
# Build Mastodon # Build Mastodon
export RAILS_ENV=development export RAILS_ENV=development
export $(cat ".env.vagrant" | xargs) export $(cat ".env.vagrant" | xargs)
bundle exec rails db:setup bundle exec rails db:setup
@ -102,10 +138,8 @@ 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", "2048"] vb.customize ["modifyvm", :id, "--memory", "8192"]
# Increase the number of CPUs. Uncomment and adjust to vb.customize ["modifyvm", :id, "--cpus", "3"]
# 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
@ -141,9 +175,15 @@ 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,6 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
class AccountsIndex < Chewy::Index class AccountsIndex < Chewy::Index
include DatetimeClampingConcern
settings index: index_preset(refresh_interval: '30s'), analysis: { settings index: index_preset(refresh_interval: '30s'), analysis: {
filter: { filter: {
english_stop: { english_stop: {
@ -21,12 +23,13 @@ class AccountsIndex < Chewy::Index
analyzer: { analyzer: {
natural: { natural: {
tokenizer: 'uax_url_email', tokenizer: 'standard',
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
), ),
@ -59,9 +62,9 @@ class AccountsIndex < Chewy::Index
field(:following_count, type: 'long') field(:following_count, type: 'long')
field(:followers_count, type: 'long') field(:followers_count, type: 'long')
field(:properties, type: 'keyword', value: ->(account) { account.searchable_properties }) field(:properties, type: 'keyword', value: ->(account) { account.searchable_properties })
field(:last_status_at, type: 'date', value: ->(account) { account.last_status_at || account.created_at }) field(:last_status_at, type: 'date', value: ->(account) { clamp_date(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', value: ->(account) { account.searchable_text }) { field :stemmed, type: 'text', analyzer: 'natural' } field(:text, type: 'text', analyzer: 'verbatim', value: ->(account) { account.searchable_text }) { field :stemmed, type: 'text', analyzer: 'natural' }
end end
end end

View File

@ -0,0 +1,14 @@
# frozen_string_literal: true
module DatetimeClampingConcern
extend ActiveSupport::Concern
MIN_ISO8601_DATETIME = '0000-01-01T00:00:00Z'.to_datetime.freeze
MAX_ISO8601_DATETIME = '9999-12-31T23:59:59Z'.to_datetime.freeze
class_methods do
def clamp_date(datetime)
datetime.clamp(MIN_ISO8601_DATETIME, MAX_ISO8601_DATETIME)
end
end
end

View File

@ -6,7 +6,7 @@ class InstancesIndex < Chewy::Index
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 } field :domain, type: 'text', index_prefixes: { min_chars: 1, max_chars: 5 }
field :accounts_count, type: 'long' field :accounts_count, type: 'long'
end end
end end

View File

@ -0,0 +1,69 @@
# frozen_string_literal: true
class PublicStatusesIndex < Chewy::Index
include DatetimeClampingConcern
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, :tags, preview_cards_status: :preview_card)
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', value: ->(status) { clamp_date(status.created_at) })
end
end

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
class StatusesIndex < Chewy::Index class StatusesIndex < Chewy::Index
include FormattingHelper include DatetimeClampingConcern
settings index: index_preset(refresh_interval: '30s', number_of_shards: 5), analysis: { settings index: index_preset(refresh_interval: '30s', number_of_shards: 5), analysis: {
filter: { filter: {
@ -9,67 +9,59 @@ class StatusesIndex < Chewy::Index
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: {
content: { verbatim: {
tokenizer: 'uax_url_email', tokenizer: 'uax_url_email',
filter: %w(lowercase),
},
content: {
tokenizer: 'standard',
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
),
},
}, },
} }
# We do not use delete_if option here because it would call a method that we index_scope ::Status.unscoped.kept.without_reblogs.includes(:media_attachments, :local_mentioned, :local_favorited, :local_reblogged, :local_bookmarked, :tags, preview_cards_status: :preview_card, preloadable_poll: :local_voters), delete_if: ->(status) { status.searchable_by.empty? }
# 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 :text, type: 'text', value: ->(status) { status.searchable_text } do field(:tags, type: 'text', analyzer: 'hashtag', value: ->(status) { status.tags.map(&:display_name) })
field :stemmed, type: 'text', analyzer: 'content' field(:searchable_by, type: 'long', value: ->(status) { status.searchable_by })
end field(:language, type: 'keyword')
field(:properties, type: 'keyword', value: ->(status) { status.searchable_properties })
field :searchable_by, type: 'long', value: ->(status, crutches) { status.searchable_by(crutches) } field(:created_at, type: 'date', value: ->(status) { clamp_date(status.created_at) })
end end
end end

View File

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

@ -5,15 +5,7 @@ class AboutController < ApplicationController
skip_before_action :require_functional! skip_before_action :require_functional!
before_action :set_instance_presenter
def show def show
expires_in(15.seconds, public: true, stale_while_revalidate: 30.seconds, stale_if_error: 1.day) unless user_signed_in? expires_in(15.seconds, public: true, stale_while_revalidate: 30.seconds, stale_if_error: 1.day) unless user_signed_in?
end end
private
def set_instance_presenter
@instance_presenter = InstancePresenter.new
end
end end

View File

@ -18,8 +18,6 @@ class AccountsController < ApplicationController
respond_to do |format| respond_to do |format|
format.html do format.html do
expires_in(15.seconds, public: true, stale_while_revalidate: 30.seconds, stale_if_error: 1.hour) unless user_signed_in? expires_in(15.seconds, public: true, stale_while_revalidate: 30.seconds, stale_if_error: 1.hour) unless user_signed_in?
@rss_url = rss_url
end end
format.rss do format.rss do
@ -52,7 +50,7 @@ class AccountsController < ApplicationController
end end
def only_media_scope def only_media_scope
Status.joins(:media_attachments).merge(@account.media_attachments.reorder(nil)).group(:id) Status.joins(:media_attachments).merge(@account.media_attachments).group(:id)
end end
def no_replies_scope def no_replies_scope
@ -84,29 +82,21 @@ class AccountsController < ApplicationController
short_account_url(@account, format: 'rss') short_account_url(@account, format: 'rss')
end end
end end
helper_method :rss_url
def media_requested? def media_requested?
request.path.split('.').first.end_with?('/media') && !tag_requested? path_without_format.end_with?('/media') && !tag_requested?
end end
def replies_requested? def replies_requested?
request.path.split('.').first.end_with?('/with_replies') && !tag_requested? path_without_format.end_with?('/with_replies') && !tag_requested?
end end
def tag_requested? def tag_requested?
request.path.split('.').first.end_with?(Addressable::URI.parse("/tagged/#{params[:tag]}").normalize) path_without_format.end_with?(Addressable::URI.parse("/tagged/#{params[:tag]}").normalize)
end end
def cached_filtered_status_page def path_without_format
cache_collection_paginated_by_id( request.path.split('.').first
filtered_statuses,
Status,
PAGE_SIZE,
params_slice(:max_id, :min_id, :since_id)
)
end
def params_slice(*keys)
params.slice(*keys).permit(*keys)
end end
end end

View File

@ -24,7 +24,7 @@ class ActivityPub::FollowersSynchronizationsController < ActivityPub::BaseContro
end end
def set_items def set_items
@items = @account.followers.where(Account.arel_table[:uri].matches("#{Account.sanitize_sql_like(uri_prefix)}/%", false, true)).or(@account.followers.where(uri: uri_prefix)).pluck(:uri) @items = @account.followers.matches_uri_prefix(uri_prefix).pluck(:uri)
end end
def collection_presenter def collection_presenter

View File

@ -24,7 +24,7 @@ class ActivityPub::InboxesController < ActivityPub::BaseController
def unknown_affected_account? def unknown_affected_account?
json = Oj.load(body, mode: :strict) json = Oj.load(body, mode: :strict)
json.is_a?(Hash) && %w(Delete Update).include?(json['type']) && json['actor'].present? && json['actor'] == value_or_id(json['object']) && !Account.where(uri: json['actor']).exists? json.is_a?(Hash) && %w(Delete Update).include?(json['type']) && json['actor'].present? && json['actor'] == value_or_id(json['object']) && !Account.exists?(uri: json['actor'])
rescue Oj::ParseError rescue Oj::ParseError
false false
end end

View File

@ -21,7 +21,7 @@ module Admin
account_action.save! account_action.save!
if account_action.with_report? if account_action.with_report?
redirect_to admin_reports_path, notice: I18n.t('admin.reports.processed_msg', id: params[:report_id]) redirect_to admin_reports_path, notice: I18n.t('admin.reports.processed_msg', id: resource_params[:report_id])
else else
redirect_to admin_account_path(@account.id) redirect_to admin_account_path(@account.id)
end end

View File

@ -16,7 +16,7 @@ module Admin
@moderation_notes = @account.targeted_moderation_notes.latest @moderation_notes = @account.targeted_moderation_notes.latest
@warnings = @account.strikes.custom.latest @warnings = @account.strikes.custom.latest
render template: 'admin/accounts/show' render 'admin/accounts/show'
end end
end end

View File

@ -6,7 +6,7 @@ module Admin
def index def index
authorize :audit_log, :index? authorize :audit_log, :index?
@auditable_accounts = Account.where(id: Admin::ActionLog.reorder(nil).select('distinct account_id')).select(:id, :username) @auditable_accounts = Account.auditable.select(:id, :username)
end end
private private

View File

@ -3,11 +3,11 @@
module Admin module Admin
class ConfirmationsController < BaseController class ConfirmationsController < BaseController
before_action :set_user before_action :set_user
before_action :check_confirmation, only: [:resend] before_action :redirect_confirmed_user, only: [:resend], if: :user_confirmed?
def create def create
authorize @user, :confirm? authorize @user, :confirm?
@user.confirm! @user.mark_email_as_confirmed!
log_action :confirm, @user log_action :confirm, @user
redirect_to admin_accounts_path redirect_to admin_accounts_path
end end
@ -25,11 +25,13 @@ module Admin
private private
def check_confirmation def redirect_confirmed_user
if @user.confirmed? flash[:error] = I18n.t('admin.accounts.resend_confirmation.already_confirmed')
flash[:error] = I18n.t('admin.accounts.resend_confirmation.already_confirmed') redirect_to admin_accounts_path
redirect_to admin_accounts_path end
end
def user_confirmed?
@user.confirmed?
end end
end end
end end

View File

@ -20,7 +20,7 @@ class Admin::Disputes::AppealsController < Admin::BaseController
authorize @appeal, :approve? authorize @appeal, :approve?
log_action :reject, @appeal log_action :reject, @appeal
@appeal.reject!(current_account) @appeal.reject!(current_account)
UserMailer.appeal_rejected(@appeal.account.user, @appeal) UserMailer.appeal_rejected(@appeal.account.user, @appeal).deliver_later
redirect_to disputes_strike_path(@appeal.strike) redirect_to disputes_strike_path(@appeal.strike)
end end

View File

@ -33,7 +33,7 @@ module Admin
# Disallow accidentally downgrading a domain block # Disallow accidentally downgrading a domain block
if existing_domain_block.present? && !@domain_block.stricter_than?(existing_domain_block) if existing_domain_block.present? && !@domain_block.stricter_than?(existing_domain_block)
@domain_block.save @domain_block.validate
flash.now[:alert] = I18n.t('admin.domain_blocks.existing_domain_block_html', name: existing_domain_block.domain, unblock_url: admin_domain_block_path(existing_domain_block)).html_safe flash.now[:alert] = I18n.t('admin.domain_blocks.existing_domain_block_html', name: existing_domain_block.domain, unblock_url: admin_domain_block_path(existing_domain_block)).html_safe
@domain_block.errors.delete(:domain) @domain_block.errors.delete(:domain)
return render :new return render :new

View File

@ -38,9 +38,9 @@ module Admin
log_action :create, @email_domain_block log_action :create, @email_domain_block
(@email_domain_block.other_domains || []).uniq.each do |domain| (@email_domain_block.other_domains || []).uniq.each do |domain|
next if EmailDomainBlock.where(domain: domain).exists? next if EmailDomainBlock.exists?(domain: domain)
other_email_domain_block = EmailDomainBlock.create!(domain: domain, parent: @email_domain_block) other_email_domain_block = EmailDomainBlock.create!(domain: domain, allow_with_approval: @email_domain_block.allow_with_approval, parent: @email_domain_block)
log_action :create, other_email_domain_block log_action :create, other_email_domain_block
end end
end end
@ -65,7 +65,7 @@ module Admin
end end
def resource_params def resource_params
params.require(:email_domain_block).permit(:domain, other_domains: []) params.require(:email_domain_block).permit(:domain, :allow_with_approval, other_domains: [])
end end
def form_email_domain_block_batch_params def form_email_domain_block_batch_params

View File

@ -4,7 +4,7 @@ require 'csv'
module Admin module Admin
class ExportDomainAllowsController < BaseController class ExportDomainAllowsController < BaseController
include AdminExportControllerConcern include Admin::ExportControllerConcern
before_action :set_dummy_import!, only: [:new] before_action :set_dummy_import!, only: [:new]

View File

@ -4,7 +4,7 @@ require 'csv'
module Admin module Admin
class ExportDomainBlocksController < BaseController class ExportDomainBlocksController < BaseController
include AdminExportControllerConcern include Admin::ExportControllerConcern
before_action :set_dummy_import!, only: [:new] before_action :set_dummy_import!, only: [:new]
@ -49,7 +49,7 @@ module Admin
next next
end end
@warning_domains = Instance.where(domain: @domain_blocks.map(&:domain)).where('EXISTS (SELECT 1 FROM follows JOIN accounts ON follows.account_id = accounts.id OR follows.target_account_id = accounts.id WHERE accounts.domain = instances.domain)').pluck(:domain) @warning_domains = instances_from_imported_blocks.pluck(:domain)
rescue ActionController::ParameterMissing rescue ActionController::ParameterMissing
flash.now[:alert] = I18n.t('admin.export_domain_blocks.no_file') flash.now[:alert] = I18n.t('admin.export_domain_blocks.no_file')
set_dummy_import! set_dummy_import!
@ -58,6 +58,10 @@ module Admin
private private
def instances_from_imported_blocks
Instance.with_domain_follows(@domain_blocks.map(&:domain))
end
def export_filename def export_filename
'domain_blocks.csv' 'domain_blocks.csv'
end end
@ -68,7 +72,7 @@ module Admin
def export_data def export_data
CSV.generate(headers: export_headers, write_headers: true) do |content| CSV.generate(headers: export_headers, write_headers: true) do |content|
DomainBlock.with_limitations.each do |instance| DomainBlock.with_limitations.order(id: :asc).each do |instance|
content << [instance.domain, instance.severity, instance.reject_media, instance.reject_reports, instance.public_comment, instance.obfuscate] content << [instance.domain, instance.severity, instance.reject_media, instance.reject_reports, instance.public_comment, instance.obfuscate]
end end
end end

View File

@ -8,7 +8,7 @@ module Admin
authorize :follow_recommendation, :show? authorize :follow_recommendation, :show?
@form = Form::AccountBatch.new @form = Form::AccountBatch.new
@accounts = filtered_follow_recommendations @accounts = filtered_follow_recommendations.page(params[:page])
end end
def update def update

View File

@ -49,7 +49,7 @@ module Admin
private private
def set_instance def set_instance
@instance = Instance.find(TagManager.instance.normalize_domain(params[:id]&.strip)) @instance = Instance.find_or_initialize_by(domain: TagManager.instance.normalize_domain(params[:id]&.strip))
end end
def set_instances def set_instances

View File

@ -24,7 +24,7 @@ module Admin
@relay.enable! @relay.enable!
redirect_to admin_relays_path redirect_to admin_relays_path
else else
render action: :new render :new
end end
end end

View File

@ -26,7 +26,7 @@ module Admin
@form = Admin::StatusBatchAction.new @form = Admin::StatusBatchAction.new
@statuses = @report.statuses.with_includes @statuses = @report.statuses.with_includes
render template: 'admin/reports/show' render 'admin/reports/show'
end end
end end

View File

@ -0,0 +1,18 @@
# 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

@ -31,6 +31,11 @@ module Admin
private private
def batched_ordered_status_edits
@status.edits.includes(:account, status: [:account]).find_each(order: :asc)
end
helper_method :batched_ordered_status_edits
def admin_status_batch_action_params def admin_status_batch_action_params
params.require(:admin_status_batch_action).permit(status_ids: []) params.require(:admin_status_batch_action).permit(status_ids: [])
end end

View File

@ -4,9 +4,10 @@ class Api::BaseController < ApplicationController
DEFAULT_STATUSES_LIMIT = 20 DEFAULT_STATUSES_LIMIT = 20
DEFAULT_ACCOUNTS_LIMIT = 40 DEFAULT_ACCOUNTS_LIMIT = 40
include RateLimitHeaders include Api::RateLimitHeaders
include AccessTokenTrackingConcern include Api::AccessTokenTrackingConcern
include ApiCachingConcern include Api::CachingConcern
include Api::ContentSecurityPolicy
skip_before_action :require_functional!, unless: :limited_federation_mode? skip_before_action :require_functional!, unless: :limited_federation_mode?
@ -17,26 +18,6 @@ class Api::BaseController < ApplicationController
protect_from_forgery with: :null_session protect_from_forgery with: :null_session
content_security_policy do |p|
# Set every directive that does not have a fallback
p.default_src :none
p.frame_ancestors :none
p.form_action :none
# Disable every directive with a fallback to cut on response size
p.base_uri false
p.font_src false
p.img_src false
p.style_src false
p.media_src false
p.frame_src false
p.manifest_src false
p.connect_src false
p.script_src false
p.child_src false
p.worker_src false
end
rescue_from ActiveRecord::RecordInvalid, Mastodon::ValidationError do |e| rescue_from ActiveRecord::RecordInvalid, Mastodon::ValidationError do |e|
render json: { error: e.to_s }, status: 422 render json: { error: e.to_s }, status: 422
end end
@ -83,7 +64,7 @@ class Api::BaseController < ApplicationController
end end
def doorkeeper_unauthorized_render_options(error: nil) def doorkeeper_unauthorized_render_options(error: nil)
{ json: { error: (error.try(:description) || 'Not authorized') } } { json: { error: error.try(:description) || 'Not authorized' } }
end end
def doorkeeper_forbidden_render_options(*) def doorkeeper_forbidden_render_options(*)
@ -124,7 +105,11 @@ class Api::BaseController < ApplicationController
end end
def require_not_suspended! def require_not_suspended!
render json: { error: 'Your login is currently disabled' }, status: 403 if current_user&.account&.suspended? render json: { error: 'Your login is currently disabled' }, status: 403 if current_user&.account&.unavailable?
end
def require_valid_pagination_options!
render json: { error: 'Pagination values for `offset` and `limit` must be positive' }, status: 400 if pagination_options_invalid?
end end
def require_user! def require_user!
@ -155,6 +140,10 @@ class Api::BaseController < ApplicationController
private private
def pagination_options_invalid?
params.slice(:limit, :offset).values.map(&:to_i).any?(&:negative?)
end
def respond_with_error(code) def respond_with_error(code)
render json: { error: Rack::Utils::HTTP_STATUS_CODES[code] }, status: code render json: { error: Rack::Utils::HTTP_STATUS_CODES[code] }, status: code
end end

View File

@ -16,6 +16,8 @@ class Api::V1::Accounts::CredentialsController < Api::BaseController
current_user.update(user_params) if user_params current_user.update(user_params) if user_params
ActivityPub::UpdateDistributionWorker.perform_async(@account.id) ActivityPub::UpdateDistributionWorker.perform_async(@account.id)
render json: @account, serializer: REST::CredentialAccountSerializer render json: @account, serializer: REST::CredentialAccountSerializer
rescue ActiveRecord::RecordInvalid => e
render json: ValidationErrorFormatter.new(e).as_json, status: 422
end end
private private
@ -30,6 +32,7 @@ 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

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

View File

@ -21,16 +21,16 @@ class Api::V1::Accounts::FollowerAccountsController < Api::BaseController
return [] if hide_results? return [] if hide_results?
scope = default_accounts scope = default_accounts
scope = scope.where.not(id: current_account.excluded_from_timeline_account_ids) unless current_account.nil? || current_account.id == @account.id scope = scope.not_excluded_by_account(current_account) unless current_account.nil? || current_account.id == @account.id
scope.merge(paginated_follows).to_a scope.merge(paginated_follows).to_a
end end
def hide_results? def hide_results?
@account.suspended? || (@account.hides_followers? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account)) @account.unavailable? || (@account.hides_followers? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account))
end end
def default_accounts def default_accounts
Account.includes(:active_relationships, :account_stat).references(:active_relationships) Account.includes(:active_relationships, :account_stat, :user).references(:active_relationships)
end end
def paginated_follows def paginated_follows

View File

@ -21,16 +21,16 @@ class Api::V1::Accounts::FollowingAccountsController < Api::BaseController
return [] if hide_results? return [] if hide_results?
scope = default_accounts scope = default_accounts
scope = scope.where.not(id: current_account.excluded_from_timeline_account_ids) unless current_account.nil? || current_account.id == @account.id scope = scope.not_excluded_by_account(current_account) unless current_account.nil? || current_account.id == @account.id
scope.merge(paginated_follows).to_a scope.merge(paginated_follows).to_a
end end
def hide_results? def hide_results?
@account.suspended? || (@account.hides_following? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account)) @account.unavailable? || (@account.hides_following? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account))
end end
def default_accounts def default_accounts
Account.includes(:passive_relationships, :account_stat).references(:passive_relationships) Account.includes(:passive_relationships, :account_stat, :user).references(:passive_relationships)
end end
def paginated_follows def paginated_follows

View File

@ -25,6 +25,6 @@ class Api::V1::Accounts::NotesController < Api::BaseController
end end
def relationships_presenter def relationships_presenter
AccountRelationshipsPresenter.new([@account.id], current_user.account_id) AccountRelationshipsPresenter.new([@account], current_user.account_id)
end end
end end

View File

@ -25,6 +25,6 @@ class Api::V1::Accounts::PinsController < Api::BaseController
end end
def relationships_presenter def relationships_presenter
AccountRelationshipsPresenter.new([@account.id], current_user.account_id) AccountRelationshipsPresenter.new([@account], current_user.account_id)
end end
end end

View File

@ -5,10 +5,8 @@ class Api::V1::Accounts::RelationshipsController < Api::BaseController
before_action :require_user! before_action :require_user!
def index def index
accounts = Account.without_suspended.where(id: account_ids).select('id') @accounts = Account.where(id: account_ids).select(:id, :domain)
# .where doesn't guarantee that our results are in the same order @accounts.merge!(Account.without_suspended) unless truthy_param?(:with_suspended)
# we requested them, so return the "right" order to the requestor.
@accounts = accounts.index_by(&:id).values_at(*account_ids).compact
render json: @accounts, each_serializer: REST::RelationshipSerializer, relationships: relationships render json: @accounts, each_serializer: REST::RelationshipSerializer, relationships: relationships
end end

View File

@ -19,7 +19,7 @@ class Api::V1::Accounts::StatusesController < Api::BaseController
end end
def load_statuses def load_statuses
@account.suspended? ? [] : cached_account_statuses @account.unavailable? ? [] : cached_account_statuses
end end
def cached_account_statuses def cached_account_statuses

View File

@ -1,6 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::AccountsController < Api::BaseController class Api::V1::AccountsController < Api::BaseController
include RegistrationHelper
before_action -> { authorize_if_got_token! :read, :'read:accounts' }, except: [:create, :follow, :unfollow, :remove_from_followers, :block, :unblock, :mute, :unmute] before_action -> { authorize_if_got_token! :read, :'read:accounts' }, except: [:create, :follow, :unfollow, :remove_from_followers, :block, :unblock, :mute, :unmute]
before_action -> { doorkeeper_authorize! :follow, :write, :'write:follows' }, only: [:follow, :unfollow, :remove_from_followers] before_action -> { doorkeeper_authorize! :follow, :write, :'write:follows' }, only: [:follow, :unfollow, :remove_from_followers]
before_action -> { doorkeeper_authorize! :follow, :write, :'write:mutes' }, only: [:mute, :unmute] before_action -> { doorkeeper_authorize! :follow, :write, :'write:mutes' }, only: [:mute, :unmute]
@ -47,7 +49,7 @@ class Api::V1::AccountsController < Api::BaseController
end end
def mute def mute
MuteService.new.call(current_user.account, @account, notifications: truthy_param?(:notifications), duration: (params[:duration]&.to_i || 0)) MuteService.new.call(current_user.account, @account, notifications: truthy_param?(:notifications), duration: params[:duration].to_i)
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
end end
@ -86,22 +88,18 @@ class Api::V1::AccountsController < Api::BaseController
end end
def relationships(**options) def relationships(**options)
AccountRelationshipsPresenter.new([@account.id], current_user.account_id, **options) AccountRelationshipsPresenter.new([@account], current_user.account_id, **options)
end end
def account_params def account_params
params.permit(:username, :email, :password, :agreement, :locale, :reason, :time_zone) params.permit(:username, :email, :password, :agreement, :locale, :reason, :time_zone, :invite_code)
end
def invite
Invite.find_by(code: params[:invite_code]) if params[:invite_code].present?
end end
def check_enabled_registrations def check_enabled_registrations
forbidden if single_user_mode? || omniauth_only? || !allowed_registrations? forbidden unless allowed_registration?(request.remote_ip, invite)
end
def allowed_registrations?
Setting.registrations_mode != 'none'
end
def omniauth_only?
ENV['OMNIAUTH_ONLY'] == 'true'
end end
end end

View File

@ -55,7 +55,7 @@ class Api::V1::Admin::EmailDomainBlocksController < Api::BaseController
end end
def resource_params def resource_params
params.permit(:domain) params.permit(:domain, :allow_with_approval)
end end
def insert_pagination_headers def insert_pagination_headers

View File

@ -0,0 +1,74 @@
# 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

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