Compare commits

..

23 commits

Author SHA1 Message Date
Essem
11900689bf
Use a consumer for identity 2024-04-10 17:44:26 -05:00
Essem
9b54b27bf7
Fix reaction picker dropdown appearance 2024-04-10 17:44:25 -05:00
Essem
40ae5aed66
Merge fixes 2024-04-10 17:44:25 -05:00
Essem
13c9fa62fa
Hydrate reactions on streaming API 2024-04-10 17:44:25 -05:00
Essem
ba37843ec2
Purge status reactions on account delete 2024-04-10 17:44:25 -05:00
Essem
b07f5f89d4
Fix rubocop lint issue 2024-04-10 17:44:25 -05:00
Essem
aae6e1b1fd
Refactor status reactions query
This was done to announcement reactions in 1b0cb3b54d. Might as well do it here too.
2024-04-10 17:44:25 -05:00
Essem
a12b2ad57a
Simplify reactions API controller 2024-04-10 17:44:25 -05:00
Essem
d54affc107
Update reaction emails
Reaction icon made by t3rminus@calamity.world
2024-04-10 17:44:24 -05:00
Essem
0d68ecf75d
Revert variant selector normalization
Probably worth tackling later, but for now it's not worth worrying about; some other implementations (e.g. Misskey's) look to have the same behavior anyways.
2024-04-10 17:44:24 -05:00
Essem
4311fff076
Move reaction normalization to API controller 2024-04-10 17:44:24 -05:00
Essem
a2ab3f541c
Quick fixes 2024-04-10 17:44:24 -05:00
Essem
11bebd28a2
Make name of like content parser function more general 2024-04-10 17:44:24 -05:00
Essem
09b64d761a
Normalize emojis with variant selectors 2024-04-10 17:44:24 -05:00
Essem
0838432237
Check for content attribute in Misskey likes 2024-04-10 17:44:24 -05:00
Essem
a27b838741
Fix rubocop complaint 2024-04-10 17:44:24 -05:00
Essem
4d832522b9
Add reaction notification column settings
This was in a previous PR. Not quite sure how it didn't carry over.
2024-04-10 17:44:23 -05:00
Essem
03ea7618ad
More cleanup 2024-04-10 17:44:23 -05:00
Essem
22fc82dfee
Linting fixes 2024-04-10 17:44:23 -05:00
Essem
938175d5e8
Refactor react services 2024-04-10 17:44:23 -05:00
Essem
28ecb2a4be
Fix reblog reactions 2024-04-10 17:44:23 -05:00
Essem
14c0e46ef4
Add notification emails for reactions 2024-04-10 17:44:23 -05:00
Essem
227a8d71b3
Add support for emoji reactions
Squashed, modified, and rebased from glitch-soc/mastodon#2221.

Co-authored-by: fef <owo@fef.moe>
Co-authored-by: Jeremy Kescher <jeremy@kescher.at>
Co-authored-by: neatchee <neatchee@gmail.com>
Co-authored-by: Ivan Rodriguez <104603218+IRod22@users.noreply.github.com>
Co-authored-by: Plastikmensch <plastikmensch@users.noreply.github.com>
2024-04-10 17:44:23 -05:00
960 changed files with 7046 additions and 25536 deletions

View file

@ -70,7 +70,7 @@ services:
hard: -1 hard: -1
libretranslate: libretranslate:
image: libretranslate/libretranslate:v1.5.7 image: libretranslate/libretranslate:v1.5.6
restart: unless-stopped restart: unless-stopped
volumes: volumes:
- lt-data:/home/libretranslate/.local - lt-data:/home/libretranslate/.local

View file

@ -1,4 +0,0 @@
# Required by ActiveRecord encryption feature
ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY=fkSxKD2bF396kdQbrP1EJ7WbU7ZgNokR
ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT=r0hvVmzBVsjxC7AMlwhOzmtc36ZCOS1E
ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY=PhdFyyfy5xJ7WVd2lWBpcPScRQHzRTNr

View file

@ -3,9 +3,3 @@ NODE_ENV=production
# Federation # Federation
LOCAL_DOMAIN=cb6e6126.ngrok.io LOCAL_DOMAIN=cb6e6126.ngrok.io
LOCAL_HTTPS=true LOCAL_HTTPS=true
# Secret values required by ActiveRecord encryption feature
# Use `bin/rails db:encryption:init` to generate fresh secrets
ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY=test_determinist_key_DO_NOT_USE_IN_PRODUCTION
ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT=test_salt_DO_NOT_USE_IN_PRODUCTION
ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY=test_primary_key_DO_NOT_USE_IN_PRODUCTION

View file

@ -380,7 +380,6 @@ module.exports = defineConfig({
"message": "Use typed hooks `useAppDispatch` and `useAppSelector` instead." "message": "Use typed hooks `useAppDispatch` and `useAppSelector` instead."
} }
], ],
"@typescript-eslint/restrict-template-expressions": ['warn', { allowNumber: true }],
'jsdoc/require-jsdoc': 'off', 'jsdoc/require-jsdoc': 'off',
// Those rules set stricter rules for TS files // Those rules set stricter rules for TS files

View file

@ -141,13 +141,6 @@
matchUpdateTypes: ['patch', 'minor'], matchUpdateTypes: ['patch', 'minor'],
groupName: 'RSpec (non-major)', groupName: 'RSpec (non-major)',
}, },
{
// Group all opentelemetry-ruby packages in the same PR
matchManagers: ['bundler'],
matchPackagePrefixes: ['opentelemetry-'],
matchUpdateTypes: ['patch', 'minor'],
groupName: 'opentelemetry-ruby (non-major)',
},
// Add labels depending on package manager // Add labels depending on package manager
{ matchManagers: ['npm', 'nvm'], addLabels: ['javascript'] }, { matchManagers: ['npm', 'nvm'], addLabels: ['javascript'] },
{ matchManagers: ['bundler', 'ruby-version'], addLabels: ['ruby'] }, { matchManagers: ['bundler', 'ruby-version'], addLabels: ['ruby'] },

21
.github/stylelint-matcher.json vendored Normal file
View file

@ -0,0 +1,21 @@
{
"problemMatcher": [
{
"owner": "stylelint",
"pattern": [
{
"regexp": "^([^\\s].*)$",
"file": 1
},
{
"regexp": "^\\s+((\\d+):(\\d+))?\\s+(✖|×)\\s+(.*)\\s{2,}(.*)$",
"line": 2,
"column": 3,
"message": 5,
"code": 6,
"loop": true
}
]
}
]
}

View file

@ -11,7 +11,7 @@ permissions:
jobs: jobs:
compute-suffix: compute-suffix:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.repository == 'TheEssem/mastodon' if: github.repository == 'glitch-soc/mastodon'
steps: steps:
- id: version_vars - id: version_vars
env: env:

View file

@ -53,7 +53,7 @@ jobs:
# Create or update the pull request # Create or update the pull request
- name: Create Pull Request - name: Create Pull Request
uses: peter-evans/create-pull-request@v6.0.5 uses: peter-evans/create-pull-request@v6.0.2
with: with:
commit-message: 'New Crowdin translations' commit-message: 'New Crowdin translations'
title: 'New Crowdin Translations (automated)' title: 'New Crowdin Translations (automated)'

View file

@ -38,5 +38,9 @@ jobs:
- name: Set up Javascript environment - name: Set up Javascript environment
uses: ./.github/actions/setup-javascript uses: ./.github/actions/setup-javascript
- uses: xt0rted/stylelint-problem-matcher@v1
- run: echo "::add-matcher::.github/stylelint-matcher.json"
- name: Stylelint - name: Stylelint
run: yarn lint:css -f github run: yarn lint:css

View file

@ -38,5 +38,5 @@ jobs:
- name: Set up Javascript environment - name: Set up Javascript environment
uses: ./.github/actions/setup-javascript uses: ./.github/actions/setup-javascript
- name: JavaScript testing - name: Jest testing
run: yarn jest --reporters github-actions summary run: yarn jest --reporters github-actions summary

View file

@ -28,9 +28,6 @@ jobs:
env: env:
RAILS_ENV: ${{ matrix.mode }} RAILS_ENV: ${{ matrix.mode }}
BUNDLE_WITH: ${{ matrix.mode }} BUNDLE_WITH: ${{ matrix.mode }}
ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY: precompile_placeholder
ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT: precompile_placeholder
ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY: precompile_placeholder
OTP_SECRET: precompile_placeholder OTP_SECRET: precompile_placeholder
SECRET_KEY_BASE: precompile_placeholder SECRET_KEY_BASE: precompile_placeholder
@ -114,9 +111,10 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
ruby-version: ruby-version:
- '3.0'
- '3.1' - '3.1'
- '3.2'
- '.ruby-version' - '.ruby-version'
- '3.3'
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@ -145,8 +143,6 @@ jobs:
uses: codecov/codecov-action@v4 uses: codecov/codecov-action@v4
with: with:
files: coverage/lcov/mastodon.lcov files: coverage/lcov/mastodon.lcov
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
test-e2e: test-e2e:
name: End to End testing name: End to End testing
@ -186,16 +182,15 @@ jobs:
DISABLE_SIMPLECOV: true DISABLE_SIMPLECOV: true
RAILS_ENV: test RAILS_ENV: test
BUNDLE_WITH: test BUNDLE_WITH: test
LOCAL_DOMAIN: localhost:3000
LOCAL_HTTPS: false
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
ruby-version: ruby-version:
- '3.0'
- '3.1' - '3.1'
- '3.2'
- '.ruby-version' - '.ruby-version'
- '3.3'
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@ -217,7 +212,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 spec/system --tag streaming --tag js - run: bundle exec rake spec:system
- name: Archive logs - name: Archive logs
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
@ -264,8 +259,8 @@ jobs:
ports: ports:
- 6379:6379 - 6379:6379
elasticsearch: search:
image: ${{ contains(matrix.search-image, 'elasticsearch') && matrix.search-image || '' }} image: ${{ matrix.search-image }}
env: env:
discovery.type: single-node discovery.type: single-node
xpack.security.enabled: false xpack.security.enabled: false
@ -277,20 +272,6 @@ jobs:
ports: ports:
- 9200:9200 - 9200:9200
opensearch:
image: ${{ contains(matrix.search-image, 'opensearch') && matrix.search-image || '' }}
env:
discovery.type: single-node
DISABLE_INSTALL_DEMO_CONFIG: true
DISABLE_SECURITY_PLUGIN: true
options: >-
--health-cmd "curl http://localhost:9200/_cluster/health"
--health-interval 10s
--health-timeout 5s
--health-retries 10
ports:
- 9200:9200
env: env:
DB_HOST: localhost DB_HOST: localhost
DB_USER: postgres DB_USER: postgres
@ -306,16 +287,15 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
ruby-version: ruby-version:
- '3.0'
- '3.1' - '3.1'
- '3.2'
- '.ruby-version' - '.ruby-version'
- '3.3'
search-image: search-image:
- docker.elastic.co/elasticsearch/elasticsearch:7.17.13 - docker.elastic.co/elasticsearch/elasticsearch:7.17.13
include: include:
- ruby-version: '.ruby-version' - ruby-version: '.ruby-version'
search-image: docker.elastic.co/elasticsearch/elasticsearch:8.10.2 search-image: docker.elastic.co/elasticsearch/elasticsearch:8.10.2
- ruby-version: '.ruby-version'
search-image: opensearchproject/opensearch:2
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4

4
.gitignore vendored
View file

@ -24,6 +24,7 @@
/public/packs-test /public/packs-test
.env .env
.env.production .env.production
.env.development
/node_modules/ /node_modules/
/build/ /build/
@ -68,6 +69,3 @@ yarn-debug.log
# Ignore Docker option files # Ignore Docker option files
docker-compose.override.yml docker-compose.override.yml
# Ignore dotenv .local files
.env*.local

View file

@ -1,5 +1,6 @@
exclude: exclude:
- 'vendor/**/*' - 'vendor/**/*'
- lib/templates/haml/scaffold/_form.html.haml
require: require:
- ./lib/linter/haml_middle_dot.rb - ./lib/linter/haml_middle_dot.rb
@ -10,6 +11,6 @@ linters:
MiddleDot: MiddleDot:
enabled: true enabled: true
LineLength: LineLength:
max: 300 max: 320
ViewLength: ViewLength:
max: 200 # Override default value of 100 inherited from rubocop max: 200 # Override default value of 100 inherited from rubocop

2
.nvmrc
View file

@ -1 +1 @@
20.13 20.11

View file

@ -96,8 +96,3 @@ app/javascript/flavours/glitch/styles/reset.scss
# Ignore win95 theme # Ignore win95 theme
app/javascript/styles/win95.scss app/javascript/styles/win95.scss
# Ignore mastomodern theme
app/javascript/styles/modern/style.scss
app/javascript/flavours/glitch/styles/modern/style.scss
app/javascript/flavours/glitch/styles/modern/glitch-fixes.scss

View file

@ -9,13 +9,12 @@ inherit_mode:
require: require:
- rubocop-rails - rubocop-rails
- rubocop-rspec - rubocop-rspec
- rubocop-rspec_rails
- rubocop-performance - rubocop-performance
- rubocop-capybara - rubocop-capybara
- ./lib/linter/rubocop_middle_dot - ./lib/linter/rubocop_middle_dot
AllCops: AllCops:
TargetRubyVersion: 3.1 # Set to minimum supported version of CI TargetRubyVersion: 3.0 # Set to minimum supported version of CI
DisplayCopNames: true DisplayCopNames: true
DisplayStyleGuide: true DisplayStyleGuide: true
ExtraDetails: true ExtraDetails: true
@ -40,7 +39,13 @@ Layout/FirstHashElementIndentation:
# Reason: Currently disabled in .rubocop_todo.yml # Reason: Currently disabled in .rubocop_todo.yml
# https://docs.rubocop.org/rubocop/cops_layout.html#layoutlinelength # https://docs.rubocop.org/rubocop/cops_layout.html#layoutlinelength
Layout/LineLength: Layout/LineLength:
Max: 300 # Default of 120 causes a duplicate entry in generated todo file Max: 320 # Default of 120 causes a duplicate entry in generated todo file
# Reason:
# https://docs.rubocop.org/rubocop/cops_lint.html#lintuselessaccessmodifier
Lint/UselessAccessModifier:
ContextCreatingMethods:
- class_methods
## Disable most Metrics/*Length cops ## Disable most Metrics/*Length cops
# Reason: those are often triggered and force significant refactors when this happend # Reason: those are often triggered and force significant refactors when this happend
@ -81,11 +86,6 @@ Metrics/CyclomaticComplexity:
Metrics/ParameterLists: Metrics/ParameterLists:
CountKeywordArgs: false CountKeywordArgs: false
# Reason: Prefer seeing a variable name
# https://docs.rubocop.org/rubocop/cops_naming.html#namingblockforwarding
Naming/BlockForwarding:
EnforcedStyle: explicit
# Reason: Prevailing style is argument file paths # Reason: Prevailing style is argument file paths
# https://docs.rubocop.org/rubocop-rails/cops_rails.html#railsfilepath # https://docs.rubocop.org/rubocop-rails/cops_rails.html#railsfilepath
Rails/FilePath: Rails/FilePath:
@ -148,6 +148,11 @@ RSpec/NamedSubject:
RSpec/NotToNot: RSpec/NotToNot:
EnforcedStyle: to_not EnforcedStyle: to_not
# Reason: Prevailing style uses numeric status codes, matches Rails/HttpStatus
# https://docs.rubocop.org/rubocop-rspec/cops_rspec_rails.html#rspecrailshttpstatus
RSpec/Rails/HttpStatus:
EnforcedStyle: numeric
# Reason: Match overrides from Rspec/FilePath rule above # Reason: Match overrides from Rspec/FilePath rule above
# https://docs.rubocop.org/rubocop-rspec/cops_rspec.html#rspecspecfilepathformat # https://docs.rubocop.org/rubocop-rspec/cops_rspec.html#rspecspecfilepathformat
RSpec/SpecFilePathFormat: RSpec/SpecFilePathFormat:
@ -158,11 +163,6 @@ RSpec/SpecFilePathFormat:
OEmbedController: oembed_controller OEmbedController: oembed_controller
OStatus: ostatus OStatus: ostatus
# Reason: Prevailing style uses numeric status codes, matches Rails/HttpStatus
# https://docs.rubocop.org/rubocop-rspec/cops_rspec_rails.html#rspecrailshttpstatus
RSpecRails/HttpStatus:
EnforcedStyle: numeric
# Reason: # Reason:
# https://docs.rubocop.org/rubocop/cops_style.html#styleclassandmodulechildren # https://docs.rubocop.org/rubocop/cops_style.html#styleclassandmodulechildren
Style/ClassAndModuleChildren: Style/ClassAndModuleChildren:
@ -182,16 +182,10 @@ Style/FormatStringToken:
AllowedMethods: AllowedMethods:
- redirect_with_vary - redirect_with_vary
# Reason: Prevailing style choice
# https://docs.rubocop.org/rubocop/cops_style.html#stylehashaslastarrayitem
Style/HashAsLastArrayItem:
Enabled: false
# Reason: Enforce modern Ruby style # Reason: Enforce modern Ruby style
# https://docs.rubocop.org/rubocop/cops_style.html#stylehashsyntax # https://docs.rubocop.org/rubocop/cops_style.html#stylehashsyntax
Style/HashSyntax: Style/HashSyntax:
EnforcedStyle: ruby19_no_mixed_keys EnforcedStyle: ruby19_no_mixed_keys
EnforcedShorthandSyntax: either
# Reason: # Reason:
# https://docs.rubocop.org/rubocop/cops_style.html#stylenumericliterals # https://docs.rubocop.org/rubocop/cops_style.html#stylenumericliterals
@ -211,11 +205,6 @@ Style/PercentLiteralDelimiters:
Style/RedundantBegin: Style/RedundantBegin:
Enabled: false Enabled: false
# Reason: Prevailing style choice
# https://docs.rubocop.org/rubocop/cops_style.html#styleredundantfetchblock
Style/RedundantFetchBlock:
Enabled: false
# Reason: Overridden to reduce implicit StandardError rescues # Reason: Overridden to reduce implicit StandardError rescues
# https://docs.rubocop.org/rubocop/cops_style.html#stylerescuestandarderror # https://docs.rubocop.org/rubocop/cops_style.html#stylerescuestandarderror
Style/RescueStandardError: Style/RescueStandardError:

View file

@ -1,11 +1,18 @@
# This configuration was generated by # This configuration was generated by
# `rubocop --auto-gen-config --auto-gen-only-exclude --no-exclude-limit --no-offense-counts --no-auto-gen-timestamp` # `rubocop --auto-gen-config --auto-gen-only-exclude --no-exclude-limit --no-offense-counts --no-auto-gen-timestamp`
# using RuboCop version 1.63.5. # using RuboCop version 1.60.2.
# The point is for the user to remove these configuration records # The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base. # one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new # Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again. # versions of RuboCop, may require this file to be generated again.
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation, Include.
# Include: **/*.gemfile, **/Gemfile, **/gems.rb
Bundler/OrderedGems:
Exclude:
- 'Gemfile'
Lint/NonLocalExitFromIterator: Lint/NonLocalExitFromIterator:
Exclude: Exclude:
- 'app/helpers/jsonld_helper.rb' - 'app/helpers/jsonld_helper.rb'
@ -29,7 +36,7 @@ Metrics/PerceivedComplexity:
# Configuration parameters: CountAsOne. # Configuration parameters: CountAsOne.
RSpec/ExampleLength: RSpec/ExampleLength:
Max: 18 Max: 20 # Override default of 5
RSpec/MultipleExpectations: RSpec/MultipleExpectations:
Max: 7 Max: 7
@ -42,10 +49,27 @@ RSpec/MultipleMemoizedHelpers:
RSpec/NestedGroups: RSpec/NestedGroups:
Max: 6 Max: 6
# Configuration parameters: Include.
# Include: app/models/**/*.rb
Rails/HasAndBelongsToMany:
Exclude:
- 'app/models/concerns/account/associations.rb'
- 'app/models/status.rb'
- 'app/models/tag.rb'
Rails/OutputSafety: Rails/OutputSafety:
Exclude: Exclude:
- 'config/initializers/simple_form.rb' - 'config/initializers/simple_form.rb'
# Configuration parameters: Include.
# Include: app/models/**/*.rb
Rails/UniqueValidationWithoutIndex:
Exclude:
- 'app/models/account_alias.rb'
- 'app/models/custom_filter_status.rb'
- 'app/models/identity.rb'
- 'app/models/webauthn_credential.rb'
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: AllowedMethods, AllowedPatterns. # Configuration parameters: AllowedMethods, AllowedPatterns.
# AllowedMethods: ==, equal?, eql? # AllowedMethods: ==, equal?, eql?
@ -54,12 +78,17 @@ Style/ClassEqualityComparison:
- 'app/helpers/jsonld_helper.rb' - 'app/helpers/jsonld_helper.rb'
- 'app/serializers/activitypub/outbox_serializer.rb' - 'app/serializers/activitypub/outbox_serializer.rb'
Style/ClassVars:
Exclude:
- 'config/initializers/devise.rb'
# This cop supports safe autocorrection (--autocorrect). # This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AllowedVars. # Configuration parameters: AllowedVars.
Style/FetchEnvVar: Style/FetchEnvVar:
Exclude: Exclude:
- 'app/lib/redis_configuration.rb' - 'app/lib/redis_configuration.rb'
- 'app/lib/translation_service.rb' - 'app/lib/translation_service.rb'
- 'config/environments/development.rb'
- 'config/environments/production.rb' - 'config/environments/production.rb'
- 'config/initializers/2_limited_federation_mode.rb' - 'config/initializers/2_limited_federation_mode.rb'
- 'config/initializers/3_omniauth.rb' - 'config/initializers/3_omniauth.rb'
@ -69,8 +98,9 @@ Style/FetchEnvVar:
- 'config/initializers/paperclip.rb' - 'config/initializers/paperclip.rb'
- 'config/initializers/vapid.rb' - 'config/initializers/vapid.rb'
- 'lib/mastodon/redis_config.rb' - 'lib/mastodon/redis_config.rb'
- 'lib/premailer_webpack_strategy.rb'
- 'lib/tasks/repo.rake' - 'lib/tasks/repo.rake'
- 'spec/system/profile_spec.rb' - 'spec/features/profile_spec.rb'
# This cop supports safe autocorrection (--autocorrect). # This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle, MaxUnannotatedPlaceholdersAllowed, AllowedMethods, AllowedPatterns. # Configuration parameters: EnforcedStyle, MaxUnannotatedPlaceholdersAllowed, AllowedMethods, AllowedPatterns.
@ -114,14 +144,35 @@ Style/GuardClause:
- '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'
- 'lib/paperclip/attachment_extensions.rb'
- 'lib/tasks/repo.rake' - 'lib/tasks/repo.rake'
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: braces, no_braces
Style/HashAsLastArrayItem:
Exclude:
- 'app/controllers/admin/statuses_controller.rb'
- 'app/controllers/api/v1/statuses_controller.rb'
- 'app/models/concerns/account/counters.rb'
- 'app/models/concerns/status/threading_concern.rb'
- 'app/models/status.rb'
- 'app/services/batched_remove_status_service.rb'
- 'app/services/notify_service.rb'
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
Style/HashTransformValues: Style/HashTransformValues:
Exclude: Exclude:
- 'app/serializers/rest/web_push_subscription_serializer.rb' - 'app/serializers/rest/web_push_subscription_serializer.rb'
- 'app/services/import_service.rb' - 'app/services/import_service.rb'
# This cop supports safe autocorrection (--autocorrect).
Style/IfUnlessModifier:
Exclude:
- 'config/environments/production.rb'
- 'config/initializers/devise.rb'
- 'config/initializers/ffmpeg.rb'
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
Style/MapToHash: Style/MapToHash:
Exclude: Exclude:
@ -156,6 +207,13 @@ Style/OptionalBooleanParameter:
- 'app/workers/unfollow_follow_worker.rb' - 'app/workers/unfollow_follow_worker.rb'
- 'lib/mastodon/redis_config.rb' - 'lib/mastodon/redis_config.rb'
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: PreferredDelimiters.
Style/PercentLiteralDelimiters:
Exclude:
- 'config/deploy.rb'
- 'config/initializers/doorkeeper.rb'
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: EnforcedStyle. # Configuration parameters: EnforcedStyle.
# SupportedStyles: short, verbose # SupportedStyles: short, verbose
@ -169,6 +227,16 @@ Style/RedundantConstantBase:
- 'config/environments/production.rb' - 'config/environments/production.rb'
- 'config/initializers/sidekiq.rb' - 'config/initializers/sidekiq.rb'
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: SafeForConstants.
Style/RedundantFetchBlock:
Exclude:
- 'config/initializers/1_hosts.rb'
- 'config/initializers/chewy.rb'
- 'config/initializers/devise.rb'
- 'config/initializers/paperclip.rb'
- 'config/puma.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!
@ -176,12 +244,52 @@ Style/SafeNavigation:
Exclude: Exclude:
- 'app/models/concerns/account/finder_concern.rb' - 'app/models/concerns/account/finder_concern.rb'
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: only_raise, only_fail, semantic
Style/SignalException:
Exclude:
- 'lib/devise/strategies/two_factor_ldap_authenticatable.rb'
- 'lib/devise/strategies/two_factor_pam_authenticatable.rb'
# This cop supports unsafe autocorrection (--autocorrect-all).
Style/SingleArgumentDig:
Exclude:
- 'lib/webpacker/manifest_extensions.rb'
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: Mode. # Configuration parameters: Mode.
Style/StringConcatenation: Style/StringConcatenation:
Exclude: Exclude:
- 'config/initializers/paperclip.rb' - 'config/initializers/paperclip.rb'
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline.
# SupportedStyles: single_quotes, double_quotes
Style/StringLiterals:
Exclude:
- 'config/environments/production.rb'
- 'config/initializers/backtrace_silencers.rb'
- 'config/initializers/http_client_proxy.rb'
- 'config/initializers/rack_attack.rb'
- 'config/initializers/webauthn.rb'
- 'config/routes.rb'
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyleForMultiline.
# SupportedStylesForMultiline: comma, consistent_comma, no_comma
Style/TrailingCommaInArguments:
Exclude:
- 'config/initializers/paperclip.rb'
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyleForMultiline.
# SupportedStylesForMultiline: comma, consistent_comma, no_comma
Style/TrailingCommaInHashLiteral:
Exclude:
- 'config/environments/production.rb'
- 'config/environments/test.rb'
# This cop supports safe autocorrection (--autocorrect). # This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: WordRegex. # Configuration parameters: WordRegex.
# SupportedStyles: percent, brackets # SupportedStyles: percent, brackets

View file

@ -1 +1 @@
3.3.1 3.2.3

22
.simplecov Normal file
View file

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

View file

@ -1,23 +0,0 @@
---
include:
- '**/*.rb'
exclude:
- spec/**/*
- test/**/*
- vendor/**/*
- '.bundle/**/*'
require: []
domains: []
reporters:
- rubocop
- require_not_found
formatter:
rubocop:
cops: safe
except: []
only: []
extra_args: []
require_paths: []
plugins:
- solargraph-rails
max_files: 5000

View file

@ -1,4 +1,4 @@
# syntax=docker/dockerfile:1.7 # syntax=docker/dockerfile:1.4
# Please see https://docs.docker.com/engine/reference/builder for information about # Please see https://docs.docker.com/engine/reference/builder for information about
# the extended buildx capabilities used in this file. # the extended buildx capabilities used in this file.
@ -7,15 +7,15 @@
ARG TARGETPLATFORM=${TARGETPLATFORM} ARG TARGETPLATFORM=${TARGETPLATFORM}
ARG BUILDPLATFORM=${BUILDPLATFORM} ARG BUILDPLATFORM=${BUILDPLATFORM}
# Ruby image to use for base image, change with [--build-arg RUBY_VERSION="3.3.1"] # Ruby image to use for base image, change with [--build-arg RUBY_VERSION="3.2.3"]
ARG RUBY_VERSION="3.3.1" ARG RUBY_VERSION="3.2.3"
# # Node version to use in base image, change with [--build-arg NODE_MAJOR_VERSION="20"] # # Node version to use in base image, change with [--build-arg NODE_MAJOR_VERSION="20"]
ARG NODE_MAJOR_VERSION="20" ARG NODE_MAJOR_VERSION="20"
# Debian image to use for base image, change with [--build-arg DEBIAN_VERSION="bookworm"] # Debian image to use for base image, change with [--build-arg DEBIAN_VERSION="bookworm"]
ARG DEBIAN_VERSION="bookworm" ARG DEBIAN_VERSION="bookworm"
# Node image to use for base image based on combined variables (ex: 20-bookworm-slim) # Node image to use for base image based on combined variables (ex: 20-bookworm-slim)
FROM docker.io/node:${NODE_MAJOR_VERSION}-${DEBIAN_VERSION}-slim as node FROM docker.io/node:${NODE_MAJOR_VERSION}-${DEBIAN_VERSION}-slim as node
# Ruby image to use for base image based on combined variables (ex: 3.3.1-slim-bookworm) # Ruby image to use for base image based on combined variables (ex: 3.2.3-slim-bookworm)
FROM docker.io/ruby:${RUBY_VERSION}-slim-${DEBIAN_VERSION} as ruby FROM docker.io/ruby:${RUBY_VERSION}-slim-${DEBIAN_VERSION} as ruby
# Resulting version string is vX.X.X-MASTODON_VERSION_PRERELEASE+MASTODON_VERSION_METADATA # Resulting version string is vX.X.X-MASTODON_VERSION_PRERELEASE+MASTODON_VERSION_METADATA
@ -29,7 +29,7 @@ ARG MASTODON_VERSION_METADATA=""
# See: https://docs.joinmastodon.org/admin/config/#rails_serve_static_files # See: https://docs.joinmastodon.org/admin/config/#rails_serve_static_files
ARG RAILS_SERVE_STATIC_FILES="true" ARG RAILS_SERVE_STATIC_FILES="true"
# Allow to use YJIT compiler # Allow to use YJIT compiler
# See: https://github.com/ruby/ruby/blob/v3_2_4/doc/yjit/yjit.md # See: https://github.com/ruby/ruby/blob/v3_2_3/doc/yjit/yjit.md
ARG RUBY_YJIT_ENABLE="1" ARG RUBY_YJIT_ENABLE="1"
# Timezone used by the Docker container and runtime, change with [--build-arg TZ=Europe/Berlin] # Timezone used by the Docker container and runtime, change with [--build-arg TZ=Europe/Berlin]
ARG TZ="Etc/UTC" ARG TZ="Etc/UTC"
@ -205,12 +205,7 @@ ARG TARGETPLATFORM
RUN \ RUN \
# Use Ruby on Rails to create Mastodon assets # Use Ruby on Rails to create Mastodon assets
ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY=precompile_placeholder \ OTP_SECRET=precompile_placeholder SECRET_KEY_BASE=precompile_placeholder bundle exec rails assets:precompile; \
ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT=precompile_placeholder \
ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY=precompile_placeholder \
OTP_SECRET=precompile_placeholder \
SECRET_KEY_BASE=precompile_placeholder \
bundle exec rails assets:precompile; \
# Cleanup temporary files # Cleanup temporary files
rm -fr /opt/mastodon/tmp; rm -fr /opt/mastodon/tmp;
@ -262,4 +257,4 @@ USER mastodon
# Expose default Puma ports # Expose default Puma ports
EXPOSE 3000 EXPOSE 3000
# Set container tini as default entry point # Set container tini as default entry point
ENTRYPOINT ["/usr/bin/tini", "--"] ENTRYPOINT ["/usr/bin/tini", "--"]

66
Gemfile
View file

@ -1,37 +1,37 @@
# frozen_string_literal: true # frozen_string_literal: true
source 'https://rubygems.org' source 'https://rubygems.org'
ruby '>= 3.1.0' ruby '>= 3.0.0'
gem 'propshaft'
gem 'puma', '~> 6.3' gem 'puma', '~> 6.3'
gem 'rack', '~> 2.2.7'
gem 'rails', '~> 7.1.1' gem 'rails', '~> 7.1.1'
gem 'propshaft'
gem 'thor', '~> 1.2' gem 'thor', '~> 1.2'
gem 'rack', '~> 2.2.7'
# For why irb is in the Gemfile, see: https://ruby.social/@st0012/111444685161478182 # For why irb is in the Gemfile, see: https://ruby.social/@st0012/111444685161478182
gem 'irb', '~> 1.8' gem 'irb', '~> 1.8'
gem 'dotenv'
gem 'haml-rails', '~>2.0' gem 'haml-rails', '~>2.0'
gem 'pg', '~> 1.5' gem 'pg', '~> 1.5'
gem 'pghero' gem 'pghero'
gem 'dotenv-rails', '~> 2.8'
gem 'aws-sdk-s3', '~> 1.123', require: false gem 'aws-sdk-s3', '~> 1.123', require: false
gem 'blurhash', '~> 0.1'
gem 'fog-core', '<= 2.4.0' gem 'fog-core', '<= 2.4.0'
gem 'fog-openstack', '~> 1.0', require: false gem 'fog-openstack', '~> 1.0', require: false
gem 'kt-paperclip', '~> 7.2' gem 'kt-paperclip', '~> 7.2'
gem 'md-paperclip-azure', '~> 2.2', require: false gem 'md-paperclip-azure', '~> 2.2', require: false
gem 'blurhash', '~> 0.1'
gem 'active_model_serializers', '~> 0.10' gem 'active_model_serializers', '~> 0.10'
gem 'addressable', '~> 2.8' gem 'addressable', '~> 2.8'
gem 'bootsnap', '~> 1.18.0', require: false gem 'bootsnap', '~> 1.18.0', require: false
gem 'browser' gem 'browser'
gem 'charlock_holmes', github: 'TheEssem/charlock_holmes', ref: '226932af4b03eb60d2e31d58b6c3efd72a3ace68' gem 'charlock_holmes', '~> 0.7.7'
gem 'chewy', '~> 7.3' gem 'chewy', '~> 7.3'
gem 'devise', '~> 4.9' gem 'devise', '~> 4.9'
gem 'devise-two-factor' gem 'devise-two-factor', '~> 4.1'
group :pam_authentication, optional: true do group :pam_authentication, optional: true do
gem 'devise_pam_authenticatable2', '~> 9.2' gem 'devise_pam_authenticatable2', '~> 9.2'
@ -39,11 +39,11 @@ end
gem 'net-ldap', '~> 0.18' gem 'net-ldap', '~> 0.18'
gem 'omniauth', '~> 2.0'
gem 'omniauth-cas', '~> 3.0.0.beta.1' gem 'omniauth-cas', '~> 3.0.0.beta.1'
gem 'omniauth_openid_connect', '~> 0.6.1'
gem 'omniauth-rails_csrf_protection', '~> 1.0'
gem 'omniauth-saml', '~> 2.0' gem 'omniauth-saml', '~> 2.0'
gem 'omniauth_openid_connect', '~> 0.6.1'
gem 'omniauth', '~> 2.0'
gem 'omniauth-rails_csrf_protection', '~> 1.0'
gem 'color_diff', '~> 0.1' gem 'color_diff', '~> 0.1'
gem 'csv', '~> 3.2' gem 'csv', '~> 3.2'
@ -53,49 +53,50 @@ gem 'ed25519', '~> 1.3'
gem 'fast_blank', '~> 1.0' gem 'fast_blank', '~> 1.0'
gem 'fastimage' gem 'fastimage'
gem 'hiredis', '~> 0.6' gem 'hiredis', '~> 0.6'
gem 'redis-namespace', '~> 1.10'
gem 'htmlentities', '~> 4.3' gem 'htmlentities', '~> 4.3'
gem 'http', '~> 5.2.0' gem 'http', '~> 5.1'
gem 'http_accept_language', '~> 2.1' gem 'http_accept_language', '~> 2.1'
gem 'httplog', '~> 1.6.2' gem 'httplog', '~> 1.6.2'
gem 'i18n' gem 'i18n', '1.14.1' # TODO: Remove version when resolved: https://github.com/glebm/i18n-tasks/issues/552 / https://github.com/ruby-i18n/i18n/pull/688
gem 'idn-ruby', require: 'idn' gem 'idn-ruby', require: 'idn'
gem 'inline_svg' gem 'inline_svg'
gem 'kaminari', '~> 1.2' gem 'kaminari', '~> 1.2'
gem 'link_header', '~> 0.0' gem 'link_header', '~> 0.0'
gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock'
gem 'mime-types', '~> 3.5.0', require: 'mime/types/columnar' gem 'mime-types', '~> 3.5.0', require: 'mime/types/columnar'
gem 'nokogiri', '~> 1.15' gem 'nokogiri', '~> 1.15'
gem 'nsa' gem 'nsa'
gem 'oj', '~> 3.14' gem 'oj', '~> 3.14'
gem 'ox', '~> 2.14' gem 'ox', '~> 2.14'
gem 'parslet' gem 'parslet'
gem 'premailer-rails' gem 'posix-spawn'
gem 'public_suffix', '~> 5.0' gem 'public_suffix', '~> 5.0'
gem 'pundit', '~> 2.3' gem 'pundit', '~> 2.3'
gem 'premailer-rails'
gem 'rack-attack', '~> 6.6' gem 'rack-attack', '~> 6.6'
gem 'rack-cors', '~> 2.0', require: 'rack/cors' gem 'rack-cors', '~> 2.0', require: 'rack/cors'
gem 'rails-i18n', '~> 7.0' gem 'rails-i18n', '~> 7.0'
gem 'redcarpet', '~> 3.6' gem 'redcarpet', '~> 3.6'
gem 'redis', '~> 4.5', require: ['redis', 'redis/connection/hiredis'] gem 'redis', '~> 4.5', require: ['redis', 'redis/connection/hiredis']
gem 'redis-namespace', '~> 1.10' gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock'
gem 'rqrcode', '~> 2.2' gem 'rqrcode', '~> 2.2'
gem 'ruby-progressbar', '~> 1.13' gem 'ruby-progressbar', '~> 1.13'
gem 'sanitize', '~> 6.0' gem 'sanitize', '~> 6.0'
gem 'scenic', '~> 1.7' gem 'scenic', '~> 1.7'
gem 'sidekiq', '~> 6.5' gem 'sidekiq', '~> 6.5'
gem 'sidekiq-bulk', '~> 0.2.0'
gem 'sidekiq-scheduler', '~> 5.0' gem 'sidekiq-scheduler', '~> 5.0'
gem 'sidekiq-unique-jobs', '~> 7.1' gem 'sidekiq-unique-jobs', '~> 7.1'
gem 'simple_form', '~> 5.2' gem 'sidekiq-bulk', '~> 0.2.0'
gem 'simple-navigation', '~> 4.4' gem 'simple-navigation', '~> 4.4'
gem 'stoplight', '~> 4.1' gem 'simple_form', '~> 5.2'
gem 'stoplight', '~> 3.0.1'
gem 'strong_migrations', '1.8.0' gem 'strong_migrations', '1.8.0'
gem 'tty-prompt', '~> 0.23', require: false gem 'tty-prompt', '~> 0.23', require: false
gem 'twitter-text', '~> 3.1.0' gem 'twitter-text', '~> 3.1.0'
gem 'tzinfo-data', '~> 1.2023' gem 'tzinfo-data', '~> 1.2023'
gem 'webauthn', '~> 3.0'
gem 'webpacker', '~> 5.4' gem 'webpacker', '~> 5.4'
gem 'webpush', github: 'ClearlyClaire/webpush', ref: 'f14a4d52e201128b1b00245d11b6de80d6cfdcd9' gem 'webpush', github: 'ClearlyClaire/webpush', ref: 'f14a4d52e201128b1b00245d11b6de80d6cfdcd9'
gem 'webauthn', '~> 3.0'
gem 'json-ld' gem 'json-ld'
gem 'json-ld-preloaded', '~> 3.2' gem 'json-ld-preloaded', '~> 3.2'
@ -103,24 +104,6 @@ gem 'rdf-normalize', '~> 0.5'
gem 'private_address_check', '~> 0.5' gem 'private_address_check', '~> 0.5'
group :opentelemetry do
gem 'opentelemetry-exporter-otlp', '~> 0.26.3', require: false
gem 'opentelemetry-instrumentation-active_job', '~> 0.7.1', require: false
gem 'opentelemetry-instrumentation-active_model_serializers', '~> 0.20.1', require: false
gem 'opentelemetry-instrumentation-concurrent_ruby', '~> 0.21.2', require: false
gem 'opentelemetry-instrumentation-excon', '~> 0.22.0', require: false
gem 'opentelemetry-instrumentation-faraday', '~> 0.24.1', require: false
gem 'opentelemetry-instrumentation-http', '~> 0.23.2', require: false
gem 'opentelemetry-instrumentation-http_client', '~> 0.22.3', require: false
gem 'opentelemetry-instrumentation-net_http', '~> 0.22.4', require: false
gem 'opentelemetry-instrumentation-pg', '~> 0.27.1', require: false
gem 'opentelemetry-instrumentation-rack', '~> 0.24.1', require: false
gem 'opentelemetry-instrumentation-rails', '~> 0.30.0', require: false
gem 'opentelemetry-instrumentation-redis', '~> 0.25.3', require: false
gem 'opentelemetry-instrumentation-sidekiq', '~> 0.25.2', require: false
gem 'opentelemetry-sdk', '~> 1.4', require: false
end
group :test do group :test do
# Adds RSpec Error/Warning annotations to GitHub PRs on the Files tab # Adds RSpec Error/Warning annotations to GitHub PRs on the Files tab
gem 'rspec-github', '~> 2.4', require: false gem 'rspec-github', '~> 2.4', require: false
@ -132,7 +115,7 @@ group :test do
gem 'email_spec' gem 'email_spec'
# Extra RSpec extension methods and helpers for sidekiq # Extra RSpec extension methods and helpers for sidekiq
gem 'rspec-sidekiq', '~> 5.0' gem 'rspec-sidekiq', '~> 4.0'
# Browser integration testing # Browser integration testing
gem 'capybara', '~> 3.39' gem 'capybara', '~> 3.39'
@ -178,7 +161,7 @@ group :development do
# Preview mail in the browser # Preview mail in the browser
gem 'letter_opener', '~> 1.8' gem 'letter_opener', '~> 1.8'
gem 'letter_opener_web', '~> 3.0' gem 'letter_opener_web', '~> 2.0'
# Security analysis CLI tools # Security analysis CLI tools
gem 'brakeman', '~> 6.0', require: false gem 'brakeman', '~> 6.0', require: false
@ -215,14 +198,13 @@ group :production do
gem 'lograge', '~> 0.12' gem 'lograge', '~> 0.12'
end end
gem 'cocoon', '~> 1.2'
gem 'concurrent-ruby', require: false gem 'concurrent-ruby', require: false
gem 'connection_pool', require: false gem 'connection_pool', require: false
gem 'xorcist', '~> 1.1' gem 'xorcist', '~> 1.1'
gem 'cocoon', '~> 1.2'
gem 'net-http', '~> 0.4.0' gem 'net-http', '~> 0.4.0'
gem 'rubyzip', '~> 2.3' gem 'rubyzip', '~> 2.3'
gem 'hcaptcha', '~> 7.1' gem 'hcaptcha', '~> 7.1'
gem 'mail', '~> 2.8'

View file

@ -7,45 +7,38 @@ GIT
hkdf (~> 0.2) hkdf (~> 0.2)
jwt (~> 2.0) jwt (~> 2.0)
GIT
remote: https://github.com/TheEssem/charlock_holmes.git
revision: 226932af4b03eb60d2e31d58b6c3efd72a3ace68
ref: 226932af4b03eb60d2e31d58b6c3efd72a3ace68
specs:
charlock_holmes (0.7.7)
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
actioncable (7.1.3.3) actioncable (7.1.3.2)
actionpack (= 7.1.3.3) actionpack (= 7.1.3.2)
activesupport (= 7.1.3.3) activesupport (= 7.1.3.2)
nio4r (~> 2.0) nio4r (~> 2.0)
websocket-driver (>= 0.6.1) websocket-driver (>= 0.6.1)
zeitwerk (~> 2.6) zeitwerk (~> 2.6)
actionmailbox (7.1.3.3) actionmailbox (7.1.3.2)
actionpack (= 7.1.3.3) actionpack (= 7.1.3.2)
activejob (= 7.1.3.3) activejob (= 7.1.3.2)
activerecord (= 7.1.3.3) activerecord (= 7.1.3.2)
activestorage (= 7.1.3.3) activestorage (= 7.1.3.2)
activesupport (= 7.1.3.3) activesupport (= 7.1.3.2)
mail (>= 2.7.1) mail (>= 2.7.1)
net-imap net-imap
net-pop net-pop
net-smtp net-smtp
actionmailer (7.1.3.3) actionmailer (7.1.3.2)
actionpack (= 7.1.3.3) actionpack (= 7.1.3.2)
actionview (= 7.1.3.3) actionview (= 7.1.3.2)
activejob (= 7.1.3.3) activejob (= 7.1.3.2)
activesupport (= 7.1.3.3) activesupport (= 7.1.3.2)
mail (~> 2.5, >= 2.5.4) mail (~> 2.5, >= 2.5.4)
net-imap net-imap
net-pop net-pop
net-smtp net-smtp
rails-dom-testing (~> 2.2) rails-dom-testing (~> 2.2)
actionpack (7.1.3.3) actionpack (7.1.3.2)
actionview (= 7.1.3.3) actionview (= 7.1.3.2)
activesupport (= 7.1.3.3) activesupport (= 7.1.3.2)
nokogiri (>= 1.8.5) nokogiri (>= 1.8.5)
racc racc
rack (>= 2.2.4) rack (>= 2.2.4)
@ -53,15 +46,15 @@ GEM
rack-test (>= 0.6.3) rack-test (>= 0.6.3)
rails-dom-testing (~> 2.2) rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6) rails-html-sanitizer (~> 1.6)
actiontext (7.1.3.3) actiontext (7.1.3.2)
actionpack (= 7.1.3.3) actionpack (= 7.1.3.2)
activerecord (= 7.1.3.3) activerecord (= 7.1.3.2)
activestorage (= 7.1.3.3) activestorage (= 7.1.3.2)
activesupport (= 7.1.3.3) activesupport (= 7.1.3.2)
globalid (>= 0.6.0) globalid (>= 0.6.0)
nokogiri (>= 1.8.5) nokogiri (>= 1.8.5)
actionview (7.1.3.3) actionview (7.1.3.2)
activesupport (= 7.1.3.3) activesupport (= 7.1.3.2)
builder (~> 3.1) builder (~> 3.1)
erubi (~> 1.11) erubi (~> 1.11)
rails-dom-testing (~> 2.2) rails-dom-testing (~> 2.2)
@ -71,22 +64,22 @@ GEM
activemodel (>= 4.1) activemodel (>= 4.1)
case_transform (>= 0.2) case_transform (>= 0.2)
jsonapi-renderer (>= 0.1.1.beta1, < 0.3) jsonapi-renderer (>= 0.1.1.beta1, < 0.3)
activejob (7.1.3.3) activejob (7.1.3.2)
activesupport (= 7.1.3.3) activesupport (= 7.1.3.2)
globalid (>= 0.3.6) globalid (>= 0.3.6)
activemodel (7.1.3.3) activemodel (7.1.3.2)
activesupport (= 7.1.3.3) activesupport (= 7.1.3.2)
activerecord (7.1.3.3) activerecord (7.1.3.2)
activemodel (= 7.1.3.3) activemodel (= 7.1.3.2)
activesupport (= 7.1.3.3) activesupport (= 7.1.3.2)
timeout (>= 0.4.0) timeout (>= 0.4.0)
activestorage (7.1.3.3) activestorage (7.1.3.2)
actionpack (= 7.1.3.3) actionpack (= 7.1.3.2)
activejob (= 7.1.3.3) activejob (= 7.1.3.2)
activerecord (= 7.1.3.3) activerecord (= 7.1.3.2)
activesupport (= 7.1.3.3) activesupport (= 7.1.3.2)
marcel (~> 1.0) marcel (~> 1.0)
activesupport (7.1.3.3) activesupport (7.1.3.2)
base64 base64
bigdecimal bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2) concurrent-ruby (~> 1.0, >= 1.0.2)
@ -104,20 +97,22 @@ GEM
activerecord (>= 3.2, < 8.0) activerecord (>= 3.2, < 8.0)
rake (>= 10.4, < 14.0) rake (>= 10.4, < 14.0)
ast (2.4.2) ast (2.4.2)
attr_required (1.0.2) attr_encrypted (4.0.0)
encryptor (~> 3.0.0)
attr_required (1.0.1)
awrence (1.2.1) awrence (1.2.1)
aws-eventstream (1.3.0) aws-eventstream (1.3.0)
aws-partitions (1.929.0) aws-partitions (1.873.0)
aws-sdk-core (3.196.1) aws-sdk-core (3.190.1)
aws-eventstream (~> 1, >= 1.3.0) aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.651.0) aws-partitions (~> 1, >= 1.651.0)
aws-sigv4 (~> 1.8) aws-sigv4 (~> 1.8)
jmespath (~> 1, >= 1.6.1) jmespath (~> 1, >= 1.6.1)
aws-sdk-kms (1.81.0) aws-sdk-kms (1.75.0)
aws-sdk-core (~> 3, >= 3.193.0) aws-sdk-core (~> 3, >= 3.188.0)
aws-sigv4 (~> 1.1) aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.151.0) aws-sdk-s3 (1.142.0)
aws-sdk-core (~> 3, >= 3.194.0) aws-sdk-core (~> 3, >= 3.189.0)
aws-sdk-kms (~> 1) aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.8) aws-sigv4 (~> 1.8)
aws-sigv4 (1.8.0) aws-sigv4 (1.8.0)
@ -137,10 +132,17 @@ GEM
erubi (>= 1.0.0) erubi (>= 1.0.0)
rack (>= 0.9.0) rack (>= 0.9.0)
rouge (>= 1.0.0) rouge (>= 1.0.0)
bigdecimal (3.1.8) better_html (2.0.2)
bindata (2.5.0) actionview (>= 6.0)
binding_of_caller (1.0.1) activesupport (>= 6.0)
debug_inspector (>= 1.2.0) ast (~> 2.0)
erubi (~> 1.4)
parser (>= 2.4)
smart_properties
bigdecimal (3.1.7)
bindata (2.4.15)
binding_of_caller (1.0.0)
debug_inspector (>= 0.0.1)
blurhash (0.1.7) blurhash (0.1.7)
bootsnap (1.18.3) bootsnap (1.18.3)
msgpack (~> 1.2) msgpack (~> 1.2)
@ -165,10 +167,11 @@ GEM
xpath (~> 3.2) xpath (~> 3.2)
case_transform (0.2) case_transform (0.2)
activesupport activesupport
cbor (0.5.9.8) cbor (0.5.9.6)
chewy (7.6.0) charlock_holmes (0.7.7)
chewy (7.5.1)
activesupport (>= 5.2) activesupport (>= 5.2)
elasticsearch (>= 7.14.0, < 8) elasticsearch (>= 7.12.0, < 7.14.0)
elasticsearch-dsl elasticsearch-dsl
chunky_png (1.4.0) chunky_png (1.4.0)
climate_control (1.2.0) climate_control (1.2.0)
@ -179,30 +182,31 @@ GEM
cose (1.3.0) cose (1.3.0)
cbor (~> 0.5.9) cbor (~> 0.5.9)
openssl-signature_algorithm (~> 1.0) openssl-signature_algorithm (~> 1.0)
crack (1.0.0) crack (0.4.6)
bigdecimal bigdecimal
rexml rexml
crass (1.0.6) crass (1.0.6)
css_parser (1.17.1) css_parser (1.14.0)
addressable addressable
csv (3.3.0) csv (3.2.8)
database_cleaner-active_record (2.1.0) database_cleaner-active_record (2.1.0)
activerecord (>= 5.a) activerecord (>= 5.a)
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.2) debug (1.9.1)
irb (~> 1.10) irb (~> 1.10)
reline (>= 0.3.8) reline (>= 0.3.8)
debug_inspector (1.2.0) debug_inspector (1.1.0)
devise (4.9.4) devise (4.9.3)
bcrypt (~> 3.0) bcrypt (~> 3.0)
orm_adapter (~> 0.1) orm_adapter (~> 0.1)
railties (>= 4.1.0) railties (>= 4.1.0)
responders responders
warden (~> 1.2.3) warden (~> 1.2.3)
devise-two-factor (5.0.0) devise-two-factor (4.1.1)
activesupport (~> 7.0) activesupport (~> 7.0)
attr_encrypted (>= 1.3, < 5, != 2)
devise (~> 4.0) devise (~> 4.0)
railties (~> 7.0) railties (~> 7.0)
rotp (~> 6.0) rotp (~> 6.0)
@ -213,31 +217,36 @@ GEM
discard (1.3.0) discard (1.3.0)
activerecord (>= 4.2, < 8) activerecord (>= 4.2, < 8)
docile (1.4.0) docile (1.4.0)
domain_name (0.6.20240107) domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
doorkeeper (5.6.9) doorkeeper (5.6.9)
railties (>= 5) railties (>= 5)
dotenv (3.1.2) dotenv (2.8.1)
dotenv-rails (2.8.1)
dotenv (= 2.8.1)
railties (>= 3.2)
drb (2.2.1) drb (2.2.1)
ed25519 (1.3.0) ed25519 (1.3.0)
elasticsearch (7.17.10) elasticsearch (7.13.3)
elasticsearch-api (= 7.17.10) elasticsearch-api (= 7.13.3)
elasticsearch-transport (= 7.17.10) elasticsearch-transport (= 7.13.3)
elasticsearch-api (7.17.10) elasticsearch-api (7.13.3)
multi_json multi_json
elasticsearch-dsl (0.1.10) elasticsearch-dsl (0.1.10)
elasticsearch-transport (7.17.10) elasticsearch-transport (7.13.3)
faraday (>= 1, < 3) faraday (~> 1)
multi_json multi_json
email_spec (2.2.2) email_spec (2.2.2)
htmlentities (~> 4.3.3) htmlentities (~> 4.3.3)
launchy (~> 2.1) launchy (~> 2.1)
mail (~> 2.7) mail (~> 2.7)
encryptor (3.0.0)
erubi (1.12.0) erubi (1.12.0)
et-orbi (1.2.11) et-orbi (1.2.7)
tzinfo tzinfo
excon (0.110.0) excon (0.109.0)
fabrication (2.31.0) fabrication (2.31.0)
faker (3.3.1) faker (3.2.3)
i18n (>= 1.8.11, < 2) i18n (>= 1.8.11, < 2)
faraday (1.10.3) faraday (1.10.3)
faraday-em_http (~> 1.0) faraday-em_http (~> 1.0)
@ -265,10 +274,10 @@ GEM
faraday_middleware (1.2.0) faraday_middleware (1.2.0)
faraday (~> 1.0) faraday (~> 1.0)
fast_blank (1.0.1) fast_blank (1.0.1)
fastimage (2.3.1) fastimage (2.3.0)
ffi (1.16.3) ffi (1.15.5)
ffi-compiler (1.3.2) ffi-compiler (1.0.1)
ffi (>= 1.15.5) ffi (>= 1.0.0)
rake rake
fog-core (2.4.0) fog-core (2.4.0)
builder builder
@ -278,11 +287,11 @@ GEM
fog-json (1.2.0) fog-json (1.2.0)
fog-core fog-core
multi_json (~> 1.10) multi_json (~> 1.10)
fog-openstack (1.1.1) fog-openstack (1.1.0)
fog-core (~> 2.1) fog-core (~> 2.1)
fog-json (>= 1.0) fog-json (>= 1.0)
formatador (1.1.0) formatador (1.1.0)
fugit (1.10.1) fugit (1.8.1)
et-orbi (~> 1, >= 1.2.7) et-orbi (~> 1, >= 1.2.7)
raabro (~> 1.4) raabro (~> 1.4)
fuubar (2.5.1) fuubar (2.5.1)
@ -290,9 +299,6 @@ GEM
ruby-progressbar (~> 1.4) ruby-progressbar (~> 1.4)
globalid (1.2.1) globalid (1.2.1)
activesupport (>= 6.1) activesupport (>= 6.1)
google-protobuf (3.25.3)
googleapis-common-protos-types (1.14.0)
google-protobuf (~> 3.18)
haml (6.3.0) haml (6.3.0)
temple (>= 0.8.2) temple (>= 0.8.2)
thor thor
@ -302,7 +308,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.58.0) haml_lint (0.57.0)
haml (>= 5.0) haml (>= 5.0)
parallel (~> 1.10) parallel (~> 1.10)
rainbow rainbow
@ -312,16 +318,15 @@ GEM
hashie (5.0.0) hashie (5.0.0)
hcaptcha (7.1.0) hcaptcha (7.1.0)
json json
highline (3.0.1) highline (2.1.0)
hiredis (0.6.3) hiredis (0.6.3)
hkdf (0.3.0) hkdf (0.3.0)
htmlentities (4.3.4) htmlentities (4.3.4)
http (5.2.0) http (5.1.1)
addressable (~> 2.8) addressable (~> 2.8)
base64 (~> 0.1)
http-cookie (~> 1.0) http-cookie (~> 1.0)
http-form_data (~> 2.2) http-form_data (~> 2.2)
llhttp-ffi (~> 0.5.0) llhttp-ffi (~> 0.4.0)
http-cookie (1.0.5) http-cookie (1.0.5)
domain_name (~> 0.5) domain_name (~> 0.5)
http-form_data (2.3.0) http-form_data (2.3.0)
@ -330,11 +335,12 @@ GEM
httplog (1.6.3) httplog (1.6.3)
rack (>= 2.0) rack (>= 2.0)
rainbow (>= 2.0.0) rainbow (>= 2.0.0)
i18n (1.14.5) i18n (1.14.1)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
i18n-tasks (1.0.14) i18n-tasks (1.0.13)
activesupport (>= 4.0.2) activesupport (>= 4.0.2)
ast (>= 2.1.0) ast (>= 2.1.0)
better_html (>= 1.0, < 3.0)
erubi erubi
highline (>= 2.0.0) highline (>= 2.0.0)
i18n i18n
@ -347,11 +353,11 @@ GEM
activesupport (>= 3.0) activesupport (>= 3.0)
nokogiri (>= 1.6) nokogiri (>= 1.6)
io-console (0.7.2) io-console (0.7.2)
irb (1.13.1) irb (1.12.0)
rdoc (>= 4.0.0) rdoc
reline (>= 0.4.2) reline (>= 0.4.2)
jmespath (1.6.2) jmespath (1.6.2)
json (2.7.2) json (2.7.1)
json-canonicalization (1.0.0) json-canonicalization (1.0.0)
json-jwt (1.15.3.1) json-jwt (1.15.3.1)
activesupport (>= 4.2) activesupport (>= 4.2)
@ -368,7 +374,7 @@ GEM
json-ld-preloaded (3.3.0) json-ld-preloaded (3.3.0)
json-ld (~> 3.3) json-ld (~> 3.3)
rdf (~> 3.3) rdf (~> 3.3)
json-schema (4.3.0) json-schema (4.2.0)
addressable (>= 2.8) addressable (>= 2.8)
jsonapi-renderer (0.2.2) jsonapi-renderer (0.2.2)
jwt (2.7.1) jwt (2.7.1)
@ -393,15 +399,15 @@ GEM
language_server-protocol (3.17.0.3) language_server-protocol (3.17.0.3)
launchy (2.5.2) launchy (2.5.2)
addressable (~> 2.8) addressable (~> 2.8)
letter_opener (1.10.0) letter_opener (1.8.1)
launchy (>= 2.2, < 4) launchy (>= 2.2, < 3)
letter_opener_web (3.0.0) letter_opener_web (2.0.0)
actionmailer (>= 6.1) actionmailer (>= 5.2)
letter_opener (~> 1.9) letter_opener (~> 1.7)
railties (>= 6.1) railties (>= 5.2)
rexml rexml
link_header (0.0.8) link_header (0.0.8)
llhttp-ffi (0.5.0) llhttp-ffi (0.4.0)
ffi-compiler (~> 1.0) ffi-compiler (~> 1.0)
rake (~> 13.0) rake (~> 13.0)
lograge (0.14.0) lograge (0.14.0)
@ -417,7 +423,7 @@ GEM
net-imap net-imap
net-pop net-pop
net-smtp net-smtp
marcel (1.0.4) marcel (1.0.2)
mario-redis-lock (1.2.1) mario-redis-lock (1.2.1)
redis (>= 3.0.5) redis (>= 3.0.5)
matrix (0.4.2) matrix (0.4.2)
@ -428,19 +434,19 @@ GEM
memory_profiler (1.0.1) memory_profiler (1.0.1)
mime-types (3.5.2) mime-types (3.5.2)
mime-types-data (~> 3.2015) mime-types-data (~> 3.2015)
mime-types-data (3.2024.0507) mime-types-data (3.2023.1205)
mini_mime (1.1.5) mini_mime (1.1.5)
mini_portile2 (2.8.6) mini_portile2 (2.8.5)
minitest (5.22.3) minitest (5.22.3)
msgpack (1.7.2) msgpack (1.7.2)
multi_json (1.15.0) multi_json (1.15.0)
multipart-post (2.4.0) multipart-post (2.3.0)
mutex_m (0.2.0) mutex_m (0.2.0)
net-http (0.4.1) net-http (0.4.1)
uri uri
net-http-persistent (4.0.2) net-http-persistent (4.0.2)
connection_pool (~> 2.2) connection_pool (~> 2.2)
net-imap (0.4.11) net-imap (0.4.10)
date date
net-protocol net-protocol
net-ldap (0.19.0) net-ldap (0.19.0)
@ -448,10 +454,10 @@ GEM
net-protocol net-protocol
net-protocol (0.2.2) net-protocol (0.2.2)
timeout timeout
net-smtp (0.5.0) net-smtp (0.4.0.1)
net-protocol net-protocol
nio4r (2.7.3) nio4r (2.5.9)
nokogiri (1.16.5) nokogiri (1.16.3)
mini_portile2 (~> 2.8.2) mini_portile2 (~> 2.8.2)
racc (~> 1.4) racc (~> 1.4)
nsa (0.3.0) nsa (0.3.0)
@ -492,100 +498,10 @@ GEM
openssl (3.2.0) openssl (3.2.0)
openssl-signature_algorithm (1.3.0) openssl-signature_algorithm (1.3.0)
openssl (> 2.0) openssl (> 2.0)
opentelemetry-api (1.2.5)
opentelemetry-common (0.20.1)
opentelemetry-api (~> 1.0)
opentelemetry-exporter-otlp (0.26.3)
google-protobuf (~> 3.14)
googleapis-common-protos-types (~> 1.3)
opentelemetry-api (~> 1.1)
opentelemetry-common (~> 0.20)
opentelemetry-sdk (~> 1.2)
opentelemetry-semantic_conventions
opentelemetry-helpers-sql-obfuscation (0.1.0)
opentelemetry-common (~> 0.20)
opentelemetry-instrumentation-action_pack (0.9.0)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-rack (~> 0.21)
opentelemetry-instrumentation-action_view (0.7.0)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-active_support (~> 0.1)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-active_job (0.7.1)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-active_model_serializers (0.20.1)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-active_record (0.7.2)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-active_support (0.5.1)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-base (0.22.3)
opentelemetry-api (~> 1.0)
opentelemetry-registry (~> 0.1)
opentelemetry-instrumentation-concurrent_ruby (0.21.3)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-excon (0.22.1)
opentelemetry-api (~> 1.0)
opentelemetry-common (~> 0.20.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-faraday (0.24.2)
opentelemetry-api (~> 1.0)
opentelemetry-common (~> 0.20.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-http (0.23.3)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-http_client (0.22.4)
opentelemetry-api (~> 1.0)
opentelemetry-common (~> 0.20.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-net_http (0.22.4)
opentelemetry-api (~> 1.0)
opentelemetry-common (~> 0.20.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-pg (0.27.3)
opentelemetry-api (~> 1.0)
opentelemetry-helpers-sql-obfuscation
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-rack (0.24.3)
opentelemetry-api (~> 1.0)
opentelemetry-common (~> 0.20.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-rails (0.30.1)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-action_pack (~> 0.9.0)
opentelemetry-instrumentation-action_view (~> 0.7.0)
opentelemetry-instrumentation-active_job (~> 0.7.0)
opentelemetry-instrumentation-active_record (~> 0.7.0)
opentelemetry-instrumentation-active_support (~> 0.5.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-redis (0.25.4)
opentelemetry-api (~> 1.0)
opentelemetry-common (~> 0.20.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-instrumentation-sidekiq (0.25.3)
opentelemetry-api (~> 1.0)
opentelemetry-common (~> 0.20.0)
opentelemetry-instrumentation-base (~> 0.22.1)
opentelemetry-registry (0.3.1)
opentelemetry-api (~> 1.1)
opentelemetry-sdk (1.4.1)
opentelemetry-api (~> 1.1)
opentelemetry-common (~> 0.20)
opentelemetry-registry (~> 0.2)
opentelemetry-semantic_conventions
opentelemetry-semantic_conventions (1.10.0)
opentelemetry-api (~> 1.0)
orm_adapter (0.5.0) orm_adapter (0.5.0)
ox (2.14.18) ox (2.14.18)
parallel (1.24.0) parallel (1.24.0)
parser (3.3.1.0) parser (3.3.0.5)
ast (~> 2.4.1) ast (~> 2.4.1)
racc racc
parslet (2.0.0) parslet (2.0.0)
@ -594,7 +510,8 @@ GEM
pg (1.5.6) pg (1.5.6)
pghero (3.4.1) pghero (3.4.1)
activerecord (>= 6) activerecord (>= 6)
premailer (1.23.0) posix-spawn (0.3.15)
premailer (1.21.0)
addressable addressable
css_parser (>= 1.12.0) css_parser (>= 1.12.0)
htmlentities (>= 4.0.0) htmlentities (>= 4.0.0)
@ -610,10 +527,10 @@ GEM
railties (>= 7.0.0) railties (>= 7.0.0)
psych (5.1.2) psych (5.1.2)
stringio stringio
public_suffix (5.0.5) public_suffix (5.0.4)
puma (6.4.2) puma (6.4.2)
nio4r (~> 2.0) nio4r (~> 2.0)
pundit (2.3.2) pundit (2.3.1)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
raabro (1.4.0) raabro (1.4.0)
racc (1.7.3) racc (1.7.3)
@ -631,7 +548,7 @@ GEM
rack-protection (3.2.0) rack-protection (3.2.0)
base64 (>= 0.1.0) base64 (>= 0.1.0)
rack (~> 2.2, >= 2.2.4) rack (~> 2.2, >= 2.2.4)
rack-proxy (0.7.7) rack-proxy (0.7.6)
rack rack
rack-session (1.0.2) rack-session (1.0.2)
rack (< 3) rack (< 3)
@ -640,20 +557,20 @@ GEM
rackup (1.0.0) rackup (1.0.0)
rack (< 3) rack (< 3)
webrick webrick
rails (7.1.3.3) rails (7.1.3.2)
actioncable (= 7.1.3.3) actioncable (= 7.1.3.2)
actionmailbox (= 7.1.3.3) actionmailbox (= 7.1.3.2)
actionmailer (= 7.1.3.3) actionmailer (= 7.1.3.2)
actionpack (= 7.1.3.3) actionpack (= 7.1.3.2)
actiontext (= 7.1.3.3) actiontext (= 7.1.3.2)
actionview (= 7.1.3.3) actionview (= 7.1.3.2)
activejob (= 7.1.3.3) activejob (= 7.1.3.2)
activemodel (= 7.1.3.3) activemodel (= 7.1.3.2)
activerecord (= 7.1.3.3) activerecord (= 7.1.3.2)
activestorage (= 7.1.3.3) activestorage (= 7.1.3.2)
activesupport (= 7.1.3.3) activesupport (= 7.1.3.2)
bundler (>= 1.15.0) bundler (>= 1.15.0)
railties (= 7.1.3.3) railties (= 7.1.3.2)
rails-controller-testing (1.0.5) rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1) actionpack (>= 5.0.1.rc1)
actionview (>= 5.0.1.rc1) actionview (>= 5.0.1.rc1)
@ -668,16 +585,16 @@ GEM
rails-i18n (7.0.9) rails-i18n (7.0.9)
i18n (>= 0.7, < 2) i18n (>= 0.7, < 2)
railties (>= 6.0.0, < 8) railties (>= 6.0.0, < 8)
railties (7.1.3.3) railties (7.1.3.2)
actionpack (= 7.1.3.3) actionpack (= 7.1.3.2)
activesupport (= 7.1.3.3) activesupport (= 7.1.3.2)
irb irb
rackup (>= 1.0.0) rackup (>= 1.0.0)
rake (>= 12.2) rake (>= 12.2)
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.2.1) rake (13.1.0)
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)
@ -692,17 +609,16 @@ GEM
redlock (1.3.2) redlock (1.3.2)
redis (>= 3.0.0, < 6.0) redis (>= 3.0.0, < 6.0)
regexp_parser (2.9.0) regexp_parser (2.9.0)
reline (0.5.7) reline (0.4.3)
io-console (~> 0.5) io-console (~> 0.5)
request_store (1.6.0) request_store (1.5.1)
rack (>= 1.4) rack (>= 1.4)
responders (3.1.1) responders (3.1.1)
actionpack (>= 5.2) actionpack (>= 5.2)
railties (>= 5.2) railties (>= 5.2)
rexml (3.2.8) rexml (3.2.6)
strscan (>= 3.0.9)
rotp (6.3.0) rotp (6.3.0)
rouge (4.2.1) rouge (4.1.2)
rpam2 (4.0.2) rpam2 (4.0.2)
rqrcode (2.2.0) rqrcode (2.2.0)
chunky_png (~> 1.0) chunky_png (~> 1.0)
@ -715,7 +631,7 @@ GEM
rspec-support (~> 3.13.0) rspec-support (~> 3.13.0)
rspec-github (2.4.0) rspec-github (2.4.0)
rspec-core (~> 3.0) rspec-core (~> 3.0)
rspec-mocks (3.13.1) rspec-mocks (3.13.0)
diff-lcs (>= 1.2.0, < 2.0) diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0) rspec-support (~> 3.13.0)
rspec-rails (6.1.2) rspec-rails (6.1.2)
@ -726,13 +642,13 @@ GEM
rspec-expectations (~> 3.13) rspec-expectations (~> 3.13)
rspec-mocks (~> 3.13) rspec-mocks (~> 3.13)
rspec-support (~> 3.13) rspec-support (~> 3.13)
rspec-sidekiq (5.0.0) rspec-sidekiq (4.1.0)
rspec-core (~> 3.0) rspec-core (~> 3.0)
rspec-expectations (~> 3.0) rspec-expectations (~> 3.0)
rspec-mocks (~> 3.0) rspec-mocks (~> 3.0)
sidekiq (>= 5, < 8) sidekiq (>= 5, < 8)
rspec-support (3.13.1) rspec-support (3.13.1)
rubocop (1.63.5) rubocop (1.62.1)
json (~> 2.3) json (~> 2.3)
language_server-protocol (>= 3.17.0) language_server-protocol (>= 3.17.0)
parallel (~> 1.10) parallel (~> 1.10)
@ -743,30 +659,27 @@ GEM
rubocop-ast (>= 1.31.1, < 2.0) rubocop-ast (>= 1.31.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.31.3) rubocop-ast (1.31.2)
parser (>= 3.3.1.0) parser (>= 3.3.0.4)
rubocop-capybara (2.20.0) rubocop-capybara (2.20.0)
rubocop (~> 1.41) rubocop (~> 1.41)
rubocop-factory_bot (2.25.1) rubocop-factory_bot (2.25.1)
rubocop (~> 1.41) rubocop (~> 1.41)
rubocop-performance (1.21.0) rubocop-performance (1.20.2)
rubocop (>= 1.48.1, < 2.0) rubocop (>= 1.48.1, < 2.0)
rubocop-ast (>= 1.31.1, < 2.0) rubocop-ast (>= 1.30.0, < 2.0)
rubocop-rails (2.24.1) rubocop-rails (2.24.0)
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.31.1, < 2.0) rubocop-ast (>= 1.31.1, < 2.0)
rubocop-rspec (2.29.2) rubocop-rspec (2.27.1)
rubocop (~> 1.40) rubocop (~> 1.40)
rubocop-capybara (~> 2.17) rubocop-capybara (~> 2.17)
rubocop-factory_bot (~> 2.22) rubocop-factory_bot (~> 2.22)
rubocop-rspec_rails (~> 2.28)
rubocop-rspec_rails (2.28.3)
rubocop (~> 1.40)
ruby-prof (1.7.0) ruby-prof (1.7.0)
ruby-progressbar (1.13.0) ruby-progressbar (1.13.0)
ruby-saml (1.16.0) ruby-saml (1.15.0)
nokogiri (>= 1.13.10) nokogiri (>= 1.13.10)
rexml rexml
ruby2_keywords (0.0.5) ruby2_keywords (0.0.5)
@ -778,10 +691,10 @@ GEM
sanitize (6.1.0) sanitize (6.1.0)
crass (~> 1.0.2) crass (~> 1.0.2)
nokogiri (>= 1.12.0) nokogiri (>= 1.12.0)
scenic (1.8.0) scenic (1.7.0)
activerecord (>= 4.0.0) activerecord (>= 4.0.0)
railties (>= 4.0.0) railties (>= 4.0.0)
selenium-webdriver (4.21.1) selenium-webdriver (4.18.1)
base64 (~> 0.2) base64 (~> 0.2)
rexml (~> 3.2, >= 3.2.5) rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 3.0) rubyzip (>= 1.2.2, < 3.0)
@ -815,14 +728,14 @@ GEM
simplecov-html (0.12.3) simplecov-html (0.12.3)
simplecov-lcov (0.8.0) simplecov-lcov (0.8.0)
simplecov_json_formatter (0.1.4) simplecov_json_formatter (0.1.4)
smart_properties (1.17.0)
stackprof (0.2.26) stackprof (0.2.26)
statsd-ruby (1.5.0) statsd-ruby (1.5.0)
stoplight (4.1.0) stoplight (3.0.2)
redlock (~> 1.0) redlock (~> 1.0)
stringio (3.1.0) stringio (3.1.0)
strong_migrations (1.8.0) strong_migrations (1.8.0)
activerecord (>= 5.2) activerecord (>= 5.2)
strscan (3.1.0)
swd (1.3.0) swd (1.3.0)
activesupport (>= 3) activesupport (>= 3)
attr_required (>= 0.0.5) attr_required (>= 0.0.5)
@ -833,7 +746,7 @@ GEM
unicode-display_width (>= 1.1.1, < 3) unicode-display_width (>= 1.1.1, < 3)
terrapin (1.0.1) terrapin (1.0.1)
climate_control climate_control
test-prof (1.3.3) test-prof (1.3.2)
thor (1.3.1) thor (1.3.1)
tilt (2.3.0) tilt (2.3.0)
timeout (0.4.1) timeout (0.4.1)
@ -850,7 +763,7 @@ GEM
tty-cursor (~> 0.7) tty-cursor (~> 0.7)
tty-screen (~> 0.8) tty-screen (~> 0.8)
wisper (~> 2.0) wisper (~> 2.0)
tty-screen (0.8.2) tty-screen (0.8.1)
twitter-text (3.1.0) twitter-text (3.1.0)
idn-ruby idn-ruby
unf (~> 0.1.0) unf (~> 0.1.0)
@ -860,9 +773,9 @@ GEM
tzinfo (>= 1.0.0) tzinfo (>= 1.0.0)
unf (0.1.4) unf (0.1.4)
unf_ext unf_ext
unf_ext (0.0.9.1) unf_ext (0.0.8.2)
unicode-display_width (2.5.0) unicode-display_width (2.5.0)
uri (0.13.0) uri (0.12.2)
validate_email (0.1.6) validate_email (0.1.6)
activemodel (>= 3.0) activemodel (>= 3.0)
mail (>= 2.2.5) mail (>= 2.2.5)
@ -883,7 +796,7 @@ GEM
webfinger (1.2.0) webfinger (1.2.0)
activesupport activesupport
httpclient (>= 2.4) httpclient (>= 2.4)
webmock (3.23.0) webmock (3.22.0)
addressable (>= 2.8.0) addressable (>= 2.8.0)
crack (>= 0.3.2) crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0) hashdiff (>= 0.4.0, < 2.0.0)
@ -901,7 +814,7 @@ GEM
xorcist (1.1.3) xorcist (1.1.3)
xpath (3.2.0) xpath (3.2.0)
nokogiri (~> 1.8) nokogiri (~> 1.8)
zeitwerk (2.6.14) zeitwerk (2.6.13)
PLATFORMS PLATFORMS
ruby ruby
@ -919,7 +832,7 @@ DEPENDENCIES
browser browser
bundler-audit (~> 0.9) bundler-audit (~> 0.9)
capybara (~> 3.39) capybara (~> 3.39)
charlock_holmes! charlock_holmes (~> 0.7.7)
chewy (~> 7.3) chewy (~> 7.3)
climate_control climate_control
cocoon (~> 1.2) cocoon (~> 1.2)
@ -930,11 +843,11 @@ DEPENDENCIES
database_cleaner-active_record database_cleaner-active_record
debug (~> 1.8) debug (~> 1.8)
devise (~> 4.9) devise (~> 4.9)
devise-two-factor devise-two-factor (~> 4.1)
devise_pam_authenticatable2 (~> 9.2) devise_pam_authenticatable2 (~> 9.2)
discard (~> 1.2) discard (~> 1.2)
doorkeeper (~> 5.6) doorkeeper (~> 5.6)
dotenv dotenv-rails (~> 2.8)
ed25519 (~> 1.3) ed25519 (~> 1.3)
email_spec email_spec
fabrication (~> 2.30) fabrication (~> 2.30)
@ -949,10 +862,10 @@ DEPENDENCIES
hcaptcha (~> 7.1) hcaptcha (~> 7.1)
hiredis (~> 0.6) hiredis (~> 0.6)
htmlentities (~> 4.3) htmlentities (~> 4.3)
http (~> 5.2.0) http (~> 5.1)
http_accept_language (~> 2.1) http_accept_language (~> 2.1)
httplog (~> 1.6.2) httplog (~> 1.6.2)
i18n i18n (= 1.14.1)
i18n-tasks (~> 1.0) i18n-tasks (~> 1.0)
idn-ruby idn-ruby
inline_svg inline_svg
@ -963,10 +876,9 @@ DEPENDENCIES
kaminari (~> 1.2) kaminari (~> 1.2)
kt-paperclip (~> 7.2) kt-paperclip (~> 7.2)
letter_opener (~> 1.8) letter_opener (~> 1.8)
letter_opener_web (~> 3.0) letter_opener_web (~> 2.0)
link_header (~> 0.0) link_header (~> 0.0)
lograge (~> 0.12) lograge (~> 0.12)
mail (~> 2.8)
mario-redis-lock (~> 1.2) mario-redis-lock (~> 1.2)
md-paperclip-azure (~> 2.2) md-paperclip-azure (~> 2.2)
memory_profiler memory_profiler
@ -981,25 +893,11 @@ DEPENDENCIES
omniauth-rails_csrf_protection (~> 1.0) omniauth-rails_csrf_protection (~> 1.0)
omniauth-saml (~> 2.0) omniauth-saml (~> 2.0)
omniauth_openid_connect (~> 0.6.1) omniauth_openid_connect (~> 0.6.1)
opentelemetry-exporter-otlp (~> 0.26.3)
opentelemetry-instrumentation-active_job (~> 0.7.1)
opentelemetry-instrumentation-active_model_serializers (~> 0.20.1)
opentelemetry-instrumentation-concurrent_ruby (~> 0.21.2)
opentelemetry-instrumentation-excon (~> 0.22.0)
opentelemetry-instrumentation-faraday (~> 0.24.1)
opentelemetry-instrumentation-http (~> 0.23.2)
opentelemetry-instrumentation-http_client (~> 0.22.3)
opentelemetry-instrumentation-net_http (~> 0.22.4)
opentelemetry-instrumentation-pg (~> 0.27.1)
opentelemetry-instrumentation-rack (~> 0.24.1)
opentelemetry-instrumentation-rails (~> 0.30.0)
opentelemetry-instrumentation-redis (~> 0.25.3)
opentelemetry-instrumentation-sidekiq (~> 0.25.2)
opentelemetry-sdk (~> 1.4)
ox (~> 2.14) ox (~> 2.14)
parslet parslet
pg (~> 1.5) pg (~> 1.5)
pghero pghero
posix-spawn
premailer-rails premailer-rails
private_address_check (~> 0.5) private_address_check (~> 0.5)
propshaft propshaft
@ -1020,7 +918,7 @@ DEPENDENCIES
rqrcode (~> 2.2) rqrcode (~> 2.2)
rspec-github (~> 2.4) rspec-github (~> 2.4)
rspec-rails (~> 6.0) rspec-rails (~> 6.0)
rspec-sidekiq (~> 5.0) rspec-sidekiq (~> 4.0)
rubocop rubocop
rubocop-capybara rubocop-capybara
rubocop-performance rubocop-performance
@ -1041,7 +939,7 @@ DEPENDENCIES
simplecov (~> 0.22) simplecov (~> 0.22)
simplecov-lcov (~> 0.8) simplecov-lcov (~> 0.8)
stackprof stackprof
stoplight (~> 4.1) stoplight (~> 3.0.1)
strong_migrations (= 1.8.0) strong_migrations (= 1.8.0)
test-prof test-prof
thor (~> 1.2) thor (~> 1.2)
@ -1055,7 +953,7 @@ DEPENDENCIES
xorcist (~> 1.1) xorcist (~> 1.1)
RUBY VERSION RUBY VERSION
ruby 3.3.1p55 ruby 3.2.2p53
BUNDLED WITH BUNDLED WITH
2.5.9 2.5.4

View file

@ -1,29 +1,3 @@
# <img src="https://github.com/TheEssem/mastodon/raw/main/public/chuckya.png" width="128"> Chuckya
Chuckya is a close-to-upstream soft fork of Mastodon Glitch Edition (more commonly known as glitch-soc) that aims to introduce more experimental features/fixes with the goal of making the overall experience more enjoyable. Although it's mainly developed for and used on the [wetdry.world](https://wetdry.world) instance, it can be deployed by any server admin as a drop-in, backwards-compatible replacement for Mastodon.
Here are some of the changes compared to glitch-soc:
- Emoji reactions (glitch-soc/mastodon#2462)
- Tenor GIF picker (originally from [koyu.space](https://github.com/koyuspace/mastodon))
- Mastodon Modern theme (licensed under CC-BY-SA 4.0, [original repo](https://codeberg.org/Freeplay/Mastodon-Modern))
- Workaround for OpenGraph video embeds when using [Jortage](https://jortage.com)
- Multiple fixes for oEmbed/OpenGraph embeds
- Polls can be posted alongside media (glitch-soc/mastodon#2524)
- Polls can have only one option
- Restores status trend half-life to 2 hours
- Allows dashes in custom emote names
- Emojis can be put side-by-side
- Minor media attachment tweaks
Changes previously in Chuckya that made their way into vanilla Mastodon:
- Unicode emojis use [`jdecked/twemoji`](https://github.com/jdecked/twemoji) v15 graphics (mastodon/mastodon#28404)
Setup instructions are the same as [glitch-soc's](https://glitch-soc.github.io/docs); just replace the glitch-soc repo URL with `https://github.com/TheEssem/mastodon`.
Original glitch-soc readme is below.
# Mastodon Glitch Edition # Mastodon Glitch Edition
[![Ruby Testing](https://github.com/glitch-soc/mastodon/actions/workflows/test-ruby.yml/badge.svg)](https://github.com/glitch-soc/mastodon/actions/workflows/test-ruby.yml) [![Ruby Testing](https://github.com/glitch-soc/mastodon/actions/workflows/test-ruby.yml/badge.svg)](https://github.com/glitch-soc/mastodon/actions/workflows/test-ruby.yml)
@ -111,8 +85,8 @@ Mastodon acts as an OAuth2 provider, so 3rd party apps can use the REST and Stre
- **PostgreSQL** 12+ - **PostgreSQL** 12+
- **Redis** 4+ - **Redis** 4+
- **Ruby** 3.1+ - **Ruby** 3.0+
- **Node.js** 18+ - **Node.js** 16+
The repository includes deployment configurations for **Docker and docker-compose** as well as specific platforms like **Heroku**, **Scalingo**, and **Nanobox**. For Helm charts, reference the [mastodon/chart repository](https://github.com/mastodon/chart). The [**standalone** installation guide](https://docs.joinmastodon.org/admin/install/) is available in the documentation. The repository includes deployment configurations for **Docker and docker-compose** as well as specific platforms like **Heroku**, **Scalingo**, and **Nanobox**. For Helm charts, reference the [mastodon/chart repository](https://github.com/mastodon/chart). The [**standalone** installation guide](https://docs.joinmastodon.org/admin/install/) is available in the documentation.
@ -133,12 +107,10 @@ A **Vagrant** configuration is included for development purposes. To use it, com
To set up **MacOS** for native development, complete the following steps: To set up **MacOS** for native development, complete the following steps:
- Use a Ruby version manager to install the specified version from `.ruby-version` - Use a Ruby version manager to install the specified version from `.ruby-version`
- Run `bundle` to install required gems
- Run `brew install postgresql@14 redis imagemagick libidn` to install required dependencies - Run `brew install postgresql@14 redis imagemagick libidn` to install required dependencies
- Navigate to Mastodon's root directory and run `brew install nvm` then `nvm use` to use the version from `.nvmrc` - Navigate to Mastodon's root directory and run `brew install nvm` then `nvm use` to use the version from `.nvmrc`
- Run `yarn` to install required packages
- Run `corepack enable && corepack prepare` - Run `corepack enable && corepack prepare`
- Run `RAILS_ENV=development bundle exec rails db:setup` - Run `bundle exec rails db:setup` (optionally prepend `RAILS_ENV=development` to target the dev environment)
- Finally, run `bin/dev` which will launch the local services via `overmind` (if installed) or `foreman` - Finally, run `bin/dev` which will launch the local services via `overmind` (if installed) or `foreman`
### Docker ### Docker

1
Vagrantfile vendored
View file

@ -173,7 +173,6 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# Otherwise, you can access the site at http://localhost:3000 and http://localhost:4000 , http://localhost:8080 # Otherwise, you can access the site at http://localhost:3000 and http://localhost:4000 , http://localhost:8080
config.vm.network :forwarded_port, guest: 3000, host: 3000 config.vm.network :forwarded_port, guest: 3000, host: 3000
config.vm.network :forwarded_port, guest: 3035, host: 3035
config.vm.network :forwarded_port, guest: 4000, host: 4000 config.vm.network :forwarded_port, guest: 4000, host: 4000
config.vm.network :forwarded_port, guest: 8080, host: 8080 config.vm.network :forwarded_port, guest: 8080, host: 8080
config.vm.network :forwarded_port, guest: 9200, host: 9200 config.vm.network :forwarded_port, guest: 9200, host: 9200

View file

@ -25,7 +25,7 @@ class AccountsController < ApplicationController
limit = params[:limit].present? ? [params[:limit].to_i, PAGE_SIZE_MAX].min : PAGE_SIZE limit = params[:limit].present? ? [params[:limit].to_i, PAGE_SIZE_MAX].min : PAGE_SIZE
@statuses = filtered_statuses.without_reblogs.limit(limit) @statuses = filtered_statuses.without_reblogs.limit(limit)
@statuses = preload_collection(@statuses, Status) @statuses = cache_collection(@statuses, Status)
end end
format.json do format.json do
@ -46,7 +46,7 @@ class AccountsController < ApplicationController
end end
def default_statuses def default_statuses
@account.statuses.not_local_only.distributable_visibility @account.statuses.not_local_only.where(visibility: [:public, :unlisted])
end end
def only_media_scope def only_media_scope

View file

@ -18,7 +18,7 @@ class ActivityPub::CollectionsController < ActivityPub::BaseController
def set_items def set_items
case params[:id] case params[:id]
when 'featured' when 'featured'
@items = for_signed_account { preload_collection(@account.pinned_statuses.not_local_only, Status) } @items = for_signed_account { cache_collection(@account.pinned_statuses.not_local_only, Status) }
@items = @items.map { |item| item.distributable? ? item : ActivityPub::TagManager.instance.uri_for(item) } @items = @items.map { |item| item.distributable? ? item : ActivityPub::TagManager.instance.uri_for(item) }
when 'tags' when 'tags'
@items = for_signed_account { @account.featured_tags } @items = for_signed_account { @account.featured_tags }

View file

@ -60,7 +60,7 @@ class ActivityPub::OutboxesController < ActivityPub::BaseController
def set_statuses def set_statuses
return unless page_requested? return unless page_requested?
@statuses = preload_collection_paginated_by_id( @statuses = cache_collection_paginated_by_id(
AccountStatusesFilter.new(@account, signed_request_account).results, AccountStatusesFilter.new(@account, signed_request_account).results,
Status, Status,
LIMIT, LIMIT,

View file

@ -31,7 +31,7 @@ class ActivityPub::RepliesController < ActivityPub::BaseController
def set_replies def set_replies
@replies = only_other_accounts? ? Status.where.not(account_id: @account.id).joins(:account).merge(Account.without_suspended) : @account.statuses @replies = only_other_accounts? ? Status.where.not(account_id: @account.id).joins(:account).merge(Account.without_suspended) : @account.statuses
@replies = @replies.distributable_visibility.where(in_reply_to_id: @status.id) @replies = @replies.where(in_reply_to_id: @status.id, visibility: [:public, :unlisted])
@replies = @replies.paginate_by_min_id(DESCENDANTS_LIMIT, params[:min_id]) @replies = @replies.paginate_by_min_id(DESCENDANTS_LIMIT, params[:min_id])
end end

View file

@ -7,6 +7,7 @@ module Admin
layout 'admin' layout 'admin'
before_action :set_pack
before_action :set_body_classes before_action :set_body_classes
before_action :set_cache_headers before_action :set_cache_headers
@ -18,6 +19,10 @@ module Admin
@body_classes = 'admin' @body_classes = 'admin'
end end
def set_pack
use_pack 'admin'
end
def set_cache_headers def set_cache_headers
response.cache_control.replace(private: true, no_store: true) response.cache_control.replace(private: true, no_store: true)
end end

View file

@ -25,8 +25,6 @@ class Admin::DomainAllowsController < Admin::BaseController
def destroy def destroy
authorize @domain_allow, :destroy? authorize @domain_allow, :destroy?
UnallowDomainService.new.call(@domain_allow) UnallowDomainService.new.call(@domain_allow)
log_action :destroy, @domain_allow
redirect_to admin_instances_path, notice: I18n.t('admin.domain_allows.destroyed_msg') redirect_to admin_instances_path, notice: I18n.t('admin.domain_allows.destroyed_msg')
end end

View file

@ -9,7 +9,7 @@ module Admin
@site_upload.destroy! @site_upload.destroy!
redirect_back fallback_location: admin_settings_path, notice: I18n.t('admin.site_uploads.destroyed_msg') redirect_to admin_settings_path, notice: I18n.t('admin.site_uploads.destroyed_msg')
end end
private private

View file

@ -9,7 +9,6 @@ class Api::BaseController < ApplicationController
include Api::CachingConcern include Api::CachingConcern
include Api::ContentSecurityPolicy include Api::ContentSecurityPolicy
include Api::ErrorHandling include Api::ErrorHandling
include Api::Pagination
skip_before_action :require_functional!, unless: :limited_federation_mode? skip_before_action :require_functional!, unless: :limited_federation_mode?
@ -30,6 +29,21 @@ class Api::BaseController < ApplicationController
protected protected
def pagination_max_id
pagination_collection.last.id
end
def pagination_since_id
pagination_collection.first.id
end
def set_pagination_headers(next_path = nil, prev_path = nil)
links = []
links << [next_path, [%w(rel next)]] if next_path
links << [prev_path, [%w(rel prev)]] if prev_path
response.headers['Link'] = LinkHeader.new(links) unless links.empty?
end
def limit_param(default_limit) def limit_param(default_limit)
return default_limit unless params[:limit] return default_limit unless params[:limit]
@ -58,6 +72,10 @@ class Api::BaseController < ApplicationController
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&.unavailable?
end end
def require_valid_pagination_options!
render json: { error: 'Pagination values for `offset` and `limit` must be positive' }, status: 400 if pagination_options_invalid?
end
def require_user! def require_user!
if !current_user if !current_user
render json: { error: 'This method requires an authenticated user' }, status: 422 render json: { error: 'This method requires an authenticated user' }, status: 422
@ -86,6 +104,14 @@ class Api::BaseController < ApplicationController
private private
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def pagination_options_invalid?
params.slice(:limit, :offset).values.map(&:to_i).any?(&:negative?)
end
def respond_with_error(code) def respond_with_error(code)
render json: { error: Rack::Utils::HTTP_STATUS_CODES[code] }, status: code render json: { error: Rack::Utils::HTTP_STATUS_CODES[code] }, status: code
end end

View file

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::Accounts::CredentialsController < Api::BaseController class Api::V1::Accounts::CredentialsController < Api::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:accounts', :'read:me' }, except: [:update] before_action -> { doorkeeper_authorize! :read, :'read:accounts' }, except: [:update]
before_action -> { doorkeeper_authorize! :write, :'write:accounts' }, only: [:update] before_action -> { doorkeeper_authorize! :write, :'write:accounts' }, only: [:update]
before_action :require_user! before_action :require_user!

View file

@ -19,11 +19,11 @@ class Api::V1::Accounts::StatusesController < Api::BaseController
end end
def load_statuses def load_statuses
@account.unavailable? ? [] : preloaded_account_statuses @account.unavailable? ? [] : cached_account_statuses
end end
def preloaded_account_statuses def cached_account_statuses
preload_collection_paginated_by_id( cache_collection_paginated_by_id(
AccountStatusesFilter.new(@account, current_account, params).results, AccountStatusesFilter.new(@account, current_account, params).results,
Status, Status,
limit_param(DEFAULT_STATUSES_LIMIT), limit_param(DEFAULT_STATUSES_LIMIT),

View file

@ -9,22 +9,16 @@ class Api::V1::AccountsController < Api::BaseController
before_action -> { doorkeeper_authorize! :follow, :write, :'write:blocks' }, only: [:block, :unblock] before_action -> { doorkeeper_authorize! :follow, :write, :'write:blocks' }, only: [:block, :unblock]
before_action -> { doorkeeper_authorize! :write, :'write:accounts' }, only: [:create] before_action -> { doorkeeper_authorize! :write, :'write:accounts' }, only: [:create]
before_action :require_user!, except: [:index, :show, :create] before_action :require_user!, except: [:show, :create]
before_action :set_account, except: [:index, :create] before_action :set_account, except: [:create]
before_action :set_accounts, only: [:index] before_action :check_account_approval, except: [:create]
before_action :check_account_approval, except: [:index, :create] before_action :check_account_confirmation, except: [:create]
before_action :check_account_confirmation, except: [:index, :create]
before_action :check_enabled_registrations, only: [:create] before_action :check_enabled_registrations, only: [:create]
before_action :check_accounts_limit, only: [:index]
skip_before_action :require_authenticated_user!, only: :create skip_before_action :require_authenticated_user!, only: :create
override_rate_limit_headers :follow, family: :follows override_rate_limit_headers :follow, family: :follows
def index
render json: @accounts, each_serializer: REST::AccountSerializer
end
def show def show
cache_if_unauthenticated! cache_if_unauthenticated!
render json: @account, serializer: REST::AccountSerializer render json: @account, serializer: REST::AccountSerializer
@ -85,10 +79,6 @@ class Api::V1::AccountsController < Api::BaseController
@account = Account.find(params[:id]) @account = Account.find(params[:id])
end end
def set_accounts
@accounts = Account.where(id: account_ids).without_unapproved
end
def check_account_approval def check_account_approval
raise(ActiveRecord::RecordNotFound) if @account.local? && @account.user_pending? raise(ActiveRecord::RecordNotFound) if @account.local? && @account.user_pending?
end end
@ -97,22 +87,10 @@ class Api::V1::AccountsController < Api::BaseController
raise(ActiveRecord::RecordNotFound) if @account.local? && !@account.user_confirmed? raise(ActiveRecord::RecordNotFound) if @account.local? && !@account.user_confirmed?
end end
def check_accounts_limit
raise(Mastodon::ValidationError) if account_ids.size > DEFAULT_ACCOUNTS_LIMIT
end
def relationships(**options) def relationships(**options)
AccountRelationshipsPresenter.new([@account], current_user.account_id, **options) AccountRelationshipsPresenter.new([@account], current_user.account_id, **options)
end end
def account_ids
Array(accounts_params[:ids]).uniq.map(&:to_i)
end
def accounts_params
params.permit(ids: [])
end
def account_params def account_params
params.permit(:username, :email, :password, :agreement, :locale, :reason, :time_zone, :invite_code) params.permit(:username, :email, :password, :agreement, :locale, :reason, :time_zone, :invite_code)
end end

View file

@ -29,11 +29,10 @@ class Api::V1::Admin::DomainBlocksController < Api::BaseController
def create def create
authorize :domain_block, :create? authorize :domain_block, :create?
@domain_block = DomainBlock.new(resource_params)
existing_domain_block = resource_params[:domain].present? ? DomainBlock.rule_for(resource_params[:domain]) : nil existing_domain_block = resource_params[:domain].present? ? DomainBlock.rule_for(resource_params[:domain]) : nil
return render json: existing_domain_block, serializer: REST::Admin::ExistingDomainBlockErrorSerializer, status: 422 if conflicts_with_existing_block?(@domain_block, existing_domain_block) return render json: existing_domain_block, serializer: REST::Admin::ExistingDomainBlockErrorSerializer, status: 422 if existing_domain_block.present?
@domain_block.save! @domain_block = DomainBlock.create!(resource_params)
DomainBlockWorker.perform_async(@domain_block.id) DomainBlockWorker.perform_async(@domain_block.id)
log_action :create, @domain_block log_action :create, @domain_block
render json: @domain_block, serializer: REST::Admin::DomainBlockSerializer render json: @domain_block, serializer: REST::Admin::DomainBlockSerializer
@ -56,10 +55,6 @@ class Api::V1::Admin::DomainBlocksController < Api::BaseController
private private
def conflicts_with_existing_block?(domain_block, existing_domain_block)
existing_domain_block.present? && (existing_domain_block.domain == TagManager.instance.normalize_domain(domain_block.domain) || !domain_block.stricter_than?(existing_domain_block))
end
def set_domain_blocks def set_domain_blocks
@domain_blocks = filtered_domain_blocks.order(id: :desc).to_a_paginated_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id)) @domain_blocks = filtered_domain_blocks.order(id: :desc).to_a_paginated_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id))
end end

View file

@ -4,6 +4,6 @@ class Api::V1::Apps::CredentialsController < Api::BaseController
def show def show
return doorkeeper_render_error unless valid_doorkeeper_token? return doorkeeper_render_error unless valid_doorkeeper_token?
render json: doorkeeper_token.application, serializer: REST::ApplicationSerializer render json: doorkeeper_token.application, serializer: REST::ApplicationSerializer, fields: %i(name website vapid_key client_id scopes)
end end
end end

View file

@ -5,7 +5,7 @@ class Api::V1::AppsController < Api::BaseController
def create def create
@app = Doorkeeper::Application.create!(application_options) @app = Doorkeeper::Application.create!(application_options)
render json: @app, serializer: REST::CredentialApplicationSerializer render json: @app, serializer: REST::ApplicationSerializer
end end
private private
@ -24,6 +24,6 @@ class Api::V1::AppsController < Api::BaseController
end end
def app_params def app_params
params.permit(:client_name, :scopes, :website, :redirect_uris, redirect_uris: []) params.permit(:client_name, :redirect_uris, :scopes, :website)
end end
end end

View file

@ -13,11 +13,11 @@ class Api::V1::BookmarksController < Api::BaseController
private private
def load_statuses def load_statuses
preloaded_bookmarks cached_bookmarks
end end
def preloaded_bookmarks def cached_bookmarks
preload_collection(results.map(&:status), Status) cache_collection(results.map(&:status), Status)
end end
def results def results

View file

@ -13,11 +13,11 @@ class Api::V1::FavouritesController < Api::BaseController
private private
def load_statuses def load_statuses
preloaded_favourites cached_favourites
end end
def preloaded_favourites def cached_favourites
preload_collection(results.map(&:status), Status) cache_collection(results.map(&:status), Status)
end end
def results def results

View file

@ -12,6 +12,10 @@ class Api::V1::FeaturedTags::SuggestionsController < Api::BaseController
private private
def set_recently_used_tags def set_recently_used_tags
@recently_used_tags = Tag.suggestions_for_account(current_account).limit(10) @recently_used_tags = Tag.recently_used(current_account).where.not(id: featured_tag_ids).limit(10)
end
def featured_tag_ids
current_account.featured_tags.pluck(:tag_id)
end end
end end

View file

@ -41,7 +41,7 @@ class Api::V1::Notifications::RequestsController < Api::BaseController
) )
NotificationRequest.preload_cache_collection(requests) do |statuses| NotificationRequest.preload_cache_collection(requests) do |statuses|
preload_collection(statuses, Status) cache_collection(statuses, Status)
end end
end end

View file

@ -50,7 +50,7 @@ class Api::V1::NotificationsController < Api::BaseController
) )
Notification.preload_cache_collection_target_statuses(notifications) do |target_statuses| Notification.preload_cache_collection_target_statuses(notifications) do |target_statuses|
preload_collection(target_statuses, Status) cache_collection(target_statuses, Status)
end end
end end

View file

@ -1,12 +1,9 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::Push::SubscriptionsController < Api::BaseController class Api::V1::Push::SubscriptionsController < Api::BaseController
include Redisable
include Lockable
before_action -> { doorkeeper_authorize! :push } before_action -> { doorkeeper_authorize! :push }
before_action :require_user! before_action :require_user!
before_action :set_push_subscription, only: [:show, :update] before_action :set_push_subscription
before_action :check_push_subscription, only: [:show, :update] before_action :check_push_subscription, only: [:show, :update]
def show def show
@ -14,18 +11,16 @@ class Api::V1::Push::SubscriptionsController < Api::BaseController
end end
def create def create
with_redis_lock("push_subscription:#{current_user.id}") do @push_subscription&.destroy!
destroy_web_push_subscriptions!
@push_subscription = Web::PushSubscription.create!( @push_subscription = Web::PushSubscription.create!(
endpoint: subscription_params[:endpoint], endpoint: subscription_params[:endpoint],
key_p256dh: subscription_params[:keys][:p256dh], key_p256dh: subscription_params[:keys][:p256dh],
key_auth: subscription_params[:keys][:auth], key_auth: subscription_params[:keys][:auth],
data: data_params, data: data_params,
user_id: current_user.id, user_id: current_user.id,
access_token_id: doorkeeper_token.id access_token_id: doorkeeper_token.id
) )
end
render json: @push_subscription, serializer: REST::WebPushSubscriptionSerializer render json: @push_subscription, serializer: REST::WebPushSubscriptionSerializer
end end
@ -36,18 +31,14 @@ class Api::V1::Push::SubscriptionsController < Api::BaseController
end end
def destroy def destroy
destroy_web_push_subscriptions! @push_subscription&.destroy!
render_empty render_empty
end end
private private
def destroy_web_push_subscriptions!
doorkeeper_token.web_push_subscriptions.destroy_all
end
def set_push_subscription def set_push_subscription
@push_subscription = doorkeeper_token.web_push_subscriptions.first @push_subscription = Web::PushSubscription.find_by(access_token_id: doorkeeper_token.id)
end end
def check_push_subscription def check_push_subscription

View file

@ -23,7 +23,7 @@ class Api::V1::Statuses::RebloggedByAccountsController < Api::V1::Statuses::Base
end end
def paginated_statuses def paginated_statuses
Status.where(reblog_of_id: @status.id).distributable_visibility.paginate_by_max_id( Status.where(reblog_of_id: @status.id).where(visibility: [:public, :unlisted]).paginate_by_max_id(
limit_param(DEFAULT_ACCOUNTS_LIMIT), limit_param(DEFAULT_ACCOUNTS_LIMIT),
params[:max_id], params[:max_id],
params[:since_id] params[:since_id]

View file

@ -5,11 +5,9 @@ class Api::V1::StatusesController < Api::BaseController
before_action -> { authorize_if_got_token! :read, :'read:statuses' }, except: [:create, :update, :destroy] before_action -> { authorize_if_got_token! :read, :'read:statuses' }, except: [:create, :update, :destroy]
before_action -> { doorkeeper_authorize! :write, :'write:statuses' }, only: [:create, :update, :destroy] before_action -> { doorkeeper_authorize! :write, :'write:statuses' }, only: [:create, :update, :destroy]
before_action :require_user!, except: [:index, :show, :context] before_action :require_user!, except: [:show, :context]
before_action :set_statuses, only: [:index] before_action :set_status, only: [:show, :context]
before_action :set_status, only: [:show, :context] before_action :set_thread, only: [:create]
before_action :set_thread, only: [:create]
before_action :check_statuses_limit, only: [:index]
override_rate_limit_headers :create, family: :statuses override_rate_limit_headers :create, family: :statuses
override_rate_limit_headers :update, family: :statuses override_rate_limit_headers :update, family: :statuses
@ -25,14 +23,9 @@ class Api::V1::StatusesController < Api::BaseController
DESCENDANTS_LIMIT = 60 DESCENDANTS_LIMIT = 60
DESCENDANTS_DEPTH_LIMIT = 20 DESCENDANTS_DEPTH_LIMIT = 20
def index
@statuses = preload_collection(@statuses, Status)
render json: @statuses, each_serializer: REST::StatusSerializer
end
def show def show
cache_if_unauthenticated! cache_if_unauthenticated!
@status = preload_collection([@status], Status).first @status = cache_collection([@status], Status).first
render json: @status, serializer: REST::StatusSerializer render json: @status, serializer: REST::StatusSerializer
end end
@ -51,8 +44,8 @@ class Api::V1::StatusesController < Api::BaseController
ancestors_results = @status.in_reply_to_id.nil? ? [] : @status.ancestors(ancestors_limit, current_account) ancestors_results = @status.in_reply_to_id.nil? ? [] : @status.ancestors(ancestors_limit, current_account)
descendants_results = @status.descendants(descendants_limit, current_account, descendants_depth_limit) descendants_results = @status.descendants(descendants_limit, current_account, descendants_depth_limit)
loaded_ancestors = preload_collection(ancestors_results, Status) loaded_ancestors = cache_collection(ancestors_results, Status)
loaded_descendants = preload_collection(descendants_results, Status) loaded_descendants = cache_collection(descendants_results, Status)
@context = Context.new(ancestors: loaded_ancestors, descendants: loaded_descendants) @context = Context.new(ancestors: loaded_ancestors, descendants: loaded_descendants)
statuses = [@status] + @context.ancestors + @context.descendants statuses = [@status] + @context.ancestors + @context.descendants
@ -120,10 +113,6 @@ class Api::V1::StatusesController < Api::BaseController
private private
def set_statuses
@statuses = Status.permitted_statuses_from_ids(status_ids, current_account)
end
def set_status def set_status
@status = Status.find(params[:id]) @status = Status.find(params[:id])
authorize @status, :show? authorize @status, :show?
@ -138,18 +127,6 @@ class Api::V1::StatusesController < Api::BaseController
render json: { error: I18n.t('statuses.errors.in_reply_not_found') }, status: 404 render json: { error: I18n.t('statuses.errors.in_reply_not_found') }, status: 404
end end
def check_statuses_limit
raise(Mastodon::ValidationError) if status_ids.size > DEFAULT_STATUSES_LIMIT
end
def status_ids
Array(statuses_params[:ids]).uniq.map(&:to_i)
end
def statuses_params
params.permit(ids: [])
end
def status_params def status_params
params.permit( params.permit(
:status, :status,

View file

@ -15,11 +15,11 @@ class Api::V1::Timelines::DirectController < Api::BaseController
private private
def load_statuses def load_statuses
preloaded_direct_statuses cached_direct_statuses
end end
def preloaded_direct_statuses def cached_direct_statuses
preload_collection direct_statuses, Status cache_collection direct_statuses, Status
end end
def direct_statuses def direct_statuses

View file

@ -21,11 +21,11 @@ class Api::V1::Timelines::HomeController < Api::V1::Timelines::BaseController
private private
def load_statuses def load_statuses
preloaded_home_statuses cached_home_statuses
end end
def preloaded_home_statuses def cached_home_statuses
preload_collection home_statuses, Status cache_collection home_statuses, Status
end end
def home_statuses def home_statuses

View file

@ -21,11 +21,11 @@ class Api::V1::Timelines::ListController < Api::V1::Timelines::BaseController
end end
def set_statuses def set_statuses
@statuses = preloaded_list_statuses @statuses = cached_list_statuses
end end
def preloaded_list_statuses def cached_list_statuses
preload_collection list_statuses, Status cache_collection list_statuses, Status
end end
def list_statuses def list_statuses

View file

@ -18,11 +18,11 @@ class Api::V1::Timelines::PublicController < Api::V1::Timelines::BaseController
end end
def load_statuses def load_statuses
preloaded_public_statuses_page cached_public_statuses_page
end end
def preloaded_public_statuses_page def cached_public_statuses_page
preload_collection(public_statuses, Status) cache_collection(public_statuses, Status)
end end
def public_statuses def public_statuses

View file

@ -23,11 +23,11 @@ class Api::V1::Timelines::TagController < Api::V1::Timelines::BaseController
end end
def load_statuses def load_statuses
preloaded_tagged_statuses cached_tagged_statuses
end end
def preloaded_tagged_statuses def cached_tagged_statuses
@tag.nil? ? [] : preload_collection(tag_timeline_statuses, Status) @tag.nil? ? [] : cache_collection(tag_timeline_statuses, Status)
end end
def tag_timeline_statuses def tag_timeline_statuses

View file

@ -20,7 +20,7 @@ class Api::V1::Trends::StatusesController < Api::BaseController
def set_statuses def set_statuses
@statuses = if enabled? @statuses = if enabled?
preload_collection(statuses_from_trends.offset(offset_param).limit(limit_param(DEFAULT_STATUSES_LIMIT)), Status) cache_collection(statuses_from_trends.offset(offset_param).limit(limit_param(DEFAULT_STATUSES_LIMIT)), Status)
else else
[] []
end end

View file

@ -9,7 +9,6 @@ class ApplicationController < ActionController::Base
include UserTrackingConcern include UserTrackingConcern
include SessionTrackingConcern include SessionTrackingConcern
include CacheConcern include CacheConcern
include PreloadingConcern
include DomainControlHelper include DomainControlHelper
include ThemingConcern include ThemingConcern
include DatabaseHelper include DatabaseHelper
@ -20,7 +19,6 @@ class ApplicationController < ActionController::Base
helper_method :current_session helper_method :current_session
helper_method :current_flavour helper_method :current_flavour
helper_method :current_skin helper_method :current_skin
helper_method :current_theme
helper_method :single_user_mode? helper_method :single_user_mode?
helper_method :use_seamless_external_login? helper_method :use_seamless_external_login?
helper_method :omniauth_only? helper_method :omniauth_only?
@ -166,7 +164,10 @@ class ApplicationController < ActionController::Base
def respond_with_error(code) def respond_with_error(code)
respond_to do |format| respond_to do |format|
format.any { render "errors/#{code}", layout: 'error', status: code, formats: [:html] } format.any do
use_pack 'error'
render "errors/#{code}", layout: 'error', status: code, formats: [:html]
end
format.json { render json: { error: Rack::Utils::HTTP_STATUS_CODES[code] }, status: code } format.json { render json: { error: Rack::Utils::HTTP_STATUS_CODES[code] }, status: code }
end end
end end
@ -175,7 +176,10 @@ class ApplicationController < ActionController::Base
return unless self_destruct? return unless self_destruct?
respond_to do |format| respond_to do |format|
format.any { render 'errors/self_destruct', layout: 'auth', status: 410, formats: [:html] } format.any do
use_pack 'error'
render 'errors/self_destruct', layout: 'auth', status: 410, formats: [:html]
end
format.json { render json: { error: Rack::Utils::HTTP_STATUS_CODES[410] }, status: 410 } format.json { render json: { error: Rack::Utils::HTTP_STATUS_CODES[410] }, status: 410 }
end end
end end

View file

@ -5,6 +5,7 @@ class Auth::ChallengesController < ApplicationController
layout 'auth' layout 'auth'
before_action :set_pack
before_action :authenticate_user! before_action :authenticate_user!
skip_before_action :check_self_destruct! skip_before_action :check_self_destruct!
@ -20,4 +21,10 @@ class Auth::ChallengesController < ApplicationController
render_challenge render_challenge
end end
end end
private
def set_pack
use_pack 'auth'
end
end end

View file

@ -6,6 +6,7 @@ class Auth::ConfirmationsController < Devise::ConfirmationsController
layout 'auth' layout 'auth'
before_action :set_body_classes before_action :set_body_classes
before_action :set_pack
before_action :set_confirmation_user!, only: [:show, :confirm_captcha] before_action :set_confirmation_user!, only: [:show, :confirm_captcha]
before_action :redirect_confirmed_user, if: :signed_in_confirmed_user? before_action :redirect_confirmed_user, if: :signed_in_confirmed_user?
@ -65,6 +66,10 @@ class Auth::ConfirmationsController < Devise::ConfirmationsController
@confirmation_user.nil? || @confirmation_user.confirmed? @confirmation_user.nil? || @confirmation_user.confirmed?
end end
def set_pack
use_pack 'auth'
end
def redirect_confirmed_user def redirect_confirmed_user
redirect_to(current_user.approved? ? root_path : edit_user_registration_path) redirect_to(current_user.approved? ? root_path : edit_user_registration_path)
end end

View file

@ -3,6 +3,7 @@
class Auth::PasswordsController < Devise::PasswordsController class Auth::PasswordsController < Devise::PasswordsController
skip_before_action :check_self_destruct! skip_before_action :check_self_destruct!
before_action :redirect_invalid_reset_token, only: :edit, unless: :reset_password_token_is_valid? before_action :redirect_invalid_reset_token, only: :edit, unless: :reset_password_token_is_valid?
before_action :set_pack
before_action :set_body_classes before_action :set_body_classes
layout 'auth' layout 'auth'
@ -31,4 +32,8 @@ class Auth::PasswordsController < Devise::PasswordsController
def reset_password_token_is_valid? def reset_password_token_is_valid?
resource_class.with_reset_password_token(params[:reset_password_token]).present? resource_class.with_reset_password_token(params[:reset_password_token]).present?
end end
def set_pack
use_pack 'auth'
end
end end

View file

@ -9,6 +9,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController
before_action :set_invite, only: [:new, :create] before_action :set_invite, only: [:new, :create]
before_action :check_enabled_registrations, only: [:new, :create] before_action :check_enabled_registrations, only: [:new, :create]
before_action :configure_sign_up_params, only: [:create] before_action :configure_sign_up_params, only: [:create]
before_action :set_pack
before_action :set_sessions, only: [:edit, :update] before_action :set_sessions, only: [:edit, :update]
before_action :set_strikes, only: [:edit, :update] before_action :set_strikes, only: [:edit, :update]
before_action :set_body_classes, only: [:new, :create, :edit, :update] before_action :set_body_classes, only: [:new, :create, :edit, :update]
@ -96,6 +97,10 @@ class Auth::RegistrationsController < Devise::RegistrationsController
private private
def set_pack
use_pack %w(edit update).include?(action_name) ? 'admin' : 'auth'
end
def set_body_classes def set_body_classes
@body_classes = %w(edit update).include?(action_name) ? 'admin' : 'lighter' @body_classes = %w(edit update).include?(action_name) ? 'admin' : 'lighter'
end end

View file

@ -12,6 +12,7 @@ class Auth::SessionsController < Devise::SessionsController
skip_before_action :require_functional! skip_before_action :require_functional!
skip_before_action :update_user_sign_in skip_before_action :update_user_sign_in
prepend_before_action :set_pack
prepend_before_action :check_suspicious!, only: [:create] prepend_before_action :check_suspicious!, only: [:create]
include Auth::TwoFactorAuthenticationConcern include Auth::TwoFactorAuthenticationConcern
@ -103,6 +104,10 @@ class Auth::SessionsController < Devise::SessionsController
private private
def set_pack
use_pack 'auth'
end
def set_body_classes def set_body_classes
@body_classes = 'lighter' @body_classes = 'lighter'
end end

View file

@ -3,6 +3,7 @@
class Auth::SetupController < ApplicationController class Auth::SetupController < ApplicationController
layout 'auth' layout 'auth'
before_action :set_pack
before_action :authenticate_user! before_action :authenticate_user!
before_action :require_unconfirmed_or_pending! before_action :require_unconfirmed_or_pending!
before_action :set_body_classes before_action :set_body_classes
@ -42,4 +43,8 @@ class Auth::SetupController < ApplicationController
def user_params def user_params
params.require(:user).permit(:email) params.require(:user).permit(:email)
end end
def set_pack
use_pack 'sign_up'
end
end end

View file

@ -1,36 +0,0 @@
# frozen_string_literal: true
module Api::Pagination
extend ActiveSupport::Concern
protected
def pagination_max_id
pagination_collection.last.id
end
def pagination_since_id
pagination_collection.first.id
end
def set_pagination_headers(next_path = nil, prev_path = nil)
links = []
links << [next_path, [%w(rel next)]] if next_path
links << [prev_path, [%w(rel prev)]] if prev_path
response.headers['Link'] = LinkHeader.new(links) unless links.empty?
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
private
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def pagination_options_invalid?
params.slice(:limit, :offset).values.map(&:to_i).any?(&:negative?)
end
end

View file

@ -83,6 +83,8 @@ module Auth::TwoFactorAuthenticationConcern
def prompt_for_two_factor(user) def prompt_for_two_factor(user)
register_attempt_in_session(user) register_attempt_in_session(user)
use_pack 'auth'
@body_classes = 'lighter' @body_classes = 'lighter'
@webauthn_enabled = user.webauthn_enabled? @webauthn_enabled = user.webauthn_enabled?
@scheme_type = if user.webauthn_enabled? && user_params[:otp_attempt].blank? @scheme_type = if user.webauthn_enabled? && user_params[:otp_attempt].blank?

View file

@ -45,4 +45,28 @@ module CacheConcern
Rails.cache.write(key, response.body, expires_in: expires_in, raw: true) Rails.cache.write(key, response.body, expires_in: expires_in, raw: true)
end end
end end
def cache_collection(raw, klass)
return raw unless klass.respond_to?(:with_includes)
raw = raw.cache_ids.to_a if raw.is_a?(ActiveRecord::Relation)
return [] if raw.empty?
cached_keys_with_value = Rails.cache.read_multi(*raw).transform_keys(&:id)
uncached_ids = raw.map(&:id) - cached_keys_with_value.keys
klass.reload_stale_associations!(cached_keys_with_value.values) if klass.respond_to?(:reload_stale_associations!)
unless uncached_ids.empty?
uncached = klass.where(id: uncached_ids).with_includes.index_by(&:id)
Rails.cache.write_multi(uncached.values.to_h { |i| [i, i] })
end
raw.filter_map { |item| cached_keys_with_value[item.id] || uncached[item.id] }
end
def cache_collection_paginated_by_id(raw, klass, limit, options)
cache_collection raw.cache_ids.to_a_paginated_by_id(limit, options), klass
end
end end

View file

@ -1,17 +0,0 @@
# frozen_string_literal: true
module PreloadingConcern
extend ActiveSupport::Concern
def preload_collection(scope, klass)
return scope unless klass.respond_to?(:preload_cacheable_associations)
scope.to_a.tap do |records|
klass.preload_cacheable_associations(records)
end
end
def preload_collection_paginated_by_id(scope, klass, limit, options)
preload_collection scope.to_a_paginated_by_id(limit, options), klass
end
end

View file

@ -66,7 +66,7 @@ module SignatureVerification
compare_signed_string = build_signed_string(include_query_string: false) compare_signed_string = build_signed_string(include_query_string: false)
return actor unless verify_signature(actor, signature, compare_signed_string).nil? return actor unless verify_signature(actor, signature, compare_signed_string).nil?
actor = stoplight_wrapper.run { actor_refresh_key!(actor) } actor = stoplight_wrap_request { actor_refresh_key!(actor) }
raise SignatureVerificationError, "Could not refresh public key #{signature_params['keyId']}" if actor.nil? raise SignatureVerificationError, "Could not refresh public key #{signature_params['keyId']}" if actor.nil?
@ -226,10 +226,10 @@ module SignatureVerification
end end
if key_id.start_with?('acct:') if key_id.start_with?('acct:')
stoplight_wrapper.run { ResolveAccountService.new.call(key_id.delete_prefix('acct:'), suppress_errors: false) } stoplight_wrap_request { ResolveAccountService.new.call(key_id.delete_prefix('acct:'), suppress_errors: false) }
elsif !ActivityPub::TagManager.instance.local_uri?(key_id) elsif !ActivityPub::TagManager.instance.local_uri?(key_id)
account = ActivityPub::TagManager.instance.uri_to_actor(key_id) account = ActivityPub::TagManager.instance.uri_to_actor(key_id)
account ||= stoplight_wrapper.run { ActivityPub::FetchRemoteKeyService.new.call(key_id, suppress_errors: false) } account ||= stoplight_wrap_request { ActivityPub::FetchRemoteKeyService.new.call(key_id, suppress_errors: false) }
account account
end end
rescue Mastodon::PrivateNetworkAddressError => e rescue Mastodon::PrivateNetworkAddressError => e
@ -238,11 +238,12 @@ module SignatureVerification
raise SignatureVerificationError, e.message raise SignatureVerificationError, e.message
end end
def stoplight_wrapper def stoplight_wrap_request(&block)
Stoplight("source:#{request.remote_ip}") Stoplight("source:#{request.remote_ip}", &block)
.with_threshold(1) .with_threshold(1)
.with_cool_off_time(5.minutes.seconds) .with_cool_off_time(5.minutes.seconds)
.with_error_handler { |error, handle| error.is_a?(HTTP::Error) || error.is_a?(OpenSSL::SSL::SSLError) ? handle.call(error) : raise(error) } .with_error_handler { |error, handle| error.is_a?(HTTP::Error) || error.is_a?(OpenSSL::SSL::SSLError) ? handle.call(error) : raise(error) }
.run
end end
def actor_refresh_key!(actor) def actor_refresh_key!(actor)

View file

@ -3,22 +3,87 @@
module ThemingConcern module ThemingConcern
extend ActiveSupport::Concern extend ActiveSupport::Concern
def use_pack(pack_name)
@core = resolve_pack_with_common(Themes.instance.core, pack_name)
@theme = resolve_pack_with_common(Themes.instance.flavour(current_flavour), pack_name, current_skin)
end
private private
def current_flavour def current_flavour
@current_flavour ||= [current_user&.setting_flavour, Setting.flavour, 'glitch', 'vanilla'].find { |flavour| Themes.instance.flavours.include?(flavour) } [current_user&.setting_flavour, Setting.flavour, 'glitch', 'vanilla'].find { |flavour| Themes.instance.flavours.include?(flavour) }
end end
def current_skin def current_skin
@current_skin ||= begin skins = Themes.instance.skins_for(current_flavour)
skins = Themes.instance.skins_for(current_flavour) [current_user&.setting_skin, Setting.skin, 'default'].find { |skin| skins.include?(skin) }
[current_user&.setting_skin, Setting.skin, 'system', 'default'].find { |skin| skins.include?(skin) }
end
end end
def current_theme def valid_pack_data?(data, pack_name)
# NOTE: this is slightly different from upstream, as it's a derived value used data['pack'].is_a?(Hash) && data['pack'][pack_name].present?
# for the sole purpose of pointing to the appropriate stylesheet pack end
[current_flavour, current_skin]
def nil_pack(data)
{
use_common: true,
flavour: data['name'],
pack: nil,
preload: nil,
skin: nil,
supported_locales: data['locales'],
}
end
def pack(data, pack_name, skin)
pack_data = {
use_common: true,
flavour: data['name'],
pack: pack_name,
preload: nil,
skin: nil,
supported_locales: data['locales'],
}
return pack_data unless data['pack'][pack_name].is_a?(Hash)
pack_data[:use_common] = false if data['pack'][pack_name]['use_common'] == false
pack_data[:pack] = nil unless data['pack'][pack_name]['filename']
preloads = data['pack'][pack_name]['preload']
pack_data[:preload] = [preloads] if preloads.is_a?(String)
pack_data[:preload] = preloads if preloads.is_a?(Array)
if skin != 'default' && data['skin'][skin]
pack_data[:skin] = skin if data['skin'][skin].include?(pack_name)
elsif data['pack'][pack_name]['stylesheet']
pack_data[:skin] = 'default'
end
pack_data
end
def resolve_pack(data, pack_name, skin)
return pack(data, pack_name, skin) if valid_pack_data?(data, pack_name)
return if data['name'].blank?
fallbacks = []
if data.key?('fallback')
fallbacks = data['fallback'] if data['fallback'].is_a?(Array)
fallbacks = [data['fallback']] if data['fallback'].is_a?(String)
elsif data['name'] != Setting.default_settings['flavour']
fallbacks = [Setting.default_settings['flavour']]
end
fallbacks.each do |fallback|
return resolve_pack(Themes.instance.flavour(fallback), pack_name, skin) if Themes.instance.flavour(fallback)
end
nil
end
def resolve_pack_with_common(data, pack_name, skin = 'default')
result = resolve_pack(data, pack_name, skin) || nil_pack(data)
result[:common] = resolve_pack(data, 'common', skin) if result.delete(:use_common)
result
end end
end end

View file

@ -7,6 +7,7 @@ module WebAppControllerConcern
vary_by 'Accept, Accept-Language, Cookie' vary_by 'Accept, Accept-Language, Cookie'
before_action :redirect_unauthenticated_to_permalinks! before_action :redirect_unauthenticated_to_permalinks!
before_action :set_pack
before_action :set_app_body_class before_action :set_app_body_class
end end
@ -36,4 +37,8 @@ module WebAppControllerConcern
end end
end end
end end
def set_pack
use_pack 'home'
end
end end

View file

@ -9,10 +9,15 @@ class Disputes::BaseController < ApplicationController
before_action :set_body_classes before_action :set_body_classes
before_action :authenticate_user! before_action :authenticate_user!
before_action :set_pack
before_action :set_cache_headers before_action :set_cache_headers
private private
def set_pack
use_pack 'admin'
end
def set_body_classes def set_body_classes
@body_classes = 'admin' @body_classes = 'admin'
end end

View file

@ -6,6 +6,7 @@ class Filters::StatusesController < ApplicationController
before_action :authenticate_user! before_action :authenticate_user!
before_action :set_filter before_action :set_filter
before_action :set_status_filters before_action :set_status_filters
before_action :set_pack
before_action :set_body_classes before_action :set_body_classes
before_action :set_cache_headers before_action :set_cache_headers
@ -26,6 +27,10 @@ class Filters::StatusesController < ApplicationController
private private
def set_pack
use_pack 'admin'
end
def set_filter def set_filter
@filter = current_account.custom_filters.find(params[:filter_id]) @filter = current_account.custom_filters.find(params[:filter_id])
end end

View file

@ -5,6 +5,7 @@ class FiltersController < ApplicationController
before_action :authenticate_user! before_action :authenticate_user!
before_action :set_filter, only: [:edit, :update, :destroy] before_action :set_filter, only: [:edit, :update, :destroy]
before_action :set_pack
before_action :set_body_classes before_action :set_body_classes
before_action :set_cache_headers before_action :set_cache_headers
@ -44,6 +45,10 @@ class FiltersController < ApplicationController
private private
def set_pack
use_pack 'settings'
end
def set_filter def set_filter
@filter = current_account.custom_filters.find(params[:id]) @filter = current_account.custom_filters.find(params[:id])
end end

View file

@ -6,6 +6,7 @@ class InvitesController < ApplicationController
layout 'admin' layout 'admin'
before_action :authenticate_user! before_action :authenticate_user!
before_action :set_pack
before_action :set_body_classes before_action :set_body_classes
before_action :set_cache_headers before_action :set_cache_headers
@ -39,6 +40,10 @@ class InvitesController < ApplicationController
private private
def set_pack
use_pack 'settings'
end
def invites def invites
current_user.invites.order(id: :desc) current_user.invites.order(id: :desc)
end end

View file

@ -10,6 +10,7 @@ class MediaController < ApplicationController
before_action :verify_permitted_status! before_action :verify_permitted_status!
before_action :check_playable, only: :player before_action :check_playable, only: :player
before_action :allow_iframing, only: :player before_action :allow_iframing, only: :player
before_action :set_pack, only: :player
content_security_policy only: :player do |policy| content_security_policy only: :player do |policy|
policy.frame_ancestors(false) policy.frame_ancestors(false)
@ -47,4 +48,8 @@ class MediaController < ApplicationController
def allow_iframing def allow_iframing
response.headers.delete('X-Frame-Options') response.headers.delete('X-Frame-Options')
end end
def set_pack
use_pack 'public'
end
end end

View file

@ -5,6 +5,7 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
before_action :store_current_location before_action :store_current_location
before_action :authenticate_resource_owner! before_action :authenticate_resource_owner!
before_action :set_pack
before_action :set_cache_headers before_action :set_cache_headers
content_security_policy do |p| content_security_policy do |p|
@ -19,6 +20,10 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
store_location_for(:user, request.url) store_location_for(:user, request.url)
end end
def set_pack
use_pack 'auth'
end
def render_success def render_success
if skip_authorization? || (matching_token? && !truthy_param?('force_login')) if skip_authorization? || (matching_token? && !truthy_param?('force_login'))
redirect_or_render authorize_response redirect_or_render authorize_response

View file

@ -5,6 +5,7 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio
before_action :store_current_location before_action :store_current_location
before_action :authenticate_resource_owner! before_action :authenticate_resource_owner!
before_action :set_pack
before_action :require_not_suspended!, only: :destroy before_action :require_not_suspended!, only: :destroy
before_action :set_body_classes before_action :set_body_classes
before_action :set_cache_headers before_action :set_cache_headers
@ -30,6 +31,10 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio
store_location_for(:user, request.url) store_location_for(:user, request.url)
end end
def set_pack
use_pack 'settings'
end
def require_not_suspended! def require_not_suspended!
forbidden if current_account.unavailable? forbidden if current_account.unavailable?
end end

View file

@ -3,6 +3,7 @@
class Redirect::BaseController < ApplicationController class Redirect::BaseController < ApplicationController
vary_by 'Accept-Language' vary_by 'Accept-Language'
before_action :set_pack
before_action :set_resource before_action :set_resource
before_action :set_app_body_class before_action :set_app_body_class
@ -21,4 +22,8 @@ class Redirect::BaseController < ApplicationController
def set_resource def set_resource
raise NotImplementedError raise NotImplementedError
end end
def set_pack
use_pack 'public'
end
end end

View file

@ -5,6 +5,7 @@ class RelationshipsController < ApplicationController
before_action :authenticate_user! before_action :authenticate_user!
before_action :set_accounts, only: :show before_action :set_accounts, only: :show
before_action :set_pack
before_action :set_relationships, only: :show before_action :set_relationships, only: :show
before_action :set_body_classes before_action :set_body_classes
before_action :set_cache_headers before_action :set_cache_headers
@ -72,6 +73,10 @@ class RelationshipsController < ApplicationController
@body_classes = 'admin' @body_classes = 'admin'
end end
def set_pack
use_pack 'admin'
end
def set_cache_headers def set_cache_headers
response.cache_control.replace(private: true, no_store: true) response.cache_control.replace(private: true, no_store: true)
end end

View file

@ -13,7 +13,7 @@ class Settings::ApplicationsController < Settings::BaseController
def new def new
@application = Doorkeeper::Application.new( @application = Doorkeeper::Application.new(
redirect_uri: Doorkeeper.configuration.native_redirect_uri, redirect_uri: Doorkeeper.configuration.native_redirect_uri,
scopes: 'read:me' scopes: 'read write follow'
) )
end end

View file

@ -1,6 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
class Settings::BaseController < ApplicationController class Settings::BaseController < ApplicationController
before_action :set_pack
layout 'admin' layout 'admin'
before_action :authenticate_user! before_action :authenticate_user!
@ -9,6 +10,10 @@ class Settings::BaseController < ApplicationController
private private
def set_pack
use_pack 'settings'
end
def set_body_classes def set_body_classes
@body_classes = 'admin' @body_classes = 'admin'
end end

View file

@ -38,7 +38,7 @@ class Settings::FeaturedTagsController < Settings::BaseController
end end
def set_recently_used_tags def set_recently_used_tags
@recently_used_tags = Tag.suggestions_for_account(current_account).limit(10) @recently_used_tags = Tag.recently_used(current_account).where.not(id: @featured_tags.map(&:id)).limit(10)
end end
def featured_tag_params def featured_tag_params

View file

@ -31,7 +31,7 @@ class Settings::ImportsController < Settings::BaseController
def show; end def show; end
def failures def failures
@bulk_import = current_account.bulk_imports.state_finished.find(params[:id]) @bulk_import = current_account.bulk_imports.where(state: :finished).find(params[:id])
respond_to do |format| respond_to do |format|
format.csv do format.csv do
@ -92,7 +92,7 @@ class Settings::ImportsController < Settings::BaseController
end end
def set_bulk_import def set_bulk_import
@bulk_import = current_account.bulk_imports.state_unconfirmed.find(params[:id]) @bulk_import = current_account.bulk_imports.where(state: :unconfirmed).find(params[:id])
end end
def set_recent_imports def set_recent_imports

View file

@ -7,4 +7,10 @@ class Settings::LoginActivitiesController < Settings::BaseController
def index def index
@login_activities = LoginActivity.where(user: current_user).order(id: :desc).page(params[:page]) @login_activities = LoginActivity.where(user: current_user).order(id: :desc).page(params[:page])
end end
private
def set_pack
use_pack 'settings'
end
end end

View file

@ -85,6 +85,10 @@ module Settings
private private
def set_pack
use_pack 'auth'
end
def redirect_invalid_otp def redirect_invalid_otp
flash[:error] = t('webauthn_credentials.otp_required') flash[:error] = t('webauthn_credentials.otp_required')
redirect_to settings_two_factor_authentication_methods_path redirect_to settings_two_factor_authentication_methods_path

View file

@ -4,12 +4,17 @@ class SharesController < ApplicationController
layout 'modal' layout 'modal'
before_action :authenticate_user! before_action :authenticate_user!
before_action :set_pack
before_action :set_body_classes before_action :set_body_classes
def show; end def show; end
private private
def set_pack
use_pack 'share'
end
def set_body_classes def set_body_classes
@body_classes = 'modal-layout compose-standalone' @body_classes = 'modal-layout compose-standalone'
end end

View file

@ -6,6 +6,7 @@ class StatusesCleanupController < ApplicationController
before_action :authenticate_user! before_action :authenticate_user!
before_action :set_policy before_action :set_policy
before_action :set_body_classes before_action :set_body_classes
before_action :set_pack
before_action :set_cache_headers before_action :set_cache_headers
def show; end def show; end
@ -26,6 +27,10 @@ class StatusesCleanupController < ApplicationController
private private
def set_pack
use_pack 'settings'
end
def set_policy def set_policy
@policy = current_account.statuses_cleanup_policy || current_account.build_statuses_cleanup_policy(enabled: false) @policy = current_account.statuses_cleanup_policy || current_account.build_statuses_cleanup_policy(enabled: false)
end end

View file

@ -41,6 +41,7 @@ class StatusesController < ApplicationController
end end
def embed def embed
use_pack 'embed'
return not_found if @status.hidden? || @status.reblog? return not_found if @status.hidden? || @status.reblog?
expires_in 180, public: true expires_in 180, public: true

View file

@ -45,7 +45,7 @@ class TagsController < ApplicationController
end end
def set_statuses def set_statuses
@statuses = preload_collection(TagFeed.new(@tag, nil, local: @local).get(limit_param), Status) @statuses = cache_collection(TagFeed.new(@tag, nil, local: @local).get(limit_param), Status)
end end
def limit_param def limit_param

View file

@ -1,23 +0,0 @@
# frozen_string_literal: true
module WellKnown
class OauthMetadataController < ActionController::Base # rubocop:disable Rails/ApplicationController
include CacheConcern
# Prevent `active_model_serializer`'s `ActionController::Serialization` from calling `current_user`
# and thus re-issuing session cookies
serialization_scope nil
def show
# Due to this document potentially changing between Mastodon versions (as
# new OAuth scopes are added), we don't use expires_in to cache upstream,
# instead just caching in the rails cache:
render_with_cache(
json: ::OauthMetadataPresenter.new,
serializer: ::OauthMetadataSerializer,
content_type: 'application/json',
expires_in: 15.minutes
)
end
end
end

View file

@ -113,14 +113,6 @@ module ApplicationHelper
content_tag(:i, nil, attributes.merge(class: class_names.join(' '))) content_tag(:i, nil, attributes.merge(class: class_names.join(' ')))
end end
def material_symbol(icon, attributes = {})
inline_svg_tag(
"400-24px/#{icon}.svg",
class: %w(icon).concat(attributes[:class].to_s.split),
role: :img
)
end
def check_icon def check_icon
inline_svg_tag 'check.svg' inline_svg_tag 'check.svg'
end end
@ -241,41 +233,6 @@ module ApplicationHelper
EmojiFormatter.new(html, custom_emojis, other_options.merge(animate: prefers_autoplay?)).to_s EmojiFormatter.new(html, custom_emojis, other_options.merge(animate: prefers_autoplay?)).to_s
end end
def mascot_url
full_asset_url(instance_presenter.mascot&.file&.url || frontend_asset_path('images/elephant_ui_plane.svg'))
end
def instance_presenter
@instance_presenter ||= InstancePresenter.new
end
def favicon_path(size = '48')
instance_presenter.favicon&.file&.url(size)
end
def app_icon_path(size = '48')
instance_presenter.app_icon&.file&.url(size)
end
# glitch-soc addition to handle the multiple flavors
def preload_locale_pack
supported_locales = Themes.instance.flavour(current_flavour)['locales']
preload_pack_asset "locales/#{current_flavour}/#{I18n.locale}-json.js" if supported_locales.include?(I18n.locale.to_s)
end
def flavoured_javascript_pack_tag(pack_name, **options)
javascript_pack_tag("flavours/#{current_flavour}/#{pack_name}", **options)
end
def flavoured_stylesheet_pack_tag(pack_name, **options)
stylesheet_pack_tag("flavours/#{current_flavour}/#{pack_name}", **options)
end
def preload_signed_in_js_packs
preload_files = Themes.instance.flavour(current_flavour)&.fetch('signed_in_preload', nil) || []
safe_join(preload_files.map { |entry| preload_pack_asset entry })
end
private private
def storage_host_var def storage_host_var

View file

@ -19,6 +19,6 @@ module BrandingHelper
end end
def render_logo def render_logo
image_tag(frontend_asset_path('images/logo.svg'), alt: 'Mastodon', class: 'logo logo--icon') image_pack_tag('logo.svg', alt: 'Mastodon', class: 'logo logo--icon')
end end
end end

View file

@ -49,11 +49,13 @@ module ContextHelper
end end
def serialized_context(named_contexts_map, context_extensions_map) def serialized_context(named_contexts_map, context_extensions_map)
context_array = []
named_contexts = named_contexts_map.keys named_contexts = named_contexts_map.keys
context_extensions = context_extensions_map.keys context_extensions = context_extensions_map.keys
context_array = named_contexts.map do |key| named_contexts.each do |key|
NAMED_CONTEXT_MAP[key] context_array << NAMED_CONTEXT_MAP[key]
end end
extensions = context_extensions.each_with_object({}) do |key, h| extensions = context_extensions.each_with_object({}) do |key, h|

View file

@ -0,0 +1,11 @@
# frozen_string_literal: true
module MascotHelper
def mascot_url
full_asset_url(instance_presenter.mascot&.file&.url || frontend_asset_path('images/elephant_ui_plane.svg'))
end
def instance_presenter
@instance_presenter ||= InstancePresenter.new
end
end

View file

@ -14,12 +14,6 @@ module RoutingHelper
end end
end end
def redirect_asset_url(source)
Request.new(:head, source, follow: false).perform do |res|
res.code == 301 ? res.headers['location'] : source
end
end
def full_asset_url(source, **options) def full_asset_url(source, **options)
source = ActionController::Base.helpers.asset_url(source, **options) unless use_storage? source = ActionController::Base.helpers.asset_url(source, **options) unless use_storage?

View file

@ -10,11 +10,11 @@ module StatusesHelper
end end
end end
def attachment_types(status) def media_summary(status)
attachments = { image: 0, video: 0, audio: 0 } attachments = { image: 0, video: 0, audio: 0 }
status.ordered_media_attachments.each do |media| status.ordered_media_attachments.each do |media|
if media.video? || media.gifv? if media.video?
attachments[:video] += 1 attachments[:video] += 1
elsif media.audio? elsif media.audio?
attachments[:audio] += 1 attachments[:audio] += 1
@ -23,12 +23,6 @@ module StatusesHelper
end end
end end
attachments
end
def media_summary(status)
attachments = attachment_types(status)
text = attachments.to_a.reject { |_, value| value.zero? }.map { |key, value| I18n.t("statuses.attached.#{key}", count: value) }.join(' · ') text = attachments.to_a.reject { |_, value| value.zero? }.map { |key, value| I18n.t("statuses.attached.#{key}", count: value) }.join(' · ')
return if text.blank? return if text.blank?

View file

@ -1,31 +0,0 @@
# frozen_string_literal: true
module ThemeHelper
def theme_style_tags(flavour_and_skin)
flavour, theme = flavour_and_skin
if theme == 'system'
stylesheet_pack_tag("skins/#{flavour}/mastodon-light", media: 'not all and (prefers-color-scheme: dark)', crossorigin: 'anonymous') +
stylesheet_pack_tag("skins/#{flavour}/default", media: '(prefers-color-scheme: dark)', crossorigin: 'anonymous')
else
stylesheet_pack_tag "skins/#{flavour}/#{theme}", media: 'all', crossorigin: 'anonymous'
end
end
def theme_color_tags(flavour_and_skin)
_, theme = flavour_and_skin
if theme == 'system'
tag.meta(name: 'theme-color', content: Themes::THEME_COLORS[:dark], media: '(prefers-color-scheme: dark)') +
tag.meta(name: 'theme-color', content: Themes::THEME_COLORS[:light], media: '(prefers-color-scheme: light)')
else
tag.meta name: 'theme-color', content: theme_color_for(theme)
end
end
private
def theme_color_for(theme)
theme == 'mastodon-light' ? Themes::THEME_COLORS[:light] : Themes::THEME_COLORS[:dark]
end
end

View file

@ -1,5 +1,6 @@
import './public-path'; // This file will be loaded on admin pages, regardless of theme.
import { createRoot } from 'react-dom/client';
import 'packs/public-path';
import Rails from '@rails/ujs'; import Rails from '@rails/ujs';
@ -260,31 +261,6 @@ Rails.delegate(
}, },
); );
async function mountReactComponent(element: Element) {
const componentName = element.getAttribute('data-admin-component');
const stringProps = element.getAttribute('data-props');
if (!stringProps) return;
const componentProps = JSON.parse(stringProps) as object;
const { default: AdminComponent } = await import(
'@/mastodon/containers/admin_component'
);
const { default: Component } = (await import(
`@/mastodon/components/admin/${componentName}`
)) as { default: React.ComponentType };
const root = createRoot(element);
root.render(
<AdminComponent>
<Component {...componentProps} />
</AdminComponent>,
);
}
ready(() => { ready(() => {
const domainBlockSeveritySelect = document.querySelector<HTMLSelectElement>( const domainBlockSeveritySelect = document.querySelector<HTMLSelectElement>(
'select#domain_block_severity', 'select#domain_block_severity',
@ -359,10 +335,6 @@ ready(() => {
if (announcementStartsAt) { if (announcementStartsAt) {
setAnnouncementEndsAttributes(announcementStartsAt); setAnnouncementEndsAttributes(announcementStartsAt);
} }
}).catch((reason) => {
document.querySelectorAll('[data-admin-component]').forEach((element) => {
void mountReactComponent(element);
});
}).catch((reason: unknown) => {
throw reason; throw reason;
}); });

View file

@ -0,0 +1,3 @@
import 'packs/public-path';
import './settings';
import './two_factor_authentication';

View file

@ -0,0 +1,6 @@
// This file will be loaded on all pages, regardless of theme.
import 'packs/public-path';
import 'font-awesome/css/font-awesome.css';
require.context('../images/', true);

View file

@ -0,0 +1,41 @@
// This file will be loaded on embed pages, regardless of theme.
import 'packs/public-path';
import ready from '../mastodon/ready';
interface SetHeightMessage {
type: 'setHeight';
id: string;
height: number;
}
function isSetHeightMessage(data: unknown): data is SetHeightMessage {
if (
data &&
typeof data === 'object' &&
'type' in data &&
data.type === 'setHeight'
)
return true;
else return false;
}
window.addEventListener('message', (e) => {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- typings are not correct, it can be null in very rare cases
if (!e.data || !isSetHeightMessage(e.data) || !window.parent) return;
const data = e.data;
ready(() => {
window.parent.postMessage(
{
type: 'setHeight',
id: data.id,
height: document.getElementsByTagName('html')[0].scrollHeight,
},
'*',
);
}).catch((e) => {
console.error('Error in setHeightMessage postMessage', e);
});
});

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