th: Merge remote-tracking branch 'glitch/main' (915cd36ac1)
				
					
				
			This commit is contained in:
		
						commit
						27f74617cc
					
				
					 2146 changed files with 42161 additions and 25152 deletions
				
			
		
							
								
								
									
										6
									
								
								.bundler-audit.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.bundler-audit.yml
									
									
									
									
									
										Normal 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 | ||||
|  | @ -4,7 +4,7 @@ FROM mcr.microsoft.com/devcontainers/ruby:1-3.2-bullseye | |||
| # Install Rails | ||||
| # RUN gem install rails webdrivers | ||||
| 
 | ||||
| ARG NODE_VERSION="16" | ||||
| ARG NODE_VERSION="20" | ||||
| 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. | ||||
|  | @ -15,6 +15,6 @@ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ | |||
| RUN gem install foreman | ||||
| 
 | ||||
| # [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 | ||||
|  |  | |||
|  | @ -70,7 +70,7 @@ services: | |||
|         hard: -1 | ||||
| 
 | ||||
|   libretranslate: | ||||
|     image: libretranslate/libretranslate:v1.3.12 | ||||
|     image: libretranslate/libretranslate:v1.5.4 | ||||
|     restart: unless-stopped | ||||
|     volumes: | ||||
|       - lt-data:/home/libretranslate/.local | ||||
|  |  | |||
|  | @ -11,7 +11,8 @@ bundle install | |||
| git checkout -- Gemfile.lock | ||||
| 
 | ||||
| # Fetch Javascript dependencies | ||||
| yarn --frozen-lockfile | ||||
| corepack prepare | ||||
| yarn install --immutable | ||||
| 
 | ||||
| # [re]create, migrate, and seed the test database | ||||
| 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 | ||||
| 
 | ||||
| # Precompile assets for test | ||||
| RAILS_ENV=test NODE_ENV=tests ./bin/rails assets:precompile | ||||
| RAILS_ENV=test ./bin/rails assets:precompile | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ | |||
| 
 | ||||
| # Order-independent | ||||
| *.sw* | ||||
| *.swp | ||||
| *~ | ||||
| .DS_Store | ||||
| .bundle | ||||
|  | @ -26,7 +27,9 @@ elasticsearch | |||
| log | ||||
| neo4j | ||||
| node_modules | ||||
| postgres | ||||
| postgres* | ||||
| postgres14 | ||||
| public/assets | ||||
| public/packs | ||||
| public/packs-test | ||||
|  |  | |||
|  | @ -4,6 +4,6 @@ ALTERNATE_DOMAINS=mastodon.internal | |||
| DB_HOST=$PWD/data/postgres | ||||
| DB_USER=mastodon | ||||
| DB_NAME=mastodon_dev | ||||
| REDIS_URL=./data/redis/redis-dev.sock | ||||
| REDIS_URL=unix://$PWD/data/redis/redis-dev.sock | ||||
| 
 | ||||
| TH_USE_INVITE_QUOTA=1 | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| # Node.js | ||||
| NODE_ENV=tests | ||||
| # In test, compile the NodeJS code as if we are in production | ||||
| NODE_ENV=production | ||||
| # Federation | ||||
| LOCAL_DOMAIN=cb6e6126.ngrok.io | ||||
| LOCAL_HTTPS=true | ||||
|  |  | |||
							
								
								
									
										34
									
								
								.eslintrc.js
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								.eslintrc.js
									
									
									
									
									
								
							|  | @ -1,4 +1,7 @@ | |||
| module.exports = { | ||||
| // @ts-check
 | ||||
| const { defineConfig } = require('eslint-define-config'); | ||||
| 
 | ||||
| module.exports = defineConfig({ | ||||
|   root: true, | ||||
| 
 | ||||
|   extends: [ | ||||
|  | @ -117,7 +120,6 @@ module.exports = { | |||
|     'react/jsx-uses-react': 'off', // not needed with new JSX transform
 | ||||
|     'react/jsx-wrap-multilines': 'error', | ||||
|     'react/no-deprecated': 'off', | ||||
|     'react/no-unknown-property': 'off', | ||||
|     'react/react-in-jsx-scope': 'off', // not needed with new JSX transform
 | ||||
|     'react/self-closing-comp': 'error', | ||||
| 
 | ||||
|  | @ -193,6 +195,7 @@ module.exports = { | |||
|       'error', | ||||
|       { | ||||
|         devDependencies: [ | ||||
|           '.eslintrc.js', | ||||
|           'config/webpack/**', | ||||
|           'app/javascript/mastodon/performance.js', | ||||
|           'app/javascript/mastodon/test_setup.js', | ||||
|  | @ -242,7 +245,7 @@ module.exports = { | |||
|           }, | ||||
|           // 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', | ||||
|             position: 'before', | ||||
|           }, | ||||
|  | @ -297,7 +300,6 @@ module.exports = { | |||
|     'formatjs/no-id': 'off', // IDs are used for translation keys
 | ||||
|     '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-multiple-plurals': 'off', // Only used by hashtag.jsx
 | ||||
|     'formatjs/no-multiple-whitespaces': 'error', | ||||
|     'formatjs/no-offset': 'error', | ||||
|     'formatjs/no-useless-message': 'error', | ||||
|  | @ -316,6 +318,7 @@ module.exports = { | |||
|   overrides: [ | ||||
|     { | ||||
|       files: [ | ||||
|         '.eslintrc.js', | ||||
|         '*.config.js', | ||||
|         '.*rc.js', | ||||
|         'ide-helper.js', | ||||
|  | @ -366,8 +369,15 @@ module.exports = { | |||
|         '@typescript-eslint/consistent-type-definitions': ['warn', 'interface'], | ||||
|         '@typescript-eslint/consistent-type-exports': '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', | ||||
| 
 | ||||
|         // Those rules set stricter rules for TS files
 | ||||
|  | @ -389,14 +399,6 @@ module.exports = { | |||
|       env: { | ||||
|         jest: true, | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       files: [ | ||||
|         'streaming/**/*', | ||||
|       ], | ||||
|       rules: { | ||||
|         'import/no-commonjs': 'off', | ||||
|       }, | ||||
|     }, | ||||
|     } | ||||
|   ], | ||||
| }; | ||||
| }); | ||||
|  |  | |||
							
								
								
									
										29
									
								
								.github/actions/setup-javascript/action.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										29
									
								
								.github/actions/setup-javascript/action.yml
									
									
									
									
										vendored
									
									
								
							|  | @ -9,11 +9,34 @@ runs: | |||
|   using: 'composite' | ||||
|   steps: | ||||
|     - name: Set up Node.js | ||||
|       uses: actions/setup-node@v3 | ||||
|       uses: actions/setup-node@v4 | ||||
|       with: | ||||
|         cache: yarn | ||||
|         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@v3 | ||||
|       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 --frozen-lockfile ${{ inputs.onlyProduction != 'false' && '--production' || '' }} | ||||
|       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' | ||||
|  |  | |||
							
								
								
									
										13
									
								
								.github/codecov.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								.github/codecov.yml
									
									
									
									
										vendored
									
									
										Normal 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 | ||||
							
								
								
									
										13
									
								
								.github/renovate.json5
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								.github/renovate.json5
									
									
									
									
										vendored
									
									
								
							|  | @ -12,6 +12,7 @@ | |||
|   // 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. | ||||
|   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: [ | ||||
|     { | ||||
|       // Require Dependency Dashboard Approval for major version bumps of these node packages | ||||
|  | @ -21,6 +22,7 @@ | |||
|         'react-hotkeys', // Requires code changes | ||||
| 
 | ||||
|         // Requires Webpacker upgrade or replacement | ||||
|         '@svgr/webpack', | ||||
|         '@types/webpack', | ||||
|         'babel-loader', | ||||
|         'compression-webpack-plugin', | ||||
|  | @ -48,7 +50,6 @@ | |||
|       matchManagers: ['bundler'], | ||||
|       matchPackageNames: [ | ||||
|         '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 | ||||
|         'sidekiq', // Requires manual upgrade | ||||
|         'sidekiq-unique-jobs', // Requires manual upgrades and sync with Sidekiq version | ||||
|  | @ -98,6 +99,16 @@ | |||
|       matchUpdateTypes: ['patch', 'minor'], | ||||
|       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 | ||||
|       matchPackagePrefixes: '@types/', | ||||
|  |  | |||
							
								
								
									
										3
									
								
								.github/workflows/build-container-image.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.github/workflows/build-container-image.yml
									
									
									
									
										vendored
									
									
								
							|  | @ -21,6 +21,8 @@ on: | |||
|         type: string | ||||
|       labels: | ||||
|         type: string | ||||
|       file_to_build: | ||||
|         type: string | ||||
| 
 | ||||
| jobs: | ||||
|   build-image: | ||||
|  | @ -86,6 +88,7 @@ jobs: | |||
|       - uses: docker/build-push-action@v5 | ||||
|         with: | ||||
|           context: . | ||||
|           file: ${{ inputs.file_to_build }} | ||||
|           build-args: | | ||||
|             MASTODON_VERSION_PRERELEASE=${{ inputs.version_prerelease }} | ||||
|             MASTODON_VERSION_METADATA=${{ inputs.version_metadata }} | ||||
|  |  | |||
							
								
								
									
										22
									
								
								.github/workflows/build-nightly.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								.github/workflows/build-nightly.yml
									
									
									
									
										vendored
									
									
								
							|  | @ -25,6 +25,7 @@ jobs: | |||
|     needs: compute-suffix | ||||
|     uses: ./.github/workflows/build-container-image.yml | ||||
|     with: | ||||
|       file_to_build: Dockerfile | ||||
|       platforms: linux/amd64,linux/arm64 | ||||
|       use_native_arm64_builder: false | ||||
|       cache: false | ||||
|  | @ -40,3 +41,24 @@ jobs: | |||
|         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: false | ||||
|       cache: false | ||||
|       push_to_images: | | ||||
|         ghcr.io/${{ github.repository_owner }}/mastodon-streaming | ||||
|       version_prerelease: ${{ needs.compute-suffix.outputs.prerelease }} | ||||
|       labels: | | ||||
|         org.opencontainers.image.description=Nightly build image used for testing purposes | ||||
|       flavor: | | ||||
|         latest=true | ||||
|       tags: | | ||||
|         type=raw,value=edge | ||||
|         type=raw,value=nightly | ||||
|         type=schedule,pattern=${{ needs.compute-suffix.outputs.prerelease }} | ||||
|     secrets: inherit | ||||
|  |  | |||
							
								
								
									
										17
									
								
								.github/workflows/build-push-pr.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										17
									
								
								.github/workflows/build-push-pr.yml
									
									
									
									
										vendored
									
									
								
							|  | @ -29,6 +29,7 @@ jobs: | |||
|     needs: compute-suffix | ||||
|     uses: ./.github/workflows/build-container-image.yml | ||||
|     with: | ||||
|       file_to_build: Dockerfile | ||||
|       platforms: linux/amd64,linux/arm64 | ||||
|       use_native_arm64_builder: false | ||||
|       push_to_images: | | ||||
|  | @ -39,3 +40,19 @@ jobs: | |||
|       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: false | ||||
|       push_to_images: | | ||||
|         ghcr.io/${{ github.repository_owner }}/mastodon-streaming | ||||
|       version_metadata: ${{ needs.compute-suffix.outputs.metadata }} | ||||
|       flavor: | | ||||
|         latest=auto | ||||
|       tags: | | ||||
|         type=ref,event=pr | ||||
|     secrets: inherit | ||||
|  |  | |||
							
								
								
									
										21
									
								
								.github/workflows/build-releases.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										21
									
								
								.github/workflows/build-releases.yml
									
									
									
									
										vendored
									
									
								
							|  | @ -12,6 +12,7 @@ jobs: | |||
|   build-image: | ||||
|     uses: ./.github/workflows/build-container-image.yml | ||||
|     with: | ||||
|       file_to_build: Dockerfile | ||||
|       platforms: linux/amd64,linux/arm64 | ||||
|       use_native_arm64_builder: false | ||||
|       push_to_images: | | ||||
|  | @ -26,3 +27,23 @@ jobs: | |||
|         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: false | ||||
|       push_to_images: | | ||||
|         ghcr.io/${{ github.repository_owner }}/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: | | ||||
|         type=pep440,pattern={{raw}} | ||||
|         type=pep440,pattern=v{{major}}.{{minor}} | ||||
|     secrets: inherit | ||||
|  |  | |||
							
								
								
									
										6
									
								
								.github/workflows/codeql.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.github/workflows/codeql.yml
									
									
									
									
										vendored
									
									
								
							|  | @ -31,7 +31,7 @@ jobs: | |||
| 
 | ||||
|       # Initializes the CodeQL tools for scanning. | ||||
|       - name: Initialize CodeQL | ||||
|         uses: github/codeql-action/init@v2 | ||||
|         uses: github/codeql-action/init@v3 | ||||
|         with: | ||||
|           languages: ${{ matrix.language }} | ||||
|           # 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). | ||||
|       # If this step fails, then you should remove it and run the build manually (see below) | ||||
|       - name: Autobuild | ||||
|         uses: github/codeql-action/autobuild@v2 | ||||
|         uses: github/codeql-action/autobuild@v3 | ||||
| 
 | ||||
|       # ℹ️ 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 | ||||
|  | @ -57,6 +57,6 @@ jobs: | |||
|       #   ./location_of_script_within_repo/buildscript.sh | ||||
| 
 | ||||
|       - name: Perform CodeQL Analysis | ||||
|         uses: github/codeql-action/analyze@v2 | ||||
|         uses: github/codeql-action/analyze@v3 | ||||
|         with: | ||||
|           category: '/language:${{matrix.language}}' | ||||
|  |  | |||
							
								
								
									
										14
									
								
								.github/workflows/test-image-build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								.github/workflows/test-image-build.yml
									
									
									
									
										vendored
									
									
								
							|  | @ -7,6 +7,7 @@ on: | |||
|       - .github/workflows/build-releases.yml | ||||
|       - .github/workflows/test-image-build.yml | ||||
|       - Dockerfile | ||||
|       - streaming/Dockerfile | ||||
| permissions: | ||||
|   contents: read | ||||
| 
 | ||||
|  | @ -18,4 +19,17 @@ jobs: | |||
| 
 | ||||
|     uses: ./.github/workflows/build-container-image.yml | ||||
|     with: | ||||
|       file_to_build: Dockerfile | ||||
|       platforms: linux/amd64 # Testing only on native platform so it is performant | ||||
|       cache: true | ||||
| 
 | ||||
|   build-image-streaming: | ||||
|     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 | ||||
|  |  | |||
							
								
								
									
										33
									
								
								.github/workflows/test-ruby.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										33
									
								
								.github/workflows/test-ruby.yml
									
									
									
									
										vendored
									
									
								
							|  | @ -48,12 +48,15 @@ jobs: | |||
|         run: |- | ||||
|           ./bin/rails assets:precompile | ||||
| 
 | ||||
|       - name: Archive asset artifacts | ||||
|         run: | | ||||
|           tar --exclude={"*.br","*.gz"} -zcf artifacts.tar.gz public/assets public/packs* | ||||
| 
 | ||||
|       - uses: actions/upload-artifact@v3 | ||||
|         if: matrix.mode == 'test' | ||||
|         with: | ||||
|           path: |- | ||||
|             ./public/assets | ||||
|             ./public/packs-test | ||||
|             ./artifacts.tar.gz | ||||
|           name: ${{ github.sha }} | ||||
|           retention-days: 0 | ||||
| 
 | ||||
|  | @ -91,7 +94,7 @@ jobs: | |||
|       DB_HOST: localhost | ||||
|       DB_USER: postgres | ||||
|       DB_PASS: postgres | ||||
|       DISABLE_SIMPLECOV: true | ||||
|       DISABLE_SIMPLECOV: ${{ matrix.ruby-version != '.ruby-version' }} | ||||
|       RAILS_ENV: test | ||||
|       ALLOW_NOPAM: true | ||||
|       PAM_ENABLED: true | ||||
|  | @ -102,7 +105,6 @@ jobs: | |||
|       SAML_ENABLED: true | ||||
|       CAS_ENABLED: true | ||||
|       BUNDLE_WITH: 'pam_authentication test' | ||||
|       CI_JOBS: ${{ matrix.ci_job }}/4 | ||||
|       GITHUB_RSPEC: ${{ matrix.ruby-version == '.ruby-version' && github.event.pull_request && 'true' }} | ||||
| 
 | ||||
|     strategy: | ||||
|  | @ -112,19 +114,18 @@ jobs: | |||
|           - '3.0' | ||||
|           - '3.1' | ||||
|           - '.ruby-version' | ||||
|         ci_job: | ||||
|           - 1 | ||||
|           - 2 | ||||
|           - 3 | ||||
|           - 4 | ||||
|     steps: | ||||
|       - uses: actions/checkout@v4 | ||||
| 
 | ||||
|       - uses: actions/download-artifact@v3 | ||||
|         with: | ||||
|           path: './public' | ||||
|           path: './' | ||||
|           name: ${{ github.sha }} | ||||
| 
 | ||||
|       - name: Expand archived asset artifacts | ||||
|         run: | | ||||
|           tar xvzf artifacts.tar.gz | ||||
| 
 | ||||
|       - name: Set up Ruby environment | ||||
|         uses: ./.github/actions/setup-ruby | ||||
|         with: | ||||
|  | @ -134,7 +135,13 @@ jobs: | |||
|       - name: Load database schema | ||||
|         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: | ||||
|     name: End to End testing | ||||
|  | @ -220,7 +227,7 @@ jobs: | |||
|           path: tmp/screenshots/ | ||||
| 
 | ||||
|   test-search: | ||||
|     name: Testing search | ||||
|     name: Elastic Search integration testing | ||||
|     runs-on: ubuntu-latest | ||||
| 
 | ||||
|     needs: | ||||
|  | @ -307,7 +314,7 @@ jobs: | |||
|       - name: Load database schema | ||||
|         run: './bin/rails db:create db:schema:load db:seed' | ||||
| 
 | ||||
|       - run: bundle exec rake spec:search | ||||
|       - run: bin/rspec --tag search | ||||
| 
 | ||||
|       - name: Archive logs | ||||
|         uses: actions/upload-artifact@v3 | ||||
|  |  | |||
							
								
								
									
										9
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							|  | @ -61,6 +61,15 @@ npm-debug.log | |||
| yarn-error.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 | ||||
| *-cloudimg-console.log | ||||
| 
 | ||||
|  |  | |||
|  | @ -12,3 +12,5 @@ linters: | |||
|     enabled: true | ||||
|   MiddleDot: | ||||
|     enabled: true | ||||
|   LineLength: | ||||
|     max: 320 | ||||
|  |  | |||
|  | @ -1,21 +1,13 @@ | |||
| # This configuration was generated by | ||||
| # `haml-lint --auto-gen-config` | ||||
| # on 2023-10-25 08:29:48 -0400 using Haml-Lint version 0.51.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 | ||||
| # one by one as the lints are removed from the code base. | ||||
| # Note that changes in the inspected code, or installation of new | ||||
| # versions of Haml-Lint, may require this file to be generated again. | ||||
| 
 | ||||
| linters: | ||||
|   # Offense count: 945 | ||||
|   # Offense count: 1 | ||||
|   LineLength: | ||||
|     enabled: false | ||||
| 
 | ||||
|   # Offense count: 10 | ||||
|   RuboCop: | ||||
|     exclude: | ||||
|       - 'app/views/admin/accounts/_buttons.html.haml' | ||||
|       - 'app/views/admin/accounts/_local_account.html.haml' | ||||
|       - 'app/views/admin/accounts/index.html.haml' | ||||
|       - 'app/views/admin/roles/_form.html.haml' | ||||
|       - 'app/views/layouts/application.html.haml' | ||||
|  |  | |||
							
								
								
									
										2
									
								
								.nvmrc
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								.nvmrc
									
									
									
									
									
								
							|  | @ -1 +1 @@ | |||
| 20.9 | ||||
| 20.11 | ||||
|  |  | |||
|  | @ -74,6 +74,8 @@ app/javascript/styles/mastodon/reset.scss | |||
| # Ignore the generated AUTHORS.md | ||||
| AUTHORS.md | ||||
| 
 | ||||
| !lint-staged.config.js | ||||
| 
 | ||||
| # Ignore glitch-soc emoji map file | ||||
| /app/javascript/flavours/glitch/features/emoji/emoji_map.json | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										60
									
								
								.rubocop.yml
									
									
									
									
									
								
							
							
						
						
									
										60
									
								
								.rubocop.yml
									
									
									
									
									
								
							|  | @ -27,7 +27,7 @@ AllCops: | |||
|     - 'node_modules/**/*' | ||||
|     - 'Vagrantfile' | ||||
|     - 'vendor/**/*' | ||||
|     - 'lib/json_ld/*' # Generated files | ||||
|     - 'config/initializers/json_ld*' # Generated files | ||||
|     - 'lib/mastodon/migration_helpers.rb' # Vendored from GitLab | ||||
|     - 'lib/templates/**/*' | ||||
| 
 | ||||
|  | @ -74,14 +74,12 @@ Metrics/ModuleLength: | |||
| Metrics/AbcSize: | ||||
|   Exclude: | ||||
|     - 'lib/mastodon/cli/*.rb' | ||||
|     - db/*migrate/**/* | ||||
| 
 | ||||
| # Reason: Currently disabled in .rubocop_todo.yml | ||||
| # https://docs.rubocop.org/rubocop/cops_metrics.html#metricscyclomaticcomplexity | ||||
| Metrics/CyclomaticComplexity: | ||||
|   Exclude: | ||||
|     - lib/mastodon/cli/*.rb | ||||
|     - db/*migrate/**/* | ||||
| 
 | ||||
| # Reason: | ||||
| # https://docs.rubocop.org/rubocop/cops_metrics.html#metricsparameterlists | ||||
|  | @ -105,20 +103,42 @@ Rails/Exit: | |||
|     - '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 | ||||
| RSpec/FilePath: | ||||
|   CustomTransform: | ||||
|     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 | ||||
|   Enabled: false | ||||
| 
 | ||||
| # Reason: | ||||
| # https://docs.rubocop.org/rubocop-rspec/cops_rspec.html#rspecnamedsubject | ||||
|  | @ -135,6 +155,16 @@ RSpec/NotToNot: | |||
| RSpec/Rails/HttpStatus: | ||||
|   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: | ||||
| # https://docs.rubocop.org/rubocop/cops_style.html#styleclassandmodulechildren | ||||
| Style/ClassAndModuleChildren: | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| # This configuration was generated by | ||||
| # `rubocop --auto-gen-config --auto-gen-only-exclude --no-exclude-limit --no-offense-counts --no-auto-gen-timestamp` | ||||
| # using RuboCop version 1.57.1. | ||||
| # using RuboCop version 1.59.0. | ||||
| # The point is for the user to remove these configuration records | ||||
| # one by one as the offenses are removed from the code base. | ||||
| # Note that changes in the inspected code, or installation of new | ||||
|  | @ -13,46 +13,13 @@ Bundler/OrderedGems: | |||
|   Exclude: | ||||
|     - 'Gemfile' | ||||
| 
 | ||||
| # This cop supports safe autocorrection (--autocorrect). | ||||
| # Configuration parameters: Max, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns. | ||||
| # URISchemes: http, https | ||||
| Layout/LineLength: | ||||
|   Exclude: | ||||
|     - 'app/models/account.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/lib/activitypub/adapter_spec.rb' | ||||
|     - 'spec/models/user_role_spec.rb' | ||||
| 
 | ||||
| Lint/NonLocalExitFromIterator: | ||||
|   Exclude: | ||||
|     - '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' | ||||
| 
 | ||||
| # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes. | ||||
| Metrics/AbcSize: | ||||
|   Max: 144 | ||||
|   Exclude: | ||||
|     - 'app/serializers/initial_state_serializer.rb' | ||||
|   Max: 90 | ||||
| 
 | ||||
| # Configuration parameters: CountBlocks, Max. | ||||
| Metrics/BlockNesting: | ||||
|  | @ -67,283 +34,33 @@ Metrics/CyclomaticComplexity: | |||
| Metrics/PerceivedComplexity: | ||||
|   Max: 27 | ||||
| 
 | ||||
| Performance/MapMethodChain: | ||||
|   Exclude: | ||||
|     - 'app/models/feed.rb' | ||||
|     - 'lib/mastodon/cli/maintenance.rb' | ||||
|     - 'spec/services/bulk_import_service_spec.rb' | ||||
|     - 'spec/services/import_service_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/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. | ||||
| RSpec/ExampleLength: | ||||
|   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/filters_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/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: | ||||
|   Max: 8 | ||||
| 
 | ||||
| # Configuration parameters: AllowSubject. | ||||
| RSpec/MultipleMemoizedHelpers: | ||||
|   Max: 21 | ||||
|   Max: 17 | ||||
| 
 | ||||
| # Configuration parameters: AllowedGroups. | ||||
| RSpec/NestedGroups: | ||||
|   Max: 6 | ||||
| 
 | ||||
| # This cop supports unsafe autocorrection (--autocorrect-all). | ||||
| Rails/ApplicationController: | ||||
|   Exclude: | ||||
|     - 'app/controllers/health_controller.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. | ||||
| # Include: app/models/**/*.rb | ||||
| Rails/HasAndBelongsToMany: | ||||
|   Exclude: | ||||
|     - 'app/models/concerns/account_associations.rb' | ||||
|     - 'app/models/preview_card.rb' | ||||
|     - 'app/models/concerns/account/associations.rb' | ||||
|     - 'app/models/status.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' | ||||
| 
 | ||||
| # 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/workers/web/push_notification_worker.rb' | ||||
|     - 'lib/paperclip/color_extractor.rb' | ||||
| 
 | ||||
| Rails/OutputSafety: | ||||
|   Exclude: | ||||
|     - '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: 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/lib/activitypub/activity/follow_spec.rb' | ||||
|     - 'spec/services/follow_service_spec.rb' | ||||
|     - 'spec/services/update_account_service_spec.rb' | ||||
| 
 | ||||
| # Configuration parameters: Include. | ||||
| # Include: app/models/**/*.rb | ||||
| Rails/UniqueValidationWithoutIndex: | ||||
|  | @ -353,19 +70,6 @@ Rails/UniqueValidationWithoutIndex: | |||
|     - 'app/models/identity.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). | ||||
| # Configuration parameters: EnforcedStyle. | ||||
| # SupportedStyles: exists, where | ||||
|  | @ -373,40 +77,28 @@ 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 unsafe autocorrection (--autocorrect-all). | ||||
| # Configuration parameters: AllowedMethods, AllowedPatterns. | ||||
| # AllowedMethods: ==, equal?, eql? | ||||
|  | @ -431,12 +123,11 @@ Style/FetchEnvVar: | |||
|     - 'config/initializers/3_omniauth.rb' | ||||
|     - 'config/initializers/blacklists.rb' | ||||
|     - 'config/initializers/cache_buster.rb' | ||||
|     - 'config/initializers/content_security_policy.rb' | ||||
|     - 'config/initializers/devise.rb' | ||||
|     - 'config/initializers/paperclip.rb' | ||||
|     - 'config/initializers/vapid.rb' | ||||
|     - 'lib/mastodon/premailer_webpack_strategy.rb' | ||||
|     - 'lib/mastodon/redis_config.rb' | ||||
|     - 'lib/premailer_webpack_strategy.rb' | ||||
|     - 'lib/tasks/repo.rake' | ||||
|     - 'spec/features/profile_spec.rb' | ||||
| 
 | ||||
|  | @ -453,7 +144,6 @@ Style/FormatStringToken: | |||
| # This cop supports unsafe autocorrection (--autocorrect-all). | ||||
| Style/GlobalStdStream: | ||||
|   Exclude: | ||||
|     - 'config/boot.rb' | ||||
|     - 'config/environments/development.rb' | ||||
|     - 'config/environments/production.rb' | ||||
| 
 | ||||
|  | @ -470,8 +160,8 @@ Style/GuardClause: | |||
|     - 'app/lib/request_pool.rb' | ||||
|     - 'app/lib/webfinger.rb' | ||||
|     - 'app/lib/webfinger_resource.rb' | ||||
|     - 'app/models/concerns/account_counters.rb' | ||||
|     - 'app/models/concerns/ldap_authenticable.rb' | ||||
|     - 'app/models/concerns/account/counters.rb' | ||||
|     - 'app/models/concerns/user/ldap_authenticable.rb' | ||||
|     - 'app/models/tag.rb' | ||||
|     - 'app/models/user.rb' | ||||
|     - 'app/services/fan_out_on_write_service.rb' | ||||
|  | @ -483,10 +173,8 @@ Style/GuardClause: | |||
|     - 'app/workers/redownload_media_worker.rb' | ||||
|     - 'app/workers/remote_account_refresh_worker.rb' | ||||
|     - 'config/initializers/devise.rb' | ||||
|     - 'db/migrate/20170901141119_truncate_preview_cards.rb' | ||||
|     - 'db/post_migrate/20220704024901_migrate_settings_to_user_roles.rb' | ||||
|     - 'lib/devise/two_factor_ldap_authenticatable.rb' | ||||
|     - 'lib/devise/two_factor_pam_authenticatable.rb' | ||||
|     - 'lib/devise/strategies/two_factor_ldap_authenticatable.rb' | ||||
|     - 'lib/devise/strategies/two_factor_pam_authenticatable.rb' | ||||
|     - 'lib/mastodon/cli/accounts.rb' | ||||
|     - 'lib/mastodon/cli/maintenance.rb' | ||||
|     - 'lib/mastodon/cli/media.rb' | ||||
|  | @ -500,12 +188,11 @@ Style/HashAsLastArrayItem: | |||
|   Exclude: | ||||
|     - 'app/controllers/admin/statuses_controller.rb' | ||||
|     - 'app/controllers/api/v1/statuses_controller.rb' | ||||
|     - 'app/models/concerns/account_counters.rb' | ||||
|     - 'app/models/concerns/status_threading_concern.rb' | ||||
|     - 'app/models/concerns/account/counters.rb' | ||||
|     - 'app/models/concerns/status/threading_concern.rb' | ||||
|     - 'app/models/status.rb' | ||||
|     - 'app/services/batched_remove_status_service.rb' | ||||
|     - 'app/services/notify_service.rb' | ||||
|     - 'db/migrate/20181024224956_migrate_account_conversations.rb' | ||||
| 
 | ||||
| # This cop supports unsafe autocorrection (--autocorrect-all). | ||||
| Style/HashTransformValues: | ||||
|  | @ -520,22 +207,6 @@ Style/IfUnlessModifier: | |||
|     - 'config/initializers/devise.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). | ||||
| Style/MapToHash: | ||||
|   Exclude: | ||||
|  | @ -600,48 +271,26 @@ Style/RedundantFetchBlock: | |||
|     - 'config/initializers/paperclip.rb' | ||||
|     - 'config/puma.rb' | ||||
| 
 | ||||
| # This cop supports safe autocorrection (--autocorrect). | ||||
| # Configuration parameters: AllowMultipleReturnValues. | ||||
| Style/RedundantReturn: | ||||
|   Exclude: | ||||
|     - 'app/controllers/api/v1/directories_controller.rb' | ||||
|     - 'app/controllers/auth/confirmations_controller.rb' | ||||
|     - 'app/lib/ostatus/tag_manager.rb' | ||||
|     - 'app/models/form/import.rb' | ||||
| 
 | ||||
| # This cop supports unsafe autocorrection (--autocorrect-all). | ||||
| # Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods, MaxChainLength. | ||||
| # AllowedMethods: present?, blank?, presence, try, try! | ||||
| Style/SafeNavigation: | ||||
|   Exclude: | ||||
|     - 'app/models/concerns/account_finder_concern.rb' | ||||
|     - 'app/models/concerns/account/finder_concern.rb' | ||||
| 
 | ||||
| # This cop supports safe autocorrection (--autocorrect). | ||||
| # Configuration parameters: EnforcedStyle. | ||||
| # SupportedStyles: only_raise, only_fail, semantic | ||||
| Style/SignalException: | ||||
|   Exclude: | ||||
|     - 'lib/devise/two_factor_ldap_authenticatable.rb' | ||||
|     - 'lib/devise/two_factor_pam_authenticatable.rb' | ||||
|     - 'lib/devise/strategies/two_factor_ldap_authenticatable.rb' | ||||
|     - 'lib/devise/strategies/two_factor_pam_authenticatable.rb' | ||||
| 
 | ||||
| # This cop supports unsafe autocorrection (--autocorrect-all). | ||||
| Style/SingleArgumentDig: | ||||
|   Exclude: | ||||
|     - '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). | ||||
| # Configuration parameters: Mode. | ||||
| Style/StringConcatenation: | ||||
|  | @ -660,13 +309,6 @@ Style/StringLiterals: | |||
|     - 'config/initializers/webauthn.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/3_omniauth.rb' | ||||
| 
 | ||||
| # This cop supports safe autocorrection (--autocorrect). | ||||
| # Configuration parameters: EnforcedStyle, AllowSafeAssignment. | ||||
| # SupportedStyles: require_parentheses, require_no_parentheses, require_parentheses_when_complex | ||||
|  | @ -690,10 +332,8 @@ Style/TrailingCommaInHashLiteral: | |||
|     - 'config/environments/test.rb' | ||||
| 
 | ||||
| # This cop supports safe autocorrection (--autocorrect). | ||||
| # Configuration parameters: EnforcedStyle, MinSize, WordRegex. | ||||
| # Configuration parameters: WordRegex. | ||||
| # SupportedStyles: percent, brackets | ||||
| Style/WordArray: | ||||
|   Exclude: | ||||
|     - 'app/helpers/languages_helper.rb' | ||||
|     - 'spec/controllers/settings/imports_controller_spec.rb' | ||||
|     - 'spec/models/form/import_spec.rb' | ||||
|   EnforcedStyle: percent | ||||
|   MinSize: 3 | ||||
|  |  | |||
							
								
								
									
										22
									
								
								.simplecov
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								.simplecov
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										3
									
								
								.watchmanconfig
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,3 @@ | |||
| { | ||||
|   "ignore_dirs": ["node_modules/", "public/"] | ||||
| } | ||||
							
								
								
									
										0
									
								
								.yarn/.gitkeep
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								.yarn/.gitkeep
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										13
									
								
								.yarn/patches/babel-plugin-lodash-npm-3.3.4-c7161075b6.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								.yarn/patches/babel-plugin-lodash-npm-3.3.4-c7161075b6.patch
									
									
									
									
									
										Normal 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; | ||||
|          } | ||||
							
								
								
									
										49
									
								
								.yarnclean
									
									
									
									
									
								
							
							
						
						
									
										49
									
								
								.yarnclean
									
									
									
									
									
								
							|  | @ -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 | ||||
|  | @ -73,6 +73,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). | ||||
| 
 | ||||
| ## 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 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. | ||||
|  |  | |||
							
								
								
									
										394
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										394
									
								
								Dockerfile
									
									
									
									
									
								
							|  | @ -1,171 +1,263 @@ | |||
| # syntax=docker/dockerfile:1.4 | ||||
| # This needs to be bookworm-slim because the Ruby image is built on bookworm-slim | ||||
| ARG NODE_IMAGE="node:20.8-bookworm-slim" | ||||
| ARG RUBY_IMAGE=ghcr.io/moritzheiber/ruby-jemalloc:3.2.2-slim | ||||
| 
 | ||||
| # hadolint ignore=DL3006 | ||||
| FROM ${RUBY_IMAGE} as ruby | ||||
| # Please see https://docs.docker.com/engine/reference/builder for information about | ||||
| # 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} | ||||
| 
 | ||||
| # build-base | ||||
| # hadolint ignore=DL3006 | ||||
| FROM ${NODE_IMAGE} as build-base | ||||
| # Ruby image to use for base image, change with [--build-arg RUBY_VERSION="3.2.2"] | ||||
| ARG RUBY_VERSION="3.2.2" | ||||
| # # 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 | ||||
| 
 | ||||
| COPY --link --from=ruby /opt/ruby /opt/ruby | ||||
| # Ruby image to use for base image based on combined variables (ex: 3.2.2-slim-bookworm) | ||||
| FROM docker.io/ruby:${RUBY_VERSION}-slim-${DEBIAN_VERSION} as ruby | ||||
| 
 | ||||
| ENV DEBIAN_FRONTEND="noninteractive" \ | ||||
|     PATH="${PATH}:/opt/ruby/bin" | ||||
| 
 | ||||
| SHELL ["/bin/bash", "-o", "pipefail", "-c"] | ||||
| 
 | ||||
| WORKDIR /opt/mastodon | ||||
| 
 | ||||
| # hadolint ignore=DL3008,DL3009 | ||||
| RUN --mount=type=cache,id=apt,target=/var/cache/apt,sharing=private \ | ||||
|     set -eux && \ | ||||
|     rm -f /etc/apt/apt.conf.d/docker-clean && \ | ||||
|     echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache && \ | ||||
|     apt-get update && \ | ||||
|     apt-get -yq dist-upgrade && \ | ||||
|     apt-get install -y --no-install-recommends \ | ||||
|         build-essential \ | ||||
|         ca-certificates \ | ||||
|         git \ | ||||
|         libgdbm-dev \ | ||||
|         libgmp-dev \ | ||||
|         libicu-dev \ | ||||
|         libidn-dev \ | ||||
|         libjemalloc-dev \ | ||||
|         libpq-dev \ | ||||
|         libreadline8 \ | ||||
|         libssl-dev \ | ||||
|         libyaml-dev \ | ||||
|         python3 \ | ||||
|         shared-mime-info \ | ||||
|         zlib1g-dev | ||||
| 
 | ||||
| COPY --link .yarn/releases/ /opt/mastodon/.yarn/releases/ | ||||
| COPY --link Gemfile* package.json yarn.lock .yarnrc.yml /opt/mastodon/ | ||||
| 
 | ||||
| ENV NODE_OPTIONS=--openssl-legacy-provider \ | ||||
|     YARN_GLOBAL_FOLDER=/opt/yarn \ | ||||
|     YARN_ENABLE_GLOBAL_CACHE=1 | ||||
| 
 | ||||
| # hadolint ignore=DL3060 | ||||
| RUN --mount=type=cache,id=bundle,target=/opt/bundle/cache,sharing=private \ | ||||
|     --mount=type=cache,id=yarn,target=/opt/yarn/cache,sharing=private \ | ||||
|     set -eux && \ | ||||
|     bundle config set cache_path /opt/bundle/cache && \ | ||||
|     bundle config set silence_root_warning 'true' && \ | ||||
|     bundle cache --no-install && \ | ||||
|     bundle config set --local deployment true && \ | ||||
|     bundle install --local -j"$(nproc)" && \ | ||||
|     yarn install --immutable | ||||
| 
 | ||||
| # Precompile assets | ||||
| # TODO(kouhai): we're currently patching node_modules because of emoji-mart. | ||||
| # we should integrate our own fork instead. | ||||
| COPY --link . /opt/mastodon | ||||
| 
 | ||||
| # build | ||||
| FROM build-base AS build | ||||
| 
 | ||||
| ENV RAILS_ENV=production \ | ||||
|     NODE_ENV=production | ||||
| 
 | ||||
| ENV NODE_OPTIONS=--openssl-legacy-provider \ | ||||
|     YARN_GLOBAL_FOLDER=/opt/yarn \ | ||||
|     YARN_ENABLE_GLOBAL_CACHE=1 | ||||
| 
 | ||||
| ENV OTP_SECRET=precompile_placeholder \ | ||||
|     SECRET_KEY_BASE=precompile_placeholder \ | ||||
|     RAKE_NO_YARN_INSTALL_HACK=1 | ||||
| 
 | ||||
| # override this at will | ||||
| ENV BOOTSNAP_READONLY=1 | ||||
| 
 | ||||
| RUN --mount=type=cache,id=yarn,target=/opt/yarn/cache,sharing=private \ | ||||
|     --mount=type=cache,id=webpacker,target=/opt/webpacker/cache,sharing=private \ | ||||
|     set -eux && \ | ||||
|     mkdir -p tmp/cache && \ | ||||
|     ln -sf /opt/webpacker/cache tmp/cache/webpacker && \ | ||||
|     mv ./emoji_data/all.json ./node_modules/emoji-mart/data/all.json && \ | ||||
|     yarn install && \ | ||||
|     bundle exec rails assets:precompile | ||||
| 
 | ||||
| # final image | ||||
| # hadolint ignore=DL3006 | ||||
| FROM ${NODE_IMAGE} as output-base | ||||
| 
 | ||||
| ENV DEBIAN_FRONTEND="noninteractive" | ||||
| 
 | ||||
| # Ignoring these here since we don't want to pin any versions and the Debian image removes apt-get content after use | ||||
| # hadolint ignore=DL3008,DL3009 | ||||
| RUN --mount=type=cache,id=apt,target=/var/cache/apt,sharing=private \ | ||||
|     set -eux && \ | ||||
|     rm -f /etc/apt/apt.conf.d/docker-clean && \ | ||||
|     echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache && \ | ||||
|     echo "Etc/UTC" > /etc/localtime && \ | ||||
|     apt-get update && \ | ||||
|     apt-get -y --no-install-recommends install \ | ||||
|         ca-certificates \ | ||||
|         ffmpeg \ | ||||
|         file \ | ||||
|         imagemagick \ | ||||
|         libicu72 \ | ||||
|         libidn12 \ | ||||
|         libjemalloc2 \ | ||||
|         libpq5 \ | ||||
|         libreadline8 \ | ||||
|         libssl3 \ | ||||
|         libyaml-0-2 \ | ||||
|         procps \ | ||||
|         tini \ | ||||
|         tzdata \ | ||||
|         wget \ | ||||
|         whois | ||||
| 
 | ||||
| # final image | ||||
| FROM output-base as output | ||||
| 
 | ||||
| # Use those args to specify your own version flags & suffixes | ||||
| ARG SOURCE_TAG="" | ||||
| # Resulting version string is vX.X.X-MASTODON_VERSION_PRERELEASE+MASTODON_VERSION_METADATA | ||||
| # 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"] | ||||
| ARG MASTODON_VERSION_PRERELEASE="" | ||||
| # Append build metadata or fork information to version.rb [--build-arg MASTODON_VERSION_METADATA="something"] | ||||
| ARG MASTODON_VERSION_METADATA="" | ||||
| 
 | ||||
| # 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" | ||||
| # Linux GID (group id) for the mastodon user, change with [--build-arg GID=1234] | ||||
| ARG GID="991" | ||||
| 
 | ||||
| SHELL ["/bin/bash", "-o", "pipefail", "-c"] | ||||
| # 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} | ||||
| 
 | ||||
| ENV PATH="${PATH}:/opt/ruby/bin:/opt/mastodon/bin" | ||||
| 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" | ||||
| 
 | ||||
| # Ignoring these here since we don't want to pin any versions and the Debian image removes apt-get content after use | ||||
| # hadolint ignore=DL3008,DL3009 | ||||
| RUN groupadd -g "${GID}" mastodon && \ | ||||
|     useradd -l -u "${UID}" -g "${GID}" -m -d /opt/mastodon mastodon && \ | ||||
|     ln -s /opt/mastodon /mastodon | ||||
| # Set default shell used for running commands | ||||
| SHELL ["/bin/bash", "-o", "pipefail", "-o", "errexit", "-c"] | ||||
| 
 | ||||
| # Note: no, cleaning here since Debian does this automatically | ||||
| # See the file /etc/apt/apt.conf.d/docker-clean within the Docker image's filesystem | ||||
| ARG TARGETPLATFORM | ||||
| 
 | ||||
| COPY --link --from=ruby /opt/ruby /opt/ruby | ||||
| COPY --link --chown=mastodon:mastodon --from=build /opt/mastodon /opt/mastodon | ||||
| RUN echo "Target platform is $TARGETPLATFORM" | ||||
| 
 | ||||
| ENV RAILS_ENV="production" \ | ||||
|     NODE_ENV="production" \ | ||||
|     RAILS_SERVE_STATIC_FILES="true" \ | ||||
|     BIND="0.0.0.0" \ | ||||
|     SOURCE_TAG="${SOURCE_TAG}" \ | ||||
|     MASTODON_VERSION_PRERELEASE="${MASTODON_VERSION_PRERELEASE}" \ | ||||
|     MASTODON_VERSION_METADATA="${MASTODON_VERSION_METADATA}" | ||||
| RUN \ | ||||
| # 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; | ||||
| 
 | ||||
| # override this at will | ||||
| ENV BOOTSNAP_READONLY=1 | ||||
| 
 | ||||
| # Set the run user | ||||
| USER mastodon | ||||
| # Set /opt/mastodon as working directory | ||||
| WORKDIR /opt/mastodon | ||||
| 
 | ||||
| # Set the work dir and the container entry point | ||||
| # hadolint ignore=DL3008,DL3005 | ||||
| RUN \ | ||||
| # Mount Apt cache and lib directories from Docker buildx caches | ||||
| --mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \ | ||||
| --mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \ | ||||
| # Apt update & upgrade to check for security updates to Debian image | ||||
|   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 \ | ||||
|   ; | ||||
| 
 | ||||
| # Create temporary build layer from base image | ||||
| FROM ruby as build | ||||
| 
 | ||||
| COPY --from=node /usr/local/bin /usr/local/bin | ||||
| COPY --from=node /usr/local/lib /usr/local/lib | ||||
| 
 | ||||
| # Copy Node package configuration files into working directory | ||||
| COPY package.json yarn.lock .yarnrc.yml /opt/mastodon/ | ||||
| COPY .yarn /opt/mastodon/.yarn | ||||
| 
 | ||||
| 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; \ | ||||
| # TODO(kouhai): fork emoji-mart instead of patching | ||||
|   mv ./emoji_data/all.json ./node_modules/emoji-mart/data/all.json | ||||
| 
 | ||||
| # 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", "--"] | ||||
| EXPOSE 3000 4000 | ||||
|  |  | |||
							
								
								
									
										30
									
								
								Gemfile
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								Gemfile
									
									
									
									
									
								
							|  | @ -5,10 +5,13 @@ ruby '>= 3.0.0' | |||
| 
 | ||||
| gem 'puma', '~> 6.3' | ||||
| gem 'rails', '~> 7.1.1' | ||||
| gem 'sprockets', '~> 3.7.2' | ||||
| gem 'propshaft' | ||||
| gem 'thor', '~> 1.2' | ||||
| 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 'pg', '~> 1.5' | ||||
| gem 'pghero' | ||||
|  | @ -16,14 +19,14 @@ gem 'dotenv-rails', '~> 2.8' | |||
| 
 | ||||
| gem 'aws-sdk-s3', '~> 1.123', require: false | ||||
| 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 'md-paperclip-azure', '~> 2.2', require: false | ||||
| gem 'blurhash', '~> 0.1' | ||||
| 
 | ||||
| gem 'active_model_serializers', '~> 0.10' | ||||
| gem 'addressable', '~> 2.8' | ||||
| gem 'bootsnap', '~> 1.16.0', require: false | ||||
| gem 'bootsnap', '~> 1.17.0', require: false | ||||
| gem 'browser' | ||||
| gem 'charlock_holmes', '~> 0.7.7' | ||||
| gem 'chewy', '~> 7.3' | ||||
|  | @ -36,15 +39,14 @@ end | |||
| 
 | ||||
| gem 'net-ldap', '~> 0.18' | ||||
| 
 | ||||
| # TODO: Point back at released omniauth-cas gem when PR merged | ||||
| # https://github.com/dlindahl/omniauth-cas/pull/68 | ||||
| gem 'omniauth-cas', github: 'stanhu/omniauth-cas', ref: '4211e6d05941b4a981f9a36b49ec166cecd0e271' | ||||
| gem 'omniauth-cas', '~> 3.0.0.beta.1' | ||||
| gem 'omniauth-saml', '~> 2.0' | ||||
| gem 'omniauth_openid_connect', '~> 0.6.1' | ||||
| gem 'omniauth', '~> 2.0' | ||||
| gem 'omniauth-rails_csrf_protection', '~> 1.0' | ||||
| 
 | ||||
| gem 'color_diff', '~> 0.1' | ||||
| gem 'csv', '~> 3.2' | ||||
| gem 'discard', '~> 1.2' | ||||
| gem 'doorkeeper', '~> 5.6' | ||||
| gem 'ed25519', '~> 1.3' | ||||
|  | @ -72,7 +74,6 @@ gem 'premailer-rails' | |||
| gem 'rack-attack', '~> 6.6' | ||||
| gem 'rack-cors', '~> 2.0', require: 'rack/cors' | ||||
| 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 'redis', '~> 4.5', require: ['redis', 'redis/connection/hiredis'] | ||||
| 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 'simple-navigation', '~> 4.4' | ||||
| gem 'simple_form', '~> 5.2' | ||||
| gem 'sprockets-rails', '~> 3.4', require: 'sprockets/railtie' | ||||
| gem 'stoplight', '~> 3.0.1' | ||||
| gem 'strong_migrations', '~> 0.8' | ||||
| gem 'strong_migrations', '1.7.0' | ||||
| gem 'tty-prompt', '~> 0.23', require: false | ||||
| gem 'twitter-text', '~> 3.1.0' | ||||
| gem 'tzinfo-data', '~> 1.2023' | ||||
|  | @ -103,15 +103,15 @@ gem 'rdf-normalize', '~> 0.5' | |||
| gem 'private_address_check', '~> 0.5' | ||||
| 
 | ||||
| group :test do | ||||
|   # Used to split testing into chunks in CI | ||||
|   gem 'rspec_chunked', '~> 0.6' | ||||
| 
 | ||||
|   # Adds RSpec Error/Warning annotations to GitHub PRs on the Files tab | ||||
|   gem 'rspec-github', '~> 2.4', require: false | ||||
| 
 | ||||
|   # RSpec progress bar formatter | ||||
|   gem 'fuubar', '~> 2.5' | ||||
| 
 | ||||
|   # RSpec helpers for email specs | ||||
|   gem 'email_spec' | ||||
| 
 | ||||
|   # Extra RSpec extenion methods and helpers for sidekiq | ||||
|   gem 'rspec-sidekiq', '~> 4.0' | ||||
| 
 | ||||
|  | @ -142,6 +142,7 @@ group :test do | |||
| 
 | ||||
|   # Coverage formatter for RSpec test if DISABLE_SIMPLECOV is false | ||||
|   gem 'simplecov', '~> 0.22', require: false | ||||
|   gem 'simplecov-lcov', '~> 0.8', require: false | ||||
| 
 | ||||
|   # Stub web requests for specs | ||||
|   gem 'webmock', '~> 3.18' | ||||
|  | @ -178,6 +179,9 @@ group :development do | |||
| end | ||||
| 
 | ||||
| group :development, :test do | ||||
|   # Interactive Debugging tools | ||||
|   gem 'debug', '~> 1.8' | ||||
| 
 | ||||
|   # Profiling tools | ||||
|   gem 'memory_profiler', require: false | ||||
|   gem 'ruby-prof', require: false | ||||
|  | @ -201,7 +205,7 @@ gem 'xorcist', '~> 1.1' | |||
| 
 | ||||
| gem 'cocoon', '~> 1.2' | ||||
| 
 | ||||
| gem 'net-http', '~> 0.3.2' | ||||
| gem 'net-http', '~> 0.4.0' | ||||
| gem 'rubyzip', '~> 2.3' | ||||
| 
 | ||||
| gem 'hcaptcha', '~> 7.1' | ||||
|  |  | |||
							
								
								
									
										387
									
								
								Gemfile.lock
									
									
									
									
									
								
							
							
						
						
									
										387
									
								
								Gemfile.lock
									
									
									
									
									
								
							|  | @ -18,71 +18,54 @@ GIT | |||
|       sidekiq (>= 3.5) | ||||
|       statsd-ruby (~> 1.4, >= 1.4.0) | ||||
| 
 | ||||
| GIT | ||||
|   remote: https://github.com/mastodon/rails-settings-cached.git | ||||
|   revision: 86328ef0bd04ce21cc0504ff5e334591e8c2ccab | ||||
|   branch: v0.6.6-aliases-true | ||||
|   specs: | ||||
|     rails-settings-cached (0.6.6) | ||||
|       rails (>= 4.2.0) | ||||
| 
 | ||||
| GIT | ||||
|   remote: https://github.com/stanhu/omniauth-cas.git | ||||
|   revision: 4211e6d05941b4a981f9a36b49ec166cecd0e271 | ||||
|   ref: 4211e6d05941b4a981f9a36b49ec166cecd0e271 | ||||
|   specs: | ||||
|     omniauth-cas (2.0.0) | ||||
|       addressable (~> 2.3) | ||||
|       nokogiri (~> 1.5) | ||||
|       omniauth (>= 1.2, < 3) | ||||
| 
 | ||||
| GEM | ||||
|   remote: https://rubygems.org/ | ||||
|   specs: | ||||
|     actioncable (7.1.1) | ||||
|       actionpack (= 7.1.1) | ||||
|       activesupport (= 7.1.1) | ||||
|     actioncable (7.1.3) | ||||
|       actionpack (= 7.1.3) | ||||
|       activesupport (= 7.1.3) | ||||
|       nio4r (~> 2.0) | ||||
|       websocket-driver (>= 0.6.1) | ||||
|       zeitwerk (~> 2.6) | ||||
|     actionmailbox (7.1.1) | ||||
|       actionpack (= 7.1.1) | ||||
|       activejob (= 7.1.1) | ||||
|       activerecord (= 7.1.1) | ||||
|       activestorage (= 7.1.1) | ||||
|       activesupport (= 7.1.1) | ||||
|     actionmailbox (7.1.3) | ||||
|       actionpack (= 7.1.3) | ||||
|       activejob (= 7.1.3) | ||||
|       activerecord (= 7.1.3) | ||||
|       activestorage (= 7.1.3) | ||||
|       activesupport (= 7.1.3) | ||||
|       mail (>= 2.7.1) | ||||
|       net-imap | ||||
|       net-pop | ||||
|       net-smtp | ||||
|     actionmailer (7.1.1) | ||||
|       actionpack (= 7.1.1) | ||||
|       actionview (= 7.1.1) | ||||
|       activejob (= 7.1.1) | ||||
|       activesupport (= 7.1.1) | ||||
|     actionmailer (7.1.3) | ||||
|       actionpack (= 7.1.3) | ||||
|       actionview (= 7.1.3) | ||||
|       activejob (= 7.1.3) | ||||
|       activesupport (= 7.1.3) | ||||
|       mail (~> 2.5, >= 2.5.4) | ||||
|       net-imap | ||||
|       net-pop | ||||
|       net-smtp | ||||
|       rails-dom-testing (~> 2.2) | ||||
|     actionpack (7.1.1) | ||||
|       actionview (= 7.1.1) | ||||
|       activesupport (= 7.1.1) | ||||
|     actionpack (7.1.3) | ||||
|       actionview (= 7.1.3) | ||||
|       activesupport (= 7.1.3) | ||||
|       nokogiri (>= 1.8.5) | ||||
|       racc | ||||
|       rack (>= 2.2.4) | ||||
|       rack-session (>= 1.0.1) | ||||
|       rack-test (>= 0.6.3) | ||||
|       rails-dom-testing (~> 2.2) | ||||
|       rails-html-sanitizer (~> 1.6) | ||||
|     actiontext (7.1.1) | ||||
|       actionpack (= 7.1.1) | ||||
|       activerecord (= 7.1.1) | ||||
|       activestorage (= 7.1.1) | ||||
|       activesupport (= 7.1.1) | ||||
|     actiontext (7.1.3) | ||||
|       actionpack (= 7.1.3) | ||||
|       activerecord (= 7.1.3) | ||||
|       activestorage (= 7.1.3) | ||||
|       activesupport (= 7.1.3) | ||||
|       globalid (>= 0.6.0) | ||||
|       nokogiri (>= 1.8.5) | ||||
|     actionview (7.1.1) | ||||
|       activesupport (= 7.1.1) | ||||
|     actionview (7.1.3) | ||||
|       activesupport (= 7.1.3) | ||||
|       builder (~> 3.1) | ||||
|       erubi (~> 1.11) | ||||
|       rails-dom-testing (~> 2.2) | ||||
|  | @ -92,22 +75,22 @@ GEM | |||
|       activemodel (>= 4.1) | ||||
|       case_transform (>= 0.2) | ||||
|       jsonapi-renderer (>= 0.1.1.beta1, < 0.3) | ||||
|     activejob (7.1.1) | ||||
|       activesupport (= 7.1.1) | ||||
|     activejob (7.1.3) | ||||
|       activesupport (= 7.1.3) | ||||
|       globalid (>= 0.3.6) | ||||
|     activemodel (7.1.1) | ||||
|       activesupport (= 7.1.1) | ||||
|     activerecord (7.1.1) | ||||
|       activemodel (= 7.1.1) | ||||
|       activesupport (= 7.1.1) | ||||
|     activemodel (7.1.3) | ||||
|       activesupport (= 7.1.3) | ||||
|     activerecord (7.1.3) | ||||
|       activemodel (= 7.1.3) | ||||
|       activesupport (= 7.1.3) | ||||
|       timeout (>= 0.4.0) | ||||
|     activestorage (7.1.1) | ||||
|       actionpack (= 7.1.1) | ||||
|       activejob (= 7.1.1) | ||||
|       activerecord (= 7.1.1) | ||||
|       activesupport (= 7.1.1) | ||||
|     activestorage (7.1.3) | ||||
|       actionpack (= 7.1.3) | ||||
|       activejob (= 7.1.3) | ||||
|       activerecord (= 7.1.3) | ||||
|       activesupport (= 7.1.3) | ||||
|       marcel (~> 1.0) | ||||
|     activesupport (7.1.1) | ||||
|     activesupport (7.1.3) | ||||
|       base64 | ||||
|       bigdecimal | ||||
|       concurrent-ruby (~> 1.0, >= 1.0.2) | ||||
|  | @ -117,7 +100,7 @@ GEM | |||
|       minitest (>= 5.1) | ||||
|       mutex_m | ||||
|       tzinfo (~> 2.0) | ||||
|     addressable (2.8.5) | ||||
|     addressable (2.8.6) | ||||
|       public_suffix (>= 2.0.2, < 6.0) | ||||
|     aes_key_wrap (1.1.0) | ||||
|     android_key_attestation (0.3.0) | ||||
|  | @ -129,21 +112,21 @@ GEM | |||
|       encryptor (~> 3.0.0) | ||||
|     attr_required (1.0.1) | ||||
|     awrence (1.2.1) | ||||
|     aws-eventstream (1.2.0) | ||||
|     aws-partitions (1.809.0) | ||||
|     aws-sdk-core (3.181.0) | ||||
|       aws-eventstream (~> 1, >= 1.0.2) | ||||
|     aws-eventstream (1.3.0) | ||||
|     aws-partitions (1.873.0) | ||||
|     aws-sdk-core (3.190.1) | ||||
|       aws-eventstream (~> 1, >= 1.3.0) | ||||
|       aws-partitions (~> 1, >= 1.651.0) | ||||
|       aws-sigv4 (~> 1.5) | ||||
|       aws-sigv4 (~> 1.8) | ||||
|       jmespath (~> 1, >= 1.6.1) | ||||
|     aws-sdk-kms (1.71.0) | ||||
|       aws-sdk-core (~> 3, >= 3.177.0) | ||||
|     aws-sdk-kms (1.75.0) | ||||
|       aws-sdk-core (~> 3, >= 3.188.0) | ||||
|       aws-sigv4 (~> 1.1) | ||||
|     aws-sdk-s3 (1.133.0) | ||||
|       aws-sdk-core (~> 3, >= 3.181.0) | ||||
|     aws-sdk-s3 (1.142.0) | ||||
|       aws-sdk-core (~> 3, >= 3.189.0) | ||||
|       aws-sdk-kms (~> 1) | ||||
|       aws-sigv4 (~> 1.6) | ||||
|     aws-sigv4 (1.6.0) | ||||
|       aws-sigv4 (~> 1.8) | ||||
|     aws-sigv4 (1.8.0) | ||||
|       aws-eventstream (~> 1, >= 1.0.2) | ||||
|     azure-storage-blob (2.0.3) | ||||
|       azure-storage-common (~> 2.0) | ||||
|  | @ -153,8 +136,9 @@ GEM | |||
|       faraday_middleware (~> 1.0, >= 1.0.0.rc1) | ||||
|       net-http-persistent (~> 4.0) | ||||
|       nokogiri (~> 1, >= 1.10.8) | ||||
|     base64 (0.1.1) | ||||
|     bcrypt (3.1.19) | ||||
|     base64 (0.2.0) | ||||
|     bcp47_spec (0.2.1) | ||||
|     bcrypt (3.1.20) | ||||
|     better_errors (2.10.1) | ||||
|       erubi (>= 1.0.0) | ||||
|       rack (>= 0.9.0) | ||||
|  | @ -166,14 +150,15 @@ GEM | |||
|       erubi (~> 1.4) | ||||
|       parser (>= 2.4) | ||||
|       smart_properties | ||||
|     bigdecimal (3.1.4) | ||||
|     bigdecimal (3.1.5) | ||||
|     bindata (2.4.15) | ||||
|     binding_of_caller (1.0.0) | ||||
|       debug_inspector (>= 0.0.1) | ||||
|     blurhash (0.1.7) | ||||
|     bootsnap (1.16.0) | ||||
|     bootsnap (1.17.1) | ||||
|       msgpack (~> 1.2) | ||||
|     brakeman (6.0.1) | ||||
|     brakeman (6.1.1) | ||||
|       racc | ||||
|     browser (5.3.1) | ||||
|     brpoplpush-redis_script (0.1.3) | ||||
|       concurrent-ruby (~> 1.0, >= 1.0.5) | ||||
|  | @ -195,7 +180,7 @@ GEM | |||
|       activesupport | ||||
|     cbor (0.5.9.6) | ||||
|     charlock_holmes (0.7.7) | ||||
|     chewy (7.3.4) | ||||
|     chewy (7.4.0) | ||||
|       activesupport (>= 5.2) | ||||
|       elasticsearch (>= 7.12.0, < 7.14.0) | ||||
|       elasticsearch-dsl | ||||
|  | @ -203,7 +188,7 @@ GEM | |||
|     climate_control (0.2.0) | ||||
|     cocoon (1.2.15) | ||||
|     color_diff (0.1) | ||||
|     concurrent-ruby (1.2.2) | ||||
|     concurrent-ruby (1.2.3) | ||||
|     connection_pool (2.4.1) | ||||
|     cose (1.3.0) | ||||
|       cbor (~> 0.5.9) | ||||
|  | @ -213,11 +198,15 @@ GEM | |||
|     crass (1.0.6) | ||||
|     css_parser (1.14.0) | ||||
|       addressable | ||||
|     csv (3.2.8) | ||||
|     database_cleaner-active_record (2.1.0) | ||||
|       activerecord (>= 5.a) | ||||
|       database_cleaner-core (~> 2.0.0) | ||||
|     database_cleaner-core (2.0.1) | ||||
|     date (3.3.3) | ||||
|     date (3.3.4) | ||||
|     debug (1.9.1) | ||||
|       irb (~> 1.10) | ||||
|       reline (>= 0.3.8) | ||||
|     debug_inspector (1.1.0) | ||||
|     devise (4.9.3) | ||||
|       bcrypt (~> 3.0) | ||||
|  | @ -235,18 +224,18 @@ GEM | |||
|       devise (>= 4.0.0) | ||||
|       rpam2 (~> 4.0) | ||||
|     diff-lcs (1.5.0) | ||||
|     discard (1.2.1) | ||||
|     discard (1.3.0) | ||||
|       activerecord (>= 4.2, < 8) | ||||
|     docile (1.4.0) | ||||
|     domain_name (0.5.20190701) | ||||
|       unf (>= 0.0.5, < 1.0.0) | ||||
|     doorkeeper (5.6.6) | ||||
|     doorkeeper (5.6.8) | ||||
|       railties (>= 5) | ||||
|     dotenv (2.8.1) | ||||
|     dotenv-rails (2.8.1) | ||||
|       dotenv (= 2.8.1) | ||||
|       railties (>= 3.2) | ||||
|     drb (2.1.1) | ||||
|     drb (2.2.0) | ||||
|       ruby2_keywords | ||||
|     ed25519 (1.3.0) | ||||
|     elasticsearch (7.13.3) | ||||
|  | @ -258,13 +247,17 @@ GEM | |||
|     elasticsearch-transport (7.13.3) | ||||
|       faraday (~> 1) | ||||
|       multi_json | ||||
|     email_spec (2.2.2) | ||||
|       htmlentities (~> 4.3.3) | ||||
|       launchy (~> 2.1) | ||||
|       mail (~> 2.7) | ||||
|     encryptor (3.0.0) | ||||
|     erubi (1.12.0) | ||||
|     et-orbi (1.2.7) | ||||
|       tzinfo | ||||
|     excon (0.100.0) | ||||
|     fabrication (2.30.0) | ||||
|     faker (3.2.1) | ||||
|     excon (0.109.0) | ||||
|     fabrication (2.31.0) | ||||
|     faker (3.2.3) | ||||
|       i18n (>= 1.8.11, < 2) | ||||
|     faraday (1.10.3) | ||||
|       faraday-em_http (~> 1.0) | ||||
|  | @ -292,25 +285,24 @@ GEM | |||
|     faraday_middleware (1.2.0) | ||||
|       faraday (~> 1.0) | ||||
|     fast_blank (1.0.1) | ||||
|     fastimage (2.2.7) | ||||
|     fastimage (2.3.0) | ||||
|     ffi (1.15.5) | ||||
|     ffi-compiler (1.0.1) | ||||
|       ffi (>= 1.0.0) | ||||
|       rake | ||||
|     fog-core (2.1.0) | ||||
|     fog-core (2.4.0) | ||||
|       builder | ||||
|       excon (~> 0.58) | ||||
|       formatador (~> 0.2) | ||||
|       excon (~> 0.71) | ||||
|       formatador (>= 0.2, < 2.0) | ||||
|       mime-types | ||||
|     fog-json (1.2.0) | ||||
|       fog-core | ||||
|       multi_json (~> 1.10) | ||||
|     fog-openstack (0.3.10) | ||||
|       fog-core (>= 1.45, <= 2.1.0) | ||||
|     fog-openstack (1.1.0) | ||||
|       fog-core (~> 2.1) | ||||
|       fog-json (>= 1.0) | ||||
|       ipaddress (>= 0.8) | ||||
|     foreman (0.87.2) | ||||
|     formatador (0.3.0) | ||||
|     formatador (1.1.0) | ||||
|     fugit (1.8.1) | ||||
|       et-orbi (~> 1, >= 1.2.7) | ||||
|       raabro (~> 1.4) | ||||
|  | @ -319,7 +311,7 @@ GEM | |||
|       ruby-progressbar (~> 1.4) | ||||
|     globalid (1.2.1) | ||||
|       activesupport (>= 6.1) | ||||
|     haml (6.2.0) | ||||
|     haml (6.3.0) | ||||
|       temple (>= 0.8.2) | ||||
|       thor | ||||
|       tilt | ||||
|  | @ -328,8 +320,8 @@ GEM | |||
|       activesupport (>= 5.1) | ||||
|       haml (>= 4.0.6) | ||||
|       railties (>= 5.1) | ||||
|     haml_lint (0.51.0) | ||||
|       haml (>= 4.0) | ||||
|     haml_lint (0.53.0) | ||||
|       haml (>= 5.0) | ||||
|       parallel (~> 1.10) | ||||
|       rainbow | ||||
|       rubocop (>= 1.0) | ||||
|  | @ -369,30 +361,29 @@ GEM | |||
|       rainbow (>= 2.2.2, < 4.0) | ||||
|       terminal-table (>= 1.5.1) | ||||
|     idn-ruby (0.1.5) | ||||
|     io-console (0.6.0) | ||||
|     ipaddress (0.8.3) | ||||
|     irb (1.8.1) | ||||
|     io-console (0.7.1) | ||||
|     irb (1.11.1) | ||||
|       rdoc | ||||
|       reline (>= 0.3.8) | ||||
|       reline (>= 0.4.2) | ||||
|     jmespath (1.6.2) | ||||
|     json (2.6.3) | ||||
|     json-canonicalization (0.3.2) | ||||
|     json (2.7.1) | ||||
|     json-canonicalization (1.0.0) | ||||
|     json-jwt (1.15.3) | ||||
|       activesupport (>= 4.2) | ||||
|       aes_key_wrap | ||||
|       bindata | ||||
|       httpclient | ||||
|     json-ld (3.2.5) | ||||
|     json-ld (3.3.1) | ||||
|       htmlentities (~> 4.3) | ||||
|       json-canonicalization (~> 0.3, >= 0.3.2) | ||||
|       json-canonicalization (~> 1.0) | ||||
|       link_header (~> 0.0, >= 0.0.8) | ||||
|       multi_json (~> 1.15) | ||||
|       rack (>= 2.2, < 4) | ||||
|       rdf (~> 3.2, >= 3.2.10) | ||||
|     json-ld-preloaded (3.2.2) | ||||
|       json-ld (~> 3.2) | ||||
|       rdf (~> 3.2) | ||||
|     json-schema (4.0.0) | ||||
|       rdf (~> 3.3) | ||||
|     json-ld-preloaded (3.3.0) | ||||
|       json-ld (~> 3.3) | ||||
|       rdf (~> 3.3) | ||||
|     json-schema (4.1.1) | ||||
|       addressable (>= 2.8) | ||||
|     jsonapi-renderer (0.2.2) | ||||
|     jwt (2.7.1) | ||||
|  | @ -433,7 +424,7 @@ GEM | |||
|       activesupport (>= 4) | ||||
|       railties (>= 4) | ||||
|       request_store (~> 1.0) | ||||
|     loofah (2.21.4) | ||||
|     loofah (2.22.0) | ||||
|       crass (~> 1.0.2) | ||||
|       nokogiri (>= 1.12.0) | ||||
|     mail (2.8.1) | ||||
|  | @ -450,39 +441,44 @@ GEM | |||
|       azure-storage-blob (~> 2.0.1) | ||||
|       hashie (~> 5.0) | ||||
|     memory_profiler (1.0.1) | ||||
|     mime-types (3.5.1) | ||||
|     mime-types (3.5.2) | ||||
|       mime-types-data (~> 3.2015) | ||||
|     mime-types-data (3.2023.0808) | ||||
|     mime-types-data (3.2023.1205) | ||||
|     mini_mime (1.1.5) | ||||
|     mini_portile2 (2.8.4) | ||||
|     mini_portile2 (2.8.5) | ||||
|     minitest (5.20.0) | ||||
|     msgpack (1.7.1) | ||||
|     msgpack (1.7.2) | ||||
|     multi_json (1.15.0) | ||||
|     multipart-post (2.3.0) | ||||
|     mutex_m (0.1.2) | ||||
|     net-http (0.3.2) | ||||
|     mutex_m (0.2.0) | ||||
|     net-http (0.4.1) | ||||
|       uri | ||||
|     net-http-persistent (4.0.2) | ||||
|       connection_pool (~> 2.2) | ||||
|     net-imap (0.4.1) | ||||
|     net-imap (0.4.9.1) | ||||
|       date | ||||
|       net-protocol | ||||
|     net-ldap (0.18.0) | ||||
|     net-ldap (0.19.0) | ||||
|     net-pop (0.1.2) | ||||
|       net-protocol | ||||
|     net-protocol (0.2.1) | ||||
|     net-protocol (0.2.2) | ||||
|       timeout | ||||
|     net-smtp (0.4.0) | ||||
|     net-smtp (0.4.0.1) | ||||
|       net-protocol | ||||
|     nio4r (2.5.9) | ||||
|     nokogiri (1.15.4) | ||||
|     nokogiri (1.16.0) | ||||
|       mini_portile2 (~> 2.8.2) | ||||
|       racc (~> 1.4) | ||||
|     oj (3.16.1) | ||||
|     oj (3.16.3) | ||||
|       bigdecimal (>= 3.0) | ||||
|     omniauth (2.1.1) | ||||
|       hashie (>= 3.4.6) | ||||
|       rack (>= 2.2.3) | ||||
|       rack-protection | ||||
|     omniauth-cas (3.0.0.beta.1) | ||||
|       addressable (~> 2.8) | ||||
|       nokogiri (~> 1.12) | ||||
|       omniauth (~> 2.1) | ||||
|     omniauth-rails_csrf_protection (1.0.1) | ||||
|       actionpack (>= 4.2) | ||||
|       omniauth (~> 2.0) | ||||
|  | @ -503,12 +499,12 @@ GEM | |||
|       validate_email | ||||
|       validate_url | ||||
|       webfinger (~> 1.2) | ||||
|     openssl (3.1.0) | ||||
|     openssl (3.2.0) | ||||
|     openssl-signature_algorithm (1.3.0) | ||||
|       openssl (> 2.0) | ||||
|     orm_adapter (0.5.0) | ||||
|     ox (2.14.17) | ||||
|     parallel (1.23.0) | ||||
|     parallel (1.24.0) | ||||
|     parser (3.2.2.4) | ||||
|       ast (~> 2.4.1) | ||||
|       racc | ||||
|  | @ -516,7 +512,7 @@ GEM | |||
|     pastel (0.8.0) | ||||
|       tty-color (~> 0.5) | ||||
|     pg (1.5.4) | ||||
|     pghero (3.3.4) | ||||
|     pghero (3.4.0) | ||||
|       activerecord (>= 6) | ||||
|     posix-spawn (0.3.15) | ||||
|     premailer (1.21.0) | ||||
|  | @ -528,15 +524,20 @@ GEM | |||
|       net-smtp | ||||
|       premailer (~> 1.7, >= 1.7.9) | ||||
|     private_address_check (0.5.0) | ||||
|     psych (5.1.1) | ||||
|     propshaft (0.8.0) | ||||
|       actionpack (>= 7.0.0) | ||||
|       activesupport (>= 7.0.0) | ||||
|       rack | ||||
|       railties (>= 7.0.0) | ||||
|     psych (5.1.2) | ||||
|       stringio | ||||
|     public_suffix (5.0.3) | ||||
|     puma (6.4.0) | ||||
|     public_suffix (5.0.4) | ||||
|     puma (6.4.2) | ||||
|       nio4r (~> 2.0) | ||||
|     pundit (2.3.0) | ||||
|     pundit (2.3.1) | ||||
|       activesupport (>= 3.0.0) | ||||
|     raabro (1.4.0) | ||||
|     racc (1.7.1) | ||||
|     racc (1.7.3) | ||||
|     rack (2.2.8) | ||||
|     rack-attack (6.7.0) | ||||
|       rack (>= 1.0, < 4) | ||||
|  | @ -552,27 +553,27 @@ GEM | |||
|       rack | ||||
|     rack-proxy (0.7.6) | ||||
|       rack | ||||
|     rack-session (1.0.1) | ||||
|     rack-session (1.0.2) | ||||
|       rack (< 3) | ||||
|     rack-test (2.1.0) | ||||
|       rack (>= 1.3) | ||||
|     rackup (1.0.0) | ||||
|       rack (< 3) | ||||
|       webrick | ||||
|     rails (7.1.1) | ||||
|       actioncable (= 7.1.1) | ||||
|       actionmailbox (= 7.1.1) | ||||
|       actionmailer (= 7.1.1) | ||||
|       actionpack (= 7.1.1) | ||||
|       actiontext (= 7.1.1) | ||||
|       actionview (= 7.1.1) | ||||
|       activejob (= 7.1.1) | ||||
|       activemodel (= 7.1.1) | ||||
|       activerecord (= 7.1.1) | ||||
|       activestorage (= 7.1.1) | ||||
|       activesupport (= 7.1.1) | ||||
|     rails (7.1.3) | ||||
|       actioncable (= 7.1.3) | ||||
|       actionmailbox (= 7.1.3) | ||||
|       actionmailer (= 7.1.3) | ||||
|       actionpack (= 7.1.3) | ||||
|       actiontext (= 7.1.3) | ||||
|       actionview (= 7.1.3) | ||||
|       activejob (= 7.1.3) | ||||
|       activemodel (= 7.1.3) | ||||
|       activerecord (= 7.1.3) | ||||
|       activestorage (= 7.1.3) | ||||
|       activesupport (= 7.1.3) | ||||
|       bundler (>= 1.15.0) | ||||
|       railties (= 7.1.1) | ||||
|       railties (= 7.1.3) | ||||
|     rails-controller-testing (1.0.5) | ||||
|       actionpack (>= 5.0.1.rc1) | ||||
|       actionview (>= 5.0.1.rc1) | ||||
|  | @ -587,21 +588,22 @@ GEM | |||
|     rails-i18n (7.0.8) | ||||
|       i18n (>= 0.7, < 2) | ||||
|       railties (>= 6.0.0, < 8) | ||||
|     railties (7.1.1) | ||||
|       actionpack (= 7.1.1) | ||||
|       activesupport (= 7.1.1) | ||||
|     railties (7.1.3) | ||||
|       actionpack (= 7.1.3) | ||||
|       activesupport (= 7.1.3) | ||||
|       irb | ||||
|       rackup (>= 1.0.0) | ||||
|       rake (>= 12.2) | ||||
|       thor (~> 1.0, >= 1.2.2) | ||||
|       zeitwerk (~> 2.6) | ||||
|     rainbow (3.1.1) | ||||
|     rake (13.0.6) | ||||
|     rdf (3.2.11) | ||||
|     rake (13.1.0) | ||||
|     rdf (3.3.1) | ||||
|       bcp47_spec (~> 0.2) | ||||
|       link_header (~> 0.0, >= 0.0.8) | ||||
|     rdf-normalize (0.6.1) | ||||
|       rdf (~> 3.2) | ||||
|     rdoc (6.5.0) | ||||
|     rdoc (6.6.2) | ||||
|       psych (>= 4.0.0) | ||||
|     redcarpet (3.6.0) | ||||
|     redis (4.8.1) | ||||
|  | @ -609,8 +611,8 @@ GEM | |||
|       redis (>= 4) | ||||
|     redlock (1.3.2) | ||||
|       redis (>= 3.0.0, < 6.0) | ||||
|     regexp_parser (2.8.2) | ||||
|     reline (0.3.9) | ||||
|     regexp_parser (2.8.3) | ||||
|     reline (0.4.2) | ||||
|       io-console (~> 0.5) | ||||
|     request_store (1.5.1) | ||||
|       rack (>= 1.4) | ||||
|  | @ -632,10 +634,10 @@ GEM | |||
|       rspec-support (~> 3.12.0) | ||||
|     rspec-github (2.4.0) | ||||
|       rspec-core (~> 3.0) | ||||
|     rspec-mocks (3.12.5) | ||||
|     rspec-mocks (3.12.6) | ||||
|       diff-lcs (>= 1.2.0, < 2.0) | ||||
|       rspec-support (~> 3.12.0) | ||||
|     rspec-rails (6.0.3) | ||||
|     rspec-rails (6.1.0) | ||||
|       actionpack (>= 6.1) | ||||
|       activesupport (>= 6.1) | ||||
|       railties (>= 6.1) | ||||
|  | @ -643,15 +645,13 @@ GEM | |||
|       rspec-expectations (~> 3.12) | ||||
|       rspec-mocks (~> 3.12) | ||||
|       rspec-support (~> 3.12) | ||||
|     rspec-sidekiq (4.0.1) | ||||
|     rspec-sidekiq (4.1.0) | ||||
|       rspec-core (~> 3.0) | ||||
|       rspec-expectations (~> 3.0) | ||||
|       rspec-mocks (~> 3.0) | ||||
|       sidekiq (>= 5, < 8) | ||||
|     rspec-support (3.12.1) | ||||
|     rspec_chunked (0.6) | ||||
|     rubocop (1.57.1) | ||||
|       base64 (~> 0.1.1) | ||||
|     rubocop (1.59.0) | ||||
|       json (~> 2.3) | ||||
|       language_server-protocol (>= 3.17.0) | ||||
|       parallel (~> 1.10) | ||||
|  | @ -659,27 +659,28 @@ GEM | |||
|       rainbow (>= 2.2.2, < 4.0) | ||||
|       regexp_parser (>= 1.8, < 3.0) | ||||
|       rexml (>= 3.2.5, < 4.0) | ||||
|       rubocop-ast (>= 1.28.1, < 2.0) | ||||
|       rubocop-ast (>= 1.30.0, < 2.0) | ||||
|       ruby-progressbar (~> 1.7) | ||||
|       unicode-display_width (>= 2.4.0, < 3.0) | ||||
|     rubocop-ast (1.29.0) | ||||
|     rubocop-ast (1.30.0) | ||||
|       parser (>= 3.2.1.0) | ||||
|     rubocop-capybara (2.19.0) | ||||
|     rubocop-capybara (2.20.0) | ||||
|       rubocop (~> 1.41) | ||||
|     rubocop-factory_bot (2.23.1) | ||||
|     rubocop-factory_bot (2.25.0) | ||||
|       rubocop (~> 1.33) | ||||
|     rubocop-performance (1.19.1) | ||||
|       rubocop (>= 1.7.0, < 2.0) | ||||
|       rubocop-ast (>= 0.4.0) | ||||
|     rubocop-rails (2.20.2) | ||||
|     rubocop-performance (1.20.2) | ||||
|       rubocop (>= 1.48.1, < 2.0) | ||||
|       rubocop-ast (>= 1.30.0, < 2.0) | ||||
|     rubocop-rails (2.23.1) | ||||
|       activesupport (>= 4.2.0) | ||||
|       rack (>= 1.1) | ||||
|       rubocop (>= 1.33.0, < 2.0) | ||||
|     rubocop-rspec (2.23.2) | ||||
|       rubocop (~> 1.33) | ||||
|       rubocop-ast (>= 1.30.0, < 2.0) | ||||
|     rubocop-rspec (2.26.1) | ||||
|       rubocop (~> 1.40) | ||||
|       rubocop-capybara (~> 2.17) | ||||
|       rubocop-factory_bot (~> 2.22) | ||||
|     ruby-prof (1.6.3) | ||||
|     ruby-prof (1.7.0) | ||||
|     ruby-progressbar (1.13.0) | ||||
|     ruby-saml (1.15.0) | ||||
|       nokogiri (>= 1.13.10) | ||||
|  | @ -690,13 +691,13 @@ GEM | |||
|       fugit (~> 1.1, >= 1.1.6) | ||||
|     safety_net_attestation (0.4.0) | ||||
|       jwt (~> 2.0) | ||||
|     sanitize (6.0.2) | ||||
|     sanitize (6.1.0) | ||||
|       crass (~> 1.0.2) | ||||
|       nokogiri (>= 1.12.0) | ||||
|     scenic (1.7.0) | ||||
|       activerecord (>= 4.0.0) | ||||
|       railties (>= 4.0.0) | ||||
|     selenium-webdriver (4.13.1) | ||||
|     selenium-webdriver (4.16.0) | ||||
|       rexml (~> 3.2, >= 3.2.5) | ||||
|       rubyzip (>= 1.2.2, < 3.0) | ||||
|       websocket (~> 1.0) | ||||
|  | @ -711,7 +712,7 @@ GEM | |||
|       rufus-scheduler (~> 3.2) | ||||
|       sidekiq (>= 6, < 8) | ||||
|       tilt (>= 1.4.0) | ||||
|     sidekiq-unique-jobs (7.1.29) | ||||
|     sidekiq-unique-jobs (7.1.31) | ||||
|       brpoplpush-redis_script (> 0.1.1, <= 2.0.0) | ||||
|       concurrent-ruby (~> 1.0, >= 1.0.5) | ||||
|       redis (< 5.0) | ||||
|  | @ -719,7 +720,7 @@ GEM | |||
|       thor (>= 0.20, < 3.0) | ||||
|     simple-navigation (4.4.0) | ||||
|       activesupport (>= 2.3.2) | ||||
|     simple_form (5.2.0) | ||||
|     simple_form (5.3.0) | ||||
|       actionpack (>= 5.2) | ||||
|       activemodel (>= 5.2) | ||||
|     simplecov (0.22.0) | ||||
|  | @ -727,36 +728,30 @@ GEM | |||
|       simplecov-html (~> 0.11) | ||||
|       simplecov_json_formatter (~> 0.1) | ||||
|     simplecov-html (0.12.3) | ||||
|     simplecov-lcov (0.8.0) | ||||
|     simplecov_json_formatter (0.1.4) | ||||
|     smart_properties (1.17.0) | ||||
|     sprockets (3.7.2) | ||||
|       concurrent-ruby (~> 1.0) | ||||
|       rack (> 1, < 3) | ||||
|     sprockets-rails (3.4.2) | ||||
|       actionpack (>= 5.2) | ||||
|       activesupport (>= 5.2) | ||||
|       sprockets (>= 3.0.0) | ||||
|     stackprof (0.2.25) | ||||
|     stackprof (0.2.26) | ||||
|     statsd-ruby (1.5.0) | ||||
|     stoplight (3.0.2) | ||||
|       redlock (~> 1.0) | ||||
|     stringio (3.0.8) | ||||
|     strong_migrations (0.8.0) | ||||
|     stringio (3.1.0) | ||||
|     strong_migrations (1.7.0) | ||||
|       activerecord (>= 5.2) | ||||
|     swd (1.3.0) | ||||
|       activesupport (>= 3) | ||||
|       attr_required (>= 0.0.5) | ||||
|       httpclient (>= 2.4) | ||||
|     sysexits (1.2.0) | ||||
|     temple (0.10.2) | ||||
|     temple (0.10.3) | ||||
|     terminal-table (3.0.2) | ||||
|       unicode-display_width (>= 1.1.1, < 3) | ||||
|     terrapin (0.6.0) | ||||
|       climate_control (>= 0.0.3, < 1.0) | ||||
|     test-prof (1.2.3) | ||||
|     thor (1.2.2) | ||||
|     test-prof (1.3.1) | ||||
|     thor (1.3.0) | ||||
|     tilt (2.3.0) | ||||
|     timeout (0.4.0) | ||||
|     timeout (0.4.1) | ||||
|     tpm-key_attestation (0.12.0) | ||||
|       bindata (~> 2.4) | ||||
|       openssl (> 2.0) | ||||
|  | @ -776,7 +771,7 @@ GEM | |||
|       unf (~> 0.1.0) | ||||
|     tzinfo (2.0.6) | ||||
|       concurrent-ruby (~> 1.0) | ||||
|     tzinfo-data (1.2023.3) | ||||
|     tzinfo-data (1.2023.4) | ||||
|       tzinfo (>= 1.0.0) | ||||
|     unf (0.1.4) | ||||
|       unf_ext | ||||
|  | @ -791,7 +786,7 @@ GEM | |||
|       public_suffix | ||||
|     warden (1.2.9) | ||||
|       rack (>= 2.0.9) | ||||
|     webauthn (3.0.0) | ||||
|     webauthn (3.1.0) | ||||
|       android_key_attestation (~> 0.3.0) | ||||
|       awrence (~> 1.1) | ||||
|       bindata (~> 2.4) | ||||
|  | @ -834,7 +829,7 @@ DEPENDENCIES | |||
|   better_errors (~> 2.9) | ||||
|   binding_of_caller (~> 1.0) | ||||
|   blurhash (~> 0.1) | ||||
|   bootsnap (~> 1.16.0) | ||||
|   bootsnap (~> 1.17.0) | ||||
|   brakeman (~> 6.0) | ||||
|   browser | ||||
|   bundler-audit (~> 0.9) | ||||
|  | @ -846,7 +841,9 @@ DEPENDENCIES | |||
|   color_diff (~> 0.1) | ||||
|   concurrent-ruby | ||||
|   connection_pool | ||||
|   csv (~> 3.2) | ||||
|   database_cleaner-active_record | ||||
|   debug (~> 1.8) | ||||
|   devise (~> 4.9) | ||||
|   devise-two-factor (~> 4.1) | ||||
|   devise_pam_authenticatable2 (~> 9.2) | ||||
|  | @ -854,12 +851,13 @@ DEPENDENCIES | |||
|   doorkeeper (~> 5.6) | ||||
|   dotenv-rails (~> 2.8) | ||||
|   ed25519 (~> 1.3) | ||||
|   email_spec | ||||
|   fabrication (~> 2.30) | ||||
|   faker (~> 3.2) | ||||
|   fast_blank (~> 1.0) | ||||
|   fastimage | ||||
|   fog-core (<= 2.4.0) | ||||
|   fog-openstack (~> 0.3) | ||||
|   fog-openstack (~> 1.0) | ||||
|   foreman | ||||
|   fuubar (~> 2.5) | ||||
|   haml-rails (~> 2.0) | ||||
|  | @ -872,6 +870,7 @@ DEPENDENCIES | |||
|   httplog (~> 1.6.2) | ||||
|   i18n-tasks (~> 1.0) | ||||
|   idn-ruby | ||||
|   irb (~> 1.8) | ||||
|   json-ld | ||||
|   json-ld-preloaded (~> 3.2) | ||||
|   json-schema (~> 4.0) | ||||
|  | @ -885,13 +884,13 @@ DEPENDENCIES | |||
|   md-paperclip-azure (~> 2.2) | ||||
|   memory_profiler | ||||
|   mime-types (~> 3.5.0) | ||||
|   net-http (~> 0.3.2) | ||||
|   net-http (~> 0.4.0) | ||||
|   net-ldap (~> 0.18) | ||||
|   nokogiri (~> 1.15) | ||||
|   nsa! | ||||
|   oj (~> 3.14) | ||||
|   omniauth (~> 2.0) | ||||
|   omniauth-cas! | ||||
|   omniauth-cas (~> 3.0.0.beta.1) | ||||
|   omniauth-rails_csrf_protection (~> 1.0) | ||||
|   omniauth-saml (~> 2.0) | ||||
|   omniauth_openid_connect (~> 0.6.1) | ||||
|  | @ -902,6 +901,7 @@ DEPENDENCIES | |||
|   posix-spawn | ||||
|   premailer-rails | ||||
|   private_address_check (~> 0.5) | ||||
|   propshaft | ||||
|   public_suffix (~> 5.0) | ||||
|   puma (~> 6.3) | ||||
|   pundit (~> 2.3) | ||||
|  | @ -912,7 +912,6 @@ DEPENDENCIES | |||
|   rails (~> 7.1.1) | ||||
|   rails-controller-testing (~> 1.0) | ||||
|   rails-i18n (~> 7.0) | ||||
|   rails-settings-cached (~> 0.6)! | ||||
|   rdf-normalize (~> 0.5) | ||||
|   redcarpet (~> 3.6) | ||||
|   redis (~> 4.5) | ||||
|  | @ -921,7 +920,6 @@ DEPENDENCIES | |||
|   rspec-github (~> 2.4) | ||||
|   rspec-rails (~> 6.0) | ||||
|   rspec-sidekiq (~> 4.0) | ||||
|   rspec_chunked (~> 0.6) | ||||
|   rubocop | ||||
|   rubocop-capybara | ||||
|   rubocop-performance | ||||
|  | @ -940,11 +938,10 @@ DEPENDENCIES | |||
|   simple-navigation (~> 4.4) | ||||
|   simple_form (~> 5.2) | ||||
|   simplecov (~> 0.22) | ||||
|   sprockets (~> 3.7.2) | ||||
|   sprockets-rails (~> 3.4) | ||||
|   simplecov-lcov (~> 0.8) | ||||
|   stackprof | ||||
|   stoplight (~> 3.0.1) | ||||
|   strong_migrations (~> 0.8) | ||||
|   strong_migrations (= 1.7.0) | ||||
|   test-prof | ||||
|   thor (~> 1.2) | ||||
|   tty-prompt (~> 0.23) | ||||
|  | @ -960,4 +957,4 @@ RUBY VERSION | |||
|    ruby 3.2.2p53 | ||||
| 
 | ||||
| BUNDLED WITH | ||||
|    2.4.20 | ||||
|    2.5.4 | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| web: env PORT=3000 RAILS_ENV=development bundle exec puma -C config/puma.rb | ||||
| sidekiq: env PORT=3000 RAILS_ENV=development bundle exec sidekiq | ||||
| stream: env PORT=4000 yarn run start | ||||
| webpack: env RAILS_ENV=development NODE_ENV=development NODE_OPTIONS=--openssl-legacy-provider ./bin/webpack-dev-server --listen-host 0.0.0.0 | ||||
| stream: env PORT=4000 yarn workspace @mastodon/streaming start | ||||
| webpack: bin/webpack-dev-server | ||||
| caddy: caddy run | ||||
|  |  | |||
							
								
								
									
										12
									
								
								SECURITY.md
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								SECURITY.md
									
									
									
									
									
								
							|  | @ -13,10 +13,8 @@ A "vulnerability in Mastodon" is a vulnerability in the code distributed through | |||
| 
 | ||||
| ## Supported Versions | ||||
| 
 | ||||
| | Version | Supported        | | ||||
| | ------- | ---------------- | | ||||
| | 4.2.x   | Yes              | | ||||
| | 4.1.x   | Yes              | | ||||
| | 4.0.x   | Until 2023-10-31 | | ||||
| | 3.5.x   | Until 2023-12-31 | | ||||
| | < 3.5   | No               | | ||||
| | Version | Supported | | ||||
| | ------- | --------- | | ||||
| | 4.2.x   | Yes       | | ||||
| | 4.1.x   | Yes       | | ||||
| | < 4.1   | No        | | ||||
|  |  | |||
							
								
								
									
										10
									
								
								Vagrantfile
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								Vagrantfile
									
									
									
									
										vendored
									
									
								
							|  | @ -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' | ||||
| 
 | ||||
| # 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 | ||||
| sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port #{ENV["PORT"]} | ||||
|  | @ -112,11 +116,11 @@ bundle install | |||
| 
 | ||||
| # Install node modules | ||||
| sudo corepack enable | ||||
| yarn set version classic | ||||
| corepack prepare | ||||
| yarn install | ||||
| 
 | ||||
| # Build Mastodon | ||||
| export RAILS_ENV=development  | ||||
| export RAILS_ENV=development | ||||
| export $(cat ".env.vagrant" | xargs) | ||||
| bundle exec rails db:setup | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,6 +1,8 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class AccountsIndex < Chewy::Index | ||||
|   include DatetimeClampingConcern | ||||
| 
 | ||||
|   settings index: index_preset(refresh_interval: '30s'), analysis: { | ||||
|     filter: { | ||||
|       english_stop: { | ||||
|  | @ -60,7 +62,7 @@ class AccountsIndex < Chewy::Index | |||
|     field(:following_count, type: 'long') | ||||
|     field(:followers_count, type: 'long') | ||||
|     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(:username, type: 'text', analyzer: 'verbatim', value: ->(account) { [account.username, account.domain].compact.join('@') }) { field :edge_ngram, type: 'text', analyzer: 'edge_ngram', search_analyzer: 'verbatim' } | ||||
|     field(:text, type: 'text', analyzer: 'verbatim', value: ->(account) { account.searchable_text }) { field :stemmed, type: 'text', analyzer: 'natural' } | ||||
|  |  | |||
							
								
								
									
										14
									
								
								app/chewy/concerns/datetime_clamping_concern.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								app/chewy/concerns/datetime_clamping_concern.rb
									
									
									
									
									
										Normal 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 | ||||
|  | @ -1,6 +1,8 @@ | |||
| # 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: { | ||||
|  | @ -53,7 +55,7 @@ class PublicStatusesIndex < Chewy::Index | |||
|   index_scope ::Status.unscoped | ||||
|                       .kept | ||||
|                       .indexable | ||||
|                       .includes(:media_attachments, :preloadable_poll, :preview_cards, :tags) | ||||
|                       .includes(:media_attachments, :preloadable_poll, :tags, preview_cards_status: :preview_card) | ||||
| 
 | ||||
|   root date_detection: false do | ||||
|     field(:id, type: 'long') | ||||
|  | @ -62,6 +64,6 @@ class PublicStatusesIndex < Chewy::Index | |||
|     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') | ||||
|     field(:created_at, type: 'date', value: ->(status) { clamp_date(status.created_at) }) | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,6 +1,8 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class StatusesIndex < Chewy::Index | ||||
|   include DatetimeClampingConcern | ||||
| 
 | ||||
|   settings index: index_preset(refresh_interval: '30s', number_of_shards: 5), analysis: { | ||||
|     filter: { | ||||
|       english_stop: { | ||||
|  | @ -50,7 +52,7 @@ class StatusesIndex < Chewy::Index | |||
|     }, | ||||
|   } | ||||
| 
 | ||||
|   index_scope ::Status.unscoped.kept.without_reblogs.includes(:media_attachments, :preview_cards, :local_mentioned, :local_favorited, :local_reblogged, :local_bookmarked, :tags, preloadable_poll: :local_voters), delete_if: ->(status) { status.searchable_by.empty? } | ||||
|   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? } | ||||
| 
 | ||||
|   root date_detection: false do | ||||
|     field(:id, type: 'long') | ||||
|  | @ -60,6 +62,6 @@ class StatusesIndex < Chewy::Index | |||
|     field(:searchable_by, type: 'long', value: ->(status) { status.searchable_by }) | ||||
|     field(:language, type: 'keyword') | ||||
|     field(:properties, type: 'keyword', value: ->(status) { status.searchable_properties }) | ||||
|     field(:created_at, type: 'date') | ||||
|     field(:created_at, type: 'date', value: ->(status) { clamp_date(status.created_at) }) | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,6 +1,8 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class TagsIndex < Chewy::Index | ||||
|   include DatetimeClampingConcern | ||||
| 
 | ||||
|   settings index: index_preset(refresh_interval: '30s'), analysis: { | ||||
|     analyzer: { | ||||
|       content: { | ||||
|  | @ -42,6 +44,6 @@ class TagsIndex < Chewy::Index | |||
|     field(:name, type: 'text', analyzer: 'content', value: :display_name) { field(:edge_ngram, type: 'text', analyzer: 'edge_ngram', search_analyzer: 'content') } | ||||
|     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 }) | ||||
|     field(:last_status_at, type: 'date', value: ->(tag) { clamp_date(tag.last_status_at || tag.created_at) }) | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -18,8 +18,6 @@ class AccountsController < ApplicationController | |||
|     respond_to do |format| | ||||
|       format.html do | ||||
|         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 | ||||
| 
 | ||||
|       format.rss do | ||||
|  | @ -52,7 +50,7 @@ class AccountsController < ApplicationController | |||
|   end | ||||
| 
 | ||||
|   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 | ||||
| 
 | ||||
|   def no_replies_scope | ||||
|  | @ -84,29 +82,21 @@ class AccountsController < ApplicationController | |||
|       short_account_url(@account, format: 'rss') | ||||
|     end | ||||
|   end | ||||
|   helper_method :rss_url | ||||
| 
 | ||||
|   def media_requested? | ||||
|     request.path.split('.').first.end_with?('/media') && !tag_requested? | ||||
|     path_without_format.end_with?('/media') && !tag_requested? | ||||
|   end | ||||
| 
 | ||||
|   def replies_requested? | ||||
|     request.path.split('.').first.end_with?('/with_replies') && !tag_requested? | ||||
|     path_without_format.end_with?('/with_replies') && !tag_requested? | ||||
|   end | ||||
| 
 | ||||
|   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 | ||||
| 
 | ||||
|   def cached_filtered_status_page | ||||
|     cache_collection_paginated_by_id( | ||||
|       filtered_statuses, | ||||
|       Status, | ||||
|       PAGE_SIZE, | ||||
|       params_slice(:max_id, :min_id, :since_id) | ||||
|     ) | ||||
|   end | ||||
| 
 | ||||
|   def params_slice(*keys) | ||||
|     params.slice(*keys).permit(*keys) | ||||
|   def path_without_format | ||||
|     request.path.split('.').first | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -21,7 +21,7 @@ module Admin | |||
|       account_action.save! | ||||
| 
 | ||||
|       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 | ||||
|         redirect_to admin_account_path(@account.id) | ||||
|       end | ||||
|  |  | |||
|  | @ -16,7 +16,7 @@ module Admin | |||
|         @moderation_notes = @account.targeted_moderation_notes.latest | ||||
|         @warnings         = @account.strikes.custom.latest | ||||
| 
 | ||||
|         render template: 'admin/accounts/show' | ||||
|         render 'admin/accounts/show' | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ module Admin | |||
| 
 | ||||
|     def index | ||||
|       authorize :audit_log, :index? | ||||
|       @auditable_accounts = Account.where(id: Admin::ActionLog.reorder(nil).select('distinct account_id')).select(:id, :username) | ||||
|       @auditable_accounts = Account.where(id: Admin::ActionLog.select('distinct account_id')).select(:id, :username) | ||||
|     end | ||||
| 
 | ||||
|     private | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ module Admin | |||
| 
 | ||||
|     def create | ||||
|       authorize @user, :confirm? | ||||
|       @user.confirm! | ||||
|       @user.mark_email_as_confirmed! | ||||
|       log_action :confirm, @user | ||||
|       redirect_to admin_accounts_path | ||||
|     end | ||||
|  |  | |||
|  | @ -20,7 +20,7 @@ class Admin::Disputes::AppealsController < Admin::BaseController | |||
|     authorize @appeal, :approve? | ||||
|     log_action :reject, @appeal | ||||
|     @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) | ||||
|   end | ||||
| 
 | ||||
|  |  | |||
|  | @ -33,7 +33,7 @@ module Admin | |||
| 
 | ||||
|       # Disallow accidentally downgrading a 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 | ||||
|         @domain_block.errors.delete(:domain) | ||||
|         return render :new | ||||
|  |  | |||
|  | @ -40,7 +40,7 @@ module Admin | |||
|           (@email_domain_block.other_domains || []).uniq.each do |domain| | ||||
|             next if EmailDomainBlock.where(domain: domain).exists? | ||||
| 
 | ||||
|             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 | ||||
|           end | ||||
|         end | ||||
|  | @ -65,7 +65,7 @@ module Admin | |||
|     end | ||||
| 
 | ||||
|     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 | ||||
| 
 | ||||
|     def form_email_domain_block_batch_params | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ require 'csv' | |||
| 
 | ||||
| module Admin | ||||
|   class ExportDomainAllowsController < BaseController | ||||
|     include AdminExportControllerConcern | ||||
|     include Admin::ExportControllerConcern | ||||
| 
 | ||||
|     before_action :set_dummy_import!, only: [:new] | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ require 'csv' | |||
| 
 | ||||
| module Admin | ||||
|   class ExportDomainBlocksController < BaseController | ||||
|     include AdminExportControllerConcern | ||||
|     include Admin::ExportControllerConcern | ||||
| 
 | ||||
|     before_action :set_dummy_import!, only: [:new] | ||||
| 
 | ||||
|  | @ -68,7 +68,7 @@ module Admin | |||
| 
 | ||||
|     def export_data | ||||
|       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] | ||||
|         end | ||||
|       end | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ module Admin | |||
|       authorize :follow_recommendation, :show? | ||||
| 
 | ||||
|       @form     = Form::AccountBatch.new | ||||
|       @accounts = filtered_follow_recommendations | ||||
|       @accounts = filtered_follow_recommendations.page(params[:page]) | ||||
|     end | ||||
| 
 | ||||
|     def update | ||||
|  |  | |||
|  | @ -24,7 +24,7 @@ module Admin | |||
|         @relay.enable! | ||||
|         redirect_to admin_relays_path | ||||
|       else | ||||
|         render action: :new | ||||
|         render :new | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|  |  | |||
|  | @ -26,7 +26,7 @@ module Admin | |||
|         @form         = Admin::StatusBatchAction.new | ||||
|         @statuses     = @report.statuses.with_includes | ||||
| 
 | ||||
|         render template: 'admin/reports/show' | ||||
|         render 'admin/reports/show' | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|  |  | |||
|  | @ -31,6 +31,11 @@ module Admin | |||
| 
 | ||||
|     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 | ||||
|       params.require(:admin_status_batch_action).permit(status_ids: []) | ||||
|     end | ||||
|  |  | |||
|  | @ -4,9 +4,10 @@ class Api::BaseController < ApplicationController | |||
|   DEFAULT_STATUSES_LIMIT = 20 | ||||
|   DEFAULT_ACCOUNTS_LIMIT = 40 | ||||
| 
 | ||||
|   include RateLimitHeaders | ||||
|   include AccessTokenTrackingConcern | ||||
|   include ApiCachingConcern | ||||
|   include Api::RateLimitHeaders | ||||
|   include Api::AccessTokenTrackingConcern | ||||
|   include Api::CachingConcern | ||||
|   include Api::ContentSecurityPolicy | ||||
| 
 | ||||
|   skip_before_action :require_functional!, unless: :limited_federation_mode? | ||||
| 
 | ||||
|  | @ -17,26 +18,6 @@ class Api::BaseController < ApplicationController | |||
| 
 | ||||
|   protect_from_forgery with: :null_session | ||||
| 
 | ||||
|   content_security_policy do |p| | ||||
|     # Set every directive that does not have a fallback | ||||
|     p.default_src :none | ||||
|     p.frame_ancestors :none | ||||
|     p.form_action :none | ||||
| 
 | ||||
|     # Disable every directive with a fallback to cut on response size | ||||
|     p.base_uri false | ||||
|     p.font_src false | ||||
|     p.img_src false | ||||
|     p.style_src false | ||||
|     p.media_src false | ||||
|     p.frame_src false | ||||
|     p.manifest_src false | ||||
|     p.connect_src false | ||||
|     p.script_src false | ||||
|     p.child_src false | ||||
|     p.worker_src false | ||||
|   end | ||||
| 
 | ||||
|   rescue_from ActiveRecord::RecordInvalid, Mastodon::ValidationError do |e| | ||||
|     render json: { error: e.to_s }, status: 422 | ||||
|   end | ||||
|  | @ -83,7 +64,7 @@ class Api::BaseController < ApplicationController | |||
|   end | ||||
| 
 | ||||
|   def doorkeeper_unauthorized_render_options(error: nil) | ||||
|     { json: { error: (error.try(:description) || 'Not authorized') } } | ||||
|     { json: { error: error.try(:description) || 'Not authorized' } } | ||||
|   end | ||||
| 
 | ||||
|   def doorkeeper_forbidden_render_options(*) | ||||
|  | @ -124,7 +105,11 @@ class Api::BaseController < ApplicationController | |||
|   end | ||||
| 
 | ||||
|   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 | ||||
| 
 | ||||
|   def require_user! | ||||
|  | @ -155,6 +140,10 @@ class Api::BaseController < ApplicationController | |||
| 
 | ||||
|   private | ||||
| 
 | ||||
|   def pagination_options_invalid? | ||||
|     params.slice(:limit, :offset).values.map(&:to_i).any?(&:negative?) | ||||
|   end | ||||
| 
 | ||||
|   def respond_with_error(code) | ||||
|     render json: { error: Rack::Utils::HTTP_STATUS_CODES[code] }, status: code | ||||
|   end | ||||
|  |  | |||
|  | @ -16,6 +16,8 @@ class Api::V1::Accounts::CredentialsController < Api::BaseController | |||
|     current_user.update(user_params) if user_params | ||||
|     ActivityPub::UpdateDistributionWorker.perform_async(@account.id) | ||||
|     render json: @account, serializer: REST::CredentialAccountSerializer | ||||
|   rescue ActiveRecord::RecordInvalid => e | ||||
|     render json: ValidationErrorFormatter.new(e).as_json, status: 422 | ||||
|   end | ||||
| 
 | ||||
|   private | ||||
|  |  | |||
|  | @ -12,7 +12,7 @@ class Api::V1::Accounts::FamiliarFollowersController < Api::BaseController | |||
|   private | ||||
| 
 | ||||
|   def set_accounts | ||||
|     @accounts = Account.without_suspended.where(id: account_ids).select('id, hide_collections').index_by(&:id).values_at(*account_ids).compact | ||||
|     @accounts = Account.without_suspended.where(id: account_ids).select('id, hide_collections') | ||||
|   end | ||||
| 
 | ||||
|   def familiar_followers | ||||
|  |  | |||
|  | @ -26,7 +26,7 @@ class Api::V1::Accounts::FollowerAccountsController < Api::BaseController | |||
|   end | ||||
| 
 | ||||
|   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 | ||||
| 
 | ||||
|   def default_accounts | ||||
|  |  | |||
|  | @ -26,7 +26,7 @@ class Api::V1::Accounts::FollowingAccountsController < Api::BaseController | |||
|   end | ||||
| 
 | ||||
|   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 | ||||
| 
 | ||||
|   def default_accounts | ||||
|  |  | |||
|  | @ -25,6 +25,6 @@ class Api::V1::Accounts::NotesController < Api::BaseController | |||
|   end | ||||
| 
 | ||||
|   def relationships_presenter | ||||
|     AccountRelationshipsPresenter.new([@account.id], current_user.account_id) | ||||
|     AccountRelationshipsPresenter.new([@account], current_user.account_id) | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -25,6 +25,6 @@ class Api::V1::Accounts::PinsController < Api::BaseController | |||
|   end | ||||
| 
 | ||||
|   def relationships_presenter | ||||
|     AccountRelationshipsPresenter.new([@account.id], current_user.account_id) | ||||
|     AccountRelationshipsPresenter.new([@account], current_user.account_id) | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -5,10 +5,8 @@ class Api::V1::Accounts::RelationshipsController < Api::BaseController | |||
|   before_action :require_user! | ||||
| 
 | ||||
|   def index | ||||
|     accounts = Account.where(id: account_ids).select('id') | ||||
|     # .where doesn't guarantee that our results are in the same order | ||||
|     # we requested them, so return the "right" order to the requestor. | ||||
|     @accounts = accounts.index_by(&:id).values_at(*account_ids).compact | ||||
|     @accounts = Account.where(id: account_ids).select(:id, :domain) | ||||
|     @accounts.merge!(Account.without_suspended) unless truthy_param?(:with_suspended) | ||||
|     render json: @accounts, each_serializer: REST::RelationshipSerializer, relationships: relationships | ||||
|   end | ||||
| 
 | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ class Api::V1::Accounts::StatusesController < Api::BaseController | |||
|   end | ||||
| 
 | ||||
|   def load_statuses | ||||
|     @account.suspended? ? [] : cached_account_statuses | ||||
|     @account.unavailable? ? [] : cached_account_statuses | ||||
|   end | ||||
| 
 | ||||
|   def cached_account_statuses | ||||
|  |  | |||
|  | @ -1,6 +1,8 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| 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 -> { doorkeeper_authorize! :follow, :write, :'write:follows' }, only: [:follow, :unfollow, :remove_from_followers] | ||||
|   before_action -> { doorkeeper_authorize! :follow, :write, :'write:mutes' }, only: [:mute, :unmute] | ||||
|  | @ -47,7 +49,7 @@ class Api::V1::AccountsController < Api::BaseController | |||
|   end | ||||
| 
 | ||||
|   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 | ||||
|   end | ||||
| 
 | ||||
|  | @ -86,22 +88,18 @@ class Api::V1::AccountsController < Api::BaseController | |||
|   end | ||||
| 
 | ||||
|   def relationships(**options) | ||||
|     AccountRelationshipsPresenter.new([@account.id], current_user.account_id, **options) | ||||
|     AccountRelationshipsPresenter.new([@account], current_user.account_id, **options) | ||||
|   end | ||||
| 
 | ||||
|   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 | ||||
| 
 | ||||
|   def check_enabled_registrations | ||||
|     forbidden if single_user_mode? || omniauth_only? || !allowed_registrations? | ||||
|   end | ||||
| 
 | ||||
|   def allowed_registrations? | ||||
|     Setting.registrations_mode != 'none' | ||||
|   end | ||||
| 
 | ||||
|   def omniauth_only? | ||||
|     ENV['OMNIAUTH_ONLY'] == 'true' | ||||
|     forbidden unless allowed_registration?(request.remote_ip, invite) | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -55,7 +55,7 @@ class Api::V1::Admin::EmailDomainBlocksController < Api::BaseController | |||
|   end | ||||
| 
 | ||||
|   def resource_params | ||||
|     params.permit(:domain) | ||||
|     params.permit(:domain, :allow_with_approval) | ||||
|   end | ||||
| 
 | ||||
|   def insert_pagination_headers | ||||
|  |  | |||
|  | @ -41,10 +41,10 @@ class Api::V1::ConversationsController < Api::BaseController | |||
|                          account: :account_stat, | ||||
|                          last_status: [ | ||||
|                            :media_attachments, | ||||
|                            :preview_cards, | ||||
|                            :status_stat, | ||||
|                            :tags, | ||||
|                            { | ||||
|                              preview_cards_status: :preview_card, | ||||
|                              active_mentions: [account: :account_stat], | ||||
|                              account: :account_stat, | ||||
|                            }, | ||||
|  |  | |||
|  | @ -12,7 +12,7 @@ class Api::V1::DirectoriesController < Api::BaseController | |||
|   private | ||||
| 
 | ||||
|   def require_enabled! | ||||
|     return not_found unless Setting.profile_directory | ||||
|     not_found unless Setting.profile_directory | ||||
|   end | ||||
| 
 | ||||
|   def set_accounts | ||||
|  |  | |||
|  | @ -25,11 +25,11 @@ class Api::V1::FollowRequestsController < Api::BaseController | |||
|   private | ||||
| 
 | ||||
|   def account | ||||
|     Account.find(params[:id]) | ||||
|     @account ||= Account.find(params[:id]) | ||||
|   end | ||||
| 
 | ||||
|   def relationships(**options) | ||||
|     AccountRelationshipsPresenter.new([params[:id]], current_user.account_id, **options) | ||||
|     AccountRelationshipsPresenter.new([account], current_user.account_id, **options) | ||||
|   end | ||||
| 
 | ||||
|   def load_accounts | ||||
|  |  | |||
|  | @ -1,11 +1,9 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class Api::V1::Instances::ActivityController < Api::BaseController | ||||
| class Api::V1::Instances::ActivityController < Api::V1::Instances::BaseController | ||||
|   before_action :require_enabled_api! | ||||
| 
 | ||||
|   skip_before_action :require_authenticated_user!, unless: :limited_federation_mode? | ||||
| 
 | ||||
|   vary_by '' | ||||
|   WEEKS_OF_ACTIVITY = 12 | ||||
| 
 | ||||
|   def show | ||||
|     cache_even_if_authenticated! | ||||
|  | @ -15,23 +13,40 @@ class Api::V1::Instances::ActivityController < Api::BaseController | |||
|   private | ||||
| 
 | ||||
|   def activity | ||||
|     statuses_tracker      = ActivityTracker.new('activity:statuses:local', :basic) | ||||
|     logins_tracker        = ActivityTracker.new('activity:logins', :unique) | ||||
|     registrations_tracker = ActivityTracker.new('activity:accounts:local', :basic) | ||||
| 
 | ||||
|     (0...12).map do |i| | ||||
|       start_of_week = i.weeks.ago | ||||
|       end_of_week   = start_of_week + 6.days | ||||
| 
 | ||||
|       { | ||||
|         week: start_of_week.to_i.to_s, | ||||
|         statuses: statuses_tracker.sum(start_of_week, end_of_week).to_s, | ||||
|         logins: logins_tracker.sum(start_of_week, end_of_week).to_s, | ||||
|         registrations: registrations_tracker.sum(start_of_week, end_of_week).to_s, | ||||
|       } | ||||
|     activity_weeks.map do |weeks_ago| | ||||
|       activity_json(*week_edge_days(weeks_ago)) | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def activity_json(start_of_week, end_of_week) | ||||
|     { | ||||
|       week: start_of_week.to_i.to_s, | ||||
|       statuses: statuses_tracker.sum(start_of_week, end_of_week).to_s, | ||||
|       logins: logins_tracker.sum(start_of_week, end_of_week).to_s, | ||||
|       registrations: registrations_tracker.sum(start_of_week, end_of_week).to_s, | ||||
|     } | ||||
|   end | ||||
| 
 | ||||
|   def activity_weeks | ||||
|     0...WEEKS_OF_ACTIVITY | ||||
|   end | ||||
| 
 | ||||
|   def week_edge_days(num) | ||||
|     [num.weeks.ago, num.weeks.ago + 6.days] | ||||
|   end | ||||
| 
 | ||||
|   def statuses_tracker | ||||
|     ActivityTracker.new('activity:statuses:local', :basic) | ||||
|   end | ||||
| 
 | ||||
|   def logins_tracker | ||||
|     ActivityTracker.new('activity:logins', :unique) | ||||
|   end | ||||
| 
 | ||||
|   def registrations_tracker | ||||
|     ActivityTracker.new('activity:accounts:local', :basic) | ||||
|   end | ||||
| 
 | ||||
|   def require_enabled_api! | ||||
|     head 404 unless Setting.activity_api_enabled && !limited_federation_mode? | ||||
|   end | ||||
|  |  | |||
							
								
								
									
										8
									
								
								app/controllers/api/v1/instances/base_controller.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								app/controllers/api/v1/instances/base_controller.rb
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class Api::V1::Instances::BaseController < Api::BaseController | ||||
|   skip_before_action :require_authenticated_user!, | ||||
|                      unless: :limited_federation_mode? | ||||
| 
 | ||||
|   vary_by '' | ||||
| end | ||||
|  | @ -1,8 +1,6 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class Api::V1::Instances::DomainBlocksController < Api::BaseController | ||||
|   skip_before_action :require_authenticated_user!, unless: :limited_federation_mode? | ||||
| 
 | ||||
| class Api::V1::Instances::DomainBlocksController < Api::V1::Instances::BaseController | ||||
|   before_action :require_enabled_api! | ||||
|   before_action :set_domain_blocks | ||||
| 
 | ||||
|  | @ -15,16 +13,40 @@ class Api::V1::Instances::DomainBlocksController < Api::BaseController | |||
|       cache_if_unauthenticated! | ||||
|     end | ||||
| 
 | ||||
|     render json: @domain_blocks, each_serializer: REST::DomainBlockSerializer, with_comment: (Setting.show_domain_blocks_rationale == 'all' || (Setting.show_domain_blocks_rationale == 'users' && user_signed_in?)) | ||||
|     render json: @domain_blocks, each_serializer: REST::DomainBlockSerializer, with_comment: show_rationale_in_response? | ||||
|   end | ||||
| 
 | ||||
|   private | ||||
| 
 | ||||
|   def require_enabled_api! | ||||
|     head 404 unless Setting.show_domain_blocks == 'all' || (Setting.show_domain_blocks == 'users' && user_signed_in?) | ||||
|     head 404 unless api_enabled? | ||||
|   end | ||||
| 
 | ||||
|   def api_enabled? | ||||
|     show_domain_blocks_for_all? || show_domain_blocks_to_user? | ||||
|   end | ||||
| 
 | ||||
|   def show_domain_blocks_for_all? | ||||
|     Setting.show_domain_blocks == 'all' | ||||
|   end | ||||
| 
 | ||||
|   def show_domain_blocks_to_user? | ||||
|     Setting.show_domain_blocks == 'users' && user_signed_in? | ||||
|   end | ||||
| 
 | ||||
|   def set_domain_blocks | ||||
|     @domain_blocks = DomainBlock.with_user_facing_limitations.by_severity | ||||
|   end | ||||
| 
 | ||||
|   def show_rationale_in_response? | ||||
|     always_show_rationale? || show_rationale_for_user? | ||||
|   end | ||||
| 
 | ||||
|   def always_show_rationale? | ||||
|     Setting.show_domain_blocks_rationale == 'all' | ||||
|   end | ||||
| 
 | ||||
|   def show_rationale_for_user? | ||||
|     Setting.show_domain_blocks_rationale == 'users' && user_signed_in? | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,13 +1,10 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class Api::V1::Instances::ExtendedDescriptionsController < Api::BaseController | ||||
|   skip_before_action :require_authenticated_user!, unless: :limited_federation_mode? | ||||
| class Api::V1::Instances::ExtendedDescriptionsController < Api::V1::Instances::BaseController | ||||
|   skip_around_action :set_locale | ||||
| 
 | ||||
|   before_action :set_extended_description | ||||
| 
 | ||||
|   vary_by '' | ||||
| 
 | ||||
|   # Override `current_user` to avoid reading session cookies unless in whitelist mode | ||||
|   def current_user | ||||
|     super if limited_federation_mode? | ||||
|  |  | |||
|  | @ -1,13 +1,10 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class Api::V1::Instances::LanguagesController < Api::BaseController | ||||
|   skip_before_action :require_authenticated_user!, unless: :limited_federation_mode? | ||||
| class Api::V1::Instances::LanguagesController < Api::V1::Instances::BaseController | ||||
|   skip_around_action :set_locale | ||||
| 
 | ||||
|   before_action :set_languages | ||||
| 
 | ||||
|   vary_by '' | ||||
| 
 | ||||
|   def show | ||||
|     cache_even_if_authenticated! | ||||
|     render json: @languages, each_serializer: REST::LanguageSerializer | ||||
|  |  | |||
|  | @ -1,13 +1,10 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class Api::V1::Instances::PeersController < Api::BaseController | ||||
| class Api::V1::Instances::PeersController < Api::V1::Instances::BaseController | ||||
|   before_action :require_enabled_api! | ||||
| 
 | ||||
|   skip_before_action :require_authenticated_user!, unless: :limited_federation_mode? | ||||
|   skip_around_action :set_locale | ||||
| 
 | ||||
|   vary_by '' | ||||
| 
 | ||||
|   # Override `current_user` to avoid reading session cookies unless in whitelist mode | ||||
|   def current_user | ||||
|     super if limited_federation_mode? | ||||
|  |  | |||
|  | @ -1,12 +1,8 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class Api::V1::Instances::PrivacyPoliciesController < Api::BaseController | ||||
|   skip_before_action :require_authenticated_user!, unless: :limited_federation_mode? | ||||
| 
 | ||||
| class Api::V1::Instances::PrivacyPoliciesController < Api::V1::Instances::BaseController | ||||
|   before_action :set_privacy_policy | ||||
| 
 | ||||
|   vary_by '' | ||||
| 
 | ||||
|   def show | ||||
|     cache_even_if_authenticated! | ||||
|     render json: @privacy_policy, serializer: REST::PrivacyPolicySerializer | ||||
|  |  | |||
|  | @ -1,13 +1,10 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class Api::V1::Instances::RulesController < Api::BaseController | ||||
|   skip_before_action :require_authenticated_user!, unless: :limited_federation_mode? | ||||
| class Api::V1::Instances::RulesController < Api::V1::Instances::BaseController | ||||
|   skip_around_action :set_locale | ||||
| 
 | ||||
|   before_action :set_rules | ||||
| 
 | ||||
|   vary_by '' | ||||
| 
 | ||||
|   # Override `current_user` to avoid reading session cookies unless in whitelist mode | ||||
|   def current_user | ||||
|     super if limited_federation_mode? | ||||
|  |  | |||
|  | @ -1,12 +1,8 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class Api::V1::Instances::TranslationLanguagesController < Api::BaseController | ||||
|   skip_before_action :require_authenticated_user!, unless: :limited_federation_mode? | ||||
| 
 | ||||
| class Api::V1::Instances::TranslationLanguagesController < Api::V1::Instances::BaseController | ||||
|   before_action :set_languages | ||||
| 
 | ||||
|   vary_by '' | ||||
| 
 | ||||
|   def show | ||||
|     cache_even_if_authenticated! | ||||
|     render json: @languages | ||||
|  |  | |||
							
								
								
									
										30
									
								
								app/controllers/api/v1/invites_controller.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								app/controllers/api/v1/invites_controller.rb
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class Api::V1::InvitesController < Api::BaseController | ||||
|   include RegistrationHelper | ||||
| 
 | ||||
|   skip_before_action :require_authenticated_user! | ||||
|   skip_around_action :set_locale | ||||
| 
 | ||||
|   before_action :set_invite | ||||
|   before_action :check_enabled_registrations! | ||||
| 
 | ||||
|   # Override `current_user` to avoid reading session cookies | ||||
|   def current_user; end | ||||
| 
 | ||||
|   def show | ||||
|     render json: { invite_code: params[:invite_code], instance_api_url: api_v2_instance_url }, status: 200 | ||||
|   end | ||||
| 
 | ||||
|   private | ||||
| 
 | ||||
|   def set_invite | ||||
|     @invite = Invite.find_by!(code: params[:invite_code]) | ||||
|   end | ||||
| 
 | ||||
|   def check_enabled_registrations! | ||||
|     return render json: { error: I18n.t('invites.invalid') }, status: 401 unless @invite.valid_for_use? | ||||
| 
 | ||||
|     raise Mastodon::NotPermittedError unless allowed_registration?(request.remote_ip, @invite) | ||||
|   end | ||||
| end | ||||
|  | @ -19,7 +19,7 @@ class Api::V1::MarkersController < Api::BaseController | |||
|       @markers = {} | ||||
| 
 | ||||
|       resource_params.each_pair do |timeline, timeline_params| | ||||
|         @markers[timeline] = current_user.markers.find_or_initialize_by(timeline: timeline) | ||||
|         @markers[timeline] = current_user.markers.find_or_create_by(timeline: timeline) | ||||
|         @markers[timeline].update!(timeline_params) | ||||
|       end | ||||
|     end | ||||
|  |  | |||
|  | @ -27,7 +27,7 @@ class Api::V1::Peers::SearchController < Api::BaseController | |||
|       @domains = InstancesIndex.query(function_score: { | ||||
|         query: { | ||||
|           prefix: { | ||||
|             domain: TagManager.instance.normalize_domain(params[:q].strip), | ||||
|             domain: normalized_domain, | ||||
|           }, | ||||
|         }, | ||||
| 
 | ||||
|  | @ -37,11 +37,18 @@ class Api::V1::Peers::SearchController < Api::BaseController | |||
|         }, | ||||
|       }).limit(10).pluck(:domain) | ||||
|     else | ||||
|       domain = params[:q].strip | ||||
|       domain = TagManager.instance.normalize_domain(domain) | ||||
|       @domains = Instance.searchable.where(Instance.arel_table[:domain].matches("#{Instance.sanitize_sql_like(domain)}%", false, true)).limit(10).pluck(:domain) | ||||
|       domain = normalized_domain | ||||
|       @domains = Instance.searchable.domain_starts_with(domain).limit(10).pluck(:domain) | ||||
|     end | ||||
|   rescue Addressable::URI::InvalidURIError | ||||
|     @domains = [] | ||||
|   end | ||||
| 
 | ||||
|   def normalized_domain | ||||
|     TagManager.instance.normalize_domain(query_value) | ||||
|   end | ||||
| 
 | ||||
|   def query_value | ||||
|     params[:q].strip | ||||
|   end | ||||
| end | ||||
|  |  | |||
							
								
								
									
										16
									
								
								app/controllers/api/v1/statuses/base_controller.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								app/controllers/api/v1/statuses/base_controller.rb
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class Api::V1::Statuses::BaseController < Api::BaseController | ||||
|   include Authorization | ||||
| 
 | ||||
|   before_action :set_status | ||||
| 
 | ||||
|   private | ||||
| 
 | ||||
|   def set_status | ||||
|     @status = Status.find(params[:status_id]) | ||||
|     authorize @status, :show? | ||||
|   rescue Mastodon::NotPermittedError | ||||
|     not_found | ||||
|   end | ||||
| end | ||||
|  | @ -1,11 +1,9 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class Api::V1::Statuses::BookmarksController < Api::BaseController | ||||
|   include Authorization | ||||
| 
 | ||||
| class Api::V1::Statuses::BookmarksController < Api::V1::Statuses::BaseController | ||||
|   before_action -> { doorkeeper_authorize! :write, :'write:bookmarks' } | ||||
|   before_action :require_user! | ||||
|   before_action :set_status, only: [:create] | ||||
|   skip_before_action :set_status, only: [:destroy] | ||||
| 
 | ||||
|   def create | ||||
|     current_account.bookmarks.find_or_create_by!(account: current_account, status: @status) | ||||
|  | @ -28,13 +26,4 @@ class Api::V1::Statuses::BookmarksController < Api::BaseController | |||
|   rescue Mastodon::NotPermittedError | ||||
|     not_found | ||||
|   end | ||||
| 
 | ||||
|   private | ||||
| 
 | ||||
|   def set_status | ||||
|     @status = Status.find(params[:status_id]) | ||||
|     authorize @status, :show? | ||||
|   rescue Mastodon::NotPermittedError | ||||
|     not_found | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,10 +1,7 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class Api::V1::Statuses::FavouritedByAccountsController < Api::BaseController | ||||
|   include Authorization | ||||
| 
 | ||||
| class Api::V1::Statuses::FavouritedByAccountsController < Api::V1::Statuses::BaseController | ||||
|   before_action -> { authorize_if_got_token! :read, :'read:accounts' } | ||||
|   before_action :set_status | ||||
|   after_action :insert_pagination_headers | ||||
| 
 | ||||
|   def index | ||||
|  | @ -61,13 +58,6 @@ class Api::V1::Statuses::FavouritedByAccountsController < Api::BaseController | |||
|     @accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT) | ||||
|   end | ||||
| 
 | ||||
|   def set_status | ||||
|     @status = Status.find(params[:status_id]) | ||||
|     authorize @status, :show? | ||||
|   rescue Mastodon::NotPermittedError | ||||
|     not_found | ||||
|   end | ||||
| 
 | ||||
|   def pagination_params(core_params) | ||||
|     params.slice(:limit).permit(:limit).merge(core_params) | ||||
|   end | ||||
|  |  | |||
|  | @ -1,11 +1,9 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class Api::V1::Statuses::FavouritesController < Api::BaseController | ||||
|   include Authorization | ||||
| 
 | ||||
| class Api::V1::Statuses::FavouritesController < Api::V1::Statuses::BaseController | ||||
|   before_action -> { doorkeeper_authorize! :write, :'write:favourites' } | ||||
|   before_action :require_user! | ||||
|   before_action :set_status, only: [:create] | ||||
|   skip_before_action :set_status, only: [:destroy] | ||||
| 
 | ||||
|   def create | ||||
|     FavouriteService.new.call(current_account, @status) | ||||
|  | @ -30,13 +28,4 @@ class Api::V1::Statuses::FavouritesController < Api::BaseController | |||
|   rescue Mastodon::NotPermittedError | ||||
|     not_found | ||||
|   end | ||||
| 
 | ||||
|   private | ||||
| 
 | ||||
|   def set_status | ||||
|     @status = Status.find(params[:status_id]) | ||||
|     authorize @status, :show? | ||||
|   rescue Mastodon::NotPermittedError | ||||
|     not_found | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,10 +1,7 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class Api::V1::Statuses::HistoriesController < Api::BaseController | ||||
|   include Authorization | ||||
| 
 | ||||
| class Api::V1::Statuses::HistoriesController < Api::V1::Statuses::BaseController | ||||
|   before_action -> { authorize_if_got_token! :read, :'read:statuses' } | ||||
|   before_action :set_status | ||||
| 
 | ||||
|   def show | ||||
|     cache_if_unauthenticated! | ||||
|  | @ -14,13 +11,6 @@ class Api::V1::Statuses::HistoriesController < Api::BaseController | |||
|   private | ||||
| 
 | ||||
|   def status_edits | ||||
|     @status.edits.includes(:account, status: [:account]).to_a.presence || [@status.build_snapshot(at_time: @status.edited_at || @status.created_at)] | ||||
|   end | ||||
| 
 | ||||
|   def set_status | ||||
|     @status = Status.find(params[:status_id]) | ||||
|     authorize @status, :show? | ||||
|   rescue Mastodon::NotPermittedError | ||||
|     not_found | ||||
|     @status.edits.ordered.includes(:account, status: [:account]).to_a.presence || [@status.build_snapshot(at_time: @status.edited_at || @status.created_at)] | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,11 +1,8 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class Api::V1::Statuses::MutesController < Api::BaseController | ||||
|   include Authorization | ||||
| 
 | ||||
| class Api::V1::Statuses::MutesController < Api::V1::Statuses::BaseController | ||||
|   before_action -> { doorkeeper_authorize! :write, :'write:mutes' } | ||||
|   before_action :require_user! | ||||
|   before_action :set_status | ||||
|   before_action :set_conversation | ||||
| 
 | ||||
|   def create | ||||
|  | @ -24,13 +21,6 @@ class Api::V1::Statuses::MutesController < Api::BaseController | |||
| 
 | ||||
|   private | ||||
| 
 | ||||
|   def set_status | ||||
|     @status = Status.find(params[:status_id]) | ||||
|     authorize @status, :show? | ||||
|   rescue Mastodon::NotPermittedError | ||||
|     not_found | ||||
|   end | ||||
| 
 | ||||
|   def set_conversation | ||||
|     @conversation = @status.conversation | ||||
|     raise Mastodon::ValidationError if @conversation.nil? | ||||
|  |  | |||
|  | @ -1,11 +1,8 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class Api::V1::Statuses::PinsController < Api::BaseController | ||||
|   include Authorization | ||||
| 
 | ||||
| class Api::V1::Statuses::PinsController < Api::V1::Statuses::BaseController | ||||
|   before_action -> { doorkeeper_authorize! :write, :'write:accounts' } | ||||
|   before_action :require_user! | ||||
|   before_action :set_status | ||||
| 
 | ||||
|   def create | ||||
|     StatusPin.create!(account: current_account, status: @status) | ||||
|  | @ -26,10 +23,6 @@ class Api::V1::Statuses::PinsController < Api::BaseController | |||
| 
 | ||||
|   private | ||||
| 
 | ||||
|   def set_status | ||||
|     @status = Status.find(params[:status_id]) | ||||
|   end | ||||
| 
 | ||||
|   def distribute_add_activity! | ||||
|     json = ActiveModelSerializers::SerializableResource.new( | ||||
|       @status, | ||||
|  |  | |||
|  | @ -1,10 +1,7 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class Api::V1::Statuses::RebloggedByAccountsController < Api::BaseController | ||||
|   include Authorization | ||||
| 
 | ||||
| class Api::V1::Statuses::RebloggedByAccountsController < Api::V1::Statuses::BaseController | ||||
|   before_action -> { authorize_if_got_token! :read, :'read:accounts' } | ||||
|   before_action :set_status | ||||
|   after_action :insert_pagination_headers | ||||
| 
 | ||||
|   def index | ||||
|  | @ -57,13 +54,6 @@ class Api::V1::Statuses::RebloggedByAccountsController < Api::BaseController | |||
|     @accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT) | ||||
|   end | ||||
| 
 | ||||
|   def set_status | ||||
|     @status = Status.find(params[:status_id]) | ||||
|     authorize @status, :show? | ||||
|   rescue Mastodon::NotPermittedError | ||||
|     not_found | ||||
|   end | ||||
| 
 | ||||
|   def pagination_params(core_params) | ||||
|     params.slice(:limit).permit(:limit).merge(core_params) | ||||
|   end | ||||
|  |  | |||
|  | @ -1,13 +1,13 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class Api::V1::Statuses::ReblogsController < Api::BaseController | ||||
|   include Authorization | ||||
| class Api::V1::Statuses::ReblogsController < Api::V1::Statuses::BaseController | ||||
|   include Redisable | ||||
|   include Lockable | ||||
| 
 | ||||
|   before_action -> { doorkeeper_authorize! :write, :'write:statuses' } | ||||
|   before_action :require_user! | ||||
|   before_action :set_reblog, only: [:create] | ||||
|   skip_before_action :set_status | ||||
| 
 | ||||
|   override_rate_limit_headers :create, family: :statuses | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,21 +1,9 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class Api::V1::Statuses::SourcesController < Api::BaseController | ||||
|   include Authorization | ||||
| 
 | ||||
| class Api::V1::Statuses::SourcesController < Api::V1::Statuses::BaseController | ||||
|   before_action -> { doorkeeper_authorize! :read, :'read:statuses' } | ||||
|   before_action :set_status | ||||
| 
 | ||||
|   def show | ||||
|     render json: @status, serializer: REST::StatusSourceSerializer | ||||
|   end | ||||
| 
 | ||||
|   private | ||||
| 
 | ||||
|   def set_status | ||||
|     @status = Status.find(params[:status_id]) | ||||
|     authorize @status, :show? | ||||
|   rescue Mastodon::NotPermittedError | ||||
|     not_found | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,10 +1,7 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class Api::V1::Statuses::TranslationsController < Api::BaseController | ||||
|   include Authorization | ||||
| 
 | ||||
| class Api::V1::Statuses::TranslationsController < Api::V1::Statuses::BaseController | ||||
|   before_action -> { doorkeeper_authorize! :read, :'read:statuses' } | ||||
|   before_action :set_status | ||||
|   before_action :set_translation | ||||
| 
 | ||||
|   rescue_from TranslationService::NotConfiguredError, with: :not_found | ||||
|  | @ -24,13 +21,6 @@ class Api::V1::Statuses::TranslationsController < Api::BaseController | |||
| 
 | ||||
|   private | ||||
| 
 | ||||
|   def set_status | ||||
|     @status = Status.find(params[:status_id]) | ||||
|     authorize @status, :show? | ||||
|   rescue Mastodon::NotPermittedError | ||||
|     not_found | ||||
|   end | ||||
| 
 | ||||
|   def set_translation | ||||
|     @translation = TranslateStatusService.new.call(@status, content_locale) | ||||
|   end | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ | |||
| 
 | ||||
| class Api::V1::StreamingController < Api::BaseController | ||||
|   def index | ||||
|     if Rails.configuration.x.streaming_api_base_url == request.host | ||||
|     if same_host? | ||||
|       not_found | ||||
|     else | ||||
|       redirect_to streaming_api_url, status: 301, allow_other_host: true | ||||
|  | @ -11,9 +11,16 @@ class Api::V1::StreamingController < Api::BaseController | |||
| 
 | ||||
|   private | ||||
| 
 | ||||
|   def same_host? | ||||
|     base_url = Addressable::URI.parse(Rails.configuration.x.streaming_api_base_url) | ||||
|     request.host == base_url.host && request.port == (base_url.port || 80) | ||||
|   end | ||||
| 
 | ||||
|   def streaming_api_url | ||||
|     Addressable::URI.parse(request.url).tap do |uri| | ||||
|       uri.host = Addressable::URI.parse(Rails.configuration.x.streaming_api_base_url).host | ||||
|       base_url = Addressable::URI.parse(Rails.configuration.x.streaming_api_base_url) | ||||
|       uri.host = base_url.host | ||||
|       uri.port = base_url.port | ||||
|     end.to_s | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -3,22 +3,23 @@ | |||
| class Api::V1::SuggestionsController < Api::BaseController | ||||
|   include Authorization | ||||
| 
 | ||||
|   before_action -> { doorkeeper_authorize! :read } | ||||
|   before_action -> { doorkeeper_authorize! :read, :'read:accounts' }, only: :index | ||||
|   before_action -> { doorkeeper_authorize! :write, :'write:accounts' }, except: :index | ||||
|   before_action :require_user! | ||||
|   before_action :set_suggestions | ||||
| 
 | ||||
|   def index | ||||
|     suggestions = suggestions_source.get(current_account, limit: limit_param(DEFAULT_ACCOUNTS_LIMIT)) | ||||
|     render json: suggestions.map(&:account), each_serializer: REST::AccountSerializer | ||||
|     render json: @suggestions.get(limit_param(DEFAULT_ACCOUNTS_LIMIT), params[:offset].to_i).map(&:account), each_serializer: REST::AccountSerializer | ||||
|   end | ||||
| 
 | ||||
|   def destroy | ||||
|     suggestions_source.remove(current_account, params[:id]) | ||||
|     @suggestions.remove(params[:id]) | ||||
|     render_empty | ||||
|   end | ||||
| 
 | ||||
|   private | ||||
| 
 | ||||
|   def suggestions_source | ||||
|     AccountSuggestions::PastInteractionsSource.new | ||||
|   def set_suggestions | ||||
|     @suggestions = AccountSuggestions.new(current_account) | ||||
|   end | ||||
| end | ||||
|  |  | |||
							
								
								
									
										33
									
								
								app/controllers/api/v1/timelines/base_controller.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								app/controllers/api/v1/timelines/base_controller.rb
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,33 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class Api::V1::Timelines::BaseController < Api::BaseController | ||||
|   after_action :insert_pagination_headers, unless: -> { @statuses.empty? } | ||||
| 
 | ||||
|   private | ||||
| 
 | ||||
|   def insert_pagination_headers | ||||
|     set_pagination_headers(next_path, prev_path) | ||||
|   end | ||||
| 
 | ||||
|   def pagination_max_id | ||||
|     @statuses.last.id | ||||
|   end | ||||
| 
 | ||||
|   def pagination_since_id | ||||
|     @statuses.first.id | ||||
|   end | ||||
| 
 | ||||
|   def next_path_params | ||||
|     permitted_params.merge(max_id: pagination_max_id) | ||||
|   end | ||||
| 
 | ||||
|   def prev_path_params | ||||
|     permitted_params.merge(min_id: pagination_since_id) | ||||
|   end | ||||
| 
 | ||||
|   def permitted_params | ||||
|     params | ||||
|       .slice(*self.class::PERMITTED_PARAMS) | ||||
|       .permit(*self.class::PERMITTED_PARAMS) | ||||
|   end | ||||
| end | ||||
|  | @ -1,9 +1,10 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class Api::V1::Timelines::HomeController < Api::BaseController | ||||
| class Api::V1::Timelines::HomeController < Api::V1::Timelines::BaseController | ||||
|   before_action -> { doorkeeper_authorize! :read, :'read:statuses' }, only: [:show] | ||||
|   before_action :require_user!, only: [:show] | ||||
|   after_action :insert_pagination_headers, unless: -> { @statuses.empty? } | ||||
| 
 | ||||
|   PERMITTED_PARAMS = %i(local limit).freeze | ||||
| 
 | ||||
|   def show | ||||
|     with_read_replica do | ||||
|  | @ -40,27 +41,11 @@ class Api::V1::Timelines::HomeController < Api::BaseController | |||
|     HomeFeed.new(current_account) | ||||
|   end | ||||
| 
 | ||||
|   def insert_pagination_headers | ||||
|     set_pagination_headers(next_path, prev_path) | ||||
|   end | ||||
| 
 | ||||
|   def pagination_params(core_params) | ||||
|     params.slice(:local, :limit).permit(:local, :limit).merge(core_params) | ||||
|   end | ||||
| 
 | ||||
|   def next_path | ||||
|     api_v1_timelines_home_url pagination_params(max_id: pagination_max_id) | ||||
|     api_v1_timelines_home_url next_path_params | ||||
|   end | ||||
| 
 | ||||
|   def prev_path | ||||
|     api_v1_timelines_home_url pagination_params(min_id: pagination_since_id) | ||||
|   end | ||||
| 
 | ||||
|   def pagination_max_id | ||||
|     @statuses.last.id | ||||
|   end | ||||
| 
 | ||||
|   def pagination_since_id | ||||
|     @statuses.first.id | ||||
|     api_v1_timelines_home_url prev_path_params | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,12 +1,12 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class Api::V1::Timelines::ListController < Api::BaseController | ||||
| class Api::V1::Timelines::ListController < Api::V1::Timelines::BaseController | ||||
|   before_action -> { doorkeeper_authorize! :read, :'read:lists' } | ||||
|   before_action :require_user! | ||||
|   before_action :set_list | ||||
|   before_action :set_statuses | ||||
| 
 | ||||
|   after_action :insert_pagination_headers, unless: -> { @statuses.empty? } | ||||
|   PERMITTED_PARAMS = %i(limit).freeze | ||||
| 
 | ||||
|   def show | ||||
|     render json: @statuses, | ||||
|  | @ -41,27 +41,11 @@ class Api::V1::Timelines::ListController < Api::BaseController | |||
|     ListFeed.new(@list) | ||||
|   end | ||||
| 
 | ||||
|   def insert_pagination_headers | ||||
|     set_pagination_headers(next_path, prev_path) | ||||
|   end | ||||
| 
 | ||||
|   def pagination_params(core_params) | ||||
|     params.slice(:limit).permit(:limit).merge(core_params) | ||||
|   end | ||||
| 
 | ||||
|   def next_path | ||||
|     api_v1_timelines_list_url params[:id], pagination_params(max_id: pagination_max_id) | ||||
|     api_v1_timelines_list_url params[:id], next_path_params | ||||
|   end | ||||
| 
 | ||||
|   def prev_path | ||||
|     api_v1_timelines_list_url params[:id], pagination_params(min_id: pagination_since_id) | ||||
|   end | ||||
| 
 | ||||
|   def pagination_max_id | ||||
|     @statuses.last.id | ||||
|   end | ||||
| 
 | ||||
|   def pagination_since_id | ||||
|     @statuses.first.id | ||||
|     api_v1_timelines_list_url params[:id], prev_path_params | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,8 +1,9 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class Api::V1::Timelines::PublicController < Api::BaseController | ||||
| class Api::V1::Timelines::PublicController < Api::V1::Timelines::BaseController | ||||
|   before_action :require_user!, only: [:show], if: :require_auth? | ||||
|   after_action :insert_pagination_headers, unless: -> { @statuses.empty? } | ||||
| 
 | ||||
|   PERMITTED_PARAMS = %i(local remote limit only_media allow_local_only).freeze | ||||
| 
 | ||||
|   def show | ||||
|     cache_if_unauthenticated! | ||||
|  | @ -45,27 +46,11 @@ class Api::V1::Timelines::PublicController < Api::BaseController | |||
|     ) | ||||
|   end | ||||
| 
 | ||||
|   def insert_pagination_headers | ||||
|     set_pagination_headers(next_path, prev_path) | ||||
|   end | ||||
| 
 | ||||
|   def pagination_params(core_params) | ||||
|     params.slice(:local, :remote, :limit, :only_media, :allow_local_only).permit(:local, :remote, :limit, :only_media, :allow_local_only).merge(core_params) | ||||
|   end | ||||
| 
 | ||||
|   def next_path | ||||
|     api_v1_timelines_public_url pagination_params(max_id: pagination_max_id) | ||||
|     api_v1_timelines_public_url next_path_params | ||||
|   end | ||||
| 
 | ||||
|   def prev_path | ||||
|     api_v1_timelines_public_url pagination_params(min_id: pagination_since_id) | ||||
|   end | ||||
| 
 | ||||
|   def pagination_max_id | ||||
|     @statuses.last.id | ||||
|   end | ||||
| 
 | ||||
|   def pagination_since_id | ||||
|     @statuses.first.id | ||||
|     api_v1_timelines_public_url prev_path_params | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -1,9 +1,10 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class Api::V1::Timelines::TagController < Api::BaseController | ||||
| class Api::V1::Timelines::TagController < Api::V1::Timelines::BaseController | ||||
|   before_action -> { doorkeeper_authorize! :read, :'read:statuses' }, only: :show, if: :require_auth? | ||||
|   before_action :load_tag | ||||
|   after_action :insert_pagination_headers, unless: -> { @statuses.empty? } | ||||
| 
 | ||||
|   PERMITTED_PARAMS = %i(local limit only_media).freeze | ||||
| 
 | ||||
|   def show | ||||
|     cache_if_unauthenticated! | ||||
|  | @ -51,27 +52,11 @@ class Api::V1::Timelines::TagController < Api::BaseController | |||
|     ) | ||||
|   end | ||||
| 
 | ||||
|   def insert_pagination_headers | ||||
|     set_pagination_headers(next_path, prev_path) | ||||
|   end | ||||
| 
 | ||||
|   def pagination_params(core_params) | ||||
|     params.slice(:local, :limit, :only_media).permit(:local, :limit, :only_media).merge(core_params) | ||||
|   end | ||||
| 
 | ||||
|   def next_path | ||||
|     api_v1_timelines_tag_url params[:id], pagination_params(max_id: pagination_max_id) | ||||
|     api_v1_timelines_tag_url params[:id], next_path_params | ||||
|   end | ||||
| 
 | ||||
|   def prev_path | ||||
|     api_v1_timelines_tag_url params[:id], pagination_params(min_id: pagination_since_id) | ||||
|   end | ||||
| 
 | ||||
|   def pagination_max_id | ||||
|     @statuses.last.id | ||||
|   end | ||||
| 
 | ||||
|   def pagination_since_id | ||||
|     @statuses.first.id | ||||
|     api_v1_timelines_tag_url params[:id], prev_path_params | ||||
|   end | ||||
| end | ||||
|  |  | |||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
		Reference in a new issue