mirror of
https://github.com/glitch-soc/mastodon.git
synced 2025-12-16 09:18:46 +00:00
Compare commits
1 Commits
ClearlyCla
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
faa5d164f7 |
@@ -70,7 +70,7 @@ services:
|
|||||||
hard: -1
|
hard: -1
|
||||||
|
|
||||||
libretranslate:
|
libretranslate:
|
||||||
image: libretranslate/libretranslate:v1.5.2
|
image: libretranslate/libretranslate:v1.4.1
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- lt-data:/home/libretranslate/.local
|
- lt-data:/home/libretranslate/.local
|
||||||
|
|||||||
@@ -24,4 +24,4 @@ RAILS_ENV=development ./bin/rails db:setup
|
|||||||
RAILS_ENV=development ./bin/rails assets:precompile
|
RAILS_ENV=development ./bin/rails assets:precompile
|
||||||
|
|
||||||
# Precompile assets for test
|
# Precompile assets for test
|
||||||
RAILS_ENV=test ./bin/rails assets:precompile
|
RAILS_ENV=test NODE_ENV=tests ./bin/rails assets:precompile
|
||||||
|
|||||||
23
.eslintrc.js
23
.eslintrc.js
@@ -1,7 +1,4 @@
|
|||||||
// @ts-check
|
module.exports = {
|
||||||
const { defineConfig } = require('eslint-define-config');
|
|
||||||
|
|
||||||
module.exports = defineConfig({
|
|
||||||
root: true,
|
root: true,
|
||||||
|
|
||||||
extends: [
|
extends: [
|
||||||
@@ -120,6 +117,7 @@ module.exports = defineConfig({
|
|||||||
'react/jsx-uses-react': 'off', // not needed with new JSX transform
|
'react/jsx-uses-react': 'off', // not needed with new JSX transform
|
||||||
'react/jsx-wrap-multilines': 'error',
|
'react/jsx-wrap-multilines': 'error',
|
||||||
'react/no-deprecated': 'off',
|
'react/no-deprecated': 'off',
|
||||||
|
'react/no-unknown-property': 'off',
|
||||||
'react/react-in-jsx-scope': 'off', // not needed with new JSX transform
|
'react/react-in-jsx-scope': 'off', // not needed with new JSX transform
|
||||||
'react/self-closing-comp': 'error',
|
'react/self-closing-comp': 'error',
|
||||||
|
|
||||||
@@ -195,7 +193,6 @@ module.exports = defineConfig({
|
|||||||
'error',
|
'error',
|
||||||
{
|
{
|
||||||
devDependencies: [
|
devDependencies: [
|
||||||
'.eslintrc.js',
|
|
||||||
'config/webpack/**',
|
'config/webpack/**',
|
||||||
'app/javascript/mastodon/performance.js',
|
'app/javascript/mastodon/performance.js',
|
||||||
'app/javascript/mastodon/test_setup.js',
|
'app/javascript/mastodon/test_setup.js',
|
||||||
@@ -300,6 +297,7 @@ module.exports = defineConfig({
|
|||||||
'formatjs/no-id': 'off', // IDs are used for translation keys
|
'formatjs/no-id': 'off', // IDs are used for translation keys
|
||||||
'formatjs/no-invalid-icu': 'error',
|
'formatjs/no-invalid-icu': 'error',
|
||||||
'formatjs/no-literal-string-in-jsx': 'off', // Should be looked at, but mainly flagging punctuation outside of strings
|
'formatjs/no-literal-string-in-jsx': 'off', // Should be looked at, but mainly flagging punctuation outside of strings
|
||||||
|
'formatjs/no-multiple-plurals': 'off', // Only used by hashtag.jsx
|
||||||
'formatjs/no-multiple-whitespaces': 'error',
|
'formatjs/no-multiple-whitespaces': 'error',
|
||||||
'formatjs/no-offset': 'error',
|
'formatjs/no-offset': 'error',
|
||||||
'formatjs/no-useless-message': 'error',
|
'formatjs/no-useless-message': 'error',
|
||||||
@@ -318,7 +316,6 @@ module.exports = defineConfig({
|
|||||||
overrides: [
|
overrides: [
|
||||||
{
|
{
|
||||||
files: [
|
files: [
|
||||||
'.eslintrc.js',
|
|
||||||
'*.config.js',
|
'*.config.js',
|
||||||
'.*rc.js',
|
'.*rc.js',
|
||||||
'ide-helper.js',
|
'ide-helper.js',
|
||||||
@@ -369,7 +366,7 @@ module.exports = defineConfig({
|
|||||||
'@typescript-eslint/consistent-type-definitions': ['warn', 'interface'],
|
'@typescript-eslint/consistent-type-definitions': ['warn', 'interface'],
|
||||||
'@typescript-eslint/consistent-type-exports': 'error',
|
'@typescript-eslint/consistent-type-exports': 'error',
|
||||||
'@typescript-eslint/consistent-type-imports': 'error',
|
'@typescript-eslint/consistent-type-imports': 'error',
|
||||||
"@typescript-eslint/prefer-nullish-coalescing": ['error', { ignorePrimitives: { boolean: true } }],
|
"@typescript-eslint/prefer-nullish-coalescing": ['error', {ignorePrimitives: {boolean: true}}],
|
||||||
|
|
||||||
'jsdoc/require-jsdoc': 'off',
|
'jsdoc/require-jsdoc': 'off',
|
||||||
|
|
||||||
@@ -392,6 +389,14 @@ module.exports = defineConfig({
|
|||||||
env: {
|
env: {
|
||||||
jest: true,
|
jest: true,
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
files: [
|
||||||
|
'streaming/**/*',
|
||||||
|
],
|
||||||
|
rules: {
|
||||||
|
'import/no-commonjs': 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
});
|
};
|
||||||
|
|||||||
2
.github/actions/setup-javascript/action.yml
vendored
2
.github/actions/setup-javascript/action.yml
vendored
@@ -9,7 +9,7 @@ runs:
|
|||||||
using: 'composite'
|
using: 'composite'
|
||||||
steps:
|
steps:
|
||||||
- name: Set up Node.js
|
- name: Set up Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version-file: '.nvmrc'
|
node-version-file: '.nvmrc'
|
||||||
|
|
||||||
|
|||||||
13
.github/codecov.yml
vendored
13
.github/codecov.yml
vendored
@@ -1,13 +0,0 @@
|
|||||||
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
|
|
||||||
12
.github/renovate.json5
vendored
12
.github/renovate.json5
vendored
@@ -22,7 +22,6 @@
|
|||||||
'react-hotkeys', // Requires code changes
|
'react-hotkeys', // Requires code changes
|
||||||
|
|
||||||
// Requires Webpacker upgrade or replacement
|
// Requires Webpacker upgrade or replacement
|
||||||
'@svgr/webpack',
|
|
||||||
'@types/webpack',
|
'@types/webpack',
|
||||||
'babel-loader',
|
'babel-loader',
|
||||||
'compression-webpack-plugin',
|
'compression-webpack-plugin',
|
||||||
@@ -50,6 +49,7 @@
|
|||||||
matchManagers: ['bundler'],
|
matchManagers: ['bundler'],
|
||||||
matchPackageNames: [
|
matchPackageNames: [
|
||||||
'rack', // Needs to be synced with Rails version
|
'rack', // Needs to be synced with Rails version
|
||||||
|
'sprockets', // Requires manual upgrade https://github.com/rails/sprockets/blob/master/UPGRADING.md#guide-to-upgrading-from-sprockets-3x-to-4x
|
||||||
'strong_migrations', // Requires manual upgrade
|
'strong_migrations', // Requires manual upgrade
|
||||||
'sidekiq', // Requires manual upgrade
|
'sidekiq', // Requires manual upgrade
|
||||||
'sidekiq-unique-jobs', // Requires manual upgrades and sync with Sidekiq version
|
'sidekiq-unique-jobs', // Requires manual upgrades and sync with Sidekiq version
|
||||||
@@ -99,16 +99,6 @@
|
|||||||
matchUpdateTypes: ['patch', 'minor'],
|
matchUpdateTypes: ['patch', 'minor'],
|
||||||
groupName: 'eslint (non-major)',
|
groupName: 'eslint (non-major)',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
// Group actions/*-artifact in the same PR
|
|
||||||
matchManagers: ['github-actions'],
|
|
||||||
matchPackageNames: [
|
|
||||||
'actions/download-artifact',
|
|
||||||
'actions/upload-artifact',
|
|
||||||
],
|
|
||||||
matchUpdateTypes: ['major'],
|
|
||||||
groupName: 'artifact actions (major)',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
// Update @types/* packages every week, with one grouped PR
|
// Update @types/* packages every week, with one grouped PR
|
||||||
matchPackagePrefixes: '@types/',
|
matchPackagePrefixes: '@types/',
|
||||||
|
|||||||
3
.github/workflows/build-container-image.yml
vendored
3
.github/workflows/build-container-image.yml
vendored
@@ -21,8 +21,6 @@ on:
|
|||||||
type: string
|
type: string
|
||||||
labels:
|
labels:
|
||||||
type: string
|
type: string
|
||||||
file_to_build:
|
|
||||||
type: string
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-image:
|
build-image:
|
||||||
@@ -88,7 +86,6 @@ jobs:
|
|||||||
- uses: docker/build-push-action@v5
|
- uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: ${{ inputs.file_to_build }}
|
|
||||||
build-args: |
|
build-args: |
|
||||||
MASTODON_VERSION_PRERELEASE=${{ inputs.version_prerelease }}
|
MASTODON_VERSION_PRERELEASE=${{ inputs.version_prerelease }}
|
||||||
MASTODON_VERSION_METADATA=${{ inputs.version_metadata }}
|
MASTODON_VERSION_METADATA=${{ inputs.version_metadata }}
|
||||||
|
|||||||
22
.github/workflows/build-nightly.yml
vendored
22
.github/workflows/build-nightly.yml
vendored
@@ -25,7 +25,6 @@ jobs:
|
|||||||
needs: compute-suffix
|
needs: compute-suffix
|
||||||
uses: ./.github/workflows/build-container-image.yml
|
uses: ./.github/workflows/build-container-image.yml
|
||||||
with:
|
with:
|
||||||
file_to_build: Dockerfile
|
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
use_native_arm64_builder: false
|
use_native_arm64_builder: false
|
||||||
cache: false
|
cache: false
|
||||||
@@ -41,24 +40,3 @@ jobs:
|
|||||||
type=raw,value=nightly
|
type=raw,value=nightly
|
||||||
type=schedule,pattern=${{ needs.compute-suffix.outputs.prerelease }}
|
type=schedule,pattern=${{ needs.compute-suffix.outputs.prerelease }}
|
||||||
secrets: inherit
|
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,7 +29,6 @@ jobs:
|
|||||||
needs: compute-suffix
|
needs: compute-suffix
|
||||||
uses: ./.github/workflows/build-container-image.yml
|
uses: ./.github/workflows/build-container-image.yml
|
||||||
with:
|
with:
|
||||||
file_to_build: Dockerfile
|
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
use_native_arm64_builder: false
|
use_native_arm64_builder: false
|
||||||
push_to_images: |
|
push_to_images: |
|
||||||
@@ -40,19 +39,3 @@ jobs:
|
|||||||
tags: |
|
tags: |
|
||||||
type=ref,event=pr
|
type=ref,event=pr
|
||||||
secrets: inherit
|
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,7 +12,6 @@ jobs:
|
|||||||
build-image:
|
build-image:
|
||||||
uses: ./.github/workflows/build-container-image.yml
|
uses: ./.github/workflows/build-container-image.yml
|
||||||
with:
|
with:
|
||||||
file_to_build: Dockerfile
|
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
use_native_arm64_builder: false
|
use_native_arm64_builder: false
|
||||||
push_to_images: |
|
push_to_images: |
|
||||||
@@ -27,23 +26,3 @@ jobs:
|
|||||||
type=pep440,pattern={{raw}}
|
type=pep440,pattern={{raw}}
|
||||||
type=pep440,pattern=v{{major}}.{{minor}}
|
type=pep440,pattern=v{{major}}.{{minor}}
|
||||||
secrets: inherit
|
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
|
|
||||||
|
|||||||
14
.github/workflows/test-image-build.yml
vendored
14
.github/workflows/test-image-build.yml
vendored
@@ -7,7 +7,6 @@ on:
|
|||||||
- .github/workflows/build-releases.yml
|
- .github/workflows/build-releases.yml
|
||||||
- .github/workflows/test-image-build.yml
|
- .github/workflows/test-image-build.yml
|
||||||
- Dockerfile
|
- Dockerfile
|
||||||
- streaming/Dockerfile
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
|
||||||
@@ -19,17 +18,4 @@ jobs:
|
|||||||
|
|
||||||
uses: ./.github/workflows/build-container-image.yml
|
uses: ./.github/workflows/build-container-image.yml
|
||||||
with:
|
with:
|
||||||
file_to_build: Dockerfile
|
|
||||||
platforms: linux/amd64 # Testing only on native platform so it is performant
|
platforms: linux/amd64 # Testing only on native platform so it is performant
|
||||||
cache: true
|
|
||||||
|
|
||||||
build-image-streaming:
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}-streaming
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
uses: ./.github/workflows/build-container-image.yml
|
|
||||||
with:
|
|
||||||
file_to_build: streaming/Dockerfile
|
|
||||||
platforms: linux/amd64 # Testing only on native platform so it is performant
|
|
||||||
cache: true
|
|
||||||
|
|||||||
12
.github/workflows/test-ruby.yml
vendored
12
.github/workflows/test-ruby.yml
vendored
@@ -94,7 +94,7 @@ jobs:
|
|||||||
DB_HOST: localhost
|
DB_HOST: localhost
|
||||||
DB_USER: postgres
|
DB_USER: postgres
|
||||||
DB_PASS: postgres
|
DB_PASS: postgres
|
||||||
DISABLE_SIMPLECOV: ${{ matrix.ruby-version != '.ruby-version' }}
|
DISABLE_SIMPLECOV: true
|
||||||
RAILS_ENV: test
|
RAILS_ENV: test
|
||||||
ALLOW_NOPAM: true
|
ALLOW_NOPAM: true
|
||||||
PAM_ENABLED: true
|
PAM_ENABLED: true
|
||||||
@@ -137,12 +137,6 @@ jobs:
|
|||||||
|
|
||||||
- run: bin/rspec
|
- run: bin/rspec
|
||||||
|
|
||||||
- name: Upload coverage reports to Codecov
|
|
||||||
if: matrix.ruby-version == '.ruby-version'
|
|
||||||
uses: codecov/codecov-action@v3
|
|
||||||
with:
|
|
||||||
files: coverage/lcov/mastodon.lcov
|
|
||||||
|
|
||||||
test-e2e:
|
test-e2e:
|
||||||
name: End to End testing
|
name: End to End testing
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -227,7 +221,7 @@ jobs:
|
|||||||
path: tmp/screenshots/
|
path: tmp/screenshots/
|
||||||
|
|
||||||
test-search:
|
test-search:
|
||||||
name: Elastic Search integration testing
|
name: Testing search
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
needs:
|
needs:
|
||||||
@@ -314,7 +308,7 @@ jobs:
|
|||||||
- name: Load database schema
|
- name: Load database schema
|
||||||
run: './bin/rails db:create db:schema:load db:seed'
|
run: './bin/rails db:create db:schema:load db:seed'
|
||||||
|
|
||||||
- run: bin/rspec --tag search
|
- run: bundle exec rake spec:search
|
||||||
|
|
||||||
- name: Archive logs
|
- name: Archive logs
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
|
|||||||
@@ -1,21 +1,33 @@
|
|||||||
# This configuration was generated by
|
# This configuration was generated by
|
||||||
# `haml-lint --auto-gen-config`
|
# `haml-lint --auto-gen-config`
|
||||||
# on 2023-12-15 11:02:19 -0500 using Haml-Lint version 0.52.0.
|
# on 2023-10-26 09:32:34 -0400 using Haml-Lint version 0.51.0.
|
||||||
# The point is for the user to remove these configuration records
|
# The point is for the user to remove these configuration records
|
||||||
# one by one as the lints are removed from the code base.
|
# one by one as the lints are removed from the code base.
|
||||||
# Note that changes in the inspected code, or installation of new
|
# Note that changes in the inspected code, or installation of new
|
||||||
# versions of Haml-Lint, may require this file to be generated again.
|
# versions of Haml-Lint, may require this file to be generated again.
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
# Offense count: 11
|
# Offense count: 16
|
||||||
LineLength:
|
LineLength:
|
||||||
exclude:
|
exclude:
|
||||||
|
- 'app/views/admin/account_actions/new.html.haml'
|
||||||
|
- 'app/views/admin/accounts/index.html.haml'
|
||||||
|
- 'app/views/admin/ip_blocks/new.html.haml'
|
||||||
- 'app/views/admin/roles/_form.html.haml'
|
- 'app/views/admin/roles/_form.html.haml'
|
||||||
|
- 'app/views/admin/settings/discovery/show.html.haml'
|
||||||
- 'app/views/auth/registrations/edit.html.haml'
|
- 'app/views/auth/registrations/edit.html.haml'
|
||||||
- 'app/views/auth/registrations/new.html.haml'
|
- 'app/views/auth/registrations/new.html.haml'
|
||||||
|
- 'app/views/filters/_filter_fields.html.haml'
|
||||||
- 'app/views/media/player.html.haml'
|
- 'app/views/media/player.html.haml'
|
||||||
- 'app/views/settings/applications/_fields.html.haml'
|
- 'app/views/settings/applications/_fields.html.haml'
|
||||||
- 'app/views/settings/imports/index.html.haml'
|
- 'app/views/settings/imports/index.html.haml'
|
||||||
- 'app/views/settings/preferences/appearance/show.html.haml'
|
- 'app/views/settings/preferences/appearance/show.html.haml'
|
||||||
- 'app/views/settings/preferences/notifications/show.html.haml'
|
- 'app/views/settings/preferences/notifications/show.html.haml'
|
||||||
- 'app/views/settings/preferences/other/show.html.haml'
|
- 'app/views/settings/preferences/other/show.html.haml'
|
||||||
|
|
||||||
|
# Offense count: 9
|
||||||
|
RuboCop:
|
||||||
|
exclude:
|
||||||
|
- 'app/views/admin/accounts/_buttons.html.haml'
|
||||||
|
- 'app/views/admin/accounts/_local_account.html.haml'
|
||||||
|
- 'app/views/admin/roles/_form.html.haml'
|
||||||
|
|||||||
15
.rubocop.yml
15
.rubocop.yml
@@ -105,21 +105,6 @@ Rails/Exit:
|
|||||||
- 'config/boot.rb'
|
- 'config/boot.rb'
|
||||||
- 'lib/mastodon/cli/*.rb'
|
- 'lib/mastodon/cli/*.rb'
|
||||||
|
|
||||||
Rails/SkipsModelValidations:
|
|
||||||
Exclude:
|
|
||||||
- 'db/*migrate/**/*'
|
|
||||||
|
|
||||||
# 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: Some single letter camel case files shouldn't be split
|
# Reason: Some single letter camel case files shouldn't be split
|
||||||
# https://docs.rubocop.org/rubocop-rspec/cops_rspec.html#rspecfilepath
|
# https://docs.rubocop.org/rubocop-rspec/cops_rspec.html#rspecfilepath
|
||||||
RSpec/FilePath:
|
RSpec/FilePath:
|
||||||
|
|||||||
@@ -26,7 +26,9 @@ Lint/NonLocalExitFromIterator:
|
|||||||
|
|
||||||
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
|
||||||
Metrics/AbcSize:
|
Metrics/AbcSize:
|
||||||
Max: 100
|
Max: 144
|
||||||
|
Exclude:
|
||||||
|
- 'app/serializers/initial_state_serializer.rb'
|
||||||
|
|
||||||
# Configuration parameters: CountBlocks, Max.
|
# Configuration parameters: CountBlocks, Max.
|
||||||
Metrics/BlockNesting:
|
Metrics/BlockNesting:
|
||||||
@@ -107,11 +109,25 @@ Rails/ApplicationController:
|
|||||||
# Include: app/models/**/*.rb
|
# Include: app/models/**/*.rb
|
||||||
Rails/HasAndBelongsToMany:
|
Rails/HasAndBelongsToMany:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'app/models/concerns/account/associations.rb'
|
- 'app/models/concerns/account_associations.rb'
|
||||||
- 'app/models/preview_card.rb'
|
- 'app/models/preview_card.rb'
|
||||||
- 'app/models/status.rb'
|
- 'app/models/status.rb'
|
||||||
- 'app/models/tag.rb'
|
- 'app/models/tag.rb'
|
||||||
|
|
||||||
|
# Configuration parameters: Include.
|
||||||
|
# Include: app/models/**/*.rb
|
||||||
|
Rails/HasManyOrHasOneDependent:
|
||||||
|
Exclude:
|
||||||
|
- 'app/models/concerns/account_counters.rb'
|
||||||
|
- 'app/models/conversation.rb'
|
||||||
|
- 'app/models/custom_emoji.rb'
|
||||||
|
- 'app/models/custom_emoji_category.rb'
|
||||||
|
- 'app/models/domain_block.rb'
|
||||||
|
- 'app/models/invite.rb'
|
||||||
|
- 'app/models/status.rb'
|
||||||
|
- 'app/models/user.rb'
|
||||||
|
- 'app/models/web/push_subscription.rb'
|
||||||
|
|
||||||
# Configuration parameters: Include.
|
# Configuration parameters: Include.
|
||||||
# Include: app/controllers/**/*.rb, app/mailers/**/*.rb
|
# Include: app/controllers/**/*.rb, app/mailers/**/*.rb
|
||||||
Rails/LexicallyScopedActionFilter:
|
Rails/LexicallyScopedActionFilter:
|
||||||
@@ -119,6 +135,23 @@ Rails/LexicallyScopedActionFilter:
|
|||||||
- 'app/controllers/auth/passwords_controller.rb'
|
- 'app/controllers/auth/passwords_controller.rb'
|
||||||
- 'app/controllers/auth/registrations_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:
|
Rails/OutputSafety:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'config/initializers/simple_form.rb'
|
- 'config/initializers/simple_form.rb'
|
||||||
@@ -141,7 +174,7 @@ Rails/SkipsModelValidations:
|
|||||||
Exclude:
|
Exclude:
|
||||||
- 'app/controllers/admin/invites_controller.rb'
|
- 'app/controllers/admin/invites_controller.rb'
|
||||||
- 'app/controllers/concerns/session_tracking_concern.rb'
|
- 'app/controllers/concerns/session_tracking_concern.rb'
|
||||||
- 'app/models/concerns/account/merging.rb'
|
- 'app/models/concerns/account_merging.rb'
|
||||||
- 'app/models/concerns/expireable.rb'
|
- 'app/models/concerns/expireable.rb'
|
||||||
- 'app/models/status.rb'
|
- 'app/models/status.rb'
|
||||||
- 'app/models/trends/links.rb'
|
- 'app/models/trends/links.rb'
|
||||||
@@ -164,6 +197,22 @@ Rails/SkipsModelValidations:
|
|||||||
- 'app/workers/move_worker.rb'
|
- 'app/workers/move_worker.rb'
|
||||||
- 'app/workers/scheduler/ip_cleanup_scheduler.rb'
|
- 'app/workers/scheduler/ip_cleanup_scheduler.rb'
|
||||||
- 'app/workers/scheduler/scheduled_statuses_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/accounts.rb'
|
||||||
- 'lib/mastodon/cli/maintenance.rb'
|
- 'lib/mastodon/cli/maintenance.rb'
|
||||||
- 'spec/lib/activitypub/activity/follow_spec.rb'
|
- 'spec/lib/activitypub/activity/follow_spec.rb'
|
||||||
@@ -179,6 +228,19 @@ Rails/UniqueValidationWithoutIndex:
|
|||||||
- 'app/models/identity.rb'
|
- 'app/models/identity.rb'
|
||||||
- 'app/models/webauthn_credential.rb'
|
- 'app/models/webauthn_credential.rb'
|
||||||
|
|
||||||
|
# Configuration parameters: Include.
|
||||||
|
# Include: app/models/**/*.rb
|
||||||
|
Rails/UnusedIgnoredColumns:
|
||||||
|
Exclude:
|
||||||
|
- 'app/models/account.rb'
|
||||||
|
- 'app/models/account_stat.rb'
|
||||||
|
- 'app/models/admin/action_log.rb'
|
||||||
|
- 'app/models/custom_filter.rb'
|
||||||
|
- 'app/models/email_domain_block.rb'
|
||||||
|
- 'app/models/report.rb'
|
||||||
|
- 'app/models/status_edit.rb'
|
||||||
|
- 'app/models/user.rb'
|
||||||
|
|
||||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||||
# Configuration parameters: EnforcedStyle.
|
# Configuration parameters: EnforcedStyle.
|
||||||
# SupportedStyles: exists, where
|
# SupportedStyles: exists, where
|
||||||
@@ -192,7 +254,7 @@ Rails/WhereExists:
|
|||||||
- 'app/lib/feed_manager.rb'
|
- 'app/lib/feed_manager.rb'
|
||||||
- 'app/lib/status_cache_hydrator.rb'
|
- 'app/lib/status_cache_hydrator.rb'
|
||||||
- 'app/lib/suspicious_sign_in_detector.rb'
|
- 'app/lib/suspicious_sign_in_detector.rb'
|
||||||
- 'app/models/concerns/account/interactions.rb'
|
- 'app/models/concerns/account_interactions.rb'
|
||||||
- 'app/models/featured_tag.rb'
|
- 'app/models/featured_tag.rb'
|
||||||
- 'app/models/poll.rb'
|
- 'app/models/poll.rb'
|
||||||
- 'app/models/session_activation.rb'
|
- 'app/models/session_activation.rb'
|
||||||
@@ -247,7 +309,7 @@ Style/FetchEnvVar:
|
|||||||
- 'config/initializers/devise.rb'
|
- 'config/initializers/devise.rb'
|
||||||
- 'config/initializers/paperclip.rb'
|
- 'config/initializers/paperclip.rb'
|
||||||
- 'config/initializers/vapid.rb'
|
- 'config/initializers/vapid.rb'
|
||||||
- 'lib/premailer_webpack_strategy.rb'
|
- 'lib/mastodon/premailer_webpack_strategy.rb'
|
||||||
- 'lib/mastodon/redis_config.rb'
|
- 'lib/mastodon/redis_config.rb'
|
||||||
- 'lib/tasks/repo.rake'
|
- 'lib/tasks/repo.rake'
|
||||||
- 'spec/features/profile_spec.rb'
|
- 'spec/features/profile_spec.rb'
|
||||||
@@ -282,8 +344,8 @@ Style/GuardClause:
|
|||||||
- 'app/lib/request_pool.rb'
|
- 'app/lib/request_pool.rb'
|
||||||
- 'app/lib/webfinger.rb'
|
- 'app/lib/webfinger.rb'
|
||||||
- 'app/lib/webfinger_resource.rb'
|
- 'app/lib/webfinger_resource.rb'
|
||||||
- 'app/models/concerns/account/counters.rb'
|
- 'app/models/concerns/account_counters.rb'
|
||||||
- 'app/models/concerns/user/ldap_authenticable.rb'
|
- 'app/models/concerns/ldap_authenticable.rb'
|
||||||
- 'app/models/tag.rb'
|
- 'app/models/tag.rb'
|
||||||
- 'app/models/user.rb'
|
- 'app/models/user.rb'
|
||||||
- 'app/services/fan_out_on_write_service.rb'
|
- 'app/services/fan_out_on_write_service.rb'
|
||||||
@@ -297,8 +359,8 @@ Style/GuardClause:
|
|||||||
- 'config/initializers/devise.rb'
|
- 'config/initializers/devise.rb'
|
||||||
- 'db/migrate/20170901141119_truncate_preview_cards.rb'
|
- 'db/migrate/20170901141119_truncate_preview_cards.rb'
|
||||||
- 'db/post_migrate/20220704024901_migrate_settings_to_user_roles.rb'
|
- 'db/post_migrate/20220704024901_migrate_settings_to_user_roles.rb'
|
||||||
- 'lib/devise/strategies/two_factor_ldap_authenticatable.rb'
|
- 'lib/devise/two_factor_ldap_authenticatable.rb'
|
||||||
- 'lib/devise/strategies/two_factor_pam_authenticatable.rb'
|
- 'lib/devise/two_factor_pam_authenticatable.rb'
|
||||||
- 'lib/mastodon/cli/accounts.rb'
|
- 'lib/mastodon/cli/accounts.rb'
|
||||||
- 'lib/mastodon/cli/maintenance.rb'
|
- 'lib/mastodon/cli/maintenance.rb'
|
||||||
- 'lib/mastodon/cli/media.rb'
|
- 'lib/mastodon/cli/media.rb'
|
||||||
@@ -312,8 +374,8 @@ Style/HashAsLastArrayItem:
|
|||||||
Exclude:
|
Exclude:
|
||||||
- 'app/controllers/admin/statuses_controller.rb'
|
- 'app/controllers/admin/statuses_controller.rb'
|
||||||
- 'app/controllers/api/v1/statuses_controller.rb'
|
- 'app/controllers/api/v1/statuses_controller.rb'
|
||||||
- 'app/models/concerns/account/counters.rb'
|
- 'app/models/concerns/account_counters.rb'
|
||||||
- 'app/models/concerns/status/threading_concern.rb'
|
- 'app/models/concerns/status_threading_concern.rb'
|
||||||
- 'app/models/status.rb'
|
- 'app/models/status.rb'
|
||||||
- 'app/services/batched_remove_status_service.rb'
|
- 'app/services/batched_remove_status_service.rb'
|
||||||
- 'app/services/notify_service.rb'
|
- 'app/services/notify_service.rb'
|
||||||
@@ -332,6 +394,22 @@ Style/IfUnlessModifier:
|
|||||||
- 'config/initializers/devise.rb'
|
- 'config/initializers/devise.rb'
|
||||||
- 'config/initializers/ffmpeg.rb'
|
- 'config/initializers/ffmpeg.rb'
|
||||||
|
|
||||||
|
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||||
|
# Configuration parameters: InverseMethods, InverseBlocks.
|
||||||
|
Style/InverseMethods:
|
||||||
|
Exclude:
|
||||||
|
- 'app/models/custom_filter.rb'
|
||||||
|
- 'app/services/update_account_service.rb'
|
||||||
|
- 'spec/controllers/activitypub/replies_controller_spec.rb'
|
||||||
|
|
||||||
|
# This cop supports safe autocorrection (--autocorrect).
|
||||||
|
# Configuration parameters: EnforcedStyle.
|
||||||
|
# SupportedStyles: line_count_dependent, lambda, literal
|
||||||
|
Style/Lambda:
|
||||||
|
Exclude:
|
||||||
|
- 'config/initializers/simple_form.rb'
|
||||||
|
- 'config/routes.rb'
|
||||||
|
|
||||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||||
Style/MapToHash:
|
Style/MapToHash:
|
||||||
Exclude:
|
Exclude:
|
||||||
@@ -396,26 +474,40 @@ Style/RedundantFetchBlock:
|
|||||||
- 'config/initializers/paperclip.rb'
|
- 'config/initializers/paperclip.rb'
|
||||||
- 'config/puma.rb'
|
- 'config/puma.rb'
|
||||||
|
|
||||||
|
# This cop supports safe autocorrection (--autocorrect).
|
||||||
|
# Configuration parameters: AllowMultipleReturnValues.
|
||||||
|
Style/RedundantReturn:
|
||||||
|
Exclude:
|
||||||
|
- 'app/controllers/api/v1/directories_controller.rb'
|
||||||
|
- 'app/controllers/auth/confirmations_controller.rb'
|
||||||
|
- 'app/lib/ostatus/tag_manager.rb'
|
||||||
|
- 'app/models/form/import.rb'
|
||||||
|
|
||||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||||
# Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods, MaxChainLength.
|
# Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods, MaxChainLength.
|
||||||
# AllowedMethods: present?, blank?, presence, try, try!
|
# AllowedMethods: present?, blank?, presence, try, try!
|
||||||
Style/SafeNavigation:
|
Style/SafeNavigation:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'app/models/concerns/account/finder_concern.rb'
|
- 'app/models/concerns/account_finder_concern.rb'
|
||||||
|
|
||||||
# This cop supports safe autocorrection (--autocorrect).
|
# This cop supports safe autocorrection (--autocorrect).
|
||||||
# Configuration parameters: EnforcedStyle.
|
# Configuration parameters: EnforcedStyle.
|
||||||
# SupportedStyles: only_raise, only_fail, semantic
|
# SupportedStyles: only_raise, only_fail, semantic
|
||||||
Style/SignalException:
|
Style/SignalException:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'lib/devise/strategies/two_factor_ldap_authenticatable.rb'
|
- 'lib/devise/two_factor_ldap_authenticatable.rb'
|
||||||
- 'lib/devise/strategies/two_factor_pam_authenticatable.rb'
|
- 'lib/devise/two_factor_pam_authenticatable.rb'
|
||||||
|
|
||||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||||
Style/SingleArgumentDig:
|
Style/SingleArgumentDig:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'lib/webpacker/manifest_extensions.rb'
|
- 'lib/webpacker/manifest_extensions.rb'
|
||||||
|
|
||||||
|
# This cop supports safe autocorrection (--autocorrect).
|
||||||
|
Style/StderrPuts:
|
||||||
|
Exclude:
|
||||||
|
- 'config/boot.rb'
|
||||||
|
|
||||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||||
# Configuration parameters: Mode.
|
# Configuration parameters: Mode.
|
||||||
Style/StringConcatenation:
|
Style/StringConcatenation:
|
||||||
@@ -434,6 +526,13 @@ Style/StringLiterals:
|
|||||||
- 'config/initializers/webauthn.rb'
|
- 'config/initializers/webauthn.rb'
|
||||||
- 'config/routes.rb'
|
- 'config/routes.rb'
|
||||||
|
|
||||||
|
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||||
|
# Configuration parameters: AllowMethodsWithArguments, AllowedMethods, AllowedPatterns, AllowComments.
|
||||||
|
# AllowedMethods: define_method, mail, respond_to
|
||||||
|
Style/SymbolProc:
|
||||||
|
Exclude:
|
||||||
|
- 'config/initializers/3_omniauth.rb'
|
||||||
|
|
||||||
# This cop supports safe autocorrection (--autocorrect).
|
# This cop supports safe autocorrection (--autocorrect).
|
||||||
# Configuration parameters: EnforcedStyle, AllowSafeAssignment.
|
# Configuration parameters: EnforcedStyle, AllowSafeAssignment.
|
||||||
# SupportedStyles: require_parentheses, require_no_parentheses, require_parentheses_when_complex
|
# SupportedStyles: require_parentheses, require_no_parentheses, require_parentheses_when_complex
|
||||||
|
|||||||
22
.simplecov
22
.simplecov
@@ -1,22 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -50,10 +50,6 @@ You can contribute in the following ways:
|
|||||||
|
|
||||||
If your contributions are accepted into Mastodon, you can request to be paid through [our OpenCollective](https://opencollective.com/mastodon).
|
If your contributions are accepted into Mastodon, you can request to be paid through [our OpenCollective](https://opencollective.com/mastodon).
|
||||||
|
|
||||||
## API Changes and Additions
|
|
||||||
|
|
||||||
Please note that any changes or additions made to the API should have an accompanying pull request on [our documentation repository](https://github.com/mastodon/documentation).
|
|
||||||
|
|
||||||
## Bug reports
|
## Bug reports
|
||||||
|
|
||||||
Bug reports and feature suggestions must use descriptive and concise titles and be submitted to [GitHub Issues](https://github.com/mastodon/mastodon/issues). Please use the search function to make sure that you are not submitting duplicates, and that a similar report or request has not already been resolved or rejected.
|
Bug reports and feature suggestions must use descriptive and concise titles and be submitted to [GitHub Issues](https://github.com/mastodon/mastodon/issues). Please use the search function to make sure that you are not submitting duplicates, and that a similar report or request has not already been resolved or rejected.
|
||||||
|
|||||||
322
Dockerfile
322
Dockerfile
@@ -1,259 +1,111 @@
|
|||||||
# syntax=docker/dockerfile:1.4
|
# syntax=docker/dockerfile:1.4
|
||||||
|
# This needs to be bookworm-slim because the Ruby image is built on bookworm-slim
|
||||||
|
ARG NODE_VERSION="20.9-bookworm-slim"
|
||||||
|
|
||||||
# Please see https://docs.docker.com/engine/reference/builder for information about
|
FROM ghcr.io/moritzheiber/ruby-jemalloc:3.2.2-slim as ruby
|
||||||
# the extended buildx capabilities used in this file.
|
FROM node:${NODE_VERSION} as build
|
||||||
# Make sure multiarch TARGETPLATFORM is available for interpolation
|
|
||||||
# See: https://docs.docker.com/build/building/multi-platform/
|
|
||||||
ARG TARGETPLATFORM=${TARGETPLATFORM}
|
|
||||||
ARG BUILDPLATFORM=${BUILDPLATFORM}
|
|
||||||
|
|
||||||
# Ruby image to use for base image, change with [--build-arg RUBY_VERSION="3.2.2"]
|
COPY --link --from=ruby /opt/ruby /opt/ruby
|
||||||
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
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# Resulting version string is vX.X.X-MASTODON_VERSION_PRERELEASE+MASTODON_VERSION_METADATA
|
ENV DEBIAN_FRONTEND="noninteractive" \
|
||||||
# Example: v4.2.0-nightly.2023.11.09+something
|
PATH="${PATH}:/opt/ruby/bin"
|
||||||
# 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
|
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||||
# 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"
|
|
||||||
|
|
||||||
# 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 \
|
|
||||||
# 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"
|
|
||||||
|
|
||||||
# Set default shell used for running commands
|
|
||||||
SHELL ["/bin/bash", "-o", "pipefail", "-o", "errexit", "-c"]
|
|
||||||
|
|
||||||
ARG TARGETPLATFORM
|
|
||||||
|
|
||||||
RUN echo "Target platform is $TARGETPLATFORM"
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
# Set /opt/mastodon as working directory
|
|
||||||
WORKDIR /opt/mastodon
|
WORKDIR /opt/mastodon
|
||||||
|
|
||||||
# hadolint ignore=DL3008,DL3005
|
# hadolint ignore=DL3008
|
||||||
RUN \
|
RUN apt-get update && \
|
||||||
# Mount Apt cache and lib directories from Docker buildx caches
|
apt-get -yq dist-upgrade && \
|
||||||
--mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \
|
apt-get install -y --no-install-recommends build-essential \
|
||||||
--mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \
|
git \
|
||||||
# Apt update & upgrade to check for security updates to Debian image
|
libicu-dev \
|
||||||
apt-get update; \
|
libidn-dev \
|
||||||
apt-get dist-upgrade -yq; \
|
libpq-dev \
|
||||||
# Install jemalloc, curl and other necessary components
|
libjemalloc-dev \
|
||||||
apt-get install -y --no-install-recommends \
|
zlib1g-dev \
|
||||||
ca-certificates \
|
libgdbm-dev \
|
||||||
curl \
|
libgmp-dev \
|
||||||
ffmpeg \
|
libssl-dev \
|
||||||
file \
|
libyaml-dev \
|
||||||
imagemagick \
|
ca-certificates \
|
||||||
libjemalloc2 \
|
libreadline8 \
|
||||||
patchelf \
|
python3 \
|
||||||
procps \
|
shared-mime-info && \
|
||||||
tini \
|
bundle config set --local deployment 'true' && \
|
||||||
tzdata \
|
bundle config set --local without 'development test' && \
|
||||||
; \
|
bundle config set silence_root_warning true && \
|
||||||
# Patch Ruby to use jemalloc
|
corepack enable
|
||||||
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
|
COPY Gemfile* package.json yarn.lock .yarnrc.yml /opt/mastodon/
|
||||||
FROM ruby as build
|
|
||||||
|
|
||||||
# Copy Node package configuration files into working directory
|
|
||||||
COPY package.json yarn.lock .yarnrc.yml /opt/mastodon/
|
|
||||||
COPY .yarn /opt/mastodon/.yarn
|
COPY .yarn /opt/mastodon/.yarn
|
||||||
|
|
||||||
COPY --from=node /usr/local/bin /usr/local/bin
|
RUN bundle install -j"$(nproc)"
|
||||||
COPY --from=node /usr/local/lib /usr/local/lib
|
|
||||||
|
|
||||||
ARG TARGETPLATFORM
|
RUN yarn workspaces focus --all --production && \
|
||||||
|
yarn cache clean
|
||||||
|
|
||||||
# hadolint ignore=DL3008
|
FROM node:${NODE_VERSION}
|
||||||
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 \
|
# Use those args to specify your own version flags & suffixes
|
||||||
# Configure Corepack
|
ARG MASTODON_VERSION_PRERELEASE=""
|
||||||
rm /usr/local/bin/yarn*; \
|
ARG MASTODON_VERSION_METADATA=""
|
||||||
corepack enable; \
|
|
||||||
corepack prepare --activate;
|
|
||||||
|
|
||||||
# Create temporary bundler specific build layer from build layer
|
ARG UID="991"
|
||||||
FROM build as bundler
|
ARG GID="991"
|
||||||
|
|
||||||
ARG TARGETPLATFORM
|
COPY --link --from=ruby /opt/ruby /opt/ruby
|
||||||
|
|
||||||
# Copy Gemfile config into working directory
|
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||||
COPY Gemfile* /opt/mastodon/
|
|
||||||
|
|
||||||
RUN \
|
ENV DEBIAN_FRONTEND="noninteractive" \
|
||||||
# Mount Ruby Gem caches
|
PATH="${PATH}:/opt/ruby/bin:/opt/mastodon/bin"
|
||||||
--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
|
# Ignoring these here since we don't want to pin any versions and the Debian image removes apt-get content after use
|
||||||
FROM build as yarn
|
# hadolint ignore=DL3008,DL3009
|
||||||
|
RUN apt-get update && \
|
||||||
|
echo "Etc/UTC" > /etc/localtime && \
|
||||||
|
groupadd -g "${GID}" mastodon && \
|
||||||
|
useradd -l -u "$UID" -g "${GID}" -m -d /opt/mastodon mastodon && \
|
||||||
|
apt-get -y --no-install-recommends install whois \
|
||||||
|
wget \
|
||||||
|
procps \
|
||||||
|
libssl3 \
|
||||||
|
libpq5 \
|
||||||
|
imagemagick \
|
||||||
|
ffmpeg \
|
||||||
|
libjemalloc2 \
|
||||||
|
libicu72 \
|
||||||
|
libidn12 \
|
||||||
|
libyaml-0-2 \
|
||||||
|
file \
|
||||||
|
ca-certificates \
|
||||||
|
tzdata \
|
||||||
|
libreadline8 \
|
||||||
|
tini && \
|
||||||
|
ln -s /opt/mastodon /mastodon && \
|
||||||
|
corepack enable
|
||||||
|
|
||||||
ARG TARGETPLATFORM
|
# 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
|
||||||
|
|
||||||
# Copy Node package configuration files into working directory
|
COPY --chown=mastodon:mastodon . /opt/mastodon
|
||||||
COPY package.json yarn.lock .yarnrc.yml /opt/mastodon/
|
COPY --chown=mastodon:mastodon --from=build /opt/mastodon /opt/mastodon
|
||||||
COPY streaming/package.json /opt/mastodon/streaming/
|
|
||||||
COPY .yarn /opt/mastodon/.yarn
|
|
||||||
|
|
||||||
# hadolint ignore=DL3008
|
ENV RAILS_ENV="production" \
|
||||||
RUN \
|
NODE_ENV="production" \
|
||||||
--mount=type=cache,id=corepack-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/corepack,sharing=locked \
|
RAILS_SERVE_STATIC_FILES="true" \
|
||||||
--mount=type=cache,id=yarn-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/yarn,sharing=locked \
|
BIND="0.0.0.0" \
|
||||||
# Install Node packages
|
MASTODON_VERSION_PRERELEASE="${MASTODON_VERSION_PRERELEASE}" \
|
||||||
yarn workspaces focus --production @mastodon/mastodon;
|
MASTODON_VERSION_METADATA="${MASTODON_VERSION_METADATA}"
|
||||||
|
|
||||||
# Create temporary assets build layer from build layer
|
# Set the run user
|
||||||
FROM build as precompiler
|
|
||||||
|
|
||||||
# Copy Mastodon sources into precompiler layer
|
|
||||||
COPY . /opt/mastodon/
|
|
||||||
|
|
||||||
# Copy bundler and node packages from build layer to container
|
|
||||||
COPY --from=yarn /opt/mastodon /opt/mastodon/
|
|
||||||
COPY --from=bundler /opt/mastodon /opt/mastodon/
|
|
||||||
COPY --from=bundler /usr/local/bundle/ /usr/local/bundle/
|
|
||||||
|
|
||||||
ARG TARGETPLATFORM
|
|
||||||
|
|
||||||
RUN \
|
|
||||||
# Use Ruby on Rails to create Mastodon assets
|
|
||||||
OTP_SECRET=precompile_placeholder SECRET_KEY_BASE=precompile_placeholder bundle exec rails assets:precompile; \
|
|
||||||
# Cleanup temporary files
|
|
||||||
rm -fr /opt/mastodon/tmp;
|
|
||||||
|
|
||||||
# Prep final Mastodon Ruby layer
|
|
||||||
FROM ruby as mastodon
|
|
||||||
|
|
||||||
ARG TARGETPLATFORM
|
|
||||||
|
|
||||||
# hadolint ignore=DL3008
|
|
||||||
RUN \
|
|
||||||
# Mount Apt cache and lib directories from Docker buildx caches
|
|
||||||
--mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \
|
|
||||||
--mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \
|
|
||||||
# Mount Corepack and Yarn caches from Docker buildx caches
|
|
||||||
--mount=type=cache,id=corepack-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/corepack,sharing=locked \
|
|
||||||
--mount=type=cache,id=yarn-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/yarn,sharing=locked \
|
|
||||||
# Apt update install non-dev versions of necessary components
|
|
||||||
apt-get install -y --no-install-recommends \
|
|
||||||
libssl3 \
|
|
||||||
libpq5 \
|
|
||||||
libicu72 \
|
|
||||||
libidn12 \
|
|
||||||
libreadline8 \
|
|
||||||
libyaml-0-2 \
|
|
||||||
;
|
|
||||||
|
|
||||||
# Copy Mastodon sources into final layer
|
|
||||||
COPY . /opt/mastodon/
|
|
||||||
|
|
||||||
# Copy compiled assets to layer
|
|
||||||
COPY --from=precompiler /opt/mastodon/public/packs /opt/mastodon/public/packs
|
|
||||||
COPY --from=precompiler /opt/mastodon/public/assets /opt/mastodon/public/assets
|
|
||||||
# Copy bundler components to layer
|
|
||||||
COPY --from=bundler /usr/local/bundle/ /usr/local/bundle/
|
|
||||||
|
|
||||||
RUN \
|
|
||||||
# Precompile bootsnap code for faster Rails startup
|
|
||||||
bundle exec bootsnap precompile --gemfile app/ lib/;
|
|
||||||
|
|
||||||
RUN \
|
|
||||||
# Pre-create and chown system volume to Mastodon user
|
|
||||||
mkdir -p /opt/mastodon/public/system; \
|
|
||||||
chown mastodon:mastodon /opt/mastodon/public/system; \
|
|
||||||
# Set Mastodon user as owner of tmp folder
|
|
||||||
chown -R mastodon:mastodon /opt/mastodon/tmp;
|
|
||||||
|
|
||||||
# Set the running user for resulting container
|
|
||||||
USER mastodon
|
USER mastodon
|
||||||
# Expose default Puma ports
|
WORKDIR /opt/mastodon
|
||||||
EXPOSE 3000
|
|
||||||
# Set container tini as default entry point
|
# Precompile assets
|
||||||
ENTRYPOINT ["/usr/bin/tini", "--"]
|
RUN OTP_SECRET=precompile_placeholder SECRET_KEY_BASE=precompile_placeholder rails assets:precompile
|
||||||
|
|
||||||
|
# Set the work dir and the container entry point
|
||||||
|
ENTRYPOINT ["/usr/bin/tini", "--"]
|
||||||
|
EXPOSE 3000 4000
|
||||||
|
|||||||
13
Gemfile
13
Gemfile
@@ -5,13 +5,10 @@ ruby '>= 3.0.0'
|
|||||||
|
|
||||||
gem 'puma', '~> 6.3'
|
gem 'puma', '~> 6.3'
|
||||||
gem 'rails', '~> 7.1.1'
|
gem 'rails', '~> 7.1.1'
|
||||||
gem 'propshaft'
|
gem 'sprockets', '~> 3.7.2'
|
||||||
gem 'thor', '~> 1.2'
|
gem 'thor', '~> 1.2'
|
||||||
gem 'rack', '~> 2.2.7'
|
gem 'rack', '~> 2.2.7'
|
||||||
|
|
||||||
# For why irb is in the Gemfile, see: https://ruby.social/@st0012/111444685161478182
|
|
||||||
gem 'irb', '~> 1.8'
|
|
||||||
|
|
||||||
gem 'haml-rails', '~>2.0'
|
gem 'haml-rails', '~>2.0'
|
||||||
gem 'pg', '~> 1.5'
|
gem 'pg', '~> 1.5'
|
||||||
gem 'pghero'
|
gem 'pghero'
|
||||||
@@ -89,6 +86,7 @@ gem 'sidekiq-unique-jobs', '~> 7.1'
|
|||||||
gem 'sidekiq-bulk', '~> 0.2.0'
|
gem 'sidekiq-bulk', '~> 0.2.0'
|
||||||
gem 'simple-navigation', '~> 4.4'
|
gem 'simple-navigation', '~> 4.4'
|
||||||
gem 'simple_form', '~> 5.2'
|
gem 'simple_form', '~> 5.2'
|
||||||
|
gem 'sprockets-rails', '~> 3.4', require: 'sprockets/railtie'
|
||||||
gem 'stoplight', '~> 3.0.1'
|
gem 'stoplight', '~> 3.0.1'
|
||||||
gem 'strong_migrations', '1.6.4'
|
gem 'strong_migrations', '1.6.4'
|
||||||
gem 'tty-prompt', '~> 0.23', require: false
|
gem 'tty-prompt', '~> 0.23', require: false
|
||||||
@@ -111,9 +109,6 @@ group :test do
|
|||||||
# RSpec progress bar formatter
|
# RSpec progress bar formatter
|
||||||
gem 'fuubar', '~> 2.5'
|
gem 'fuubar', '~> 2.5'
|
||||||
|
|
||||||
# RSpec helpers for email specs
|
|
||||||
gem 'email_spec'
|
|
||||||
|
|
||||||
# Extra RSpec extenion methods and helpers for sidekiq
|
# Extra RSpec extenion methods and helpers for sidekiq
|
||||||
gem 'rspec-sidekiq', '~> 4.0'
|
gem 'rspec-sidekiq', '~> 4.0'
|
||||||
|
|
||||||
@@ -144,7 +139,6 @@ group :test do
|
|||||||
|
|
||||||
# Coverage formatter for RSpec test if DISABLE_SIMPLECOV is false
|
# Coverage formatter for RSpec test if DISABLE_SIMPLECOV is false
|
||||||
gem 'simplecov', '~> 0.22', require: false
|
gem 'simplecov', '~> 0.22', require: false
|
||||||
gem 'simplecov-lcov', '~> 0.8', require: false
|
|
||||||
|
|
||||||
# Stub web requests for specs
|
# Stub web requests for specs
|
||||||
gem 'webmock', '~> 3.18'
|
gem 'webmock', '~> 3.18'
|
||||||
@@ -181,9 +175,6 @@ group :development do
|
|||||||
end
|
end
|
||||||
|
|
||||||
group :development, :test do
|
group :development, :test do
|
||||||
# Interactive Debugging tools
|
|
||||||
gem 'debug', '~> 1.8'
|
|
||||||
|
|
||||||
# Profiling tools
|
# Profiling tools
|
||||||
gem 'memory_profiler', require: false
|
gem 'memory_profiler', require: false
|
||||||
gem 'ruby-prof', require: false
|
gem 'ruby-prof', require: false
|
||||||
|
|||||||
115
Gemfile.lock
115
Gemfile.lock
@@ -118,7 +118,7 @@ GEM
|
|||||||
minitest (>= 5.1)
|
minitest (>= 5.1)
|
||||||
mutex_m
|
mutex_m
|
||||||
tzinfo (~> 2.0)
|
tzinfo (~> 2.0)
|
||||||
addressable (2.8.6)
|
addressable (2.8.5)
|
||||||
public_suffix (>= 2.0.2, < 6.0)
|
public_suffix (>= 2.0.2, < 6.0)
|
||||||
aes_key_wrap (1.1.0)
|
aes_key_wrap (1.1.0)
|
||||||
android_key_attestation (0.3.0)
|
android_key_attestation (0.3.0)
|
||||||
@@ -130,21 +130,21 @@ GEM
|
|||||||
encryptor (~> 3.0.0)
|
encryptor (~> 3.0.0)
|
||||||
attr_required (1.0.1)
|
attr_required (1.0.1)
|
||||||
awrence (1.2.1)
|
awrence (1.2.1)
|
||||||
aws-eventstream (1.3.0)
|
aws-eventstream (1.2.0)
|
||||||
aws-partitions (1.857.0)
|
aws-partitions (1.828.0)
|
||||||
aws-sdk-core (3.188.0)
|
aws-sdk-core (3.183.1)
|
||||||
aws-eventstream (~> 1, >= 1.0.2)
|
aws-eventstream (~> 1, >= 1.0.2)
|
||||||
aws-partitions (~> 1, >= 1.651.0)
|
aws-partitions (~> 1, >= 1.651.0)
|
||||||
aws-sigv4 (~> 1.5)
|
aws-sigv4 (~> 1.5)
|
||||||
jmespath (~> 1, >= 1.6.1)
|
jmespath (~> 1, >= 1.6.1)
|
||||||
aws-sdk-kms (1.73.0)
|
aws-sdk-kms (1.71.0)
|
||||||
aws-sdk-core (~> 3, >= 3.188.0)
|
aws-sdk-core (~> 3, >= 3.177.0)
|
||||||
aws-sigv4 (~> 1.1)
|
aws-sigv4 (~> 1.1)
|
||||||
aws-sdk-s3 (1.140.0)
|
aws-sdk-s3 (1.136.0)
|
||||||
aws-sdk-core (~> 3, >= 3.188.0)
|
aws-sdk-core (~> 3, >= 3.181.0)
|
||||||
aws-sdk-kms (~> 1)
|
aws-sdk-kms (~> 1)
|
||||||
aws-sigv4 (~> 1.6)
|
aws-sigv4 (~> 1.6)
|
||||||
aws-sigv4 (1.7.0)
|
aws-sigv4 (1.6.0)
|
||||||
aws-eventstream (~> 1, >= 1.0.2)
|
aws-eventstream (~> 1, >= 1.0.2)
|
||||||
azure-storage-blob (2.0.3)
|
azure-storage-blob (2.0.3)
|
||||||
azure-storage-common (~> 2.0)
|
azure-storage-common (~> 2.0)
|
||||||
@@ -154,9 +154,9 @@ GEM
|
|||||||
faraday_middleware (~> 1.0, >= 1.0.0.rc1)
|
faraday_middleware (~> 1.0, >= 1.0.0.rc1)
|
||||||
net-http-persistent (~> 4.0)
|
net-http-persistent (~> 4.0)
|
||||||
nokogiri (~> 1, >= 1.10.8)
|
nokogiri (~> 1, >= 1.10.8)
|
||||||
base64 (0.2.0)
|
base64 (0.1.1)
|
||||||
bcp47_spec (0.2.1)
|
bcp47_spec (0.2.1)
|
||||||
bcrypt (3.1.20)
|
bcrypt (3.1.19)
|
||||||
better_errors (2.10.1)
|
better_errors (2.10.1)
|
||||||
erubi (>= 1.0.0)
|
erubi (>= 1.0.0)
|
||||||
rack (>= 0.9.0)
|
rack (>= 0.9.0)
|
||||||
@@ -168,14 +168,14 @@ GEM
|
|||||||
erubi (~> 1.4)
|
erubi (~> 1.4)
|
||||||
parser (>= 2.4)
|
parser (>= 2.4)
|
||||||
smart_properties
|
smart_properties
|
||||||
bigdecimal (3.1.5)
|
bigdecimal (3.1.4)
|
||||||
bindata (2.4.15)
|
bindata (2.4.15)
|
||||||
binding_of_caller (1.0.0)
|
binding_of_caller (1.0.0)
|
||||||
debug_inspector (>= 0.0.1)
|
debug_inspector (>= 0.0.1)
|
||||||
blurhash (0.1.7)
|
blurhash (0.1.7)
|
||||||
bootsnap (1.17.0)
|
bootsnap (1.17.0)
|
||||||
msgpack (~> 1.2)
|
msgpack (~> 1.2)
|
||||||
brakeman (6.1.0)
|
brakeman (6.0.1)
|
||||||
browser (5.3.1)
|
browser (5.3.1)
|
||||||
brpoplpush-redis_script (0.1.3)
|
brpoplpush-redis_script (0.1.3)
|
||||||
concurrent-ruby (~> 1.0, >= 1.0.5)
|
concurrent-ruby (~> 1.0, >= 1.0.5)
|
||||||
@@ -197,7 +197,7 @@ GEM
|
|||||||
activesupport
|
activesupport
|
||||||
cbor (0.5.9.6)
|
cbor (0.5.9.6)
|
||||||
charlock_holmes (0.7.7)
|
charlock_holmes (0.7.7)
|
||||||
chewy (7.4.0)
|
chewy (7.3.4)
|
||||||
activesupport (>= 5.2)
|
activesupport (>= 5.2)
|
||||||
elasticsearch (>= 7.12.0, < 7.14.0)
|
elasticsearch (>= 7.12.0, < 7.14.0)
|
||||||
elasticsearch-dsl
|
elasticsearch-dsl
|
||||||
@@ -220,9 +220,6 @@ GEM
|
|||||||
database_cleaner-core (~> 2.0.0)
|
database_cleaner-core (~> 2.0.0)
|
||||||
database_cleaner-core (2.0.1)
|
database_cleaner-core (2.0.1)
|
||||||
date (3.3.4)
|
date (3.3.4)
|
||||||
debug (1.9.0)
|
|
||||||
irb (~> 1.10)
|
|
||||||
reline (>= 0.3.8)
|
|
||||||
debug_inspector (1.1.0)
|
debug_inspector (1.1.0)
|
||||||
devise (4.9.3)
|
devise (4.9.3)
|
||||||
bcrypt (~> 3.0)
|
bcrypt (~> 3.0)
|
||||||
@@ -245,13 +242,13 @@ GEM
|
|||||||
docile (1.4.0)
|
docile (1.4.0)
|
||||||
domain_name (0.5.20190701)
|
domain_name (0.5.20190701)
|
||||||
unf (>= 0.0.5, < 1.0.0)
|
unf (>= 0.0.5, < 1.0.0)
|
||||||
doorkeeper (5.6.8)
|
doorkeeper (5.6.6)
|
||||||
railties (>= 5)
|
railties (>= 5)
|
||||||
dotenv (2.8.1)
|
dotenv (2.8.1)
|
||||||
dotenv-rails (2.8.1)
|
dotenv-rails (2.8.1)
|
||||||
dotenv (= 2.8.1)
|
dotenv (= 2.8.1)
|
||||||
railties (>= 3.2)
|
railties (>= 3.2)
|
||||||
drb (2.2.0)
|
drb (2.1.1)
|
||||||
ruby2_keywords
|
ruby2_keywords
|
||||||
ed25519 (1.3.0)
|
ed25519 (1.3.0)
|
||||||
elasticsearch (7.13.3)
|
elasticsearch (7.13.3)
|
||||||
@@ -263,16 +260,12 @@ GEM
|
|||||||
elasticsearch-transport (7.13.3)
|
elasticsearch-transport (7.13.3)
|
||||||
faraday (~> 1)
|
faraday (~> 1)
|
||||||
multi_json
|
multi_json
|
||||||
email_spec (2.2.2)
|
|
||||||
htmlentities (~> 4.3.3)
|
|
||||||
launchy (~> 2.1)
|
|
||||||
mail (~> 2.7)
|
|
||||||
encryptor (3.0.0)
|
encryptor (3.0.0)
|
||||||
erubi (1.12.0)
|
erubi (1.12.0)
|
||||||
et-orbi (1.2.7)
|
et-orbi (1.2.7)
|
||||||
tzinfo
|
tzinfo
|
||||||
excon (0.104.0)
|
excon (0.104.0)
|
||||||
fabrication (2.31.0)
|
fabrication (2.30.0)
|
||||||
faker (3.2.2)
|
faker (3.2.2)
|
||||||
i18n (>= 1.8.11, < 2)
|
i18n (>= 1.8.11, < 2)
|
||||||
faraday (1.10.3)
|
faraday (1.10.3)
|
||||||
@@ -326,7 +319,7 @@ GEM
|
|||||||
ruby-progressbar (~> 1.4)
|
ruby-progressbar (~> 1.4)
|
||||||
globalid (1.2.1)
|
globalid (1.2.1)
|
||||||
activesupport (>= 6.1)
|
activesupport (>= 6.1)
|
||||||
haml (6.3.0)
|
haml (6.2.0)
|
||||||
temple (>= 0.8.2)
|
temple (>= 0.8.2)
|
||||||
thor
|
thor
|
||||||
tilt
|
tilt
|
||||||
@@ -335,7 +328,7 @@ GEM
|
|||||||
activesupport (>= 5.1)
|
activesupport (>= 5.1)
|
||||||
haml (>= 4.0.6)
|
haml (>= 4.0.6)
|
||||||
railties (>= 5.1)
|
railties (>= 5.1)
|
||||||
haml_lint (0.52.0)
|
haml_lint (0.51.0)
|
||||||
haml (>= 4.0)
|
haml (>= 4.0)
|
||||||
parallel (~> 1.10)
|
parallel (~> 1.10)
|
||||||
rainbow
|
rainbow
|
||||||
@@ -377,11 +370,11 @@ GEM
|
|||||||
terminal-table (>= 1.5.1)
|
terminal-table (>= 1.5.1)
|
||||||
idn-ruby (0.1.5)
|
idn-ruby (0.1.5)
|
||||||
io-console (0.6.0)
|
io-console (0.6.0)
|
||||||
irb (1.10.1)
|
irb (1.8.3)
|
||||||
rdoc
|
rdoc
|
||||||
reline (>= 0.3.8)
|
reline (>= 0.3.8)
|
||||||
jmespath (1.6.2)
|
jmespath (1.6.2)
|
||||||
json (2.7.1)
|
json (2.6.3)
|
||||||
json-canonicalization (1.0.0)
|
json-canonicalization (1.0.0)
|
||||||
json-jwt (1.15.3)
|
json-jwt (1.15.3)
|
||||||
activesupport (>= 4.2)
|
activesupport (>= 4.2)
|
||||||
@@ -439,7 +432,7 @@ GEM
|
|||||||
activesupport (>= 4)
|
activesupport (>= 4)
|
||||||
railties (>= 4)
|
railties (>= 4)
|
||||||
request_store (~> 1.0)
|
request_store (~> 1.0)
|
||||||
loofah (2.22.0)
|
loofah (2.21.4)
|
||||||
crass (~> 1.0.2)
|
crass (~> 1.0.2)
|
||||||
nokogiri (>= 1.12.0)
|
nokogiri (>= 1.12.0)
|
||||||
mail (2.8.1)
|
mail (2.8.1)
|
||||||
@@ -465,7 +458,7 @@ GEM
|
|||||||
msgpack (1.7.2)
|
msgpack (1.7.2)
|
||||||
multi_json (1.15.0)
|
multi_json (1.15.0)
|
||||||
multipart-post (2.3.0)
|
multipart-post (2.3.0)
|
||||||
mutex_m (0.2.0)
|
mutex_m (0.1.2)
|
||||||
net-http (0.4.0)
|
net-http (0.4.0)
|
||||||
uri
|
uri
|
||||||
net-http-persistent (4.0.2)
|
net-http-persistent (4.0.2)
|
||||||
@@ -481,11 +474,10 @@ GEM
|
|||||||
net-smtp (0.4.0)
|
net-smtp (0.4.0)
|
||||||
net-protocol
|
net-protocol
|
||||||
nio4r (2.5.9)
|
nio4r (2.5.9)
|
||||||
nokogiri (1.15.5)
|
nokogiri (1.15.4)
|
||||||
mini_portile2 (~> 2.8.2)
|
mini_portile2 (~> 2.8.2)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
oj (3.16.3)
|
oj (3.16.1)
|
||||||
bigdecimal (>= 3.0)
|
|
||||||
omniauth (2.1.1)
|
omniauth (2.1.1)
|
||||||
hashie (>= 3.4.6)
|
hashie (>= 3.4.6)
|
||||||
rack (>= 2.2.3)
|
rack (>= 2.2.3)
|
||||||
@@ -515,7 +507,7 @@ GEM
|
|||||||
openssl (> 2.0)
|
openssl (> 2.0)
|
||||||
orm_adapter (0.5.0)
|
orm_adapter (0.5.0)
|
||||||
ox (2.14.17)
|
ox (2.14.17)
|
||||||
parallel (1.24.0)
|
parallel (1.23.0)
|
||||||
parser (3.2.2.4)
|
parser (3.2.2.4)
|
||||||
ast (~> 2.4.1)
|
ast (~> 2.4.1)
|
||||||
racc
|
racc
|
||||||
@@ -523,7 +515,7 @@ GEM
|
|||||||
pastel (0.8.0)
|
pastel (0.8.0)
|
||||||
tty-color (~> 0.5)
|
tty-color (~> 0.5)
|
||||||
pg (1.5.4)
|
pg (1.5.4)
|
||||||
pghero (3.4.0)
|
pghero (3.3.4)
|
||||||
activerecord (>= 6)
|
activerecord (>= 6)
|
||||||
posix-spawn (0.3.15)
|
posix-spawn (0.3.15)
|
||||||
premailer (1.21.0)
|
premailer (1.21.0)
|
||||||
@@ -535,14 +527,9 @@ GEM
|
|||||||
net-smtp
|
net-smtp
|
||||||
premailer (~> 1.7, >= 1.7.9)
|
premailer (~> 1.7, >= 1.7.9)
|
||||||
private_address_check (0.5.0)
|
private_address_check (0.5.0)
|
||||||
propshaft (0.8.0)
|
|
||||||
actionpack (>= 7.0.0)
|
|
||||||
activesupport (>= 7.0.0)
|
|
||||||
rack
|
|
||||||
railties (>= 7.0.0)
|
|
||||||
psych (5.1.1.1)
|
psych (5.1.1.1)
|
||||||
stringio
|
stringio
|
||||||
public_suffix (5.0.4)
|
public_suffix (5.0.3)
|
||||||
puma (6.4.0)
|
puma (6.4.0)
|
||||||
nio4r (~> 2.0)
|
nio4r (~> 2.0)
|
||||||
pundit (2.3.1)
|
pundit (2.3.1)
|
||||||
@@ -608,13 +595,13 @@ GEM
|
|||||||
thor (~> 1.0, >= 1.2.2)
|
thor (~> 1.0, >= 1.2.2)
|
||||||
zeitwerk (~> 2.6)
|
zeitwerk (~> 2.6)
|
||||||
rainbow (3.1.1)
|
rainbow (3.1.1)
|
||||||
rake (13.1.0)
|
rake (13.0.6)
|
||||||
rdf (3.3.1)
|
rdf (3.3.1)
|
||||||
bcp47_spec (~> 0.2)
|
bcp47_spec (~> 0.2)
|
||||||
link_header (~> 0.0, >= 0.0.8)
|
link_header (~> 0.0, >= 0.0.8)
|
||||||
rdf-normalize (0.6.1)
|
rdf-normalize (0.6.1)
|
||||||
rdf (~> 3.2)
|
rdf (~> 3.2)
|
||||||
rdoc (6.6.1)
|
rdoc (6.5.0)
|
||||||
psych (>= 4.0.0)
|
psych (>= 4.0.0)
|
||||||
redcarpet (3.6.0)
|
redcarpet (3.6.0)
|
||||||
redis (4.8.1)
|
redis (4.8.1)
|
||||||
@@ -622,8 +609,8 @@ GEM
|
|||||||
redis (>= 4)
|
redis (>= 4)
|
||||||
redlock (1.3.2)
|
redlock (1.3.2)
|
||||||
redis (>= 3.0.0, < 6.0)
|
redis (>= 3.0.0, < 6.0)
|
||||||
regexp_parser (2.8.3)
|
regexp_parser (2.8.2)
|
||||||
reline (0.4.1)
|
reline (0.3.9)
|
||||||
io-console (~> 0.5)
|
io-console (~> 0.5)
|
||||||
request_store (1.5.1)
|
request_store (1.5.1)
|
||||||
rack (>= 1.4)
|
rack (>= 1.4)
|
||||||
@@ -648,7 +635,7 @@ GEM
|
|||||||
rspec-mocks (3.12.6)
|
rspec-mocks (3.12.6)
|
||||||
diff-lcs (>= 1.2.0, < 2.0)
|
diff-lcs (>= 1.2.0, < 2.0)
|
||||||
rspec-support (~> 3.12.0)
|
rspec-support (~> 3.12.0)
|
||||||
rspec-rails (6.1.0)
|
rspec-rails (6.0.3)
|
||||||
actionpack (>= 6.1)
|
actionpack (>= 6.1)
|
||||||
activesupport (>= 6.1)
|
activesupport (>= 6.1)
|
||||||
railties (>= 6.1)
|
railties (>= 6.1)
|
||||||
@@ -662,7 +649,7 @@ GEM
|
|||||||
rspec-mocks (~> 3.0)
|
rspec-mocks (~> 3.0)
|
||||||
sidekiq (>= 5, < 8)
|
sidekiq (>= 5, < 8)
|
||||||
rspec-support (3.12.1)
|
rspec-support (3.12.1)
|
||||||
rubocop (1.59.0)
|
rubocop (1.57.2)
|
||||||
json (~> 2.3)
|
json (~> 2.3)
|
||||||
language_server-protocol (>= 3.17.0)
|
language_server-protocol (>= 3.17.0)
|
||||||
parallel (~> 1.10)
|
parallel (~> 1.10)
|
||||||
@@ -670,7 +657,7 @@ GEM
|
|||||||
rainbow (>= 2.2.2, < 4.0)
|
rainbow (>= 2.2.2, < 4.0)
|
||||||
regexp_parser (>= 1.8, < 3.0)
|
regexp_parser (>= 1.8, < 3.0)
|
||||||
rexml (>= 3.2.5, < 4.0)
|
rexml (>= 3.2.5, < 4.0)
|
||||||
rubocop-ast (>= 1.30.0, < 2.0)
|
rubocop-ast (>= 1.28.1, < 2.0)
|
||||||
ruby-progressbar (~> 1.7)
|
ruby-progressbar (~> 1.7)
|
||||||
unicode-display_width (>= 2.4.0, < 3.0)
|
unicode-display_width (>= 2.4.0, < 3.0)
|
||||||
rubocop-ast (1.30.0)
|
rubocop-ast (1.30.0)
|
||||||
@@ -679,14 +666,13 @@ GEM
|
|||||||
rubocop (~> 1.41)
|
rubocop (~> 1.41)
|
||||||
rubocop-factory_bot (2.24.0)
|
rubocop-factory_bot (2.24.0)
|
||||||
rubocop (~> 1.33)
|
rubocop (~> 1.33)
|
||||||
rubocop-performance (1.20.0)
|
rubocop-performance (1.19.1)
|
||||||
rubocop (>= 1.48.1, < 2.0)
|
rubocop (>= 1.7.0, < 2.0)
|
||||||
rubocop-ast (>= 1.30.0, < 2.0)
|
rubocop-ast (>= 0.4.0)
|
||||||
rubocop-rails (2.23.0)
|
rubocop-rails (2.22.1)
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 4.2.0)
|
||||||
rack (>= 1.1)
|
rack (>= 1.1)
|
||||||
rubocop (>= 1.33.0, < 2.0)
|
rubocop (>= 1.33.0, < 2.0)
|
||||||
rubocop-ast (>= 1.30.0, < 2.0)
|
|
||||||
rubocop-rspec (2.25.0)
|
rubocop-rspec (2.25.0)
|
||||||
rubocop (~> 1.40)
|
rubocop (~> 1.40)
|
||||||
rubocop-capybara (~> 2.17)
|
rubocop-capybara (~> 2.17)
|
||||||
@@ -708,7 +694,7 @@ GEM
|
|||||||
scenic (1.7.0)
|
scenic (1.7.0)
|
||||||
activerecord (>= 4.0.0)
|
activerecord (>= 4.0.0)
|
||||||
railties (>= 4.0.0)
|
railties (>= 4.0.0)
|
||||||
selenium-webdriver (4.16.0)
|
selenium-webdriver (4.15.0)
|
||||||
rexml (~> 3.2, >= 3.2.5)
|
rexml (~> 3.2, >= 3.2.5)
|
||||||
rubyzip (>= 1.2.2, < 3.0)
|
rubyzip (>= 1.2.2, < 3.0)
|
||||||
websocket (~> 1.0)
|
websocket (~> 1.0)
|
||||||
@@ -739,14 +725,20 @@ GEM
|
|||||||
simplecov-html (~> 0.11)
|
simplecov-html (~> 0.11)
|
||||||
simplecov_json_formatter (~> 0.1)
|
simplecov_json_formatter (~> 0.1)
|
||||||
simplecov-html (0.12.3)
|
simplecov-html (0.12.3)
|
||||||
simplecov-lcov (0.8.0)
|
|
||||||
simplecov_json_formatter (0.1.4)
|
simplecov_json_formatter (0.1.4)
|
||||||
smart_properties (1.17.0)
|
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.25)
|
||||||
statsd-ruby (1.5.0)
|
statsd-ruby (1.5.0)
|
||||||
stoplight (3.0.2)
|
stoplight (3.0.2)
|
||||||
redlock (~> 1.0)
|
redlock (~> 1.0)
|
||||||
stringio (3.1.0)
|
stringio (3.0.9)
|
||||||
strong_migrations (1.6.4)
|
strong_migrations (1.6.4)
|
||||||
activerecord (>= 5.2)
|
activerecord (>= 5.2)
|
||||||
swd (1.3.0)
|
swd (1.3.0)
|
||||||
@@ -754,12 +746,12 @@ GEM
|
|||||||
attr_required (>= 0.0.5)
|
attr_required (>= 0.0.5)
|
||||||
httpclient (>= 2.4)
|
httpclient (>= 2.4)
|
||||||
sysexits (1.2.0)
|
sysexits (1.2.0)
|
||||||
temple (0.10.3)
|
temple (0.10.2)
|
||||||
terminal-table (3.0.2)
|
terminal-table (3.0.2)
|
||||||
unicode-display_width (>= 1.1.1, < 3)
|
unicode-display_width (>= 1.1.1, < 3)
|
||||||
terrapin (0.6.0)
|
terrapin (0.6.0)
|
||||||
climate_control (>= 0.0.3, < 1.0)
|
climate_control (>= 0.0.3, < 1.0)
|
||||||
test-prof (1.3.1)
|
test-prof (1.2.3)
|
||||||
thor (1.3.0)
|
thor (1.3.0)
|
||||||
tilt (2.3.0)
|
tilt (2.3.0)
|
||||||
timeout (0.4.1)
|
timeout (0.4.1)
|
||||||
@@ -853,7 +845,6 @@ DEPENDENCIES
|
|||||||
concurrent-ruby
|
concurrent-ruby
|
||||||
connection_pool
|
connection_pool
|
||||||
database_cleaner-active_record
|
database_cleaner-active_record
|
||||||
debug (~> 1.8)
|
|
||||||
devise (~> 4.9)
|
devise (~> 4.9)
|
||||||
devise-two-factor (~> 4.1)
|
devise-two-factor (~> 4.1)
|
||||||
devise_pam_authenticatable2 (~> 9.2)
|
devise_pam_authenticatable2 (~> 9.2)
|
||||||
@@ -861,7 +852,6 @@ DEPENDENCIES
|
|||||||
doorkeeper (~> 5.6)
|
doorkeeper (~> 5.6)
|
||||||
dotenv-rails (~> 2.8)
|
dotenv-rails (~> 2.8)
|
||||||
ed25519 (~> 1.3)
|
ed25519 (~> 1.3)
|
||||||
email_spec
|
|
||||||
fabrication (~> 2.30)
|
fabrication (~> 2.30)
|
||||||
faker (~> 3.2)
|
faker (~> 3.2)
|
||||||
fast_blank (~> 1.0)
|
fast_blank (~> 1.0)
|
||||||
@@ -879,7 +869,6 @@ DEPENDENCIES
|
|||||||
httplog (~> 1.6.2)
|
httplog (~> 1.6.2)
|
||||||
i18n-tasks (~> 1.0)
|
i18n-tasks (~> 1.0)
|
||||||
idn-ruby
|
idn-ruby
|
||||||
irb (~> 1.8)
|
|
||||||
json-ld
|
json-ld
|
||||||
json-ld-preloaded (~> 3.2)
|
json-ld-preloaded (~> 3.2)
|
||||||
json-schema (~> 4.0)
|
json-schema (~> 4.0)
|
||||||
@@ -910,7 +899,6 @@ DEPENDENCIES
|
|||||||
posix-spawn
|
posix-spawn
|
||||||
premailer-rails
|
premailer-rails
|
||||||
private_address_check (~> 0.5)
|
private_address_check (~> 0.5)
|
||||||
propshaft
|
|
||||||
public_suffix (~> 5.0)
|
public_suffix (~> 5.0)
|
||||||
puma (~> 6.3)
|
puma (~> 6.3)
|
||||||
pundit (~> 2.3)
|
pundit (~> 2.3)
|
||||||
@@ -948,7 +936,8 @@ DEPENDENCIES
|
|||||||
simple-navigation (~> 4.4)
|
simple-navigation (~> 4.4)
|
||||||
simple_form (~> 5.2)
|
simple_form (~> 5.2)
|
||||||
simplecov (~> 0.22)
|
simplecov (~> 0.22)
|
||||||
simplecov-lcov (~> 0.8)
|
sprockets (~> 3.7.2)
|
||||||
|
sprockets-rails (~> 3.4)
|
||||||
stackprof
|
stackprof
|
||||||
stoplight (~> 3.0.1)
|
stoplight (~> 3.0.1)
|
||||||
strong_migrations (= 1.6.4)
|
strong_migrations (= 1.6.4)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
web: env PORT=3000 RAILS_ENV=development bundle exec puma -C config/puma.rb
|
web: env PORT=3000 RAILS_ENV=development bundle exec puma -C config/puma.rb
|
||||||
sidekiq: env PORT=3000 RAILS_ENV=development bundle exec sidekiq
|
sidekiq: env PORT=3000 RAILS_ENV=development bundle exec sidekiq
|
||||||
stream: env PORT=4000 yarn workspace @mastodon/streaming start
|
stream: env PORT=4000 yarn run start
|
||||||
webpack: bin/webpack-dev-server
|
webpack: bin/webpack-dev-server
|
||||||
|
|||||||
6
Vagrantfile
vendored
6
Vagrantfile
vendored
@@ -10,11 +10,7 @@ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
|
|||||||
sudo apt-add-repository 'deb https://dl.yarnpkg.com/debian/ stable main'
|
sudo apt-add-repository 'deb https://dl.yarnpkg.com/debian/ stable main'
|
||||||
|
|
||||||
# Add repo for NodeJS
|
# Add repo for NodeJS
|
||||||
sudo mkdir -p /etc/apt/keyrings
|
curl -sL https://deb.nodesource.com/setup_16.x | sudo bash -
|
||||||
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
|
|
||||||
NODE_MAJOR=20
|
|
||||||
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list
|
|
||||||
sudo apt-get update
|
|
||||||
|
|
||||||
# Add firewall rule to redirect 80 to PORT and save
|
# Add firewall rule to redirect 80 to PORT and save
|
||||||
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port #{ENV["PORT"]}
|
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port #{ENV["PORT"]}
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class AccountsIndex < Chewy::Index
|
class AccountsIndex < Chewy::Index
|
||||||
include DatetimeClampingConcern
|
|
||||||
|
|
||||||
settings index: index_preset(refresh_interval: '30s'), analysis: {
|
settings index: index_preset(refresh_interval: '30s'), analysis: {
|
||||||
filter: {
|
filter: {
|
||||||
english_stop: {
|
english_stop: {
|
||||||
@@ -62,7 +60,7 @@ class AccountsIndex < Chewy::Index
|
|||||||
field(:following_count, type: 'long')
|
field(:following_count, type: 'long')
|
||||||
field(:followers_count, type: 'long')
|
field(:followers_count, type: 'long')
|
||||||
field(:properties, type: 'keyword', value: ->(account) { account.searchable_properties })
|
field(:properties, type: 'keyword', value: ->(account) { account.searchable_properties })
|
||||||
field(:last_status_at, type: 'date', value: ->(account) { clamp_date(account.last_status_at || account.created_at) })
|
field(:last_status_at, type: 'date', value: ->(account) { account.last_status_at || account.created_at })
|
||||||
field(:display_name, type: 'text', analyzer: 'verbatim') { field :edge_ngram, type: 'text', analyzer: 'edge_ngram', search_analyzer: 'verbatim' }
|
field(:display_name, type: 'text', analyzer: 'verbatim') { field :edge_ngram, type: 'text', analyzer: 'edge_ngram', search_analyzer: 'verbatim' }
|
||||||
field(:username, type: 'text', analyzer: 'verbatim', value: ->(account) { [account.username, account.domain].compact.join('@') }) { field :edge_ngram, type: 'text', analyzer: 'edge_ngram', search_analyzer: 'verbatim' }
|
field(:username, type: 'text', analyzer: 'verbatim', value: ->(account) { [account.username, account.domain].compact.join('@') }) { field :edge_ngram, type: 'text', analyzer: 'edge_ngram', search_analyzer: 'verbatim' }
|
||||||
field(:text, type: 'text', analyzer: 'verbatim', value: ->(account) { account.searchable_text }) { field :stemmed, type: 'text', analyzer: 'natural' }
|
field(:text, type: 'text', analyzer: 'verbatim', value: ->(account) { account.searchable_text }) { field :stemmed, type: 'text', analyzer: 'natural' }
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
# 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,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class PublicStatusesIndex < Chewy::Index
|
class PublicStatusesIndex < Chewy::Index
|
||||||
include DatetimeClampingConcern
|
|
||||||
|
|
||||||
settings index: index_preset(refresh_interval: '30s', number_of_shards: 5), analysis: {
|
settings index: index_preset(refresh_interval: '30s', number_of_shards: 5), analysis: {
|
||||||
filter: {
|
filter: {
|
||||||
english_stop: {
|
english_stop: {
|
||||||
@@ -64,6 +62,6 @@ class PublicStatusesIndex < Chewy::Index
|
|||||||
field(:tags, type: 'text', analyzer: 'hashtag', value: ->(status) { status.tags.map(&:display_name) })
|
field(:tags, type: 'text', analyzer: 'hashtag', value: ->(status) { status.tags.map(&:display_name) })
|
||||||
field(:language, type: 'keyword')
|
field(:language, type: 'keyword')
|
||||||
field(:properties, type: 'keyword', value: ->(status) { status.searchable_properties })
|
field(:properties, type: 'keyword', value: ->(status) { status.searchable_properties })
|
||||||
field(:created_at, type: 'date', value: ->(status) { clamp_date(status.created_at) })
|
field(:created_at, type: 'date')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class StatusesIndex < Chewy::Index
|
class StatusesIndex < Chewy::Index
|
||||||
include DatetimeClampingConcern
|
|
||||||
|
|
||||||
settings index: index_preset(refresh_interval: '30s', number_of_shards: 5), analysis: {
|
settings index: index_preset(refresh_interval: '30s', number_of_shards: 5), analysis: {
|
||||||
filter: {
|
filter: {
|
||||||
english_stop: {
|
english_stop: {
|
||||||
@@ -62,6 +60,6 @@ class StatusesIndex < Chewy::Index
|
|||||||
field(:searchable_by, type: 'long', value: ->(status) { status.searchable_by })
|
field(:searchable_by, type: 'long', value: ->(status) { status.searchable_by })
|
||||||
field(:language, type: 'keyword')
|
field(:language, type: 'keyword')
|
||||||
field(:properties, type: 'keyword', value: ->(status) { status.searchable_properties })
|
field(:properties, type: 'keyword', value: ->(status) { status.searchable_properties })
|
||||||
field(:created_at, type: 'date', value: ->(status) { clamp_date(status.created_at) })
|
field(:created_at, type: 'date')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class TagsIndex < Chewy::Index
|
class TagsIndex < Chewy::Index
|
||||||
include DatetimeClampingConcern
|
|
||||||
|
|
||||||
settings index: index_preset(refresh_interval: '30s'), analysis: {
|
settings index: index_preset(refresh_interval: '30s'), analysis: {
|
||||||
analyzer: {
|
analyzer: {
|
||||||
content: {
|
content: {
|
||||||
@@ -44,6 +42,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(: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(:reviewed, type: 'boolean', value: ->(tag) { tag.reviewed? })
|
||||||
field(:usage, type: 'long', value: ->(tag, crutches) { tag.history.aggregate(crutches.time_period).accounts })
|
field(:usage, type: 'long', value: ->(tag, crutches) { tag.history.aggregate(crutches.time_period).accounts })
|
||||||
field(:last_status_at, type: 'date', value: ->(tag) { clamp_date(tag.last_status_at || tag.created_at) })
|
field(:last_status_at, type: 'date', value: ->(tag) { tag.last_status_at || tag.created_at })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ class AccountsController < ApplicationController
|
|||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html do
|
format.html do
|
||||||
expires_in(15.seconds, public: true, stale_while_revalidate: 30.seconds, stale_if_error: 1.hour) unless user_signed_in?
|
expires_in(15.seconds, public: true, stale_while_revalidate: 30.seconds, stale_if_error: 1.hour) unless user_signed_in?
|
||||||
|
|
||||||
|
@rss_url = rss_url
|
||||||
end
|
end
|
||||||
|
|
||||||
format.rss do
|
format.rss do
|
||||||
@@ -50,7 +52,7 @@ class AccountsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def only_media_scope
|
def only_media_scope
|
||||||
Status.joins(:media_attachments).merge(@account.media_attachments).group(:id)
|
Status.joins(:media_attachments).merge(@account.media_attachments.reorder(nil)).group(:id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def no_replies_scope
|
def no_replies_scope
|
||||||
@@ -82,21 +84,29 @@ class AccountsController < ApplicationController
|
|||||||
short_account_url(@account, format: 'rss')
|
short_account_url(@account, format: 'rss')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
helper_method :rss_url
|
|
||||||
|
|
||||||
def media_requested?
|
def media_requested?
|
||||||
path_without_format.end_with?('/media') && !tag_requested?
|
request.path.split('.').first.end_with?('/media') && !tag_requested?
|
||||||
end
|
end
|
||||||
|
|
||||||
def replies_requested?
|
def replies_requested?
|
||||||
path_without_format.end_with?('/with_replies') && !tag_requested?
|
request.path.split('.').first.end_with?('/with_replies') && !tag_requested?
|
||||||
end
|
end
|
||||||
|
|
||||||
def tag_requested?
|
def tag_requested?
|
||||||
path_without_format.end_with?(Addressable::URI.parse("/tagged/#{params[:tag]}").normalize)
|
request.path.split('.').first.end_with?(Addressable::URI.parse("/tagged/#{params[:tag]}").normalize)
|
||||||
end
|
end
|
||||||
|
|
||||||
def path_without_format
|
def cached_filtered_status_page
|
||||||
request.path.split('.').first
|
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)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ module Admin
|
|||||||
@moderation_notes = @account.targeted_moderation_notes.latest
|
@moderation_notes = @account.targeted_moderation_notes.latest
|
||||||
@warnings = @account.strikes.custom.latest
|
@warnings = @account.strikes.custom.latest
|
||||||
|
|
||||||
render 'admin/accounts/show'
|
render template: 'admin/accounts/show'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ module Admin
|
|||||||
|
|
||||||
def index
|
def index
|
||||||
authorize :audit_log, :index?
|
authorize :audit_log, :index?
|
||||||
@auditable_accounts = Account.where(id: Admin::ActionLog.select('distinct account_id')).select(:id, :username)
|
@auditable_accounts = Account.where(id: Admin::ActionLog.reorder(nil).select('distinct account_id')).select(:id, :username)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ require 'csv'
|
|||||||
|
|
||||||
module Admin
|
module Admin
|
||||||
class ExportDomainAllowsController < BaseController
|
class ExportDomainAllowsController < BaseController
|
||||||
include Admin::ExportControllerConcern
|
include AdminExportControllerConcern
|
||||||
|
|
||||||
before_action :set_dummy_import!, only: [:new]
|
before_action :set_dummy_import!, only: [:new]
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ require 'csv'
|
|||||||
|
|
||||||
module Admin
|
module Admin
|
||||||
class ExportDomainBlocksController < BaseController
|
class ExportDomainBlocksController < BaseController
|
||||||
include Admin::ExportControllerConcern
|
include AdminExportControllerConcern
|
||||||
|
|
||||||
before_action :set_dummy_import!, only: [:new]
|
before_action :set_dummy_import!, only: [:new]
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ module Admin
|
|||||||
@relay.enable!
|
@relay.enable!
|
||||||
redirect_to admin_relays_path
|
redirect_to admin_relays_path
|
||||||
else
|
else
|
||||||
render :new
|
render action: :new
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ module Admin
|
|||||||
@form = Admin::StatusBatchAction.new
|
@form = Admin::StatusBatchAction.new
|
||||||
@statuses = @report.statuses.with_includes
|
@statuses = @report.statuses.with_includes
|
||||||
|
|
||||||
render 'admin/reports/show'
|
render template: 'admin/reports/show'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ module Admin
|
|||||||
private
|
private
|
||||||
|
|
||||||
def batched_ordered_status_edits
|
def batched_ordered_status_edits
|
||||||
@status.edits.includes(:account, status: [:account]).find_each(order: :asc)
|
@status.edits.reorder(nil).includes(:account, status: [:account]).find_each(order: :asc)
|
||||||
end
|
end
|
||||||
helper_method :batched_ordered_status_edits
|
helper_method :batched_ordered_status_edits
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ class Api::BaseController < ApplicationController
|
|||||||
DEFAULT_STATUSES_LIMIT = 20
|
DEFAULT_STATUSES_LIMIT = 20
|
||||||
DEFAULT_ACCOUNTS_LIMIT = 40
|
DEFAULT_ACCOUNTS_LIMIT = 40
|
||||||
|
|
||||||
include Api::RateLimitHeaders
|
include RateLimitHeaders
|
||||||
include Api::AccessTokenTrackingConcern
|
include AccessTokenTrackingConcern
|
||||||
include Api::CachingConcern
|
include ApiCachingConcern
|
||||||
include Api::ContentSecurityPolicy
|
include Api::ContentSecurityPolicy
|
||||||
|
|
||||||
skip_before_action :require_functional!, unless: :limited_federation_mode?
|
skip_before_action :require_functional!, unless: :limited_federation_mode?
|
||||||
@@ -64,7 +64,7 @@ class Api::BaseController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def doorkeeper_unauthorized_render_options(error: nil)
|
def doorkeeper_unauthorized_render_options(error: nil)
|
||||||
{ json: { error: error.try(:description) || 'Not authorized' } }
|
{ json: { error: (error.try(:description) || 'Not authorized') } }
|
||||||
end
|
end
|
||||||
|
|
||||||
def doorkeeper_forbidden_render_options(*)
|
def doorkeeper_forbidden_render_options(*)
|
||||||
@@ -105,11 +105,7 @@ class Api::BaseController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def require_not_suspended!
|
def require_not_suspended!
|
||||||
render json: { error: 'Your login is currently disabled' }, status: 403 if current_user&.account&.unavailable?
|
render json: { error: 'Your login is currently disabled' }, status: 403 if current_user&.account&.suspended?
|
||||||
end
|
|
||||||
|
|
||||||
def require_valid_pagination_options!
|
|
||||||
render json: { error: 'Pagination values for `offset` and `limit` must be positive' }, status: 400 if pagination_options_invalid?
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def require_user!
|
def require_user!
|
||||||
@@ -140,10 +136,6 @@ class Api::BaseController < ApplicationController
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def pagination_options_invalid?
|
|
||||||
params.slice(:limit, :offset).values.map(&:to_i).any?(&:negative?)
|
|
||||||
end
|
|
||||||
|
|
||||||
def respond_with_error(code)
|
def respond_with_error(code)
|
||||||
render json: { error: Rack::Utils::HTTP_STATUS_CODES[code] }, status: code
|
render json: { error: Rack::Utils::HTTP_STATUS_CODES[code] }, status: code
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -16,8 +16,6 @@ class Api::V1::Accounts::CredentialsController < Api::BaseController
|
|||||||
current_user.update(user_params) if user_params
|
current_user.update(user_params) if user_params
|
||||||
ActivityPub::UpdateDistributionWorker.perform_async(@account.id)
|
ActivityPub::UpdateDistributionWorker.perform_async(@account.id)
|
||||||
render json: @account, serializer: REST::CredentialAccountSerializer
|
render json: @account, serializer: REST::CredentialAccountSerializer
|
||||||
rescue ActiveRecord::RecordInvalid => e
|
|
||||||
render json: ValidationErrorFormatter.new(e).as_json, status: 422
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ class Api::V1::Accounts::FamiliarFollowersController < Api::BaseController
|
|||||||
private
|
private
|
||||||
|
|
||||||
def set_accounts
|
def set_accounts
|
||||||
@accounts = Account.without_suspended.where(id: account_ids).select('id, hide_collections')
|
@accounts = Account.without_suspended.where(id: account_ids).select('id, hide_collections').index_by(&:id).values_at(*account_ids).compact
|
||||||
end
|
end
|
||||||
|
|
||||||
def familiar_followers
|
def familiar_followers
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ class Api::V1::Accounts::FollowerAccountsController < Api::BaseController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def hide_results?
|
def hide_results?
|
||||||
@account.unavailable? || (@account.hides_followers? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account))
|
@account.suspended? || (@account.hides_followers? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account))
|
||||||
end
|
end
|
||||||
|
|
||||||
def default_accounts
|
def default_accounts
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ class Api::V1::Accounts::FollowingAccountsController < Api::BaseController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def hide_results?
|
def hide_results?
|
||||||
@account.unavailable? || (@account.hides_following? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account))
|
@account.suspended? || (@account.hides_following? && current_account&.id != @account.id) || (current_account && @account.blocking?(current_account))
|
||||||
end
|
end
|
||||||
|
|
||||||
def default_accounts
|
def default_accounts
|
||||||
|
|||||||
@@ -25,6 +25,6 @@ class Api::V1::Accounts::NotesController < Api::BaseController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def relationships_presenter
|
def relationships_presenter
|
||||||
AccountRelationshipsPresenter.new([@account], current_user.account_id)
|
AccountRelationshipsPresenter.new([@account.id], current_user.account_id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -25,6 +25,6 @@ class Api::V1::Accounts::PinsController < Api::BaseController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def relationships_presenter
|
def relationships_presenter
|
||||||
AccountRelationshipsPresenter.new([@account], current_user.account_id)
|
AccountRelationshipsPresenter.new([@account.id], current_user.account_id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -5,8 +5,11 @@ class Api::V1::Accounts::RelationshipsController < Api::BaseController
|
|||||||
before_action :require_user!
|
before_action :require_user!
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@accounts = Account.where(id: account_ids).select(:id, :domain)
|
scope = Account.where(id: account_ids).select('id')
|
||||||
@accounts.merge!(Account.without_suspended) unless truthy_param?(:with_suspended)
|
scope.merge!(Account.without_suspended) unless truthy_param?(:with_suspended)
|
||||||
|
# .where doesn't guarantee that our results are in the same order
|
||||||
|
# we requested them, so return the "right" order to the requestor.
|
||||||
|
@accounts = scope.index_by(&:id).values_at(*account_ids).compact
|
||||||
render json: @accounts, each_serializer: REST::RelationshipSerializer, relationships: relationships
|
render json: @accounts, each_serializer: REST::RelationshipSerializer, relationships: relationships
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ class Api::V1::Accounts::StatusesController < Api::BaseController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def load_statuses
|
def load_statuses
|
||||||
@account.unavailable? ? [] : cached_account_statuses
|
@account.suspended? ? [] : cached_account_statuses
|
||||||
end
|
end
|
||||||
|
|
||||||
def cached_account_statuses
|
def cached_account_statuses
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ class Api::V1::AccountsController < Api::BaseController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def mute
|
def mute
|
||||||
MuteService.new.call(current_user.account, @account, notifications: truthy_param?(:notifications), duration: params[:duration].to_i)
|
MuteService.new.call(current_user.account, @account, notifications: truthy_param?(:notifications), duration: (params[:duration]&.to_i || 0))
|
||||||
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
|
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ class Api::V1::AccountsController < Api::BaseController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def relationships(**options)
|
def relationships(**options)
|
||||||
AccountRelationshipsPresenter.new([@account], current_user.account_id, **options)
|
AccountRelationshipsPresenter.new([@account.id], current_user.account_id, **options)
|
||||||
end
|
end
|
||||||
|
|
||||||
def account_params
|
def account_params
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ class Api::V1::DirectoriesController < Api::BaseController
|
|||||||
private
|
private
|
||||||
|
|
||||||
def require_enabled!
|
def require_enabled!
|
||||||
not_found unless Setting.profile_directory
|
return not_found unless Setting.profile_directory
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_accounts
|
def set_accounts
|
||||||
|
|||||||
@@ -25,11 +25,11 @@ class Api::V1::FollowRequestsController < Api::BaseController
|
|||||||
private
|
private
|
||||||
|
|
||||||
def account
|
def account
|
||||||
@account ||= Account.find(params[:id])
|
Account.find(params[:id])
|
||||||
end
|
end
|
||||||
|
|
||||||
def relationships(**options)
|
def relationships(**options)
|
||||||
AccountRelationshipsPresenter.new([account], current_user.account_id, **options)
|
AccountRelationshipsPresenter.new([params[:id]], current_user.account_id, **options)
|
||||||
end
|
end
|
||||||
|
|
||||||
def load_accounts
|
def load_accounts
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
class Api::V1::Instances::ActivityController < Api::V1::Instances::BaseController
|
class Api::V1::Instances::ActivityController < Api::V1::Instances::BaseController
|
||||||
before_action :require_enabled_api!
|
before_action :require_enabled_api!
|
||||||
|
|
||||||
WEEKS_OF_ACTIVITY = 12
|
|
||||||
|
|
||||||
def show
|
def show
|
||||||
cache_even_if_authenticated!
|
cache_even_if_authenticated!
|
||||||
render_with_cache json: :activity, expires_in: 1.day
|
render_with_cache json: :activity, expires_in: 1.day
|
||||||
@@ -13,40 +11,23 @@ class Api::V1::Instances::ActivityController < Api::V1::Instances::BaseControlle
|
|||||||
private
|
private
|
||||||
|
|
||||||
def activity
|
def activity
|
||||||
activity_weeks.map do |weeks_ago|
|
statuses_tracker = ActivityTracker.new('activity:statuses:local', :basic)
|
||||||
activity_json(*week_edge_days(weeks_ago))
|
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,
|
||||||
|
}
|
||||||
end
|
end
|
||||||
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!
|
def require_enabled_api!
|
||||||
head 404 unless Setting.activity_api_enabled && !limited_federation_mode?
|
head 404 unless Setting.activity_api_enabled && !limited_federation_mode?
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -19,19 +19,7 @@ class Api::V1::Instances::DomainBlocksController < Api::V1::Instances::BaseContr
|
|||||||
private
|
private
|
||||||
|
|
||||||
def require_enabled_api!
|
def require_enabled_api!
|
||||||
head 404 unless api_enabled?
|
head 404 unless Setting.show_domain_blocks == 'all' || (Setting.show_domain_blocks == 'users' && user_signed_in?)
|
||||||
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
|
end
|
||||||
|
|
||||||
def set_domain_blocks
|
def set_domain_blocks
|
||||||
|
|||||||
@@ -11,6 +11,6 @@ class Api::V1::Statuses::HistoriesController < Api::V1::Statuses::BaseController
|
|||||||
private
|
private
|
||||||
|
|
||||||
def status_edits
|
def status_edits
|
||||||
@status.edits.ordered.includes(:account, status: [:account]).to_a.presence || [@status.build_snapshot(at_time: @status.edited_at || @status.created_at)]
|
@status.edits.includes(:account, status: [:account]).to_a.presence || [@status.build_snapshot(at_time: @status.edited_at || @status.created_at)]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
# 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,10 +1,9 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::Timelines::HomeController < Api::V1::Timelines::BaseController
|
class Api::V1::Timelines::HomeController < Api::BaseController
|
||||||
before_action -> { doorkeeper_authorize! :read, :'read:statuses' }, only: [:show]
|
before_action -> { doorkeeper_authorize! :read, :'read:statuses' }, only: [:show]
|
||||||
before_action :require_user!, only: [:show]
|
before_action :require_user!, only: [:show]
|
||||||
|
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
|
||||||
PERMITTED_PARAMS = %i(local limit).freeze
|
|
||||||
|
|
||||||
def show
|
def show
|
||||||
with_read_replica do
|
with_read_replica do
|
||||||
@@ -41,11 +40,27 @@ class Api::V1::Timelines::HomeController < Api::V1::Timelines::BaseController
|
|||||||
HomeFeed.new(current_account)
|
HomeFeed.new(current_account)
|
||||||
end
|
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
|
def next_path
|
||||||
api_v1_timelines_home_url next_path_params
|
api_v1_timelines_home_url pagination_params(max_id: pagination_max_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def prev_path
|
def prev_path
|
||||||
api_v1_timelines_home_url prev_path_params
|
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
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::Timelines::ListController < Api::V1::Timelines::BaseController
|
class Api::V1::Timelines::ListController < Api::BaseController
|
||||||
before_action -> { doorkeeper_authorize! :read, :'read:lists' }
|
before_action -> { doorkeeper_authorize! :read, :'read:lists' }
|
||||||
before_action :require_user!
|
before_action :require_user!
|
||||||
before_action :set_list
|
before_action :set_list
|
||||||
before_action :set_statuses
|
before_action :set_statuses
|
||||||
|
|
||||||
PERMITTED_PARAMS = %i(limit).freeze
|
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
|
||||||
|
|
||||||
def show
|
def show
|
||||||
render json: @statuses,
|
render json: @statuses,
|
||||||
@@ -41,11 +41,27 @@ class Api::V1::Timelines::ListController < Api::V1::Timelines::BaseController
|
|||||||
ListFeed.new(@list)
|
ListFeed.new(@list)
|
||||||
end
|
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
|
def next_path
|
||||||
api_v1_timelines_list_url params[:id], next_path_params
|
api_v1_timelines_list_url params[:id], pagination_params(max_id: pagination_max_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def prev_path
|
def prev_path
|
||||||
api_v1_timelines_list_url params[:id], prev_path_params
|
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
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::Timelines::PublicController < Api::V1::Timelines::BaseController
|
class Api::V1::Timelines::PublicController < Api::BaseController
|
||||||
before_action :require_user!, only: [:show], if: :require_auth?
|
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
|
def show
|
||||||
cache_if_unauthenticated!
|
cache_if_unauthenticated!
|
||||||
@@ -46,11 +45,27 @@ class Api::V1::Timelines::PublicController < Api::V1::Timelines::BaseController
|
|||||||
)
|
)
|
||||||
end
|
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
|
def next_path
|
||||||
api_v1_timelines_public_url next_path_params
|
api_v1_timelines_public_url pagination_params(max_id: pagination_max_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def prev_path
|
def prev_path
|
||||||
api_v1_timelines_public_url prev_path_params
|
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
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::Timelines::TagController < Api::V1::Timelines::BaseController
|
class Api::V1::Timelines::TagController < Api::BaseController
|
||||||
before_action -> { doorkeeper_authorize! :read, :'read:statuses' }, only: :show, if: :require_auth?
|
before_action -> { doorkeeper_authorize! :read, :'read:statuses' }, only: :show, if: :require_auth?
|
||||||
before_action :load_tag
|
before_action :load_tag
|
||||||
|
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
|
||||||
PERMITTED_PARAMS = %i(local limit only_media).freeze
|
|
||||||
|
|
||||||
def show
|
def show
|
||||||
cache_if_unauthenticated!
|
cache_if_unauthenticated!
|
||||||
@@ -52,11 +51,27 @@ class Api::V1::Timelines::TagController < Api::V1::Timelines::BaseController
|
|||||||
)
|
)
|
||||||
end
|
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
|
def next_path
|
||||||
api_v1_timelines_tag_url params[:id], next_path_params
|
api_v1_timelines_tag_url params[:id], pagination_params(max_id: pagination_max_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def prev_path
|
def prev_path
|
||||||
api_v1_timelines_tag_url params[:id], prev_path_params
|
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
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2,22 +2,12 @@
|
|||||||
|
|
||||||
class Api::V2::MediaController < Api::V1::MediaController
|
class Api::V2::MediaController < Api::V1::MediaController
|
||||||
def create
|
def create
|
||||||
@media_attachment = current_account.media_attachments.create!(media_and_delay_params)
|
@media_attachment = current_account.media_attachments.create!({ delay_processing: true }.merge(media_attachment_params))
|
||||||
render json: @media_attachment, serializer: REST::MediaAttachmentSerializer, status: status_from_media_processing
|
render json: @media_attachment, serializer: REST::MediaAttachmentSerializer, status: @media_attachment.not_processed? ? 202 : 200
|
||||||
rescue Paperclip::Errors::NotIdentifiedByImageMagickError
|
rescue Paperclip::Errors::NotIdentifiedByImageMagickError
|
||||||
render json: file_type_error, status: 422
|
render json: file_type_error, status: 422
|
||||||
rescue Paperclip::Error => e
|
rescue Paperclip::Error => e
|
||||||
Rails.logger.error "#{e.class}: #{e.message}"
|
Rails.logger.error "#{e.class}: #{e.message}"
|
||||||
render json: processing_error, status: 500
|
render json: processing_error, status: 500
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def media_and_delay_params
|
|
||||||
{ delay_processing: true }.merge(media_attachment_params)
|
|
||||||
end
|
|
||||||
|
|
||||||
def status_from_media_processing
|
|
||||||
@media_attachment.not_processed? ? 202 : 200
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -8,12 +8,6 @@ class Api::V2::SearchController < Api::BaseController
|
|||||||
before_action -> { authorize_if_got_token! :read, :'read:search' }
|
before_action -> { authorize_if_got_token! :read, :'read:search' }
|
||||||
before_action :validate_search_params!
|
before_action :validate_search_params!
|
||||||
|
|
||||||
with_options unless: :user_signed_in? do
|
|
||||||
before_action :query_pagination_error, if: :pagination_requested?
|
|
||||||
before_action :remote_resolve_error, if: :remote_resolve_requested?
|
|
||||||
end
|
|
||||||
before_action :require_valid_pagination_options!
|
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@search = Search.new(search_results)
|
@search = Search.new(search_results)
|
||||||
render json: @search, serializer: REST::SearchSerializer
|
render json: @search, serializer: REST::SearchSerializer
|
||||||
@@ -27,22 +21,12 @@ class Api::V2::SearchController < Api::BaseController
|
|||||||
|
|
||||||
def validate_search_params!
|
def validate_search_params!
|
||||||
params.require(:q)
|
params.require(:q)
|
||||||
end
|
|
||||||
|
|
||||||
def query_pagination_error
|
return if user_signed_in?
|
||||||
render json: { error: 'Search queries pagination is not supported without authentication' }, status: 401
|
|
||||||
end
|
|
||||||
|
|
||||||
def remote_resolve_error
|
return render json: { error: 'Search queries pagination is not supported without authentication' }, status: 401 if params[:offset].present?
|
||||||
render json: { error: 'Search queries that resolve remote resources are not supported without authentication' }, status: 401
|
|
||||||
end
|
|
||||||
|
|
||||||
def remote_resolve_requested?
|
render json: { error: 'Search queries that resolve remote resources are not supported without authentication' }, status: 401 if truthy_param?(:resolve)
|
||||||
truthy_param?(:resolve)
|
|
||||||
end
|
|
||||||
|
|
||||||
def pagination_requested?
|
|
||||||
params[:offset].present?
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def search_results
|
def search_results
|
||||||
@@ -50,15 +34,7 @@ class Api::V2::SearchController < Api::BaseController
|
|||||||
params[:q],
|
params[:q],
|
||||||
current_account,
|
current_account,
|
||||||
limit_param(RESULTS_LIMIT),
|
limit_param(RESULTS_LIMIT),
|
||||||
combined_search_params
|
search_params.merge(resolve: truthy_param?(:resolve), exclude_unreviewed: truthy_param?(:exclude_unreviewed), following: truthy_param?(:following))
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def combined_search_params
|
|
||||||
search_params.merge(
|
|
||||||
resolve: truthy_param?(:resolve),
|
|
||||||
exclude_unreviewed: truthy_param?(:exclude_unreviewed),
|
|
||||||
following: truthy_param?(:following)
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -3,13 +3,37 @@
|
|||||||
class Api::Web::PushSubscriptionsController < Api::Web::BaseController
|
class Api::Web::PushSubscriptionsController < Api::Web::BaseController
|
||||||
before_action :require_user!
|
before_action :require_user!
|
||||||
before_action :set_push_subscription, only: :update
|
before_action :set_push_subscription, only: :update
|
||||||
before_action :destroy_previous_subscriptions, only: :create, if: :prior_subscriptions?
|
|
||||||
after_action :update_session_with_subscription, only: :create
|
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@push_subscription = ::Web::PushSubscription.create!(web_push_subscription_params)
|
active_session = current_session
|
||||||
|
|
||||||
render json: @push_subscription, serializer: REST::WebPushSubscriptionSerializer
|
unless active_session.web_push_subscription.nil?
|
||||||
|
active_session.web_push_subscription.destroy!
|
||||||
|
active_session.update!(web_push_subscription: nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Mobile devices do not support regular notifications, so we enable push notifications by default
|
||||||
|
alerts_enabled = active_session.detection.device.mobile? || active_session.detection.device.tablet?
|
||||||
|
|
||||||
|
data = {
|
||||||
|
policy: 'all',
|
||||||
|
alerts: Notification::TYPES.index_with { alerts_enabled },
|
||||||
|
}
|
||||||
|
|
||||||
|
data.deep_merge!(data_params) if params[:data]
|
||||||
|
|
||||||
|
push_subscription = ::Web::PushSubscription.create!(
|
||||||
|
endpoint: subscription_params[:endpoint],
|
||||||
|
key_p256dh: subscription_params[:keys][:p256dh],
|
||||||
|
key_auth: subscription_params[:keys][:auth],
|
||||||
|
data: data,
|
||||||
|
user_id: active_session.user_id,
|
||||||
|
access_token_id: active_session.access_token_id
|
||||||
|
)
|
||||||
|
|
||||||
|
active_session.update!(web_push_subscription: push_subscription)
|
||||||
|
|
||||||
|
render json: push_subscription, serializer: REST::WebPushSubscriptionSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
@@ -19,41 +43,6 @@ class Api::Web::PushSubscriptionsController < Api::Web::BaseController
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def active_session
|
|
||||||
@active_session ||= current_session
|
|
||||||
end
|
|
||||||
|
|
||||||
def destroy_previous_subscriptions
|
|
||||||
active_session.web_push_subscription.destroy!
|
|
||||||
active_session.update!(web_push_subscription: nil)
|
|
||||||
end
|
|
||||||
|
|
||||||
def prior_subscriptions?
|
|
||||||
active_session.web_push_subscription.present?
|
|
||||||
end
|
|
||||||
|
|
||||||
def subscription_data
|
|
||||||
default_subscription_data.tap do |data|
|
|
||||||
data.deep_merge!(data_params) if params[:data]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def default_subscription_data
|
|
||||||
{
|
|
||||||
policy: 'all',
|
|
||||||
alerts: Notification::TYPES.index_with { alerts_enabled },
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
def alerts_enabled
|
|
||||||
# Mobile devices do not support regular notifications, so we enable push notifications by default
|
|
||||||
active_session.detection.device.mobile? || active_session.detection.device.tablet?
|
|
||||||
end
|
|
||||||
|
|
||||||
def update_session_with_subscription
|
|
||||||
active_session.update!(web_push_subscription: @push_subscription)
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_push_subscription
|
def set_push_subscription
|
||||||
@push_subscription = ::Web::PushSubscription.find(params[:id])
|
@push_subscription = ::Web::PushSubscription.find(params[:id])
|
||||||
end
|
end
|
||||||
@@ -62,17 +51,6 @@ class Api::Web::PushSubscriptionsController < Api::Web::BaseController
|
|||||||
@subscription_params ||= params.require(:subscription).permit(:endpoint, keys: [:auth, :p256dh])
|
@subscription_params ||= params.require(:subscription).permit(:endpoint, keys: [:auth, :p256dh])
|
||||||
end
|
end
|
||||||
|
|
||||||
def web_push_subscription_params
|
|
||||||
{
|
|
||||||
access_token_id: active_session.access_token_id,
|
|
||||||
data: subscription_data,
|
|
||||||
endpoint: subscription_params[:endpoint],
|
|
||||||
key_auth: subscription_params[:keys][:auth],
|
|
||||||
key_p256dh: subscription_params[:keys][:p256dh],
|
|
||||||
user_id: active_session.user_id,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
def data_params
|
def data_params
|
||||||
@data_params ||= params.require(:data).permit(:policy, alerts: Notification::TYPES)
|
@data_params ||= params.require(:data).permit(:policy, alerts: Notification::TYPES)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Auth::ConfirmationsController < Devise::ConfirmationsController
|
class Auth::ConfirmationsController < Devise::ConfirmationsController
|
||||||
include Auth::CaptchaConcern
|
include CaptchaConcern
|
||||||
|
|
||||||
layout 'auth'
|
layout 'auth'
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ class Auth::ConfirmationsController < Devise::ConfirmationsController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def captcha_user_bypass?
|
def captcha_user_bypass?
|
||||||
@confirmation_user.nil? || @confirmation_user.confirmed?
|
return true if @confirmation_user.nil? || @confirmation_user.confirmed?
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_pack
|
def set_pack
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
class Auth::RegistrationsController < Devise::RegistrationsController
|
class Auth::RegistrationsController < Devise::RegistrationsController
|
||||||
include RegistrationHelper
|
include RegistrationHelper
|
||||||
include Auth::RegistrationSpamConcern
|
include RegistrationSpamConcern
|
||||||
|
|
||||||
layout :determine_layout
|
layout :determine_layout
|
||||||
|
|
||||||
@@ -125,7 +125,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def require_not_suspended!
|
def require_not_suspended!
|
||||||
forbidden if current_account.unavailable?
|
forbidden if current_account.suspended?
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_rules
|
def set_rules
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class Auth::SessionsController < Devise::SessionsController
|
|||||||
prepend_before_action :set_pack
|
prepend_before_action :set_pack
|
||||||
prepend_before_action :check_suspicious!, only: [:create]
|
prepend_before_action :check_suspicious!, only: [:create]
|
||||||
|
|
||||||
include Auth::TwoFactorAuthenticationConcern
|
include TwoFactorAuthenticationConcern
|
||||||
|
|
||||||
before_action :set_body_classes
|
before_action :set_body_classes
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Api::AccessTokenTrackingConcern
|
module AccessTokenTrackingConcern
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
ACCESS_TOKEN_UPDATE_FREQUENCY = 24.hours.freeze
|
ACCESS_TOKEN_UPDATE_FREQUENCY = 24.hours.freeze
|
||||||
@@ -34,8 +34,8 @@ module AccountOwnedConcern
|
|||||||
end
|
end
|
||||||
|
|
||||||
def check_account_suspension
|
def check_account_suspension
|
||||||
if @account.permanently_unavailable?
|
if @account.suspended_permanently?
|
||||||
permanent_unavailability_response
|
permanent_suspension_response
|
||||||
elsif @account.suspended? && !skip_temporary_suspension_response?
|
elsif @account.suspended? && !skip_temporary_suspension_response?
|
||||||
temporary_suspension_response
|
temporary_suspension_response
|
||||||
end
|
end
|
||||||
@@ -45,7 +45,7 @@ module AccountOwnedConcern
|
|||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
def permanent_unavailability_response
|
def permanent_suspension_response
|
||||||
expires_in(3.minutes, public: true)
|
expires_in(3.minutes, public: true)
|
||||||
gone
|
gone
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Admin::ExportControllerConcern
|
module AdminExportControllerConcern
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
private
|
private
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Api::CachingConcern
|
module ApiCachingConcern
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
def cache_if_unauthenticated!
|
def cache_if_unauthenticated!
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Auth::CaptchaConcern
|
module CaptchaConcern
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
include Hcaptcha::Adapters::ViewMethods
|
include Hcaptcha::Adapters::ViewMethods
|
||||||
@@ -43,7 +43,7 @@ module ChallengableConcern
|
|||||||
|
|
||||||
def render_challenge
|
def render_challenge
|
||||||
@body_classes = 'lighter'
|
@body_classes = 'lighter'
|
||||||
render 'auth/challenges/new', layout: 'auth'
|
render template: 'auth/challenges/new', layout: 'auth'
|
||||||
end
|
end
|
||||||
|
|
||||||
def challenge_passed?
|
def challenge_passed?
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Settings::ExportControllerConcern
|
module ExportControllerConcern
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
included do
|
included do
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Api::RateLimitHeaders
|
module RateLimitHeaders
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
class_methods do
|
class_methods do
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Auth::RegistrationSpamConcern
|
module RegistrationSpamConcern
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
def set_registration_form_time
|
def set_registration_form_time
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Auth::TwoFactorAuthenticationConcern
|
module TwoFactorAuthenticationConcern
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
included do
|
included do
|
||||||
@@ -11,7 +11,7 @@ class Disputes::AppealsController < Disputes::BaseController
|
|||||||
redirect_to disputes_strike_path(@strike), notice: I18n.t('disputes.strikes.appealed_msg')
|
redirect_to disputes_strike_path(@strike), notice: I18n.t('disputes.strikes.appealed_msg')
|
||||||
rescue ActiveRecord::RecordInvalid => e
|
rescue ActiveRecord::RecordInvalid => e
|
||||||
@appeal = e.record
|
@appeal = e.record
|
||||||
render 'disputes/strikes/show'
|
render template: 'disputes/strikes/show'
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ class FiltersController < ApplicationController
|
|||||||
if @filter.save
|
if @filter.save
|
||||||
redirect_to filters_path
|
redirect_to filters_path
|
||||||
else
|
else
|
||||||
render :new
|
render action: :new
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ class FiltersController < ApplicationController
|
|||||||
if @filter.update(resource_params)
|
if @filter.update(resource_params)
|
||||||
redirect_to filters_path
|
redirect_to filters_path
|
||||||
else
|
else
|
||||||
render :edit
|
render action: :edit
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio
|
|||||||
end
|
end
|
||||||
|
|
||||||
def require_not_suspended!
|
def require_not_suspended!
|
||||||
forbidden if current_account.unavailable?
|
forbidden if current_account.suspended?
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_cache_headers
|
def set_cache_headers
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ class RelationshipsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def set_relationships
|
def set_relationships
|
||||||
@relationships = AccountRelationshipsPresenter.new(@accounts, current_user.account_id)
|
@relationships = AccountRelationshipsPresenter.new(@accounts.pluck(:id), current_user.account_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def form_account_batch_params
|
def form_account_batch_params
|
||||||
|
|||||||
@@ -23,6 +23,6 @@ class Settings::BaseController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def require_not_suspended!
|
def require_not_suspended!
|
||||||
forbidden if current_account.unavailable?
|
forbidden if current_account.suspended?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class Settings::DeletesController < Settings::BaseController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def require_not_suspended!
|
def require_not_suspended!
|
||||||
forbidden if current_account.unavailable?
|
forbidden if current_account.suspended?
|
||||||
end
|
end
|
||||||
|
|
||||||
def challenge_passed?
|
def challenge_passed?
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
module Settings
|
module Settings
|
||||||
module Exports
|
module Exports
|
||||||
class BlockedAccountsController < BaseController
|
class BlockedAccountsController < BaseController
|
||||||
include Settings::ExportControllerConcern
|
include ExportControllerConcern
|
||||||
|
|
||||||
def index
|
def index
|
||||||
send_export_file
|
send_export_file
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
module Settings
|
module Settings
|
||||||
module Exports
|
module Exports
|
||||||
class BlockedDomainsController < BaseController
|
class BlockedDomainsController < BaseController
|
||||||
include Settings::ExportControllerConcern
|
include ExportControllerConcern
|
||||||
|
|
||||||
def index
|
def index
|
||||||
send_export_file
|
send_export_file
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
module Settings
|
module Settings
|
||||||
module Exports
|
module Exports
|
||||||
class BookmarksController < BaseController
|
class BookmarksController < BaseController
|
||||||
include Settings::ExportControllerConcern
|
include ExportControllerConcern
|
||||||
|
|
||||||
def index
|
def index
|
||||||
send_export_file
|
send_export_file
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
module Settings
|
module Settings
|
||||||
module Exports
|
module Exports
|
||||||
class FollowingAccountsController < BaseController
|
class FollowingAccountsController < BaseController
|
||||||
include Settings::ExportControllerConcern
|
include ExportControllerConcern
|
||||||
|
|
||||||
def index
|
def index
|
||||||
send_export_file
|
send_export_file
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
module Settings
|
module Settings
|
||||||
module Exports
|
module Exports
|
||||||
class ListsController < BaseController
|
class ListsController < BaseController
|
||||||
include Settings::ExportControllerConcern
|
include ExportControllerConcern
|
||||||
|
|
||||||
def index
|
def index
|
||||||
send_export_file
|
send_export_file
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
module Settings
|
module Settings
|
||||||
module Exports
|
module Exports
|
||||||
class MutedAccountsController < BaseController
|
class MutedAccountsController < BaseController
|
||||||
include Settings::ExportControllerConcern
|
include ExportControllerConcern
|
||||||
|
|
||||||
def index
|
def index
|
||||||
send_export_file
|
send_export_file
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ class StatusesCleanupController < ApplicationController
|
|||||||
if @policy.update(resource_params)
|
if @policy.update(resource_params)
|
||||||
redirect_to statuses_cleanup_path, notice: I18n.t('generic.changes_saved_msg')
|
redirect_to statuses_cleanup_path, notice: I18n.t('generic.changes_saved_msg')
|
||||||
else
|
else
|
||||||
render :show
|
render action: :show
|
||||||
end
|
end
|
||||||
rescue ActionController::ParameterMissing
|
rescue ActionController::ParameterMissing
|
||||||
# Do nothing
|
# Do nothing
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ module WellKnown
|
|||||||
end
|
end
|
||||||
|
|
||||||
def check_account_suspension
|
def check_account_suspension
|
||||||
gone if @account.permanently_unavailable?
|
gone if @account.suspended_permanently?
|
||||||
end
|
end
|
||||||
|
|
||||||
def gone
|
def gone
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module Admin::AccountActionsHelper
|
|
||||||
def account_action_type_label(type)
|
|
||||||
safe_join(
|
|
||||||
[
|
|
||||||
I18n.t("simple_form.labels.admin_account_action.types.#{type}"),
|
|
||||||
content_tag(:span, I18n.t("simple_form.hints.admin_account_action.types.#{type}"), class: 'hint'),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module Admin::AccountsHelper
|
|
||||||
def admin_accounts_moderation_options
|
|
||||||
[
|
|
||||||
[t('admin.accounts.moderation.active'), 'active'],
|
|
||||||
[t('admin.accounts.moderation.silenced'), 'silenced'],
|
|
||||||
[t('admin.accounts.moderation.disabled'), 'disabled'],
|
|
||||||
[t('admin.accounts.moderation.suspended'), 'suspended'],
|
|
||||||
[safe_join([t('admin.accounts.moderation.pending'), "(#{pending_user_count_label})"], ' '), 'pending'],
|
|
||||||
]
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def pending_user_count_label
|
|
||||||
number_with_delimiter User.pending.count
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module Admin::IpBlocksHelper
|
|
||||||
def ip_blocks_severity_label(severity)
|
|
||||||
safe_join(
|
|
||||||
[
|
|
||||||
I18n.t("simple_form.labels.ip_block.severities.#{severity}"),
|
|
||||||
content_tag(:span, I18n.t("simple_form.hints.ip_block.severities.#{severity}"), class: 'hint'),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module Admin
|
|
||||||
module RolesHelper
|
|
||||||
def privilege_label(privilege)
|
|
||||||
safe_join(
|
|
||||||
[
|
|
||||||
t("admin.roles.privileges.#{privilege}"),
|
|
||||||
content_tag(:span, t("admin.roles.privileges.#{privilege}_description"), class: 'hint'),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def disable_permissions?(permissions)
|
|
||||||
permissions.filter { |privilege| role_flag_value(privilege).zero? }
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def role_flag_value(privilege)
|
|
||||||
UserRole::FLAGS[privilege] & current_user.role.computed_permissions
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module Admin::Settings::DiscoveryHelper
|
|
||||||
def discovery_warning_hint_text
|
|
||||||
authorized_fetch_overridden? ? t('admin.settings.security.authorized_fetch_overridden_hint') : nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def discovery_hint_text
|
|
||||||
t('admin.settings.security.authorized_fetch_hint')
|
|
||||||
end
|
|
||||||
|
|
||||||
def discovery_recommended_value
|
|
||||||
authorized_fetch_overridden? ? :overridden : nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -110,11 +110,11 @@ module ApplicationHelper
|
|||||||
def can?(action, record)
|
def can?(action, record)
|
||||||
return false if record.nil?
|
return false if record.nil?
|
||||||
|
|
||||||
policy(record).public_send(:"#{action}?")
|
policy(record).public_send("#{action}?")
|
||||||
end
|
end
|
||||||
|
|
||||||
def fa_icon(icon, attributes = {})
|
def fa_icon(icon, attributes = {})
|
||||||
class_names = attributes[:class]&.split || []
|
class_names = attributes[:class]&.split(' ') || []
|
||||||
class_names << 'fa'
|
class_names << 'fa'
|
||||||
class_names += icon.split.map { |cl| "fa-#{cl}" }
|
class_names += icon.split.map { |cl| "fa-#{cl}" }
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module FiltersHelper
|
|
||||||
def filter_action_label(action)
|
|
||||||
safe_join(
|
|
||||||
[
|
|
||||||
t("simple_form.labels.filters.actions.#{action}"),
|
|
||||||
content_tag(:span, t("simple_form.hints.filters.actions.#{action}"), class: 'hint'),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
import type { ApiRelationshipJSON } from 'flavours/glitch/api_types/relationships';
|
|
||||||
import { createAppAsyncThunk } from 'flavours/glitch/store/typed_functions';
|
import { createAppAsyncThunk } from 'flavours/glitch/store/typed_functions';
|
||||||
|
|
||||||
import api from '../api';
|
import api from '../api';
|
||||||
@@ -6,7 +5,8 @@ import api from '../api';
|
|||||||
export const submitAccountNote = createAppAsyncThunk(
|
export const submitAccountNote = createAppAsyncThunk(
|
||||||
'account_note/submit',
|
'account_note/submit',
|
||||||
async (args: { id: string; value: string }, { getState }) => {
|
async (args: { id: string; value: string }, { getState }) => {
|
||||||
const response = await api(getState).post<ApiRelationshipJSON>(
|
// TODO: replace `unknown` with `ApiRelationshipJSON` when it is merged
|
||||||
|
const response = await api(getState).post<unknown>(
|
||||||
`/api/v1/accounts/${args.id}/note`,
|
`/api/v1/accounts/${args.id}/note`,
|
||||||
{
|
{
|
||||||
comment: args.value,
|
comment: args.value,
|
||||||
|
|||||||
@@ -1,15 +1,5 @@
|
|||||||
import api, { getLinks } from '../api';
|
import api, { getLinks } from '../api';
|
||||||
|
|
||||||
import {
|
|
||||||
followAccountSuccess, unfollowAccountSuccess,
|
|
||||||
authorizeFollowRequestSuccess, rejectFollowRequestSuccess,
|
|
||||||
followAccountRequest, followAccountFail,
|
|
||||||
unfollowAccountRequest, unfollowAccountFail,
|
|
||||||
muteAccountSuccess, unmuteAccountSuccess,
|
|
||||||
blockAccountSuccess, unblockAccountSuccess,
|
|
||||||
pinAccountSuccess, unpinAccountSuccess,
|
|
||||||
fetchRelationshipsSuccess,
|
|
||||||
} from './accounts_typed';
|
|
||||||
import { importFetchedAccount, importFetchedAccounts } from './importer';
|
import { importFetchedAccount, importFetchedAccounts } from './importer';
|
||||||
|
|
||||||
export const ACCOUNT_FETCH_REQUEST = 'ACCOUNT_FETCH_REQUEST';
|
export const ACCOUNT_FETCH_REQUEST = 'ACCOUNT_FETCH_REQUEST';
|
||||||
@@ -20,22 +10,36 @@ export const ACCOUNT_LOOKUP_REQUEST = 'ACCOUNT_LOOKUP_REQUEST';
|
|||||||
export const ACCOUNT_LOOKUP_SUCCESS = 'ACCOUNT_LOOKUP_SUCCESS';
|
export const ACCOUNT_LOOKUP_SUCCESS = 'ACCOUNT_LOOKUP_SUCCESS';
|
||||||
export const ACCOUNT_LOOKUP_FAIL = 'ACCOUNT_LOOKUP_FAIL';
|
export const ACCOUNT_LOOKUP_FAIL = 'ACCOUNT_LOOKUP_FAIL';
|
||||||
|
|
||||||
|
export const ACCOUNT_FOLLOW_REQUEST = 'ACCOUNT_FOLLOW_REQUEST';
|
||||||
|
export const ACCOUNT_FOLLOW_SUCCESS = 'ACCOUNT_FOLLOW_SUCCESS';
|
||||||
|
export const ACCOUNT_FOLLOW_FAIL = 'ACCOUNT_FOLLOW_FAIL';
|
||||||
|
|
||||||
|
export const ACCOUNT_UNFOLLOW_REQUEST = 'ACCOUNT_UNFOLLOW_REQUEST';
|
||||||
|
export const ACCOUNT_UNFOLLOW_SUCCESS = 'ACCOUNT_UNFOLLOW_SUCCESS';
|
||||||
|
export const ACCOUNT_UNFOLLOW_FAIL = 'ACCOUNT_UNFOLLOW_FAIL';
|
||||||
|
|
||||||
export const ACCOUNT_BLOCK_REQUEST = 'ACCOUNT_BLOCK_REQUEST';
|
export const ACCOUNT_BLOCK_REQUEST = 'ACCOUNT_BLOCK_REQUEST';
|
||||||
|
export const ACCOUNT_BLOCK_SUCCESS = 'ACCOUNT_BLOCK_SUCCESS';
|
||||||
export const ACCOUNT_BLOCK_FAIL = 'ACCOUNT_BLOCK_FAIL';
|
export const ACCOUNT_BLOCK_FAIL = 'ACCOUNT_BLOCK_FAIL';
|
||||||
|
|
||||||
export const ACCOUNT_UNBLOCK_REQUEST = 'ACCOUNT_UNBLOCK_REQUEST';
|
export const ACCOUNT_UNBLOCK_REQUEST = 'ACCOUNT_UNBLOCK_REQUEST';
|
||||||
|
export const ACCOUNT_UNBLOCK_SUCCESS = 'ACCOUNT_UNBLOCK_SUCCESS';
|
||||||
export const ACCOUNT_UNBLOCK_FAIL = 'ACCOUNT_UNBLOCK_FAIL';
|
export const ACCOUNT_UNBLOCK_FAIL = 'ACCOUNT_UNBLOCK_FAIL';
|
||||||
|
|
||||||
export const ACCOUNT_MUTE_REQUEST = 'ACCOUNT_MUTE_REQUEST';
|
export const ACCOUNT_MUTE_REQUEST = 'ACCOUNT_MUTE_REQUEST';
|
||||||
|
export const ACCOUNT_MUTE_SUCCESS = 'ACCOUNT_MUTE_SUCCESS';
|
||||||
export const ACCOUNT_MUTE_FAIL = 'ACCOUNT_MUTE_FAIL';
|
export const ACCOUNT_MUTE_FAIL = 'ACCOUNT_MUTE_FAIL';
|
||||||
|
|
||||||
export const ACCOUNT_UNMUTE_REQUEST = 'ACCOUNT_UNMUTE_REQUEST';
|
export const ACCOUNT_UNMUTE_REQUEST = 'ACCOUNT_UNMUTE_REQUEST';
|
||||||
|
export const ACCOUNT_UNMUTE_SUCCESS = 'ACCOUNT_UNMUTE_SUCCESS';
|
||||||
export const ACCOUNT_UNMUTE_FAIL = 'ACCOUNT_UNMUTE_FAIL';
|
export const ACCOUNT_UNMUTE_FAIL = 'ACCOUNT_UNMUTE_FAIL';
|
||||||
|
|
||||||
export const ACCOUNT_PIN_REQUEST = 'ACCOUNT_PIN_REQUEST';
|
export const ACCOUNT_PIN_REQUEST = 'ACCOUNT_PIN_REQUEST';
|
||||||
|
export const ACCOUNT_PIN_SUCCESS = 'ACCOUNT_PIN_SUCCESS';
|
||||||
export const ACCOUNT_PIN_FAIL = 'ACCOUNT_PIN_FAIL';
|
export const ACCOUNT_PIN_FAIL = 'ACCOUNT_PIN_FAIL';
|
||||||
|
|
||||||
export const ACCOUNT_UNPIN_REQUEST = 'ACCOUNT_UNPIN_REQUEST';
|
export const ACCOUNT_UNPIN_REQUEST = 'ACCOUNT_UNPIN_REQUEST';
|
||||||
|
export const ACCOUNT_UNPIN_SUCCESS = 'ACCOUNT_UNPIN_SUCCESS';
|
||||||
export const ACCOUNT_UNPIN_FAIL = 'ACCOUNT_UNPIN_FAIL';
|
export const ACCOUNT_UNPIN_FAIL = 'ACCOUNT_UNPIN_FAIL';
|
||||||
|
|
||||||
export const FOLLOWERS_FETCH_REQUEST = 'FOLLOWERS_FETCH_REQUEST';
|
export const FOLLOWERS_FETCH_REQUEST = 'FOLLOWERS_FETCH_REQUEST';
|
||||||
@@ -55,6 +59,7 @@ export const FOLLOWING_EXPAND_SUCCESS = 'FOLLOWING_EXPAND_SUCCESS';
|
|||||||
export const FOLLOWING_EXPAND_FAIL = 'FOLLOWING_EXPAND_FAIL';
|
export const FOLLOWING_EXPAND_FAIL = 'FOLLOWING_EXPAND_FAIL';
|
||||||
|
|
||||||
export const RELATIONSHIPS_FETCH_REQUEST = 'RELATIONSHIPS_FETCH_REQUEST';
|
export const RELATIONSHIPS_FETCH_REQUEST = 'RELATIONSHIPS_FETCH_REQUEST';
|
||||||
|
export const RELATIONSHIPS_FETCH_SUCCESS = 'RELATIONSHIPS_FETCH_SUCCESS';
|
||||||
export const RELATIONSHIPS_FETCH_FAIL = 'RELATIONSHIPS_FETCH_FAIL';
|
export const RELATIONSHIPS_FETCH_FAIL = 'RELATIONSHIPS_FETCH_FAIL';
|
||||||
|
|
||||||
export const FOLLOW_REQUESTS_FETCH_REQUEST = 'FOLLOW_REQUESTS_FETCH_REQUEST';
|
export const FOLLOW_REQUESTS_FETCH_REQUEST = 'FOLLOW_REQUESTS_FETCH_REQUEST';
|
||||||
@@ -86,9 +91,8 @@ export const PINNED_ACCOUNTS_EDITOR_SUGGESTIONS_CHANGE = 'PINNED_ACCOUNTS_EDITOR
|
|||||||
|
|
||||||
export const PINNED_ACCOUNTS_EDITOR_RESET = 'PINNED_ACCOUNTS_EDITOR_RESET';
|
export const PINNED_ACCOUNTS_EDITOR_RESET = 'PINNED_ACCOUNTS_EDITOR_RESET';
|
||||||
|
|
||||||
export const ACCOUNT_REVEAL = 'ACCOUNT_REVEAL';
|
|
||||||
|
|
||||||
export * from './accounts_typed';
|
export const ACCOUNT_REVEAL = 'ACCOUNT_REVEAL';
|
||||||
|
|
||||||
export function fetchAccount(id) {
|
export function fetchAccount(id) {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
@@ -164,12 +168,12 @@ export function followAccount(id, options = { reblogs: true }) {
|
|||||||
const alreadyFollowing = getState().getIn(['relationships', id, 'following']);
|
const alreadyFollowing = getState().getIn(['relationships', id, 'following']);
|
||||||
const locked = getState().getIn(['accounts', id, 'locked'], false);
|
const locked = getState().getIn(['accounts', id, 'locked'], false);
|
||||||
|
|
||||||
dispatch(followAccountRequest({ id, locked }));
|
dispatch(followAccountRequest(id, locked));
|
||||||
|
|
||||||
api(getState).post(`/api/v1/accounts/${id}/follow`, options).then(response => {
|
api(getState).post(`/api/v1/accounts/${id}/follow`, options).then(response => {
|
||||||
dispatch(followAccountSuccess({relationship: response.data, alreadyFollowing}));
|
dispatch(followAccountSuccess(response.data, alreadyFollowing));
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
dispatch(followAccountFail({ id, error, locked }));
|
dispatch(followAccountFail(error, locked));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -179,22 +183,74 @@ export function unfollowAccount(id) {
|
|||||||
dispatch(unfollowAccountRequest(id));
|
dispatch(unfollowAccountRequest(id));
|
||||||
|
|
||||||
api(getState).post(`/api/v1/accounts/${id}/unfollow`).then(response => {
|
api(getState).post(`/api/v1/accounts/${id}/unfollow`).then(response => {
|
||||||
dispatch(unfollowAccountSuccess({relationship: response.data, statuses: getState().get('statuses')}));
|
dispatch(unfollowAccountSuccess(response.data, getState().get('statuses')));
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
dispatch(unfollowAccountFail({ id, error }));
|
dispatch(unfollowAccountFail(error));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function followAccountRequest(id, locked) {
|
||||||
|
return {
|
||||||
|
type: ACCOUNT_FOLLOW_REQUEST,
|
||||||
|
id,
|
||||||
|
locked,
|
||||||
|
skipLoading: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function followAccountSuccess(relationship, alreadyFollowing) {
|
||||||
|
return {
|
||||||
|
type: ACCOUNT_FOLLOW_SUCCESS,
|
||||||
|
relationship,
|
||||||
|
alreadyFollowing,
|
||||||
|
skipLoading: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function followAccountFail(error, locked) {
|
||||||
|
return {
|
||||||
|
type: ACCOUNT_FOLLOW_FAIL,
|
||||||
|
error,
|
||||||
|
locked,
|
||||||
|
skipLoading: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function unfollowAccountRequest(id) {
|
||||||
|
return {
|
||||||
|
type: ACCOUNT_UNFOLLOW_REQUEST,
|
||||||
|
id,
|
||||||
|
skipLoading: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function unfollowAccountSuccess(relationship, statuses) {
|
||||||
|
return {
|
||||||
|
type: ACCOUNT_UNFOLLOW_SUCCESS,
|
||||||
|
relationship,
|
||||||
|
statuses,
|
||||||
|
skipLoading: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function unfollowAccountFail(error) {
|
||||||
|
return {
|
||||||
|
type: ACCOUNT_UNFOLLOW_FAIL,
|
||||||
|
error,
|
||||||
|
skipLoading: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function blockAccount(id) {
|
export function blockAccount(id) {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
dispatch(blockAccountRequest(id));
|
dispatch(blockAccountRequest(id));
|
||||||
|
|
||||||
api(getState).post(`/api/v1/accounts/${id}/block`).then(response => {
|
api(getState).post(`/api/v1/accounts/${id}/block`).then(response => {
|
||||||
// Pass in entire statuses map so we can use it to filter stuff in different parts of the reducers
|
// Pass in entire statuses map so we can use it to filter stuff in different parts of the reducers
|
||||||
dispatch(blockAccountSuccess({ relationship: response.data, statuses: getState().get('statuses') }));
|
dispatch(blockAccountSuccess(response.data, getState().get('statuses')));
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
dispatch(blockAccountFail({ id, error }));
|
dispatch(blockAccountFail(id, error));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -204,9 +260,9 @@ export function unblockAccount(id) {
|
|||||||
dispatch(unblockAccountRequest(id));
|
dispatch(unblockAccountRequest(id));
|
||||||
|
|
||||||
api(getState).post(`/api/v1/accounts/${id}/unblock`).then(response => {
|
api(getState).post(`/api/v1/accounts/${id}/unblock`).then(response => {
|
||||||
dispatch(unblockAccountSuccess({ relationship: response.data }));
|
dispatch(unblockAccountSuccess(response.data));
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
dispatch(unblockAccountFail({ id, error }));
|
dispatch(unblockAccountFail(id, error));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -217,6 +273,15 @@ export function blockAccountRequest(id) {
|
|||||||
id,
|
id,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function blockAccountSuccess(relationship, statuses) {
|
||||||
|
return {
|
||||||
|
type: ACCOUNT_BLOCK_SUCCESS,
|
||||||
|
relationship,
|
||||||
|
statuses,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function blockAccountFail(error) {
|
export function blockAccountFail(error) {
|
||||||
return {
|
return {
|
||||||
type: ACCOUNT_BLOCK_FAIL,
|
type: ACCOUNT_BLOCK_FAIL,
|
||||||
@@ -231,6 +296,13 @@ export function unblockAccountRequest(id) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function unblockAccountSuccess(relationship) {
|
||||||
|
return {
|
||||||
|
type: ACCOUNT_UNBLOCK_SUCCESS,
|
||||||
|
relationship,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function unblockAccountFail(error) {
|
export function unblockAccountFail(error) {
|
||||||
return {
|
return {
|
||||||
type: ACCOUNT_UNBLOCK_FAIL,
|
type: ACCOUNT_UNBLOCK_FAIL,
|
||||||
@@ -245,9 +317,9 @@ export function muteAccount(id, notifications, duration=0) {
|
|||||||
|
|
||||||
api(getState).post(`/api/v1/accounts/${id}/mute`, { notifications, duration }).then(response => {
|
api(getState).post(`/api/v1/accounts/${id}/mute`, { notifications, duration }).then(response => {
|
||||||
// Pass in entire statuses map so we can use it to filter stuff in different parts of the reducers
|
// Pass in entire statuses map so we can use it to filter stuff in different parts of the reducers
|
||||||
dispatch(muteAccountSuccess({ relationship: response.data, statuses: getState().get('statuses') }));
|
dispatch(muteAccountSuccess(response.data, getState().get('statuses')));
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
dispatch(muteAccountFail({ id, error }));
|
dispatch(muteAccountFail(id, error));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -257,9 +329,9 @@ export function unmuteAccount(id) {
|
|||||||
dispatch(unmuteAccountRequest(id));
|
dispatch(unmuteAccountRequest(id));
|
||||||
|
|
||||||
api(getState).post(`/api/v1/accounts/${id}/unmute`).then(response => {
|
api(getState).post(`/api/v1/accounts/${id}/unmute`).then(response => {
|
||||||
dispatch(unmuteAccountSuccess({ relationship: response.data }));
|
dispatch(unmuteAccountSuccess(response.data));
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
dispatch(unmuteAccountFail({ id, error }));
|
dispatch(unmuteAccountFail(id, error));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -271,6 +343,14 @@ export function muteAccountRequest(id) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function muteAccountSuccess(relationship, statuses) {
|
||||||
|
return {
|
||||||
|
type: ACCOUNT_MUTE_SUCCESS,
|
||||||
|
relationship,
|
||||||
|
statuses,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function muteAccountFail(error) {
|
export function muteAccountFail(error) {
|
||||||
return {
|
return {
|
||||||
type: ACCOUNT_MUTE_FAIL,
|
type: ACCOUNT_MUTE_FAIL,
|
||||||
@@ -285,6 +365,13 @@ export function unmuteAccountRequest(id) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function unmuteAccountSuccess(relationship) {
|
||||||
|
return {
|
||||||
|
type: ACCOUNT_UNMUTE_SUCCESS,
|
||||||
|
relationship,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function unmuteAccountFail(error) {
|
export function unmuteAccountFail(error) {
|
||||||
return {
|
return {
|
||||||
type: ACCOUNT_UNMUTE_FAIL,
|
type: ACCOUNT_UNMUTE_FAIL,
|
||||||
@@ -481,7 +568,7 @@ export function fetchRelationships(accountIds) {
|
|||||||
dispatch(fetchRelationshipsRequest(newAccountIds));
|
dispatch(fetchRelationshipsRequest(newAccountIds));
|
||||||
|
|
||||||
api(getState).get(`/api/v1/accounts/relationships?with_suspended=true&${newAccountIds.map(id => `id[]=${id}`).join('&')}`).then(response => {
|
api(getState).get(`/api/v1/accounts/relationships?with_suspended=true&${newAccountIds.map(id => `id[]=${id}`).join('&')}`).then(response => {
|
||||||
dispatch(fetchRelationshipsSuccess({ relationships: response.data }));
|
dispatch(fetchRelationshipsSuccess(response.data));
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
dispatch(fetchRelationshipsFail(error));
|
dispatch(fetchRelationshipsFail(error));
|
||||||
});
|
});
|
||||||
@@ -496,6 +583,14 @@ export function fetchRelationshipsRequest(ids) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function fetchRelationshipsSuccess(relationships) {
|
||||||
|
return {
|
||||||
|
type: RELATIONSHIPS_FETCH_SUCCESS,
|
||||||
|
relationships,
|
||||||
|
skipLoading: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function fetchRelationshipsFail(error) {
|
export function fetchRelationshipsFail(error) {
|
||||||
return {
|
return {
|
||||||
type: RELATIONSHIPS_FETCH_FAIL,
|
type: RELATIONSHIPS_FETCH_FAIL,
|
||||||
@@ -583,7 +678,7 @@ export function authorizeFollowRequest(id) {
|
|||||||
|
|
||||||
api(getState)
|
api(getState)
|
||||||
.post(`/api/v1/follow_requests/${id}/authorize`)
|
.post(`/api/v1/follow_requests/${id}/authorize`)
|
||||||
.then(() => dispatch(authorizeFollowRequestSuccess({ id })))
|
.then(() => dispatch(authorizeFollowRequestSuccess(id)))
|
||||||
.catch(error => dispatch(authorizeFollowRequestFail(id, error)));
|
.catch(error => dispatch(authorizeFollowRequestFail(id, error)));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -595,6 +690,13 @@ export function authorizeFollowRequestRequest(id) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function authorizeFollowRequestSuccess(id) {
|
||||||
|
return {
|
||||||
|
type: FOLLOW_REQUEST_AUTHORIZE_SUCCESS,
|
||||||
|
id,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function authorizeFollowRequestFail(id, error) {
|
export function authorizeFollowRequestFail(id, error) {
|
||||||
return {
|
return {
|
||||||
type: FOLLOW_REQUEST_AUTHORIZE_FAIL,
|
type: FOLLOW_REQUEST_AUTHORIZE_FAIL,
|
||||||
@@ -610,7 +712,7 @@ export function rejectFollowRequest(id) {
|
|||||||
|
|
||||||
api(getState)
|
api(getState)
|
||||||
.post(`/api/v1/follow_requests/${id}/reject`)
|
.post(`/api/v1/follow_requests/${id}/reject`)
|
||||||
.then(() => dispatch(rejectFollowRequestSuccess({ id })))
|
.then(() => dispatch(rejectFollowRequestSuccess(id)))
|
||||||
.catch(error => dispatch(rejectFollowRequestFail(id, error)));
|
.catch(error => dispatch(rejectFollowRequestFail(id, error)));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -622,6 +724,13 @@ export function rejectFollowRequestRequest(id) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function rejectFollowRequestSuccess(id) {
|
||||||
|
return {
|
||||||
|
type: FOLLOW_REQUEST_REJECT_SUCCESS,
|
||||||
|
id,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function rejectFollowRequestFail(id, error) {
|
export function rejectFollowRequestFail(id, error) {
|
||||||
return {
|
return {
|
||||||
type: FOLLOW_REQUEST_REJECT_FAIL,
|
type: FOLLOW_REQUEST_REJECT_FAIL,
|
||||||
@@ -635,7 +744,7 @@ export function pinAccount(id) {
|
|||||||
dispatch(pinAccountRequest(id));
|
dispatch(pinAccountRequest(id));
|
||||||
|
|
||||||
api(getState).post(`/api/v1/accounts/${id}/pin`).then(response => {
|
api(getState).post(`/api/v1/accounts/${id}/pin`).then(response => {
|
||||||
dispatch(pinAccountSuccess({ relationship: response.data }));
|
dispatch(pinAccountSuccess(response.data));
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
dispatch(pinAccountFail(error));
|
dispatch(pinAccountFail(error));
|
||||||
});
|
});
|
||||||
@@ -647,7 +756,7 @@ export function unpinAccount(id) {
|
|||||||
dispatch(unpinAccountRequest(id));
|
dispatch(unpinAccountRequest(id));
|
||||||
|
|
||||||
api(getState).post(`/api/v1/accounts/${id}/unpin`).then(response => {
|
api(getState).post(`/api/v1/accounts/${id}/unpin`).then(response => {
|
||||||
dispatch(unpinAccountSuccess({ relationship: response.data }));
|
dispatch(unpinAccountSuccess(response.data));
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
dispatch(unpinAccountFail(error));
|
dispatch(unpinAccountFail(error));
|
||||||
});
|
});
|
||||||
@@ -661,6 +770,13 @@ export function pinAccountRequest(id) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function pinAccountSuccess(relationship) {
|
||||||
|
return {
|
||||||
|
type: ACCOUNT_PIN_SUCCESS,
|
||||||
|
relationship,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function pinAccountFail(error) {
|
export function pinAccountFail(error) {
|
||||||
return {
|
return {
|
||||||
type: ACCOUNT_PIN_FAIL,
|
type: ACCOUNT_PIN_FAIL,
|
||||||
@@ -675,6 +791,13 @@ export function unpinAccountRequest(id) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function unpinAccountSuccess(relationship) {
|
||||||
|
return {
|
||||||
|
type: ACCOUNT_UNPIN_SUCCESS,
|
||||||
|
relationship,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function unpinAccountFail(error) {
|
export function unpinAccountFail(error) {
|
||||||
return {
|
return {
|
||||||
type: ACCOUNT_UNPIN_FAIL,
|
type: ACCOUNT_UNPIN_FAIL,
|
||||||
@@ -682,6 +805,11 @@ export function unpinAccountFail(error) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const revealAccount = id => ({
|
||||||
|
type: ACCOUNT_REVEAL,
|
||||||
|
id,
|
||||||
|
});
|
||||||
|
|
||||||
export function fetchPinnedAccounts() {
|
export function fetchPinnedAccounts() {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
dispatch(fetchPinnedAccountsRequest());
|
dispatch(fetchPinnedAccountsRequest());
|
||||||
|
|||||||
@@ -1,97 +0,0 @@
|
|||||||
import { createAction } from '@reduxjs/toolkit';
|
|
||||||
|
|
||||||
import type { ApiAccountJSON } from 'flavours/glitch/api_types/accounts';
|
|
||||||
import type { ApiRelationshipJSON } from 'flavours/glitch/api_types/relationships';
|
|
||||||
|
|
||||||
export const revealAccount = createAction<{
|
|
||||||
id: string;
|
|
||||||
}>('accounts/revealAccount');
|
|
||||||
|
|
||||||
export const importAccounts = createAction<{ accounts: ApiAccountJSON[] }>(
|
|
||||||
'accounts/importAccounts',
|
|
||||||
);
|
|
||||||
|
|
||||||
function actionWithSkipLoadingTrue<Args extends object>(args: Args) {
|
|
||||||
return {
|
|
||||||
payload: {
|
|
||||||
...args,
|
|
||||||
skipLoading: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export const followAccountSuccess = createAction(
|
|
||||||
'accounts/followAccount/SUCCESS',
|
|
||||||
actionWithSkipLoadingTrue<{
|
|
||||||
relationship: ApiRelationshipJSON;
|
|
||||||
alreadyFollowing: boolean;
|
|
||||||
}>,
|
|
||||||
);
|
|
||||||
|
|
||||||
export const unfollowAccountSuccess = createAction(
|
|
||||||
'accounts/unfollowAccount/SUCCESS',
|
|
||||||
actionWithSkipLoadingTrue<{
|
|
||||||
relationship: ApiRelationshipJSON;
|
|
||||||
statuses: unknown;
|
|
||||||
alreadyFollowing?: boolean;
|
|
||||||
}>,
|
|
||||||
);
|
|
||||||
|
|
||||||
export const authorizeFollowRequestSuccess = createAction<{ id: string }>(
|
|
||||||
'accounts/followRequestAuthorize/SUCCESS',
|
|
||||||
);
|
|
||||||
|
|
||||||
export const rejectFollowRequestSuccess = createAction<{ id: string }>(
|
|
||||||
'accounts/followRequestReject/SUCCESS',
|
|
||||||
);
|
|
||||||
|
|
||||||
export const followAccountRequest = createAction(
|
|
||||||
'accounts/follow/REQUEST',
|
|
||||||
actionWithSkipLoadingTrue<{ id: string; locked: boolean }>,
|
|
||||||
);
|
|
||||||
|
|
||||||
export const followAccountFail = createAction(
|
|
||||||
'accounts/follow/FAIL',
|
|
||||||
actionWithSkipLoadingTrue<{ id: string; error: string; locked: boolean }>,
|
|
||||||
);
|
|
||||||
|
|
||||||
export const unfollowAccountRequest = createAction(
|
|
||||||
'accounts/unfollow/REQUEST',
|
|
||||||
actionWithSkipLoadingTrue<{ id: string }>,
|
|
||||||
);
|
|
||||||
|
|
||||||
export const unfollowAccountFail = createAction(
|
|
||||||
'accounts/unfollow/FAIL',
|
|
||||||
actionWithSkipLoadingTrue<{ id: string; error: string }>,
|
|
||||||
);
|
|
||||||
|
|
||||||
export const blockAccountSuccess = createAction<{
|
|
||||||
relationship: ApiRelationshipJSON;
|
|
||||||
statuses: unknown;
|
|
||||||
}>('accounts/block/SUCCESS');
|
|
||||||
|
|
||||||
export const unblockAccountSuccess = createAction<{
|
|
||||||
relationship: ApiRelationshipJSON;
|
|
||||||
}>('accounts/unblock/SUCCESS');
|
|
||||||
|
|
||||||
export const muteAccountSuccess = createAction<{
|
|
||||||
relationship: ApiRelationshipJSON;
|
|
||||||
statuses: unknown;
|
|
||||||
}>('accounts/mute/SUCCESS');
|
|
||||||
|
|
||||||
export const unmuteAccountSuccess = createAction<{
|
|
||||||
relationship: ApiRelationshipJSON;
|
|
||||||
}>('accounts/unmute/SUCCESS');
|
|
||||||
|
|
||||||
export const pinAccountSuccess = createAction<{
|
|
||||||
relationship: ApiRelationshipJSON;
|
|
||||||
}>('accounts/pin/SUCCESS');
|
|
||||||
|
|
||||||
export const unpinAccountSuccess = createAction<{
|
|
||||||
relationship: ApiRelationshipJSON;
|
|
||||||
}>('accounts/unpin/SUCCESS');
|
|
||||||
|
|
||||||
export const fetchRelationshipsSuccess = createAction(
|
|
||||||
'relationships/fetch/SUCCESS',
|
|
||||||
actionWithSkipLoadingTrue<{ relationships: ApiRelationshipJSON[] }>,
|
|
||||||
);
|
|
||||||
@@ -1,13 +1,11 @@
|
|||||||
import api, { getLinks } from '../api';
|
import api, { getLinks } from '../api';
|
||||||
|
|
||||||
import { blockDomainSuccess, unblockDomainSuccess } from "./domain_blocks_typed";
|
|
||||||
|
|
||||||
export * from "./domain_blocks_typed";
|
|
||||||
|
|
||||||
export const DOMAIN_BLOCK_REQUEST = 'DOMAIN_BLOCK_REQUEST';
|
export const DOMAIN_BLOCK_REQUEST = 'DOMAIN_BLOCK_REQUEST';
|
||||||
|
export const DOMAIN_BLOCK_SUCCESS = 'DOMAIN_BLOCK_SUCCESS';
|
||||||
export const DOMAIN_BLOCK_FAIL = 'DOMAIN_BLOCK_FAIL';
|
export const DOMAIN_BLOCK_FAIL = 'DOMAIN_BLOCK_FAIL';
|
||||||
|
|
||||||
export const DOMAIN_UNBLOCK_REQUEST = 'DOMAIN_UNBLOCK_REQUEST';
|
export const DOMAIN_UNBLOCK_REQUEST = 'DOMAIN_UNBLOCK_REQUEST';
|
||||||
|
export const DOMAIN_UNBLOCK_SUCCESS = 'DOMAIN_UNBLOCK_SUCCESS';
|
||||||
export const DOMAIN_UNBLOCK_FAIL = 'DOMAIN_UNBLOCK_FAIL';
|
export const DOMAIN_UNBLOCK_FAIL = 'DOMAIN_UNBLOCK_FAIL';
|
||||||
|
|
||||||
export const DOMAIN_BLOCKS_FETCH_REQUEST = 'DOMAIN_BLOCKS_FETCH_REQUEST';
|
export const DOMAIN_BLOCKS_FETCH_REQUEST = 'DOMAIN_BLOCKS_FETCH_REQUEST';
|
||||||
@@ -26,7 +24,7 @@ export function blockDomain(domain) {
|
|||||||
const at_domain = '@' + domain;
|
const at_domain = '@' + domain;
|
||||||
const accounts = getState().get('accounts').filter(item => item.get('acct').endsWith(at_domain)).valueSeq().map(item => item.get('id'));
|
const accounts = getState().get('accounts').filter(item => item.get('acct').endsWith(at_domain)).valueSeq().map(item => item.get('id'));
|
||||||
|
|
||||||
dispatch(blockDomainSuccess({ domain, accounts }));
|
dispatch(blockDomainSuccess(domain, accounts));
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
dispatch(blockDomainFail(domain, err));
|
dispatch(blockDomainFail(domain, err));
|
||||||
});
|
});
|
||||||
@@ -40,6 +38,14 @@ export function blockDomainRequest(domain) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function blockDomainSuccess(domain, accounts) {
|
||||||
|
return {
|
||||||
|
type: DOMAIN_BLOCK_SUCCESS,
|
||||||
|
domain,
|
||||||
|
accounts,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function blockDomainFail(domain, error) {
|
export function blockDomainFail(domain, error) {
|
||||||
return {
|
return {
|
||||||
type: DOMAIN_BLOCK_FAIL,
|
type: DOMAIN_BLOCK_FAIL,
|
||||||
@@ -55,7 +61,7 @@ export function unblockDomain(domain) {
|
|||||||
api(getState).delete('/api/v1/domain_blocks', { params: { domain } }).then(() => {
|
api(getState).delete('/api/v1/domain_blocks', { params: { domain } }).then(() => {
|
||||||
const at_domain = '@' + domain;
|
const at_domain = '@' + domain;
|
||||||
const accounts = getState().get('accounts').filter(item => item.get('acct').endsWith(at_domain)).valueSeq().map(item => item.get('id'));
|
const accounts = getState().get('accounts').filter(item => item.get('acct').endsWith(at_domain)).valueSeq().map(item => item.get('id'));
|
||||||
dispatch(unblockDomainSuccess({ domain, accounts }));
|
dispatch(unblockDomainSuccess(domain, accounts));
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
dispatch(unblockDomainFail(domain, err));
|
dispatch(unblockDomainFail(domain, err));
|
||||||
});
|
});
|
||||||
@@ -69,6 +75,14 @@ export function unblockDomainRequest(domain) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function unblockDomainSuccess(domain, accounts) {
|
||||||
|
return {
|
||||||
|
type: DOMAIN_UNBLOCK_SUCCESS,
|
||||||
|
domain,
|
||||||
|
accounts,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function unblockDomainFail(domain, error) {
|
export function unblockDomainFail(domain, error) {
|
||||||
return {
|
return {
|
||||||
type: DOMAIN_UNBLOCK_FAIL,
|
type: DOMAIN_UNBLOCK_FAIL,
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
import { createAction } from '@reduxjs/toolkit';
|
|
||||||
|
|
||||||
import type { Account } from 'flavours/glitch/models/account';
|
|
||||||
|
|
||||||
export const blockDomainSuccess = createAction<{
|
|
||||||
domain: string;
|
|
||||||
accounts: Account[];
|
|
||||||
}>('domain_blocks/block/SUCCESS');
|
|
||||||
|
|
||||||
export const unblockDomainSuccess = createAction<{
|
|
||||||
domain: string;
|
|
||||||
accounts: Account[];
|
|
||||||
}>('domain_blocks/unblock/SUCCESS');
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { importAccounts } from '../accounts_typed';
|
import { normalizeAccount, normalizeStatus, normalizePoll } from './normalizer';
|
||||||
|
|
||||||
import { normalizeStatus, normalizePoll } from './normalizer';
|
|
||||||
|
|
||||||
|
export const ACCOUNT_IMPORT = 'ACCOUNT_IMPORT';
|
||||||
|
export const ACCOUNTS_IMPORT = 'ACCOUNTS_IMPORT';
|
||||||
export const STATUS_IMPORT = 'STATUS_IMPORT';
|
export const STATUS_IMPORT = 'STATUS_IMPORT';
|
||||||
export const STATUSES_IMPORT = 'STATUSES_IMPORT';
|
export const STATUSES_IMPORT = 'STATUSES_IMPORT';
|
||||||
export const POLLS_IMPORT = 'POLLS_IMPORT';
|
export const POLLS_IMPORT = 'POLLS_IMPORT';
|
||||||
@@ -13,6 +13,14 @@ function pushUnique(array, object) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function importAccount(account) {
|
||||||
|
return { type: ACCOUNT_IMPORT, account };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function importAccounts(accounts) {
|
||||||
|
return { type: ACCOUNTS_IMPORT, accounts };
|
||||||
|
}
|
||||||
|
|
||||||
export function importStatus(status) {
|
export function importStatus(status) {
|
||||||
return { type: STATUS_IMPORT, status };
|
return { type: STATUS_IMPORT, status };
|
||||||
}
|
}
|
||||||
@@ -37,7 +45,7 @@ export function importFetchedAccounts(accounts) {
|
|||||||
const normalAccounts = [];
|
const normalAccounts = [];
|
||||||
|
|
||||||
function processAccount(account) {
|
function processAccount(account) {
|
||||||
pushUnique(normalAccounts, account);
|
pushUnique(normalAccounts, normalizeAccount(account));
|
||||||
|
|
||||||
if (account.moved) {
|
if (account.moved) {
|
||||||
processAccount(account.moved);
|
processAccount(account.moved);
|
||||||
@@ -46,7 +54,7 @@ export function importFetchedAccounts(accounts) {
|
|||||||
|
|
||||||
accounts.forEach(processAccount);
|
accounts.forEach(processAccount);
|
||||||
|
|
||||||
return importAccounts({ accounts: normalAccounts });
|
return importAccounts(normalAccounts);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function importFetchedStatus(status) {
|
export function importFetchedStatus(status) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import escapeTextContentForBrowser from 'escape-html';
|
|||||||
|
|
||||||
import emojify from '../../features/emoji/emoji';
|
import emojify from '../../features/emoji/emoji';
|
||||||
import { autoHideCW } from '../../utils/content_warning';
|
import { autoHideCW } from '../../utils/content_warning';
|
||||||
|
import { unescapeHTML } from '../../utils/html';
|
||||||
|
|
||||||
const domParser = new DOMParser();
|
const domParser = new DOMParser();
|
||||||
|
|
||||||
@@ -16,6 +17,32 @@ export function searchTextFromRawStatus (status) {
|
|||||||
return domParser.parseFromString(searchContent, 'text/html').documentElement.textContent;
|
return domParser.parseFromString(searchContent, 'text/html').documentElement.textContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function normalizeAccount(account) {
|
||||||
|
account = { ...account };
|
||||||
|
|
||||||
|
const emojiMap = makeEmojiMap(account.emojis);
|
||||||
|
const displayName = account.display_name.trim().length === 0 ? account.username : account.display_name;
|
||||||
|
|
||||||
|
account.display_name_html = emojify(escapeTextContentForBrowser(displayName), emojiMap);
|
||||||
|
account.note_emojified = emojify(account.note, emojiMap);
|
||||||
|
account.note_plain = unescapeHTML(account.note);
|
||||||
|
|
||||||
|
if (account.fields) {
|
||||||
|
account.fields = account.fields.map(pair => ({
|
||||||
|
...pair,
|
||||||
|
name_emojified: emojify(escapeTextContentForBrowser(pair.name), emojiMap),
|
||||||
|
value_emojified: emojify(pair.value, emojiMap),
|
||||||
|
value_plain: unescapeHTML(pair.value),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (account.moved) {
|
||||||
|
account.moved = account.moved.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return account;
|
||||||
|
}
|
||||||
|
|
||||||
export function normalizeFilterResult(result) {
|
export function normalizeFilterResult(result) {
|
||||||
const normalResult = { ...result };
|
const normalResult = { ...result };
|
||||||
|
|
||||||
|
|||||||
@@ -18,12 +18,10 @@ import {
|
|||||||
importFetchedStatuses,
|
importFetchedStatuses,
|
||||||
} from './importer';
|
} from './importer';
|
||||||
import { submitMarkers } from './markers';
|
import { submitMarkers } from './markers';
|
||||||
import { notificationsUpdate } from "./notifications_typed";
|
|
||||||
import { register as registerPushNotifications } from './push_notifications';
|
import { register as registerPushNotifications } from './push_notifications';
|
||||||
import { saveSettings } from './settings';
|
import { saveSettings } from './settings';
|
||||||
|
|
||||||
export * from "./notifications_typed";
|
export const NOTIFICATIONS_UPDATE = 'NOTIFICATIONS_UPDATE';
|
||||||
|
|
||||||
export const NOTIFICATIONS_UPDATE_NOOP = 'NOTIFICATIONS_UPDATE_NOOP';
|
export const NOTIFICATIONS_UPDATE_NOOP = 'NOTIFICATIONS_UPDATE_NOOP';
|
||||||
|
|
||||||
// tracking the notif cleaning request
|
// tracking the notif cleaning request
|
||||||
@@ -109,8 +107,12 @@ export function updateNotifications(notification, intlMessages, intlLocale) {
|
|||||||
dispatch(importFetchedAccount(notification.report.target_account));
|
dispatch(importFetchedAccount(notification.report.target_account));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dispatch({
|
||||||
dispatch(notificationsUpdate({ notification, preferPendingItems, playSound: playSound && !filtered}));
|
type: NOTIFICATIONS_UPDATE,
|
||||||
|
notification,
|
||||||
|
usePendingItems: preferPendingItems,
|
||||||
|
meta: (playSound && !filtered) ? { sound: 'boop' } : undefined,
|
||||||
|
});
|
||||||
|
|
||||||
fetchRelatedRelationships(dispatch, [notification]);
|
fetchRelatedRelationships(dispatch, [notification]);
|
||||||
} else if (playSound && !filtered) {
|
} else if (playSound && !filtered) {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user