Compare commits
360 commits
kb_develop
...
kbtopic-re
Author | SHA1 | Date | |
---|---|---|---|
|
91e252259d | ||
|
f3c3ea42c2 | ||
|
3aed93711c | ||
|
f53bb4cd7d | ||
|
9896bed85f | ||
|
2c828748a3 | ||
|
1623d54ec0 | ||
|
722fb1ff55 | ||
|
933ee420c3 | ||
|
0cdf11d6ad | ||
|
a13b33d851 | ||
|
8cf246e4d3 | ||
|
629bb74451 | ||
|
b8cc9b3290 | ||
|
2c085ea044 | ||
|
bb89a64af0 | ||
|
c543e823ab | ||
|
7a7e0ba4cd | ||
|
c727701839 | ||
|
1824b1fd29 | ||
|
1bf8a642f0 | ||
|
dc2cfd50a0 | ||
|
a2a6117143 | ||
|
24803db2bc | ||
|
90183b6c27 | ||
|
c3022fe10f | ||
|
f3d60a4a6f | ||
|
1dd8a99d9f | ||
|
66a42c11ba | ||
|
132f32dd70 | ||
|
e557769a3c | ||
|
d887790e86 | ||
|
d0c6f30378 | ||
|
ba75ba3adc | ||
|
c92e21813e | ||
|
076005eae2 | ||
|
b10fde673d | ||
|
68810643d8 | ||
|
f2cfa4f482 | ||
|
989ca63b59 | ||
|
f2cdbefa3c | ||
|
86627624f1 | ||
|
c09f9a93f1 | ||
|
963f4977d6 | ||
|
5fde019e39 | ||
|
520974e052 | ||
|
3d474807bf | ||
|
09208eafa4 | ||
|
25c4574480 | ||
|
e2c5a2abaa | ||
|
a80f77a996 | ||
|
1297ad759e | ||
|
1fdcaaebbb | ||
|
375add0c83 | ||
|
a4bc438010 | ||
|
1d152d2181 | ||
|
250c3b0c1f | ||
|
1dafd8c9dd | ||
|
6637ecb460 | ||
|
e9f197740d | ||
|
12c0e58d9a | ||
|
f7c19226cf | ||
|
b64ad77e21 | ||
|
37bf59f76a | ||
|
129e72b914 | ||
|
6d12831686 | ||
|
efe8def0c6 | ||
|
8224178e8c | ||
|
d4bbe8b719 | ||
|
c77158c8b7 | ||
|
9c80b16401 | ||
|
eb42425427 | ||
|
00b56932de | ||
|
d47199dd4b | ||
|
0182fc389e | ||
|
7036d5ad25 | ||
|
11481df4dc | ||
|
0d5123199f | ||
|
1b11bb23d7 | ||
|
d051366308 | ||
|
7f4ec7d9cf | ||
|
32b521b7f4 | ||
|
44d71d59ef | ||
|
1cc853059f | ||
|
7efe20337c | ||
|
54ad57ea95 | ||
|
064d333620 | ||
|
4b39bced3e | ||
|
0789ec93f8 | ||
|
975db93e3f | ||
|
c025824f98 | ||
|
9860046b04 | ||
|
71a4a92dda | ||
|
426ee069b5 | ||
|
7fc10bc7b0 | ||
|
4130d9659c | ||
|
208dbb8821 | ||
|
3c09fd3f89 | ||
|
f7a3dd0e38 | ||
|
a1c260696f | ||
|
ebdb80168e | ||
|
c538c23ef7 | ||
|
b8239dc9b1 | ||
|
96bc94160d | ||
|
7ee568f2c4 | ||
|
b6c12c6d1f | ||
|
ca41a95872 | ||
|
6e16cac09f | ||
|
38e0a360ca | ||
|
b195956ecb | ||
|
a73ade526a | ||
|
6ffa262546 | ||
|
991796172a | ||
|
71d46e26b2 | ||
|
887533392f | ||
|
43ccb04548 | ||
|
75ae084976 | ||
|
474013b48c | ||
|
9d7ecf92fe | ||
|
d78535eab9 | ||
|
7ede5460d8 | ||
|
32b5da558e | ||
|
7132e660a6 | ||
|
0372344d33 | ||
|
2fddfbf0c2 | ||
|
c60b6aa65d | ||
|
0c27b62a25 | ||
|
7c65b6f9df | ||
|
37c82a3003 | ||
|
ba5320671c | ||
|
47512fe518 | ||
|
955e75e820 | ||
|
b7e967817b | ||
|
198b59ca3e | ||
|
b3615a803e | ||
|
170668ed69 | ||
|
d1d3ff087a | ||
|
558c73a21e | ||
|
e0f15a6875 | ||
|
a13756148d | ||
|
304c0417ed | ||
|
3bf128e62a | ||
|
84d03e4e16 | ||
|
68a5724b3e | ||
|
229e100dc0 | ||
|
11c8177498 | ||
|
bd2988bdf4 | ||
|
6b066eac2c | ||
|
5dda094daa | ||
|
02ac18da51 | ||
|
3acd87419c | ||
|
e0ce4b9b6b | ||
|
ef1bf8e9f2 | ||
|
12c8a6498c | ||
|
da60acced5 | ||
|
80849fbfba | ||
|
79ccba1758 | ||
|
72356bd5ec | ||
|
6664f16b14 | ||
|
cddb69ed52 | ||
|
68f951b945 | ||
|
f1172ca8fe | ||
|
e9d62b284a | ||
|
8d4ae81ab4 | ||
|
83dd09d4dc | ||
|
6ab96ba647 | ||
|
97b9e8849d | ||
|
f1a6f4333a | ||
|
3a5e310a6d | ||
|
8c51a8ba94 | ||
|
977164decc | ||
|
67f5122ba6 | ||
|
30ee67e2c6 | ||
|
07741f307e | ||
|
d8ea8bc3bb | ||
|
f7182ddc8b | ||
|
4709121f72 | ||
|
dab31f7a88 | ||
|
855022f4d9 | ||
|
a8f12a6fd8 | ||
|
ef87cd6910 | ||
|
042a9c42be | ||
|
6d6263ce07 | ||
|
f94b1fce41 | ||
|
d7cb6068b1 | ||
|
8ed0408adb | ||
|
0ada6e4168 | ||
|
0d809652d9 | ||
|
dbf14784bf | ||
|
8ab2c4a9fc | ||
|
4372d17114 | ||
|
65f338c812 | ||
|
39eff1c3ca | ||
|
feb4e0a007 | ||
|
24551375cf | ||
|
90f7b90223 | ||
|
e291f95a04 | ||
|
b981175f08 | ||
|
695f0c5eaa | ||
|
2e4ba88ceb | ||
|
3d2bc0c513 | ||
|
9d4ec09e7a | ||
|
2d13a41462 | ||
|
b4bbea51c4 | ||
|
9e2c0c4cef | ||
|
48922c6aff | ||
|
6d6e1ed958 | ||
|
6452796879 | ||
|
8cc5084ca1 | ||
|
c4f47adb49 | ||
|
a5a2c6dc7e | ||
|
3ea1f074ab | ||
|
c058c45a8e | ||
|
24d3599690 | ||
|
6c743831aa | ||
|
3f965d83b0 | ||
|
ae281f31db | ||
|
e17c78b679 | ||
|
ccffa11f2b | ||
|
d475bcce65 | ||
|
1b68020331 | ||
|
e8e93b82f1 | ||
|
aa04efb92a | ||
|
c45ce549af | ||
|
8d5b73d70d | ||
|
16e36d8477 | ||
|
545e8fbd0c | ||
|
865a30ab0d | ||
|
cc57fa4a41 | ||
|
5305e939c4 | ||
|
f993d7578b | ||
|
65baf9b04a | ||
|
050d76c010 | ||
|
b135a831ea | ||
|
04070aa608 | ||
|
1e8420464c | ||
|
c9a554bdca | ||
|
5ec840a32f | ||
|
b709ef8ac3 | ||
|
4e2aa78a56 | ||
|
3357ae9889 | ||
|
6fa48fabb2 | ||
|
9244ffc425 | ||
|
82688387a8 | ||
|
23238ddd95 | ||
|
912268295c | ||
|
face71b7b2 | ||
|
7cd7445abe | ||
|
1131f2c439 | ||
|
8c579c5b34 | ||
|
741f166407 | ||
|
0c738ea0ca | ||
|
6ac29ab1ac | ||
|
b99abe44b0 | ||
|
acc662e490 | ||
|
35386bd054 | ||
|
0557257647 | ||
|
9de0de7d65 | ||
|
7d80e90976 | ||
|
721f6f9c97 | ||
|
29b904483e | ||
|
9d64a77bcf | ||
|
fbe9728f36 | ||
|
3bbf3e9709 | ||
|
79931bf3ae | ||
|
22e2e7f02b | ||
|
41d00bc28b | ||
|
3e5d78cc5b | ||
|
df6b808750 | ||
|
aedc5f6921 | ||
|
89cafb01b4 | ||
|
2133f2b47e | ||
|
833ea0725d | ||
|
eacf6f2342 | ||
|
84bca6fd54 | ||
|
cbaba54e9d | ||
|
d41a741e00 | ||
|
03a0f7caf9 | ||
|
8b34daf254 | ||
|
b4394ec129 | ||
|
24c25ec4f5 | ||
|
94fa5b7168 | ||
|
4354f84c5c | ||
|
e3f0b955b8 | ||
|
05f6f7d28a | ||
|
64ab9be93f | ||
|
a2310a06fa | ||
|
79013c730d | ||
|
b81c28e7dc | ||
|
ce13fca0c5 | ||
|
98e6dfcbcf | ||
|
7cb93ef5a1 | ||
|
66d9e47178 | ||
|
e7dd0b37c7 | ||
|
b0e63fbe1c | ||
|
e96044f389 | ||
|
715cbee93d | ||
|
17d8e2b6e3 | ||
|
bd9223f0b9 | ||
|
40157e063d | ||
|
926c67c648 | ||
|
17e4345eb2 | ||
|
9ed6a14d45 | ||
|
1a1f3f037d | ||
|
3032d9d0dd | ||
|
a20686f593 | ||
|
7696122cfc | ||
|
ffb4ca4231 | ||
|
c6b740ace2 | ||
|
3233caba60 | ||
|
80542ea172 | ||
|
ae3b7dd28d | ||
|
8f59b63176 | ||
|
82b6413f61 | ||
|
a88d202c6b | ||
|
e4c72836a3 | ||
|
89358f1750 | ||
|
2c268e47e7 | ||
|
a97647158c | ||
|
49b6a49c76 | ||
|
d4944a2467 | ||
|
91db45b197 | ||
|
7a70d95435 | ||
|
1326c8cb1d | ||
|
199acce481 | ||
|
b1b949f16c | ||
|
6463415e06 | ||
|
22ec828951 | ||
|
13b13c8726 | ||
|
5679bb5394 | ||
|
1fc66c1970 | ||
|
57a6c5f4e9 | ||
|
65c67fb827 | ||
|
d845d1e9fb | ||
|
ca4139be07 | ||
|
ffc853c086 | ||
|
577e407ffc | ||
|
b68c622a07 | ||
|
7bc301e184 | ||
|
dee744c793 | ||
|
e097f0e9eb | ||
|
6027764c31 | ||
|
b754e28190 | ||
|
cba4682ced | ||
|
b92f42a6bd | ||
|
8dea1c422a | ||
|
bc32ff9b57 | ||
|
20162a821c | ||
|
3159f3b2f6 | ||
|
361f528c89 | ||
|
bed614d44e | ||
|
64d94f9e57 | ||
|
8489f6c8fc | ||
|
c01d219c12 | ||
|
ee62ac53e1 | ||
|
b33f9ea603 | ||
|
b64a5a7d84 | ||
|
3dc95902d7 | ||
|
5810bd3310 | ||
|
df2611a10f |
|
@ -9,6 +9,7 @@ services:
|
|||
environment:
|
||||
RAILS_ENV: development
|
||||
NODE_ENV: development
|
||||
VITE_RUBY_HOST: 0.0.0.0
|
||||
BIND: 0.0.0.0
|
||||
BOOTSNAP_CACHE_DIR: /tmp
|
||||
REDIS_HOST: redis
|
||||
|
@ -22,11 +23,12 @@ services:
|
|||
ES_PORT: '9200'
|
||||
LIBRE_TRANSLATE_ENDPOINT: http://libretranslate:5000
|
||||
LOCAL_DOMAIN: ${LOCAL_DOMAIN:-localhost:3000}
|
||||
VITE_DEV_SERVER_PUBLIC: ${VITE_DEV_SERVER_PUBLIC:-localhost:3036}
|
||||
# Overrides default command so things don't shut down after the process ends.
|
||||
command: sleep infinity
|
||||
ports:
|
||||
- '3000:3000'
|
||||
- '3035:3035'
|
||||
- '3036:3036'
|
||||
- '4000:4000'
|
||||
networks:
|
||||
- external_network
|
||||
|
|
|
@ -2,3 +2,5 @@
|
|||
ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY=fkSxKD2bF396kdQbrP1EJ7WbU7ZgNokR
|
||||
ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT=r0hvVmzBVsjxC7AMlwhOzmtc36ZCOS1E
|
||||
ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY=PhdFyyfy5xJ7WVd2lWBpcPScRQHzRTNr
|
||||
|
||||
MASTODON_USE_LIBVIPS=false
|
||||
|
|
|
@ -43,7 +43,6 @@ ES_PASS=password
|
|||
# Make sure to use `bundle exec rails secret` to generate secrets
|
||||
# -------
|
||||
SECRET_KEY_BASE=
|
||||
OTP_SECRET=
|
||||
|
||||
# Encryption secrets
|
||||
# ------------------
|
||||
|
@ -110,6 +109,3 @@ FETCH_REPLIES_MAX_SINGLE=500
|
|||
|
||||
# Max number of replies Collection pages to fetch - total
|
||||
FETCH_REPLIES_MAX_PAGES=500
|
||||
|
||||
# Maximum allowed character count
|
||||
MAX_CHARS=5555
|
||||
|
|
8
.github/ISSUE_TEMPLATE/3.troubleshooting.yml
vendored
|
@ -50,7 +50,7 @@ body:
|
|||
label: Mastodon version
|
||||
description: |
|
||||
This is displayed at the bottom of the About page, eg. `v4.4.0-alpha.1`
|
||||
placeholder: v4.3.0
|
||||
placeholder: v4.4.0-beta.1
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
|
@ -60,9 +60,9 @@ body:
|
|||
Details about your environment, like how Mastodon is deployed, if containers are used, version numbers, etc.
|
||||
value: |
|
||||
Please at least include those informations:
|
||||
- Operating system: (eg. Ubuntu 22.04)
|
||||
- Ruby version: (from `ruby --version`, eg. v3.4.1)
|
||||
- Node.js version: (from `node --version`, eg. v20.18.0)
|
||||
- Operating system: (eg. Ubuntu 24.04.2)
|
||||
- Ruby version: (from `ruby --version`, eg. v3.4.4)
|
||||
- Node.js version: (from `node --version`, eg. v22.16.0)
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
|
|
21
.github/renovate.json5
vendored
|
@ -25,26 +25,12 @@
|
|||
'tesseract.js', // Requires code changes
|
||||
'react-hotkeys', // Requires code changes
|
||||
|
||||
// Requires Webpacker upgrade or replacement
|
||||
'@svgr/webpack',
|
||||
'@types/webpack',
|
||||
'babel-loader',
|
||||
'compression-webpack-plugin',
|
||||
'css-loader',
|
||||
'imports-loader',
|
||||
'mini-css-extract-plugin',
|
||||
'postcss-loader',
|
||||
'sass-loader',
|
||||
'terser-webpack-plugin',
|
||||
'webpack',
|
||||
'webpack-assets-manifest',
|
||||
'webpack-bundle-analyzer',
|
||||
'webpack-dev-server',
|
||||
'webpack-cli',
|
||||
|
||||
// react-router: Requires manual upgrade
|
||||
'history',
|
||||
'react-router-dom',
|
||||
|
||||
// react-spring: Requires manual upgrade when upgrading react
|
||||
'@react-spring/web',
|
||||
],
|
||||
matchUpdateTypes: ['major'],
|
||||
dependencyDashboardApproval: true,
|
||||
|
@ -53,7 +39,6 @@
|
|||
// Require Dependency Dashboard Approval for major version bumps of these Ruby packages
|
||||
matchManagers: ['bundler'],
|
||||
matchPackageNames: [
|
||||
'rack', // Needs to be synced with Rails version
|
||||
'strong_migrations', // Requires manual upgrade
|
||||
'sidekiq', // Requires manual upgrade
|
||||
'sidekiq-unique-jobs', // Requires manual upgrades and sync with Sidekiq version
|
||||
|
|
41
.github/workflows/chromatic.yml
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
name: 'Chromatic'
|
||||
|
||||
on:
|
||||
push:
|
||||
branches-ignore:
|
||||
- renovate/*
|
||||
- stable-*
|
||||
paths:
|
||||
- 'package.json'
|
||||
- 'yarn.lock'
|
||||
- '**/*.js'
|
||||
- '**/*.jsx'
|
||||
- '**/*.ts'
|
||||
- '**/*.tsx'
|
||||
- '**/*.css'
|
||||
- '**/*.scss'
|
||||
- '.github/workflows/chromatic.yml'
|
||||
|
||||
jobs:
|
||||
chromatic:
|
||||
name: Run Chromatic
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'mastodon/mastodon'
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up Javascript environment
|
||||
uses: ./.github/actions/setup-javascript
|
||||
|
||||
- name: Build Storybook
|
||||
run: yarn build-storybook
|
||||
|
||||
- name: Run Chromatic
|
||||
uses: chromaui/action@v12
|
||||
with:
|
||||
# ⚠️ Make sure to configure a `CHROMATIC_PROJECT_TOKEN` repository secret
|
||||
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
|
||||
zip: true
|
||||
storybookBuildDir: 'storybook-static'
|
2
.github/workflows/test-js.yml
vendored
|
@ -43,4 +43,4 @@ jobs:
|
|||
uses: ./.github/actions/setup-javascript
|
||||
|
||||
- name: JavaScript testing
|
||||
run: yarn jest --reporters github-actions summary
|
||||
run: yarn test:js
|
||||
|
|
35
.github/workflows/test-ruby.yml
vendored
|
@ -52,7 +52,7 @@ jobs:
|
|||
public/assets
|
||||
public/packs
|
||||
public/packs-test
|
||||
tmp/cache/webpacker
|
||||
tmp/cache/vite
|
||||
key: ${{ matrix.mode }}-assets-${{ github.head_ref || github.ref_name }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ matrix.mode }}-assets-${{ github.head_ref || github.ref_name }}-${{ github.sha }}
|
||||
|
@ -66,7 +66,7 @@ jobs:
|
|||
|
||||
- name: Archive asset artifacts
|
||||
run: |
|
||||
tar --exclude={"*.br","*.gz"} -zcf artifacts.tar.gz public/assets public/packs*
|
||||
tar --exclude={"*.br","*.gz"} -zcf artifacts.tar.gz public/assets public/packs* tmp/cache/vite/last-build*.json
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: matrix.mode == 'test'
|
||||
|
@ -147,7 +147,7 @@ jobs:
|
|||
uses: ./.github/actions/setup-ruby
|
||||
with:
|
||||
ruby-version: ${{ matrix.ruby-version}}
|
||||
additional-system-dependencies: ffmpeg imagemagick libpam-dev
|
||||
additional-system-dependencies: ffmpeg libpam-dev
|
||||
|
||||
- name: Load database schema
|
||||
run: |
|
||||
|
@ -177,8 +177,8 @@ jobs:
|
|||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
test-libvips:
|
||||
name: Libvips tests
|
||||
test-imagemagick:
|
||||
name: ImageMagick tests
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs:
|
||||
|
@ -224,7 +224,7 @@ jobs:
|
|||
CAS_ENABLED: true
|
||||
BUNDLE_WITH: 'pam_authentication test'
|
||||
GITHUB_RSPEC: ${{ matrix.ruby-version == '.ruby-version' && github.event.pull_request && 'true' }}
|
||||
MASTODON_USE_LIBVIPS: true
|
||||
MASTODON_USE_LIBVIPS: false
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
@ -249,7 +249,7 @@ jobs:
|
|||
uses: ./.github/actions/setup-ruby
|
||||
with:
|
||||
ruby-version: ${{ matrix.ruby-version}}
|
||||
additional-system-dependencies: ffmpeg libpam-dev
|
||||
additional-system-dependencies: ffmpeg imagemagick libpam-dev
|
||||
|
||||
- name: Load database schema
|
||||
run: './bin/rails db:create db:schema:load db:seed'
|
||||
|
@ -329,7 +329,7 @@ jobs:
|
|||
uses: ./.github/actions/setup-ruby
|
||||
with:
|
||||
ruby-version: ${{ matrix.ruby-version}}
|
||||
additional-system-dependencies: ffmpeg imagemagick
|
||||
additional-system-dependencies: ffmpeg
|
||||
|
||||
- name: Set up Javascript environment
|
||||
uses: ./.github/actions/setup-javascript
|
||||
|
@ -337,6 +337,21 @@ jobs:
|
|||
- name: Load database schema
|
||||
run: './bin/rails db:create db:schema:load db:seed'
|
||||
|
||||
- name: Cache Playwright Chromium browser
|
||||
id: playwright-cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cache/ms-playwright
|
||||
key: playwright-browsers-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
|
||||
|
||||
- name: Install Playwright Chromium browser (with deps)
|
||||
if: steps.playwright-cache.outputs.cache-hit != 'true'
|
||||
run: yarn run playwright install --with-deps chromium
|
||||
|
||||
- name: Install Playwright Chromium browser deps
|
||||
if: steps.playwright-cache.outputs.cache-hit == 'true'
|
||||
run: yarn run playwright install-deps chromium
|
||||
|
||||
- run: bin/rspec spec/system --tag streaming --tag js
|
||||
|
||||
- name: Archive logs
|
||||
|
@ -350,7 +365,7 @@ jobs:
|
|||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: e2e-screenshots
|
||||
name: e2e-screenshots-${{ matrix.ruby-version }}
|
||||
path: tmp/capybara/
|
||||
|
||||
test-search:
|
||||
|
@ -448,7 +463,7 @@ jobs:
|
|||
uses: ./.github/actions/setup-ruby
|
||||
with:
|
||||
ruby-version: ${{ matrix.ruby-version}}
|
||||
additional-system-dependencies: ffmpeg imagemagick
|
||||
additional-system-dependencies: ffmpeg
|
||||
|
||||
- name: Set up Javascript environment
|
||||
uses: ./.github/actions/setup-javascript
|
||||
|
|
6
.gitignore
vendored
|
@ -21,10 +21,11 @@
|
|||
/public/system
|
||||
/public/assets
|
||||
/public/packs
|
||||
/public/packs-dev
|
||||
/public/packs-test
|
||||
.env
|
||||
.env.production
|
||||
/node_modules/
|
||||
node_modules/
|
||||
/build/
|
||||
|
||||
# Ignore elasticsearch config
|
||||
|
@ -77,3 +78,6 @@ docker-compose.override.yml
|
|||
|
||||
# Ignore local-only rspec configuration
|
||||
.rspec-local
|
||||
|
||||
*storybook.log
|
||||
storybook-static
|
||||
|
|
2
.nvmrc
|
@ -1 +1 @@
|
|||
22.14
|
||||
22.16
|
||||
|
|
|
@ -18,10 +18,6 @@
|
|||
!/log/.keep
|
||||
/tmp
|
||||
/coverage
|
||||
/public/system
|
||||
/public/assets
|
||||
/public/packs
|
||||
/public/packs-test
|
||||
.env
|
||||
.env.production
|
||||
.env.development
|
||||
|
@ -60,10 +56,11 @@ docker-compose.override.yml
|
|||
/public/packs
|
||||
/public/packs-test
|
||||
/public/system
|
||||
/public/vite*
|
||||
|
||||
# Ignore emoji map file
|
||||
/app/javascript/mastodon/features/emoji/emoji_map.json
|
||||
/app/javascript/mastodon/features/emoji/emoji_sheet.json
|
||||
/app/javascript/mastodon/features/emoji/emoji_data.json
|
||||
|
||||
# Ignore locale files
|
||||
/app/javascript/mastodon/locales/*.json
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
---
|
||||
Naming/BlockForwarding:
|
||||
EnforcedStyle: explicit
|
||||
|
||||
Naming/PredicateMethod:
|
||||
Enabled: false
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# This configuration was generated by
|
||||
# `rubocop --auto-gen-config --auto-gen-only-exclude --no-offense-counts --no-auto-gen-timestamp`
|
||||
# using RuboCop version 1.75.2.
|
||||
# using RuboCop version 1.76.0.
|
||||
# The point is for the user to remove these configuration records
|
||||
# one by one as the offenses are removed from the code base.
|
||||
# Note that changes in the inspected code, or installation of new
|
||||
|
@ -31,58 +31,14 @@ Metrics/PerceivedComplexity:
|
|||
- 'app/services/delivery_antenna_service.rb'
|
||||
- 'app/services/post_status_service.rb'
|
||||
|
||||
Rails/OutputSafety:
|
||||
Exclude:
|
||||
- 'config/initializers/simple_form.rb'
|
||||
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
# Configuration parameters: AllowedVars.
|
||||
Style/FetchEnvVar:
|
||||
Exclude:
|
||||
- 'config/environments/production.rb'
|
||||
- 'config/initializers/2_limited_federation_mode.rb'
|
||||
- 'config/initializers/3_omniauth.rb'
|
||||
- 'config/initializers/cache_buster.rb'
|
||||
- 'config/initializers/devise.rb'
|
||||
- 'config/initializers/paperclip.rb'
|
||||
- 'config/initializers/vapid.rb'
|
||||
- 'lib/tasks/repo.rake'
|
||||
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
# Configuration parameters: EnforcedStyle, MaxUnannotatedPlaceholdersAllowed, Mode, AllowedMethods, AllowedPatterns.
|
||||
# SupportedStyles: annotated, template, unannotated
|
||||
# AllowedMethods: redirect
|
||||
Style/FormatStringToken:
|
||||
Exclude:
|
||||
- 'config/initializers/devise.rb'
|
||||
- 'lib/paperclip/color_extractor.rb'
|
||||
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
# Configuration parameters: MinBodyLength, AllowConsecutiveConditionals.
|
||||
Style/GuardClause:
|
||||
Enabled: false
|
||||
|
||||
# Configuration parameters: AllowedMethods.
|
||||
# AllowedMethods: respond_to_missing?
|
||||
Style/OptionalBooleanParameter:
|
||||
Exclude:
|
||||
- 'app/lib/admin/system_check/message.rb'
|
||||
- 'app/lib/request.rb'
|
||||
- 'app/lib/webfinger.rb'
|
||||
- 'app/services/block_domain_service.rb'
|
||||
- 'app/services/fetch_resource_service.rb'
|
||||
- 'app/workers/domain_block_worker.rb'
|
||||
- 'app/workers/unfollow_follow_worker.rb'
|
||||
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: short, verbose
|
||||
Style/PreferredHashMethods:
|
||||
Exclude:
|
||||
- 'config/initializers/paperclip.rb'
|
||||
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
Style/RedundantConstantBase:
|
||||
Exclude:
|
||||
- 'config/environments/production.rb'
|
||||
- 'config/initializers/sidekiq.rb'
|
||||
|
|
|
@ -1 +1 @@
|
|||
3.4.3
|
||||
3.4.4
|
||||
|
|
16
.storybook/main.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
import type { StorybookConfig } from '@storybook/react-vite';
|
||||
|
||||
const config: StorybookConfig = {
|
||||
stories: ['../app/javascript/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
|
||||
addons: [
|
||||
'@storybook/addon-docs',
|
||||
'@storybook/addon-a11y',
|
||||
'@storybook/addon-vitest',
|
||||
],
|
||||
framework: {
|
||||
name: '@storybook/react-vite',
|
||||
options: {},
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
7
.storybook/manager.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { addons } from 'storybook/manager-api';
|
||||
|
||||
import theme from './storybook-theme';
|
||||
|
||||
addons.setConfig({
|
||||
theme,
|
||||
});
|
18
.storybook/preview-head.html
Normal file
|
@ -0,0 +1,18 @@
|
|||
<style>
|
||||
/* Increase docs font size */
|
||||
.sbdocs.sbdocs-content :where(p:not(.sb-anchor, .sb-unstyled, .sb-unstyled p)),
|
||||
.sbdocs.sbdocs-content :where(li:not(.sb-anchor, .sb-unstyled, .sb-unstyled li)) {
|
||||
font-size: 1.0666rem; /* 17px */
|
||||
line-height: 1.585; /* 27px */
|
||||
}
|
||||
|
||||
.sbdocs.sbdocs-content :where(p:not(.sb-anchor, .sb-unstyled, .sb-unstyled p)) code,
|
||||
.sbdocs.sbdocs-content :where(li:not(.sb-anchor, .sb-unstyled, .sb-unstyled li)) code {
|
||||
font-size: 0.875rem; /* ~15px */
|
||||
}
|
||||
|
||||
/* Bring numbers back for ordered lists */
|
||||
ol {
|
||||
list-style: revert !important;
|
||||
}
|
||||
</style>
|
29
.storybook/preview.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
import type { Preview } from '@storybook/react-vite';
|
||||
|
||||
// If you want to run the dark theme during development,
|
||||
// you can change the below to `/application.scss`
|
||||
import '../app/javascript/styles/mastodon-light.scss';
|
||||
|
||||
const preview: Preview = {
|
||||
// Auto-generate docs: https://storybook.js.org/docs/writing-docs/autodocs
|
||||
tags: ['autodocs'],
|
||||
parameters: {
|
||||
layout: 'centered',
|
||||
|
||||
controls: {
|
||||
matchers: {
|
||||
color: /(background|color)$/i,
|
||||
date: /Date$/i,
|
||||
},
|
||||
},
|
||||
|
||||
a11y: {
|
||||
// 'todo' - show a11y violations in the test UI only
|
||||
// 'error' - fail CI on a11y violations
|
||||
// 'off' - skip a11y checks entirely
|
||||
test: 'todo',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default preview;
|
7
.storybook/storybook-addon-vitest.d.ts
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
// The addon package.json incorrectly exports types, so we need to override them here.
|
||||
// See: https://github.com/storybookjs/storybook/blob/v9.0.4/code/addons/vitest/package.json#L70-L76
|
||||
declare module '@storybook/addon-vitest/vitest-plugin' {
|
||||
export * from '@storybook/addon-vitest/dist/vitest-plugin/index';
|
||||
}
|
||||
|
||||
export {};
|
7
.storybook/storybook-theme.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { create } from 'storybook/theming';
|
||||
|
||||
export default create({
|
||||
base: 'light',
|
||||
brandTitle: 'Mastodon Storybook',
|
||||
brandImage: 'https://joinmastodon.org/logos/wordmark-black-text.svg',
|
||||
});
|
8
.storybook/vitest.setup.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
import * as a11yAddonAnnotations from '@storybook/addon-a11y/preview';
|
||||
import { setProjectAnnotations } from '@storybook/react-vite';
|
||||
|
||||
import * as projectAnnotations from './preview';
|
||||
|
||||
// This is an important step to apply the right configuration when testing your stories.
|
||||
// More info at: https://storybook.js.org/docs/api/portable-stories/portable-stories-vitest#setprojectannotations
|
||||
setProjectAnnotations([a11yAddonAnnotations, projectAnnotations]);
|
283
CHANGELOG.md
|
@ -2,9 +2,290 @@
|
|||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [4.4.0] - UNRELEASED
|
||||
|
||||
### Added
|
||||
|
||||
- **Add “Followers you know” widget to user profiles and hover cards** (#34652, #34678, #34681, #34697, #34699, #34769, #34774 and #34914 by @diondiondion)
|
||||
- **Add featured tab to profiles on web UI and rework pinned posts** (#34405, #34483, #34491, #34754, #34855, #34858, #34868, and #34869 by @ChaosExAnima, @ClearlyClaire, @Gargron, and @diondiondion)
|
||||
- Add endorsed accounts to featured tab in web UI (#34421 and #34568 by @Gargron)\
|
||||
This also includes the following new REST API endpoints:
|
||||
- `GET /api/v1/accounts/:id/endorsements`: https://docs.joinmastodon.org/methods/accounts/#endorsements
|
||||
- `POST /api/v1/accounts/:id/endorse`: https://docs.joinmastodon.org/methods/accounts/#endorse
|
||||
- `POST /api/v1/accounts/:id/unendorse`: https://docs.joinmastodon.org/methods/accounts/#unendorse
|
||||
- Add ability to add and remove hashtags from featured tags in web UI (#34489, #34887, and #34490 by @ClearlyClaire and @Gargron)\
|
||||
This is achieved through the new REST API endpoints:
|
||||
- `POST /api/v1/tags/:id/feature`: https://docs.joinmastodon.org/methods/tags/#feature
|
||||
- `POST /api/v1/tags/:id/unfeature`: https://docs.joinmastodon.org/methods/tags/#unfeature
|
||||
- Add reminder when about to post without alt text in web UI (#33760 and #33784 by @Gargron)
|
||||
- Add a warning in Web UI when composing a post when the selected and detected language are different (#33042, #33683, #33700, #33724, #33770, and #34193 by @ClearlyClaire and @Gargron)
|
||||
- Add ability to reorder and translate server rules (#34637, #34737, #34494, #34756, and #34820 by @ChaosExAnima and @ClearlyClaire)\
|
||||
Rules are now shown in the user’s language, if a translation has been set.\
|
||||
In the REST API, `Rule` entities now have a new `translations` attribute: https://docs.joinmastodon.org/entities/Rule/#translations
|
||||
- Add emoji from Twemoji 15.1.0, including in the emoji picker/completion (#33395, #34321, #34620, and #34677 by @ChaosExAnima, @ClearlyClaire, @TheEssem, and @eramdam)
|
||||
- Add experimental support for verifying and displaying remote quote posts (#34370, #34481, #34510, #34551, #34480, #34479, #34553, #34584, #34623, #34738, #34766, #34770, #34772, #34773, #34786, #34790, and #34864 by @ClearlyClaire and @diondiondion)\
|
||||
Support for verifying remote quotes according to [FEP-044f](https://codeberg.org/fediverse/fep/src/branch/main/fep/044f/fep-044f.md) and displaying them in the Web UI has been implemented. Such quotes are currently only processed if the `inbound_quotes` experimental feature is enabled (`EXPERIMENTAL_FEATURES=inbound_quotes`).\
|
||||
Quoting other people is not implemented yet, and it is currently not possible to mark your own posts as allowing quotes. However, a new “Who can quote” setting has been added to the “Posting defaults” section of the user settings. This setting allows you to set a default that will be used for new posts made on Mastodon 4.5 and newer, when quote posts will be fully implemented.\
|
||||
In the REST API, quote posts are represented by a new `quote` attribute on `Status` and `StatusEdit` entities: https://docs.joinmastodon.org/entities/StatusEdit/#quote https://docs.joinmastodon.org/entities/Status/#quote
|
||||
- Add option to remove account from followers in web UI (#34488 by @Gargron)
|
||||
- Add relationship tags to profiles and hover cards in web UI (#34467 and #34792 by @Gargron and @diondiondion)
|
||||
- Add ability to open posts in a new tab by middle-clicking in web UI (#32988, #33106, #33419, and #34700 by @ClearlyClaire, @Gargron, and @tribela)
|
||||
- Add new filter action to blur media (#34256 by @ClearlyClaire)\
|
||||
In the REST API, this adds a new possible value of `blur` to the `filter_action` attribute: https://docs.joinmastodon.org/entities/Filter/#filter_action
|
||||
- Add dropdown menu to hashtag links in web UI (#34393 by @Gargron)
|
||||
- **Add server setting to allow referrer** (#33214, #33239, #33903, and #34731 by @ChaosExAnima, @ClearlyClaire, @Gargron, and @renchap)\
|
||||
In order to protect the privacy of users of small or thematic servers, Mastodon previously avoided transmitting referrer information when clicking outside links, which unfortunately made Mastodon completely invisible to other websites, even though the privacy implications on large generic servers are very limited.\
|
||||
Server administrators can now chose to opt in to transmit referrer information when following an external link. Only the domain name is transmitted, not the referrer path.
|
||||
- Add double tap to zoom and swipe to dismiss to media modal in web UI (#34210 by @Gargron)
|
||||
- Add link from Web UI for Hashtags to the Moderation UI (#31448 by @ThisIsMissEm)
|
||||
- **Add terms of service** (#33055, #33233, #33230, #33703, #33699, #33994, #33993, #34105, #34122, #34200, and #34527 by @ClearlyClaire, @Gargron, @mjankowski, and @oneiros)\
|
||||
Server administrators can now fill in Terms of Service, optionally using a provided template.
|
||||
- **Add age verification on sign-up** (#34150, #34663, and #34636 by @ClearlyClaire and @Gargron)\
|
||||
Server administrators now have a setting to set a minimum age requirement for creating a new server, asking users for their date of birth. The date of birth is checked against the minimum age requirement server-side but not stored.\
|
||||
The following REST API changes have been made to accommodate this:
|
||||
- `registrations.min_age` has been added to the `Instance` entity: https://docs.joinmastodon.org/entities/Instance/#registrations-min_age
|
||||
- the `date_of_birth` parameter has been added to the account creation API: https://docs.joinmastodon.org/methods/accounts/#create
|
||||
- Add ability to dismiss alt text badge by tapping it in web UI (#33737 by @Gargron)
|
||||
- Add loading indicator to timeline gap indicators in web UI (#33762 by @Gargron)
|
||||
- Add interaction modal when trying to interact with a poll while logged out (#32609 by @ThisIsMissEm)
|
||||
- **Add experimental FASP support** (#34031, #34415, and #34765 by @oneiros)\
|
||||
This is a first step towards supporting “Fediverse Auxiliary Service Providers” (https://github.com/mastodon/fediverse_auxiliary_service_provider_specifications). This is mostly interesting to developers who would like to implement their own FASP, but also includes the capability to share data with a discovery provider (see https://www.fediscovery.org).
|
||||
- Add ability for admins to send announcements to all users via email (#33928 and #34411 by @ClearlyClaire)\
|
||||
This is meant for critical announcements only, as this will potentially send a lot of emails and cannot be opted out of by users.
|
||||
- Add option to use system scrollbar styling (#32117 by @vmstan)
|
||||
- Add hover cards to follow suggestions (#33749 by @ClearlyClaire)
|
||||
- Add `t` hotkey for post translations (#33441 by @ClearlyClaire)
|
||||
- Add timestamp to all announcements in Web UI (#18329 by @ClearlyClaire)
|
||||
- Add dropdown menu with quick actions to lists of accounts in web UI (#34391, #34709, and #34767 by @Gargron, @diondiondion, and @mkljczk)
|
||||
- Add support for displaying “year in review” notification in web UI (#32710, #32765, #32709, #32807, #32914, #33148, and #33882 by @Gargron and @mjankowski)\
|
||||
Note that the notification is currently not generated automatically, and at the moment requires a manual undocumented administrator action.
|
||||
- Add experimental support for receiving HTTP Message Signatures (RFC9421) (#34814 by @oneiros)\
|
||||
For now, this needs to be explicitly enabled through the `http_message_signatures` feature flag (`EXPERIMENTAL_FEATURES=http_message_signatures`). This currently only covers verifying such signatures (inbound HTTP requests), not issuing them (outbound HTTP requests).
|
||||
- Add experimental server-side feature to fetch remote replies (#32615, #34147, #34149, #34151, #34615, #34682, and #34702 by @ClearlyClaire and @sneakers-the-rat)\
|
||||
This experimental feature causes the server to recursively fetch replies in background tasks whenever a user opens a remote post. This happens asynchronously and the client is currently not notified of the existence of new replies, which will thus only be displayed the next time this post’s context gets requested.\
|
||||
This feature needs to be explicitly enabled server-side by setting `FETCH_REPLIES_ENABLED` environment variable to `true`.
|
||||
- Add simple feature flag system through the `EXPERIMENTAL_FEATURES` environment variable (#34038 and #34124 by @oneiros)\
|
||||
This allows enabling comma-separated feature flags for experimental features.\
|
||||
The current supported feature flags are `inbound_quotes`, `fasp` and `http_message_signatures`.
|
||||
- Add `dev:populate_sample_data` rake task to populate test data (#34676, #34733, #34771, #34787, and #34791 by @ClearlyClaire and @diondiondion)
|
||||
- Add support for displaying fallback representation when receiving MathML (#27107 by @4e554c4c)
|
||||
- Add warning for Elasticsearch index analyzers mismatch (#34515 and #34567 by @ClearlyClaire and @Gargron)
|
||||
- Add `-only-mapping` option to `tootctl search deploy` (#34466 and #34566 by @Gargron)
|
||||
- Add server-side support for grouping account sign-up notifications (#34298 by @ClearlyClaire)
|
||||
- Add `registrations.reason_required` attribute to `/api/v2/instance` response (#34280 by @ClearlyClaire)\
|
||||
This is documented at https://docs.joinmastodon.org/entities/Instance/#registrations-reason_required
|
||||
- Add `EXTRA_MEDIA_HOSTS` environment variable to add extra hosts to Content-Security-Policy (#34184 by @shleeable)
|
||||
- Add `Deprecation` headers on deprecated API endpoints (#34262 and #34397 by @ClearlyClaire)\
|
||||
This is documented at https://docs.joinmastodon.org/api/guidelines/#deprecations
|
||||
- Add `about`, `privacy_policy` and `terms_of_service` URLs to `/api/v2/instance` (#33849 by @ClearlyClaire)
|
||||
- Add API to delete media attachments that are not in use (#33991 and #34035 by @ClearlyClaire and @ThisIsMissEm)\
|
||||
`DELETE /api/v1/media/:id`: https://docs.joinmastodon.org/methods/media/#delete
|
||||
- Add optional `delete_media` parameter to `DELETE /api/v1/statuses/:id` (#33988 by @ClearlyClaire)\
|
||||
This is documented at https://docs.joinmastodon.org/methods/statuses/#delete
|
||||
- Add `og:locale` to expose status language in OpenGraph previews (#34012 by @ThisIsMissEm)
|
||||
- Add `-skip-filled-timeline` option to `tootctl feed build` to skip half-filled feeds (#33844 by @ClearlyClaire)
|
||||
- Add support for changing the base Docker registry with the `BASE_REGISTRY` `ARG` (#33712 by @wolfspyre)
|
||||
- Add an optional metric exporter (#33734, #33840, #34172, #34192, 34223)\
|
||||
Optionally enable the `prometheus_exporter` ruby gem (see https://github.com/discourse/prometheus_exporter) to collect and expose metrics. See the documentation for all the details: https://docs.joinmastodon.org/admin/config/#prometheus
|
||||
- Add `attribution_domains` attribute to `PATCH /api/v1/accounts/update_credentials` (#32730 by @c960657)\
|
||||
This is documented at https://docs.joinmastodon.org/methods/accounts/#update_credentials
|
||||
- Add support for standard WebPush in addition to previous draft (#33572, #33528, and #33587 by @ClearlyClaire and @p1gp1g)
|
||||
- Add support for Active Record query log tags (#33342 by @renchap)
|
||||
- Add OTel trace & span IDs to logs (#33339 and #33362 by @renchap)
|
||||
- Add missing `on_delete: :cascade` foreign keys option to various database columns (#33175 by @mjankowski)
|
||||
- Add explicit migration breakpoints (#33089 by @ClearlyClaire)
|
||||
- Add rel alternate rss/json links to pages for tags (#33179 by @mjankowski)
|
||||
- Add media attachment description limit to instance API response (#33153 by @mjankowski)\
|
||||
This adds the `configuration.media_attachments.description_limit` attribute to the `Instance` entity, documented at https://docs.joinmastodon.org/entities/Instance/#description_limit
|
||||
- Add `maxlength` to registration reason input (#33162 by @mjankowski)
|
||||
- Add `REPLICA_PREPARED_STATEMENTS` and `REPLICA_DB_TASKS` environment variables (#32908 by @shleeable)\
|
||||
See documentation at https://docs.joinmastodon.org/admin/scaling/#read-replicas
|
||||
- Add a range of reserved usernames to reduce potential misuse by malicious actors (#32828 by @jmking-iftas)
|
||||
- Add operations on relays to the admin audit log (#32819 by @ThisIsMissEm)
|
||||
- Add userinfo OAuth endpoint (#32548 by @ThisIsMissEm)
|
||||
- Add the standard VCS attributes to OpenTelemetry spans (#32904 by @renchap)
|
||||
- Add endpoint to remove web push subscription (#32626 by @oneiros)\
|
||||
Mastodon now sets a new `Unsubscribe-URL` request header when performing WebPush requests. This URL can be used by the WebPush server to disable the WebPush subscription on Mastodon’s side in case of unfixable errors.
|
||||
- Add missing content warning text to RSS feeds (#32406 by @mjankowski)
|
||||
- Add Swiss German to languages dropdown (#29281 by @FlohEinstein)
|
||||
|
||||
### Changed
|
||||
|
||||
- Change design of lists in web UI (#32881, #33054, and #33036 by @Gargron)
|
||||
- Change design of edit media modal in web UI (#33516, #33702, #33725, #33725, #33771, and #34345 by @Gargron)
|
||||
- Change design of audio player in web UI (#34520, #34740, and #34865 by @ClearlyClaire, @Gargron, and @diondiondion)
|
||||
- Change design of interaction modal in web UI (#33278 by @Gargron)
|
||||
- Change list timelines to reflect added and removed users retroactively (#32930 by @Gargron)
|
||||
- Change account search to be more forgiving of spaces (#34455 by @Gargron)
|
||||
- Change unfollow button label from “Mutual” to “Unfollow” in web UI (#34392 by @Gargron)
|
||||
- Change “Specific people” to “Private mention” in menu in web UI (#33963 by @Gargron)
|
||||
- Change language names in compose box language picker to be localized (#33402 by @c960657)
|
||||
- Change onboarding flow in web UI (#32998, #33119, and #33471 by @ClearlyClaire and @Gargron)
|
||||
- Change emoji categories in admin interface to be ordered by name (#33630 by @ShadowJonathan)
|
||||
- Change design of rich text elements in web UI (#32633 by @Gargron)
|
||||
- Change wording of “single choice” to “pick one” in poll authoring form (#32397 by @ThisIsMissEm)
|
||||
- Change returned favorite and boost counts to use those provided by the remote server, if available (#32620, #34594, #34618, and #34619 by @ClearlyClaire and @sneakers-the-rat)
|
||||
- Change label of favourite notifications on private mentions (#31659 by @ClearlyClaire)
|
||||
- Change `libvips` to be enabled by default in place of ImageMagick (#34741 and #34753 by @ClearlyClaire and @diondiondion)
|
||||
- Change avatar and header size limits from 2MB to 8MB when using libvips (#33002 by @Gargron)
|
||||
- Change search to use query params in web UI (#32949 and #33670 by @ClearlyClaire and @Gargron)
|
||||
- Change build system from Webpack to Vite (#34454, #34450, #34758, #34768, #34813, #34808, #34837, and #34732 by @ChaosExAnima, @ClearlyClaire, @mjankowski, and @renchap)\
|
||||
One known limitation is that themes’ main style file needs to have a very specific file name: `app/javascript/styles/:name.scss` where `:name` is the name of the theme in `config/themes.yml`
|
||||
- Change account creation API to forbid creation from user tokens (#34828 by @ThisIsMissEm)
|
||||
- Change `/api/v2/instance` to be enabled without authentication when limited federation mode is enabled (#34576 by @ClearlyClaire)
|
||||
- Change `DEFAULT_LOCALE` to not override unauthenticated users’ browser language (#34535 by @ClearlyClaire)\
|
||||
If you want to preserve the old behavior, you can add `FORCE_DEFAULT_LOCALE=true`.
|
||||
- Change size of profile picture on profile page from 90px to 92px (#34807 by @larouxn)
|
||||
- Change passthrough video processing to emit `moov` atom at start of video (#34726 by @ClearlyClaire)
|
||||
- Change kerning to be disabled for Japanese text to preserve monospaced alignment for readability (#34448 by @nagutabby)
|
||||
- Change error handling of various endpoints to return 422 instead of 500 on invalid parameters (#29308, #34434, and #34452 by @danielmbrasil and @mjankowski)
|
||||
- Change Web UI to use `<time>` tags for various timestamps (#34131 by @scarf005)
|
||||
- Change devcontainer to be accessible from local network (#34269 by @ChaosExAnima)
|
||||
- Change video transcoding code to skip re-encoding yuvj420p videos (#34098 by @rinsuki)
|
||||
- Change web client settings to be saved earlier and more often (#34074 by @ClearlyClaire)
|
||||
- Change test coverage report generation to be disabled by default, with opt-in through the `COVERAGE` environment variable (#33824 by @mjankowski)
|
||||
- Change devcontainer to store bootsnap cache outside of bind mounts (#33677 by @c960657)
|
||||
- Change error handling in the `mastodon:setup` rake task to summarize encountered errors at the end (#33603 by @mjankowski)
|
||||
- Change tooltip of some moderation interface timestamps to include time in addition to date (#33191 by @ThisIsMissEm)
|
||||
- Change organization and wording of `README.md`, `CONTRIBUTING.md` and `DEVELOPMENT.md` (#32143, #33328, #33517, #33637, #33728, #34675, and #34761 by @Lamparter, @andypiper, @diondiondion, @larouxn, @mikkelricky, and @mjankowski)
|
||||
- Change custom CSS to be cached for longer and invalidated based on its contents (#33207 and #33583 by @mjankowski and @tribela)
|
||||
- Change `tootctl maintenance fix-duplicates` to disable database statement timeouts (#33484 by @mjankowski)
|
||||
- Change some icons in settings sidebar to avoid “double icon” near each other (#33449 by @mjankowski)
|
||||
- Change animation on feed generation screen in web UI (#33311 by @Gargron)
|
||||
- Change OTel instrumentation to not start traces with Redis spans (#33090 by @robbkidd)
|
||||
- Change new post delivery to skip suspended followers (#27509 and #33030 by @ClearlyClaire and @oneiros)
|
||||
- Change URL truncation to account for ellipses (#33229 by @FND)
|
||||
- Change ability to navigate of unconfirmed users (#33209 by @Gargron)
|
||||
- Change hashtag trends to be stored in the database instead of redis (#32837, #33189, and #34016 by @Gargron and @onekopaka)
|
||||
- Change “social web” to “fediverse” in a few banners in web UI (#33101 by @Gargron)
|
||||
- Change server rules to be collapsible (#33039 by @Gargron)
|
||||
- Change design of modal loading and error screens in web UI (#33092 by @Gargron)
|
||||
- Change error messages to be more accurate when failing to add an account to a list (#33082 by @Gargron)
|
||||
- Change timezone picker in the default settings to show the default timezone (#31803 by @c960657)
|
||||
- Change `tootctl accounts modify --disable-2fa` to remove webauthn credentials (#29883 by @mszpro)
|
||||
- Change preview card processing to be more liberal in what it accepts (#31357 by @c960657)
|
||||
- Change scheduled statuses to be discarded if the author’s account is frozen (#30729 by @PauloVilarinho)
|
||||
- Change display of statuses in admin panel (#30813 by @ThisIsMissEm)
|
||||
- Change parsing of `ALLOWED_PRIVATE_ADDRESSES` to happen at startup (#32850 by @ClearlyClaire)
|
||||
- Change WebPush delivery to skip notifications older than 2 days old (#32842 by @ThisIsMissEm)
|
||||
- Change PWA manifest to prefer official mobile apps (#27254 by @jake-anto)
|
||||
|
||||
### Removed
|
||||
|
||||
- **Remove support for Redis namespaces** (#34664 and #34665 by @ClearlyClaire)\
|
||||
See https://github.com/mastodon/redis_namespace_migration
|
||||
- Remove support for imports started on pre-4.2.0 Mastodon versions (#34371 by @mjankowski)
|
||||
- Remove support for PostgreSQL 12 and earlier (#34744 by @ClearlyClaire)
|
||||
- Remove support for Node.JS < 20 (#34390 by @renchap)
|
||||
- Remove support for Redis < 6.2 (#30413 by @ClearlyClaire)
|
||||
- Remove support for Ruby 3.1 (#32363 by @mjankowski)
|
||||
- Remove support for OAuth Password Grant Type (#30960 by @ThisIsMissEm)\
|
||||
https://docs.joinmastodon.org/spec/oauth/#token
|
||||
- Remove `OTP_SECRET` environment variable and legacy OTP code (#34743, #34757, #34748, and #34810 by @ClearlyClaire and @mjankowski)\
|
||||
This breaks zero-downtime migrations from versions earlier than 4.3.0.
|
||||
- Remove broken support for HTTP Basic Authentication (#34501 by @ThisIsMissEm)
|
||||
- Remove system tooltip for alt text in web UI (#33736 by @Gargron)
|
||||
- Remove `thing_type` and `thing_id` columns from settings table (#31971 and #33196 by @ClearlyClaire and @mjankowski)
|
||||
- Remove redundant temporary index creation in `tootctl status remove` (#33023 by @ClearlyClaire)
|
||||
- Remove duplicate indexes from database (#32454 by @mjankowski)
|
||||
- Remove redundant title attribute in column links (#32258 by @c960657)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix remote suspension of a user causing local instance to remove remote follows (#27588 by @ShadowJonathan)
|
||||
- Fix blocked accounts not being automatically removed from trending statuses (#34891 by @ClearlyClaire)
|
||||
- Fix nested buttons in search popout in web UI (#34871 by @Gargron)
|
||||
- Fix not being able to scroll dropdown on touch devices in web UI (#34873 by @Gargron)
|
||||
- Fix inconsistent filtering of silenced accounts for other silenced accounts (#34863 by @ClearlyClaire)
|
||||
- Fix update checker listing updates older or equal to current running version (#33906 by @ClearlyClaire)
|
||||
- Fix `NoMethodError` in edge case of emoji cache handling (#34749 by @dariusk)
|
||||
- Fix handling of inlined `featured` collections in ActivityPub actor objects (#34789 and #34811 by @ClearlyClaire)
|
||||
- Fix long link names in admin sidebar being truncated (#34727 by @diondiondion)
|
||||
- Fix admin dashboard crash on specific Elasticsearch connection errors (#34683 by @ClearlyClaire)
|
||||
- Fix OIDC account creation failing for long display names (#34639 by @defnull)
|
||||
- Fix use of the deprecated `/api/v1/instance` endpoint in the moderation interface (#34613 by @renchap)
|
||||
- Fix directory scroll position reset (#34560 by @przucidlo)
|
||||
- Fix needlessly complex SVG paths for oEmbed and logo (#34538 by @edent)
|
||||
- Fix avatar sizing with long account name in some UI elements (#34514 by @gomasy)
|
||||
- Fix empty menu section in status dropdown (#34431 by @ClearlyClaire)
|
||||
- Fix the delete suggestion button not working (#34396 and #34398 by @ClearlyClaire and @renchap)
|
||||
- Fix radio buttons not always being correctly centered (#34389 by @ChaosExAnima)
|
||||
- Fix visual glitches with adding post filters (#34387 by @ChaosExAnima)
|
||||
- Fix bugs with upload progress (#34325 by @ChaosExAnima)
|
||||
- Fix being unable to hide controls in full screen video in web UI (#34308 by @Gargron)
|
||||
- Fix extra space under left-indented vertical videos (#34313 by @ClearlyClaire)
|
||||
- Fix SASS deprecation notices (#34278 by @ChaosExAnima)
|
||||
- Fix display of failed-to-load image attachments in web UI (#34217 by @Gargron)
|
||||
- Fix duplicate REST API requests on submitting account personal note with ctrl+enter (#34213 by @ClearlyClaire)
|
||||
- Fix unnecessary rerenders in composer dropdown menu (#34133 by @ClearlyClaire)
|
||||
- Fix behavior of database schema loading with `SKIP_POST_DEPLOYMENT_MIGRATIONS` (#34089 by @ClearlyClaire)
|
||||
- Fix infinite scroll not working on profile media tab in web UI (#33860 and #34171 by @ClearlyClaire and @Gargron)
|
||||
- Fix minor inefficiencies in domain suspension code (#33897 by @larouxn)
|
||||
- Fix potential inefficiency in media privacy system check (#33858 by @ClearlyClaire)
|
||||
- Fix public timeline inefficiency by adding the `language` column to the public timelines index (#33779 by @ClearlyClaire)
|
||||
- Fix re-encoding of high-framerate VFR videos with FFmpeg 6+ (#33634 by @ClearlyClaire)
|
||||
- Fix error when processing invalid `Announce` activity with missing object (#33570 by @ShadowJonathan)
|
||||
- Fix color contrast in report modal (#33468 by @ClearlyClaire)
|
||||
- Fix error 500 when passing an invalid `lang` parameter (#33467 by @ClearlyClaire)
|
||||
- Fix `/share` not using server-set characters limit (#33459 by @kescherCode)
|
||||
- Fix audio player modal having white-on-white buttons in light theme (#33444 by @ClearlyClaire)
|
||||
- Fix favorite & bookmark text toggle in timeline, status and image view (#27209 by @gunchleoc)
|
||||
- Fix Web UI erroneously stopping to offer expanding search results after second page (#33428 by @ClearlyClaire)
|
||||
- Fix missing value limits for `UserRole` position (#33172 and #33349 by @mjankowski)
|
||||
- Fix clicking on a profile mention while logged out potentially leading to incorrect account (#33324 by @ClearlyClaire)
|
||||
- Fix missing `NOT NULL` constraints on various database columns (#33244, #33284, #33308, #33330, #33374, and #34498 by @ClearlyClaire and @mjankowski)
|
||||
- Fix long account username overflowing on profiles (#33286 by @mjankowski)
|
||||
- Fix Vagrant failure to sync dangling symlinks (#28101 by @filippog)
|
||||
- Fix Chromium showing scrollbar on embedded posts (#33237 by @ClearlyClaire)
|
||||
- Fix missing top border on Admin Hashtags UI (#31443 by @ThisIsMissEm)
|
||||
- Fix design of search bar on explore screen in light theme in web UI (#33224 by @Gargron)
|
||||
- Fix various visual sign-up flow issues (#33206 by @Gargron)
|
||||
- Fix support of bidi text in account profiles (#33088 by @mokazemi)
|
||||
- Fix wording of the error returned when scheduling a status too soon (#33156 by @mjankowski)
|
||||
- Fix `inbox_url` presence on Relay not being validated (#32364 by @mjankowski)
|
||||
- Fix ability to include multiple copies of `embed.js` (#33107 by @YKWeyer)
|
||||
- Fix `rel="me"` check being case-sensitive (#32238 by @c960657)
|
||||
- Fix wrong video dimensions for some rotated videos (#33008 and #33261 by @Gargron and @tribela)
|
||||
- Fix error when viewing statuses to deleted replies in moderation view (#32986 by @ClearlyClaire)
|
||||
- Fix missing autofocus on boost modal (#32953 by @tribela)
|
||||
- Fix logic in “last used at per application” OAuth token list (#32912 by @mjankowski)
|
||||
- Fix admin dashboard linking to pages the user does not have permission to see (#32843 by @ThisIsMissEm)
|
||||
- Fix backspace navigation hotkey going back two pages instead of one on some browsers (#32826 by @c960657)
|
||||
- Fix typo in translation string (#32821 by @ThisIsMissEm)
|
||||
- Fix list of follow requests not having a back button (#32797 by @ClearlyClaire)
|
||||
- Fix out-of-view post contents being inconsistent with in-view post contents (#32778, #32887, and #32895 by @ClearlyClaire)
|
||||
- Fix `httplog` gem being used in production (#32776 and #32796 by @ClearlyClaire and @oneiros)
|
||||
- Fix use of deprecated `execCommand` for copying text by using the `clipboard` API (#32598 by @renchap)
|
||||
- Fix some translation strings not being properly pluralized (#27094 by @gunchleoc)
|
||||
|
||||
## [4.3.8] - 2025-05-06
|
||||
|
||||
### Security
|
||||
|
||||
- Update dependencies
|
||||
- Check scheme on account, profile, and media URLs ([GHSA-x2rc-v5wx-g3m5](https://github.com/mastodon/mastodon/security/advisories/GHSA-x2rc-v5wx-g3m5))
|
||||
|
||||
### Added
|
||||
|
||||
- Add warning for REDIS_NAMESPACE deprecation at startup (#34581 by @ClearlyClaire)
|
||||
- Add built-in context for interaction policies (#34574 by @ClearlyClaire)
|
||||
|
||||
### Changed
|
||||
|
||||
- Change activity distribution error handling to skip retrying for deleted accounts (#33617 by @ClearlyClaire)
|
||||
|
||||
### Removed
|
||||
|
||||
- Remove double-query for signed query strings (#34610 by @ClearlyClaire)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix incorrect redirect in response to unauthenticated API requests in limited federation mode (#34549 by @ClearlyClaire)
|
||||
- Fix sign-up e-mail confirmation page reloading on error or redirect (#34548 by @ClearlyClaire)
|
||||
|
||||
## [4.3.7] - 2025-04-02
|
||||
|
||||
### Add
|
||||
### Added
|
||||
|
||||
- Add delay to profile updates to debounce them (#34137 by @ClearlyClaire)
|
||||
- Add support for paginating partial collections in `SynchronizeFollowersService` (#34272 and #34277 by @ClearlyClaire)
|
||||
|
|
|
@ -13,7 +13,7 @@ ARG BASE_REGISTRY="docker.io"
|
|||
|
||||
# Ruby image to use for base image, change with [--build-arg RUBY_VERSION="3.4.x"]
|
||||
# renovate: datasource=docker depName=docker.io/ruby
|
||||
ARG RUBY_VERSION="3.4.2"
|
||||
ARG RUBY_VERSION="3.4.4"
|
||||
# # Node.js version to use in base image, change with [--build-arg NODE_MAJOR_VERSION="20"]
|
||||
# renovate: datasource=node-version depName=node
|
||||
ARG NODE_MAJOR_VERSION="22"
|
||||
|
@ -186,7 +186,7 @@ FROM build AS libvips
|
|||
|
||||
# libvips version to compile, change with [--build-arg VIPS_VERSION="8.15.2"]
|
||||
# renovate: datasource=github-releases depName=libvips packageName=libvips/libvips
|
||||
ARG VIPS_VERSION=8.16.1
|
||||
ARG VIPS_VERSION=8.17.0
|
||||
# libvips download URL, change with [--build-arg VIPS_URL="https://github.com/libvips/libvips/releases/download"]
|
||||
ARG VIPS_URL=https://github.com/libvips/libvips/releases/download
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
- [FEP-f1d5: NodeInfo in Fediverse Software](https://codeberg.org/fediverse/fep/src/branch/main/fep/f1d5/fep-f1d5.md)
|
||||
- [FEP-8fcf: Followers collection synchronization across servers](https://codeberg.org/fediverse/fep/src/branch/main/fep/8fcf/fep-8fcf.md)
|
||||
- [FEP-5feb: Search indexing consent for actors](https://codeberg.org/fediverse/fep/src/branch/main/fep/5feb/fep-5feb.md)
|
||||
- [FEP-044f: Consent-respecting quote posts](https://codeberg.org/fediverse/fep/src/branch/main/fep/044f/fep-044f.md): partial support for incoming quote-posts
|
||||
|
||||
## ActivityPub in Mastodon
|
||||
|
||||
|
|
28
Gemfile
|
@ -5,7 +5,6 @@ ruby '>= 3.2.0', '< 3.5.0'
|
|||
|
||||
gem 'propshaft'
|
||||
gem 'puma', '~> 6.3'
|
||||
gem 'rack', '~> 2.2.7'
|
||||
gem 'rails', '~> 8.0'
|
||||
gem 'thor', '~> 1.2'
|
||||
|
||||
|
@ -52,8 +51,9 @@ gem 'faraday-httpclient'
|
|||
gem 'fast_blank', '~> 1.0'
|
||||
gem 'fastimage'
|
||||
gem 'hiredis', '~> 0.6'
|
||||
gem 'hiredis-client'
|
||||
gem 'htmlentities', '~> 4.3'
|
||||
gem 'http', '~> 5.2.0'
|
||||
gem 'http', '~> 5.3.0'
|
||||
gem 'http_accept_language', '~> 2.1'
|
||||
gem 'httplog', '~> 1.7.0', require: false
|
||||
gem 'i18n'
|
||||
|
@ -62,9 +62,9 @@ gem 'inline_svg'
|
|||
gem 'irb', '~> 1.8'
|
||||
gem 'kaminari', '~> 1.2'
|
||||
gem 'link_header', '~> 0.0'
|
||||
gem 'linzer', '~> 0.6.1'
|
||||
gem 'linzer', '~> 0.7.2'
|
||||
gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock'
|
||||
gem 'mime-types', '~> 3.6.0', require: 'mime/types/columnar'
|
||||
gem 'mime-types', '~> 3.7.0', require: 'mime/types/columnar'
|
||||
gem 'mutex_m'
|
||||
gem 'nokogiri', '~> 1.15'
|
||||
gem 'oj', '~> 3.14'
|
||||
|
@ -74,19 +74,18 @@ gem 'premailer-rails'
|
|||
gem 'public_suffix', '~> 6.0'
|
||||
gem 'pundit', '~> 2.3'
|
||||
gem 'rack-attack', '~> 6.6'
|
||||
gem 'rack-cors', '~> 2.0', require: 'rack/cors'
|
||||
gem 'rack-cors', require: 'rack/cors'
|
||||
gem 'rails-i18n', '~> 8.0'
|
||||
gem 'redcarpet', '~> 3.6'
|
||||
gem 'redis', '~> 4.5', require: ['redis', 'redis/connection/hiredis']
|
||||
gem 'redis-namespace', '~> 1.10'
|
||||
gem 'rqrcode', '~> 2.2'
|
||||
gem 'rqrcode', '~> 3.0'
|
||||
gem 'ruby-progressbar', '~> 1.13'
|
||||
gem 'sanitize', '~> 7.0'
|
||||
gem 'scenic', '~> 1.7'
|
||||
gem 'sidekiq', '~> 6.5'
|
||||
gem 'sidekiq', '< 8'
|
||||
gem 'sidekiq-bulk', '~> 0.2.0'
|
||||
gem 'sidekiq-scheduler', '~> 5.0'
|
||||
gem 'sidekiq-unique-jobs', '~> 7.1'
|
||||
gem 'sidekiq-unique-jobs', '> 8'
|
||||
gem 'simple_form', '~> 5.2'
|
||||
gem 'simple-navigation', '~> 4.4'
|
||||
gem 'stoplight', '~> 4.1'
|
||||
|
@ -95,7 +94,6 @@ gem 'tty-prompt', '~> 0.23', require: false
|
|||
gem 'twitter-text', '~> 3.1.0'
|
||||
gem 'tzinfo-data', '~> 1.2023'
|
||||
gem 'webauthn', '~> 3.0'
|
||||
gem 'webpacker', '~> 5.4'
|
||||
gem 'webpush', github: 'mastodon/webpush', ref: '9631ac63045cfabddacc69fc06e919b4c13eb913'
|
||||
|
||||
gem 'json-ld'
|
||||
|
@ -112,7 +110,7 @@ group :opentelemetry do
|
|||
gem 'opentelemetry-instrumentation-active_model_serializers', '~> 0.22.0', require: false
|
||||
gem 'opentelemetry-instrumentation-concurrent_ruby', '~> 0.22.0', require: false
|
||||
gem 'opentelemetry-instrumentation-excon', '~> 0.23.0', require: false
|
||||
gem 'opentelemetry-instrumentation-faraday', '~> 0.26.0', require: false
|
||||
gem 'opentelemetry-instrumentation-faraday', '~> 0.27.0', require: false
|
||||
gem 'opentelemetry-instrumentation-http', '~> 0.24.0', require: false
|
||||
gem 'opentelemetry-instrumentation-http_client', '~> 0.23.0', require: false
|
||||
gem 'opentelemetry-instrumentation-net_http', '~> 0.23.0', require: false
|
||||
|
@ -139,7 +137,7 @@ group :test do
|
|||
|
||||
# Browser integration testing
|
||||
gem 'capybara', '~> 3.39'
|
||||
gem 'selenium-webdriver'
|
||||
gem 'capybara-playwright-driver'
|
||||
|
||||
# Used to reset the database between system tests
|
||||
gem 'database_cleaner-active_record'
|
||||
|
@ -203,7 +201,7 @@ group :development, :test do
|
|||
gem 'faker', '~> 3.2'
|
||||
|
||||
# Generate factory objects
|
||||
gem 'fabrication', '~> 2.30'
|
||||
gem 'fabrication'
|
||||
|
||||
# Profiling tools
|
||||
gem 'memory_profiler', require: false
|
||||
|
@ -212,7 +210,7 @@ group :development, :test do
|
|||
gem 'test-prof', require: false
|
||||
|
||||
# RSpec runner for rails
|
||||
gem 'rspec-rails', '~> 7.0'
|
||||
gem 'rspec-rails', '~> 8.0'
|
||||
end
|
||||
|
||||
group :production do
|
||||
|
@ -230,3 +228,5 @@ gem 'rubyzip', '~> 2.3'
|
|||
gem 'hcaptcha', '~> 7.1'
|
||||
|
||||
gem 'mail', '~> 2.8'
|
||||
|
||||
gem 'vite_rails', '~> 3.0.19'
|
||||
|
|
233
Gemfile.lock
|
@ -90,11 +90,11 @@ GEM
|
|||
public_suffix (>= 2.0.2, < 7.0)
|
||||
aes_key_wrap (1.1.0)
|
||||
android_key_attestation (0.3.0)
|
||||
annotaterb (4.14.0)
|
||||
annotaterb (4.15.0)
|
||||
ast (2.4.3)
|
||||
attr_required (1.0.2)
|
||||
aws-eventstream (1.3.2)
|
||||
aws-partitions (1.1087.0)
|
||||
aws-partitions (1.1103.0)
|
||||
aws-sdk-core (3.215.1)
|
||||
aws-eventstream (~> 1, >= 1.3.0)
|
||||
aws-partitions (~> 1, >= 1.992.0)
|
||||
|
@ -109,9 +109,9 @@ GEM
|
|||
aws-sigv4 (~> 1.5)
|
||||
aws-sigv4 (1.11.0)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
azure-blob (0.5.7)
|
||||
azure-blob (0.5.8)
|
||||
rexml
|
||||
base64 (0.2.0)
|
||||
base64 (0.3.0)
|
||||
bcp47_spec (0.2.1)
|
||||
bcrypt (3.1.20)
|
||||
benchmark (0.4.0)
|
||||
|
@ -124,14 +124,11 @@ GEM
|
|||
binding_of_caller (1.0.1)
|
||||
debug_inspector (>= 1.2.0)
|
||||
blurhash (0.1.8)
|
||||
bootsnap (1.18.4)
|
||||
bootsnap (1.18.6)
|
||||
msgpack (~> 1.2)
|
||||
brakeman (7.0.2)
|
||||
racc
|
||||
browser (6.2.0)
|
||||
brpoplpush-redis_script (0.1.3)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.5)
|
||||
redis (>= 1.0, < 6)
|
||||
builder (3.3.0)
|
||||
bundler-audit (0.9.2)
|
||||
bundler (>= 1.2.0, < 3)
|
||||
|
@ -145,9 +142,14 @@ GEM
|
|||
rack-test (>= 0.6.3)
|
||||
regexp_parser (>= 1.5, < 3.0)
|
||||
xpath (~> 3.2)
|
||||
capybara-playwright-driver (0.5.6)
|
||||
addressable
|
||||
capybara
|
||||
playwright-ruby-client (>= 1.16.0)
|
||||
case_transform (0.2)
|
||||
activesupport
|
||||
cbor (0.5.9.8)
|
||||
cgi (0.4.2)
|
||||
charlock_holmes (0.7.9)
|
||||
chewy (7.6.0)
|
||||
activesupport (>= 5.2)
|
||||
|
@ -160,7 +162,7 @@ GEM
|
|||
cocoon (1.2.15)
|
||||
color_diff (0.1)
|
||||
concurrent-ruby (1.3.5)
|
||||
connection_pool (2.5.0)
|
||||
connection_pool (2.5.3)
|
||||
cose (1.3.1)
|
||||
cbor (~> 0.5.9)
|
||||
openssl-signature_algorithm (~> 1.0)
|
||||
|
@ -170,8 +172,8 @@ GEM
|
|||
crass (1.0.6)
|
||||
css_parser (1.21.1)
|
||||
addressable
|
||||
csv (3.3.4)
|
||||
database_cleaner-active_record (2.2.0)
|
||||
csv (3.3.5)
|
||||
database_cleaner-active_record (2.2.1)
|
||||
activerecord (>= 5.a)
|
||||
database_cleaner-core (~> 2.0.0)
|
||||
database_cleaner-core (2.0.1)
|
||||
|
@ -194,7 +196,7 @@ GEM
|
|||
devise_pam_authenticatable2 (9.2.0)
|
||||
devise (>= 4.0.0)
|
||||
rpam2 (~> 4.0)
|
||||
diff-lcs (1.6.1)
|
||||
diff-lcs (1.6.2)
|
||||
discard (1.4.0)
|
||||
activerecord (>= 4.2, < 9.0)
|
||||
docile (1.4.1)
|
||||
|
@ -202,7 +204,8 @@ GEM
|
|||
doorkeeper (5.8.2)
|
||||
railties (>= 5)
|
||||
dotenv (3.1.8)
|
||||
drb (2.2.1)
|
||||
drb (2.2.3)
|
||||
dry-cli (1.2.0)
|
||||
elasticsearch (7.17.11)
|
||||
elasticsearch-api (= 7.17.11)
|
||||
elasticsearch-transport (= 7.17.11)
|
||||
|
@ -224,10 +227,10 @@ GEM
|
|||
tzinfo
|
||||
excon (1.2.5)
|
||||
logger
|
||||
fabrication (2.31.0)
|
||||
fabrication (3.0.0)
|
||||
faker (3.5.1)
|
||||
i18n (>= 1.8.11, < 2)
|
||||
faraday (2.13.0)
|
||||
faraday (2.13.1)
|
||||
faraday-net_http (>= 2.0, < 3.5)
|
||||
json
|
||||
logger
|
||||
|
@ -261,15 +264,16 @@ GEM
|
|||
fog-core (~> 2.1)
|
||||
fog-json (>= 1.0)
|
||||
formatador (1.1.0)
|
||||
forwardable (1.3.3)
|
||||
fugit (1.11.1)
|
||||
et-orbi (~> 1, >= 1.2.11)
|
||||
raabro (~> 1.4)
|
||||
globalid (1.2.1)
|
||||
activesupport (>= 6.1)
|
||||
google-protobuf (4.30.2)
|
||||
google-protobuf (4.31.0)
|
||||
bigdecimal
|
||||
rake (>= 13)
|
||||
googleapis-common-protos-types (1.19.0)
|
||||
googleapis-common-protos-types (1.20.0)
|
||||
google-protobuf (>= 3.18, < 5.a)
|
||||
haml (6.3.0)
|
||||
temple (>= 0.8.2)
|
||||
|
@ -293,11 +297,12 @@ GEM
|
|||
highline (3.1.2)
|
||||
reline
|
||||
hiredis (0.6.3)
|
||||
hiredis-client (0.24.0)
|
||||
redis-client (= 0.24.0)
|
||||
hkdf (0.3.0)
|
||||
htmlentities (4.3.4)
|
||||
http (5.2.0)
|
||||
http (5.3.1)
|
||||
addressable (~> 2.8)
|
||||
base64 (~> 0.1)
|
||||
http-cookie (~> 1.0)
|
||||
http-form_data (~> 2.2)
|
||||
llhttp-ffi (~> 0.5.0)
|
||||
|
@ -337,7 +342,7 @@ GEM
|
|||
azure-blob (~> 0.5.2)
|
||||
hashie (~> 5.0)
|
||||
jmespath (1.6.2)
|
||||
json (2.10.2)
|
||||
json (2.12.2)
|
||||
json-canonicalization (1.0.0)
|
||||
json-jwt (1.16.7)
|
||||
activesupport (>= 4.2)
|
||||
|
@ -381,7 +386,7 @@ GEM
|
|||
marcel (~> 1.0.1)
|
||||
mime-types
|
||||
terrapin (>= 0.6.0, < 2.0)
|
||||
language_server-protocol (3.17.0.4)
|
||||
language_server-protocol (3.17.0.5)
|
||||
launchy (3.1.1)
|
||||
addressable (~> 2.8)
|
||||
childprocess (~> 5.0)
|
||||
|
@ -395,7 +400,11 @@ GEM
|
|||
rexml
|
||||
link_header (0.0.8)
|
||||
lint_roller (1.1.0)
|
||||
linzer (0.6.5)
|
||||
linzer (0.7.3)
|
||||
cgi (~> 0.4.2)
|
||||
forwardable (~> 1.3, >= 1.3.3)
|
||||
logger (~> 1.7, >= 1.7.0)
|
||||
net-http (~> 0.6.0)
|
||||
openssl (~> 3.0, >= 3.0.0)
|
||||
rack (>= 2.2, < 4.0)
|
||||
starry (~> 0.2)
|
||||
|
@ -410,7 +419,7 @@ GEM
|
|||
activesupport (>= 4)
|
||||
railties (>= 4)
|
||||
request_store (~> 1.0)
|
||||
loofah (2.24.0)
|
||||
loofah (2.24.1)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.12.0)
|
||||
mail (2.8.1)
|
||||
|
@ -423,19 +432,19 @@ GEM
|
|||
redis (>= 3.0.5)
|
||||
matrix (0.4.2)
|
||||
memory_profiler (1.1.0)
|
||||
mime-types (3.6.2)
|
||||
mime-types (3.7.0)
|
||||
logger
|
||||
mime-types-data (~> 3.2015)
|
||||
mime-types-data (3.2025.0408)
|
||||
mime-types-data (~> 3.2025, >= 3.2025.0507)
|
||||
mime-types-data (3.2025.0514)
|
||||
mini_mime (1.1.5)
|
||||
mini_portile2 (2.8.8)
|
||||
mini_portile2 (2.8.9)
|
||||
minitest (5.25.5)
|
||||
msgpack (1.8.0)
|
||||
multi_json (1.15.0)
|
||||
mutex_m (0.3.0)
|
||||
net-http (0.6.0)
|
||||
uri
|
||||
net-imap (0.5.6)
|
||||
net-imap (0.5.8)
|
||||
date
|
||||
net-protocol
|
||||
net-ldap (0.19.0)
|
||||
|
@ -446,10 +455,10 @@ GEM
|
|||
net-smtp (0.5.1)
|
||||
net-protocol
|
||||
nio4r (2.7.4)
|
||||
nokogiri (1.18.7)
|
||||
nokogiri (1.18.8)
|
||||
mini_portile2 (~> 2.8.2)
|
||||
racc (~> 1.4)
|
||||
oj (3.16.10)
|
||||
oj (3.16.11)
|
||||
bigdecimal (>= 3.0)
|
||||
ostruct (>= 0.2)
|
||||
omniauth (2.1.3)
|
||||
|
@ -463,7 +472,7 @@ GEM
|
|||
omniauth-rails_csrf_protection (1.0.2)
|
||||
actionpack (>= 4.2)
|
||||
omniauth (~> 2.0)
|
||||
omniauth-saml (2.2.3)
|
||||
omniauth-saml (2.2.4)
|
||||
omniauth (~> 2.1)
|
||||
ruby-saml (~> 1.18)
|
||||
omniauth_openid_connect (0.8.0)
|
||||
|
@ -495,13 +504,15 @@ GEM
|
|||
opentelemetry-common (~> 0.20)
|
||||
opentelemetry-sdk (~> 1.2)
|
||||
opentelemetry-semantic_conventions
|
||||
opentelemetry-helpers-sql (0.1.1)
|
||||
opentelemetry-api (~> 1.0)
|
||||
opentelemetry-helpers-sql-obfuscation (0.3.0)
|
||||
opentelemetry-common (~> 0.21)
|
||||
opentelemetry-instrumentation-action_mailer (0.4.0)
|
||||
opentelemetry-api (~> 1.0)
|
||||
opentelemetry-instrumentation-active_support (~> 0.7)
|
||||
opentelemetry-instrumentation-base (~> 0.23.0)
|
||||
opentelemetry-instrumentation-action_pack (0.12.0)
|
||||
opentelemetry-instrumentation-action_pack (0.12.1)
|
||||
opentelemetry-api (~> 1.0)
|
||||
opentelemetry-instrumentation-base (~> 0.23.0)
|
||||
opentelemetry-instrumentation-rack (~> 0.21)
|
||||
|
@ -536,7 +547,7 @@ GEM
|
|||
opentelemetry-instrumentation-excon (0.23.0)
|
||||
opentelemetry-api (~> 1.0)
|
||||
opentelemetry-instrumentation-base (~> 0.23.0)
|
||||
opentelemetry-instrumentation-faraday (0.26.0)
|
||||
opentelemetry-instrumentation-faraday (0.27.0)
|
||||
opentelemetry-api (~> 1.0)
|
||||
opentelemetry-instrumentation-base (~> 0.23.0)
|
||||
opentelemetry-instrumentation-http (0.24.0)
|
||||
|
@ -548,8 +559,9 @@ GEM
|
|||
opentelemetry-instrumentation-net_http (0.23.0)
|
||||
opentelemetry-api (~> 1.0)
|
||||
opentelemetry-instrumentation-base (~> 0.23.0)
|
||||
opentelemetry-instrumentation-pg (0.30.0)
|
||||
opentelemetry-instrumentation-pg (0.30.1)
|
||||
opentelemetry-api (~> 1.0)
|
||||
opentelemetry-helpers-sql
|
||||
opentelemetry-helpers-sql-obfuscation
|
||||
opentelemetry-instrumentation-base (~> 0.23.0)
|
||||
opentelemetry-instrumentation-rack (0.26.0)
|
||||
|
@ -583,7 +595,7 @@ GEM
|
|||
opentelemetry-api (~> 1.0)
|
||||
orm_adapter (0.5.0)
|
||||
ostruct (0.6.1)
|
||||
ox (2.14.22)
|
||||
ox (2.14.23)
|
||||
bigdecimal (>= 3.0)
|
||||
parallel (1.27.0)
|
||||
parser (3.3.8.0)
|
||||
|
@ -593,8 +605,11 @@ GEM
|
|||
pastel (0.8.0)
|
||||
tty-color (~> 0.5)
|
||||
pg (1.5.9)
|
||||
pghero (3.6.2)
|
||||
activerecord (>= 6.1)
|
||||
pghero (3.7.0)
|
||||
activerecord (>= 7.1)
|
||||
playwright-ruby-client (1.52.0)
|
||||
concurrent-ruby (>= 1.1.6)
|
||||
mime-types (>= 3.0)
|
||||
pp (0.6.2)
|
||||
prettyprint
|
||||
premailer (1.27.0)
|
||||
|
@ -614,21 +629,22 @@ GEM
|
|||
activesupport (>= 7.0.0)
|
||||
rack
|
||||
railties (>= 7.0.0)
|
||||
psych (5.2.3)
|
||||
psych (5.2.6)
|
||||
date
|
||||
stringio
|
||||
public_suffix (6.0.1)
|
||||
public_suffix (6.0.2)
|
||||
puma (6.6.0)
|
||||
nio4r (~> 2.0)
|
||||
pundit (2.5.0)
|
||||
activesupport (>= 3.0.0)
|
||||
raabro (1.4.0)
|
||||
racc (1.8.1)
|
||||
rack (2.2.13)
|
||||
rack (3.1.16)
|
||||
rack-attack (6.7.0)
|
||||
rack (>= 1.0, < 4)
|
||||
rack-cors (2.0.2)
|
||||
rack (>= 2.0.0)
|
||||
rack-cors (3.0.0)
|
||||
logger
|
||||
rack (>= 3.0.14)
|
||||
rack-oauth2 (2.2.1)
|
||||
activesupport
|
||||
attr_required
|
||||
|
@ -636,18 +652,19 @@ GEM
|
|||
faraday-follow_redirects
|
||||
json-jwt (>= 1.11.0)
|
||||
rack (>= 2.1.0)
|
||||
rack-protection (3.2.0)
|
||||
rack-protection (4.1.1)
|
||||
base64 (>= 0.1.0)
|
||||
rack (~> 2.2, >= 2.2.4)
|
||||
logger (>= 1.6.0)
|
||||
rack (>= 3.0.0, < 4)
|
||||
rack-proxy (0.7.7)
|
||||
rack
|
||||
rack-session (1.0.2)
|
||||
rack (< 3)
|
||||
rack-session (2.1.1)
|
||||
base64 (>= 0.1.0)
|
||||
rack (>= 3.0.0)
|
||||
rack-test (2.2.0)
|
||||
rack (>= 1.3)
|
||||
rackup (1.0.1)
|
||||
rack (< 3)
|
||||
webrick
|
||||
rackup (2.2.1)
|
||||
rack (>= 3)
|
||||
rails (8.0.2)
|
||||
actioncable (= 8.0.2)
|
||||
actionmailbox (= 8.0.2)
|
||||
|
@ -681,7 +698,7 @@ GEM
|
|||
thor (~> 1.0, >= 1.2.2)
|
||||
zeitwerk (~> 2.6)
|
||||
rainbow (3.1.1)
|
||||
rake (13.2.1)
|
||||
rake (13.3.0)
|
||||
rdf (3.3.2)
|
||||
bcp47_spec (~> 0.2)
|
||||
bigdecimal (~> 3.1, >= 3.1.5)
|
||||
|
@ -692,8 +709,8 @@ GEM
|
|||
psych (>= 4.0.0)
|
||||
redcarpet (3.6.1)
|
||||
redis (4.8.1)
|
||||
redis-namespace (1.11.0)
|
||||
redis (>= 4)
|
||||
redis-client (0.24.0)
|
||||
connection_pool
|
||||
redlock (1.3.2)
|
||||
redis (>= 3.0.0, < 6.0)
|
||||
regexp_parser (2.10.0)
|
||||
|
@ -706,30 +723,30 @@ GEM
|
|||
railties (>= 5.2)
|
||||
rexml (3.4.1)
|
||||
rotp (6.3.0)
|
||||
rouge (4.5.1)
|
||||
rouge (4.5.2)
|
||||
rpam2 (4.0.2)
|
||||
rqrcode (2.2.0)
|
||||
rqrcode (3.1.0)
|
||||
chunky_png (~> 1.0)
|
||||
rqrcode_core (~> 1.0)
|
||||
rqrcode_core (1.2.0)
|
||||
rqrcode_core (~> 2.0)
|
||||
rqrcode_core (2.0.0)
|
||||
rspec (3.13.0)
|
||||
rspec-core (~> 3.13.0)
|
||||
rspec-expectations (~> 3.13.0)
|
||||
rspec-mocks (~> 3.13.0)
|
||||
rspec-core (3.13.3)
|
||||
rspec-support (~> 3.13.0)
|
||||
rspec-expectations (3.13.3)
|
||||
rspec-expectations (3.13.4)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.13.0)
|
||||
rspec-github (3.0.0)
|
||||
rspec-core (~> 3.0)
|
||||
rspec-mocks (3.13.2)
|
||||
rspec-mocks (3.13.4)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.13.0)
|
||||
rspec-rails (7.1.1)
|
||||
actionpack (>= 7.0)
|
||||
activesupport (>= 7.0)
|
||||
railties (>= 7.0)
|
||||
rspec-rails (8.0.0)
|
||||
actionpack (>= 7.2)
|
||||
activesupport (>= 7.2)
|
||||
railties (>= 7.2)
|
||||
rspec-core (~> 3.13)
|
||||
rspec-expectations (~> 3.13)
|
||||
rspec-mocks (~> 3.13)
|
||||
|
@ -739,8 +756,8 @@ GEM
|
|||
rspec-expectations (~> 3.0)
|
||||
rspec-mocks (~> 3.0)
|
||||
sidekiq (>= 5, < 9)
|
||||
rspec-support (3.13.2)
|
||||
rubocop (1.75.2)
|
||||
rspec-support (3.13.3)
|
||||
rubocop (1.76.1)
|
||||
json (~> 2.3)
|
||||
language_server-protocol (~> 3.17.0.2)
|
||||
lint_roller (~> 1.1.0)
|
||||
|
@ -748,10 +765,10 @@ GEM
|
|||
parser (>= 3.3.0.2)
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
regexp_parser (>= 2.9.3, < 3.0)
|
||||
rubocop-ast (>= 1.44.0, < 2.0)
|
||||
rubocop-ast (>= 1.45.0, < 2.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (>= 2.4.0, < 4.0)
|
||||
rubocop-ast (1.44.1)
|
||||
rubocop-ast (1.45.1)
|
||||
parser (>= 3.3.7.2)
|
||||
prism (~> 1.4)
|
||||
rubocop-capybara (2.22.1)
|
||||
|
@ -764,25 +781,26 @@ GEM
|
|||
lint_roller (~> 1.1)
|
||||
rubocop (>= 1.75.0, < 2.0)
|
||||
rubocop-ast (>= 1.38.0, < 2.0)
|
||||
rubocop-rails (2.31.0)
|
||||
rubocop-rails (2.32.0)
|
||||
activesupport (>= 4.2.0)
|
||||
lint_roller (~> 1.1)
|
||||
rack (>= 1.1)
|
||||
rubocop (>= 1.75.0, < 2.0)
|
||||
rubocop-ast (>= 1.38.0, < 2.0)
|
||||
rubocop-rspec (3.5.0)
|
||||
rubocop-ast (>= 1.44.0, < 2.0)
|
||||
rubocop-rspec (3.6.0)
|
||||
lint_roller (~> 1.1)
|
||||
rubocop (~> 1.72, >= 1.72.1)
|
||||
rubocop-rspec_rails (2.31.0)
|
||||
lint_roller (~> 1.1)
|
||||
rubocop (~> 1.72, >= 1.72.1)
|
||||
rubocop-rspec (~> 3.5)
|
||||
ruby-prof (1.7.1)
|
||||
ruby-prof (1.7.2)
|
||||
base64
|
||||
ruby-progressbar (1.13.0)
|
||||
ruby-saml (1.18.0)
|
||||
nokogiri (>= 1.13.10)
|
||||
rexml
|
||||
ruby-vips (2.2.3)
|
||||
ruby-vips (2.2.4)
|
||||
ffi (~> 1.12)
|
||||
logger
|
||||
rubyzip (2.4.1)
|
||||
|
@ -797,31 +815,24 @@ GEM
|
|||
activerecord (>= 4.0.0)
|
||||
railties (>= 4.0.0)
|
||||
securerandom (0.4.1)
|
||||
selenium-webdriver (4.31.0)
|
||||
base64 (~> 0.2)
|
||||
logger (~> 1.4)
|
||||
rexml (~> 3.2, >= 3.2.5)
|
||||
rubyzip (>= 1.2.2, < 3.0)
|
||||
websocket (~> 1.0)
|
||||
semantic_range (3.1.0)
|
||||
shoulda-matchers (6.4.0)
|
||||
shoulda-matchers (6.5.0)
|
||||
activesupport (>= 5.2.0)
|
||||
sidekiq (6.5.12)
|
||||
connection_pool (>= 2.2.5, < 3)
|
||||
rack (~> 2.0)
|
||||
redis (>= 4.5.0, < 5)
|
||||
sidekiq (7.3.9)
|
||||
base64
|
||||
connection_pool (>= 2.3.0)
|
||||
logger
|
||||
rack (>= 2.2.4)
|
||||
redis-client (>= 0.22.2)
|
||||
sidekiq-bulk (0.2.0)
|
||||
sidekiq
|
||||
sidekiq-scheduler (5.0.6)
|
||||
rufus-scheduler (~> 3.2)
|
||||
sidekiq (>= 6, < 8)
|
||||
tilt (>= 1.4.0, < 3)
|
||||
sidekiq-unique-jobs (7.1.33)
|
||||
brpoplpush-redis_script (> 0.1.1, <= 2.0.0)
|
||||
sidekiq-unique-jobs (8.0.11)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.5)
|
||||
redis (< 5.0)
|
||||
sidekiq (>= 5.0, < 7.0)
|
||||
thor (>= 0.20, < 3.0)
|
||||
sidekiq (>= 7.0.0, < 9.0.0)
|
||||
thor (>= 1.0, < 3.0)
|
||||
simple-navigation (4.4.0)
|
||||
activesupport (>= 2.3.2)
|
||||
simple_form (5.3.1)
|
||||
|
@ -839,7 +850,7 @@ GEM
|
|||
base64
|
||||
stoplight (4.1.1)
|
||||
redlock (~> 1.0)
|
||||
stringio (3.1.6)
|
||||
stringio (3.1.7)
|
||||
strong_migrations (2.3.0)
|
||||
activerecord (>= 7)
|
||||
swd (2.0.3)
|
||||
|
@ -889,6 +900,15 @@ GEM
|
|||
validate_url (1.0.15)
|
||||
activemodel (>= 3.0.0)
|
||||
public_suffix
|
||||
vite_rails (3.0.19)
|
||||
railties (>= 5.1, < 9)
|
||||
vite_ruby (~> 3.0, >= 3.2.2)
|
||||
vite_ruby (3.9.2)
|
||||
dry-cli (>= 0.7, < 2)
|
||||
logger (~> 1.6)
|
||||
mutex_m
|
||||
rack-proxy (~> 0.6, >= 0.6.1)
|
||||
zeitwerk (~> 2.2)
|
||||
warden (1.2.9)
|
||||
rack (>= 2.0.9)
|
||||
webauthn (3.4.0)
|
||||
|
@ -907,13 +927,7 @@ GEM
|
|||
addressable (>= 2.8.0)
|
||||
crack (>= 0.3.2)
|
||||
hashdiff (>= 0.4.0, < 2.0.0)
|
||||
webpacker (5.4.4)
|
||||
activesupport (>= 5.2)
|
||||
rack-proxy (>= 0.6.1)
|
||||
railties (>= 5.2)
|
||||
semantic_range (>= 2.3.0)
|
||||
webrick (1.9.1)
|
||||
websocket (1.2.11)
|
||||
websocket-driver (0.7.7)
|
||||
base64
|
||||
websocket-extensions (>= 0.1.0)
|
||||
|
@ -941,6 +955,7 @@ DEPENDENCIES
|
|||
browser
|
||||
bundler-audit (~> 0.9)
|
||||
capybara (~> 3.39)
|
||||
capybara-playwright-driver
|
||||
charlock_holmes (~> 0.7.7)
|
||||
chewy (~> 7.3)
|
||||
climate_control
|
||||
|
@ -958,7 +973,7 @@ DEPENDENCIES
|
|||
doorkeeper (~> 5.6)
|
||||
dotenv
|
||||
email_spec
|
||||
fabrication (~> 2.30)
|
||||
fabrication
|
||||
faker (~> 3.2)
|
||||
faraday-httpclient
|
||||
fast_blank (~> 1.0)
|
||||
|
@ -970,8 +985,9 @@ DEPENDENCIES
|
|||
haml_lint
|
||||
hcaptcha (~> 7.1)
|
||||
hiredis (~> 0.6)
|
||||
hiredis-client
|
||||
htmlentities (~> 4.3)
|
||||
http (~> 5.2.0)
|
||||
http (~> 5.3.0)
|
||||
http_accept_language (~> 2.1)
|
||||
httplog (~> 1.7.0)
|
||||
i18n
|
||||
|
@ -988,12 +1004,12 @@ DEPENDENCIES
|
|||
letter_opener (~> 1.8)
|
||||
letter_opener_web (~> 3.0)
|
||||
link_header (~> 0.0)
|
||||
linzer (~> 0.6.1)
|
||||
linzer (~> 0.7.2)
|
||||
lograge (~> 0.12)
|
||||
mail (~> 2.8)
|
||||
mario-redis-lock (~> 1.2)
|
||||
memory_profiler
|
||||
mime-types (~> 3.6.0)
|
||||
mime-types (~> 3.7.0)
|
||||
mutex_m
|
||||
net-http (~> 0.6.0)
|
||||
net-ldap (~> 0.18)
|
||||
|
@ -1010,7 +1026,7 @@ DEPENDENCIES
|
|||
opentelemetry-instrumentation-active_model_serializers (~> 0.22.0)
|
||||
opentelemetry-instrumentation-concurrent_ruby (~> 0.22.0)
|
||||
opentelemetry-instrumentation-excon (~> 0.23.0)
|
||||
opentelemetry-instrumentation-faraday (~> 0.26.0)
|
||||
opentelemetry-instrumentation-faraday (~> 0.27.0)
|
||||
opentelemetry-instrumentation-http (~> 0.24.0)
|
||||
opentelemetry-instrumentation-http_client (~> 0.23.0)
|
||||
opentelemetry-instrumentation-net_http (~> 0.23.0)
|
||||
|
@ -1030,19 +1046,17 @@ DEPENDENCIES
|
|||
public_suffix (~> 6.0)
|
||||
puma (~> 6.3)
|
||||
pundit (~> 2.3)
|
||||
rack (~> 2.2.7)
|
||||
rack-attack (~> 6.6)
|
||||
rack-cors (~> 2.0)
|
||||
rack-cors
|
||||
rack-test (~> 2.1)
|
||||
rails (~> 8.0)
|
||||
rails-i18n (~> 8.0)
|
||||
rdf-normalize (~> 0.5)
|
||||
redcarpet (~> 3.6)
|
||||
redis (~> 4.5)
|
||||
redis-namespace (~> 1.10)
|
||||
rqrcode (~> 2.2)
|
||||
rqrcode (~> 3.0)
|
||||
rspec-github (~> 3.0)
|
||||
rspec-rails (~> 7.0)
|
||||
rspec-rails (~> 8.0)
|
||||
rspec-sidekiq (~> 5.0)
|
||||
rubocop
|
||||
rubocop-capybara
|
||||
|
@ -1057,12 +1071,11 @@ DEPENDENCIES
|
|||
rubyzip (~> 2.3)
|
||||
sanitize (~> 7.0)
|
||||
scenic (~> 1.7)
|
||||
selenium-webdriver
|
||||
shoulda-matchers
|
||||
sidekiq (~> 6.5)
|
||||
sidekiq (< 8)
|
||||
sidekiq-bulk (~> 0.2.0)
|
||||
sidekiq-scheduler (~> 5.0)
|
||||
sidekiq-unique-jobs (~> 7.1)
|
||||
sidekiq-unique-jobs (> 8)
|
||||
simple-navigation (~> 4.4)
|
||||
simple_form (~> 5.2)
|
||||
simplecov (~> 0.22)
|
||||
|
@ -1075,9 +1088,9 @@ DEPENDENCIES
|
|||
tty-prompt (~> 0.23)
|
||||
twitter-text (~> 3.1.0)
|
||||
tzinfo-data (~> 1.2023)
|
||||
vite_rails (~> 3.0.19)
|
||||
webauthn (~> 3.0)
|
||||
webmock (~> 3.18)
|
||||
webpacker (~> 5.4)
|
||||
webpush!
|
||||
xorcist (~> 1.1)
|
||||
|
||||
|
@ -1085,4 +1098,4 @@ RUBY VERSION
|
|||
ruby 3.4.1p0
|
||||
|
||||
BUNDLED WITH
|
||||
2.6.8
|
||||
2.6.9
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
web: env PORT=3000 RAILS_ENV=development bundle exec puma -C config/puma.rb
|
||||
sidekiq: env PORT=3000 RAILS_ENV=development bundle exec sidekiq
|
||||
stream: env PORT=4000 yarn workspace @mastodon/streaming start
|
||||
webpack: bin/webpack-dev-server
|
||||
vite: yarn dev
|
||||
|
|
124
README.md
|
@ -1,27 +1,123 @@
|
|||
NAS is an KMY & Mastodon Fork
|
||||
#  kmyblue
|
||||
|
||||
The following are just a few of the most common features. There are many other minor changes to the specifications.
|
||||
[](https://github.com/kmycode/mastodon/actions/workflows/test-ruby.yml)
|
||||
|
||||
Emoji reactions
|
||||
! FOR ENGLISH USER ! We do not provide English documentation for kmyblue; we assume that you will use automatic translation software, such as Google, to translate the site.
|
||||
|
||||
Local Public (Does not appear on the federated timeline of remote servers, but does appear on followers' home timelines. This is different from local only)
|
||||
kmyblueは、ActivityPubに接続するSNSの1つである[Mastodon](https://github.com/mastodon/mastodon)のフォークです。創作作家のためのMastodonを目指して開発しました。
|
||||
|
||||
Bookmark classification
|
||||
kmyblueはフォーク名であり、同時に[サーバー名](https://kmy.blue)でもあります。以下は特に記述がない限り、フォークとしてのkmyblueをさします。
|
||||
|
||||
Set who can search your posts for each post (Searchability)
|
||||
kmyblueは AGPL ライセンスで公開されているため、どなたでも自由にフォークし、このソースコードを元に自分でサーバーを立てて公開することができます。確かにサーバーkmyblueは創作作家向けの利用規約が設定されていますが、フォークとしてのkmyblueのルールは全くの別物です。いかなるコミュニティにも平等にお使いいただけます。
|
||||
kmyblueは、閉鎖的なコミュニティ、あまり目立ちたくないコミュニティには特に強力な機能を提供します。kmyblueはプライバシーを考慮したうえで強力な独自機能を提供するため、汎用サーバーとして利用するにもある程度十分な機能が揃っています。
|
||||
|
||||
Quote posts, modest quotes (references)
|
||||
テストコード、Lint どちらも動いています。
|
||||
|
||||
Record posts that meet certain conditions such as domains, accounts, and keywords (Subscriptions/Antennas)
|
||||
### アジェンダ
|
||||
|
||||
Send posts to a designated set of followers (Circles) (different from direct messages)
|
||||
- 利用方法
|
||||
- kmyblueの開発方針
|
||||
- kmyblueは何でないか
|
||||
- kmyblueの独自機能
|
||||
- 英語のサポートについて
|
||||
|
||||
Notification of new posts on lists
|
||||
## 利用方法
|
||||
|
||||
Exclude posts from people you follow when filtering posts
|
||||
### インストール方法
|
||||
|
||||
Hide number of followers and followings
|
||||
[Wiki](https://github.com/kmycode/mastodon/wiki/Installation)を参照してください。
|
||||
|
||||
Automatically delete posts after a specified time has passed
|
||||
### 開発への参加方法
|
||||
|
||||
Expanding moderation functions
|
||||
CONTRIBUTING.mdを参照してください。
|
||||
|
||||
### テスト
|
||||
|
||||
```
|
||||
# デバッグ実行(以下のいずれか)
|
||||
foreman start
|
||||
DB_USER=postgres DB_PASS=password foreman start
|
||||
|
||||
# 一部を除く全てのテストを行う
|
||||
RAILS_ENV=test bundle exec rspec spec
|
||||
|
||||
# ElasticSearch連携テストを行う
|
||||
新
|
||||
RAILS_ENV=test ES_ENABLED=true bundle exec rspec --tag search
|
||||
旧
|
||||
RAILS_ENV=test ES_ENABLED=true RUN_SEARCH_SPECS=true bundle exec rspec spec/search
|
||||
```
|
||||
|
||||
## kmyblueの開発方針
|
||||
|
||||
### 本家Mastodonへの積極的追従
|
||||
|
||||
kmyblueは、追加機能を控えめにする代わりに本家Mastodonに積極的に追従を行います。kmyblueの追加機能そのままに、Mastodonの新機能も利用できるよう調整を行います。
|
||||
|
||||
### ゆるやかな内輪での運用
|
||||
|
||||
kmyblueは同人向けサーバーとして出発したため、同人作家に需要のある「内輪ノリを外部にできるだけもらさない」という部分に特化しています。
|
||||
|
||||
「ローカル公開」は、投稿を見せたくない人に見つかりにくくする効果があります。「サークル」は、フォロワーの中でも特に見せたい人だけに見せる効果があります。
|
||||
「検索許可」という独自の検索オプションを利用することで、公開投稿の一部だけを検索されにくくするだけでなく、非収載投稿が誰でも自由に検索できるようになります。
|
||||
|
||||
内輪とは自分のサーバーに限ったものではありません。内輪同士で複数のサーバーを運営するとき、お互いが深く繋がれる「フレンドサーバー」というシステムも用意しています。
|
||||
|
||||
### 少人数サーバーでの運用
|
||||
|
||||
kmyblueは、人の少ないサーバーでの運用を考慮して設計しています。そのため、Fedibirdにあるような、人の多いサーバー向けの機能はあまり作っていません。
|
||||
|
||||
サーバーの負荷については一部度外視している部分があります。たとえば絵文字リアクション機能はサーバーへ著しい負荷をかける場合があります。ただしkmyblueでは、絵文字リアクション機能そのものを無効にしたり、負荷の高いストリーミング処理を無効にする管理者オプションも存在します。
|
||||
|
||||
もちろん人の多いサーバーでの運用が不便になるような修正は行っていません。人数にかかわらず、そのままお使いいただけます。
|
||||
|
||||
### 比較的高い防御力
|
||||
|
||||
kmyblueでは、「Fediverseは将来的に荒むのではないか」「Fediverseは将来的にスパムに溢れるのではないか」を念頭に設計している部分があります。投稿だけでなく絵文字リアクションも対象にした防衛策があります。
|
||||
|
||||
管理者は「NGワード」「NGルール」機能の利用が可能です。設定を変更することで、一部のモデレーターもこの機能を利用できます。
|
||||
利用者は、独自拡張されたフィルター機能、絵文字リアクションのブロックなどを利用できます。
|
||||
|
||||
ただし防御力の高さは自由を犠牲にします。例えばNGワードが多すぎると、他のサーバーからの投稿が制限され、かつそれに気づきにくくなります。
|
||||
|
||||
## kmyblueは何でないか
|
||||
|
||||
kmyblueは、企業・政府機関向けに開発されたものではありません。開発者はセキュリティに関する専門知識を有しておらず、高度なセキュリティを求められる機関向けのソフトウェアを制作する能力はありません。また、kmyblueのメンテナは現在1人のみであり、そのメンテナが飽きたら開発がストップするリスクも高いです。Mastodonのような高い信頼性・安全性を保証することはできないので、導入の際はご自身で安全を十分に確認してからお使いになることを強くおすすめします。
|
||||
個人サーバーであっても、安定性を強く求める方にはおすすめできません。glitch-socがよりよい選択肢になるでしょう。
|
||||
|
||||
kmyblueは、Misskeyではありません。Misskeyは「楽しむ」をコンセプトにしていますが、kmyblueはMastodonの思想を受け継ぎ、炎上や喧騒を避けることのできる落ち着いた場所を目指しています。そのため、思想に合わない機能は実装しないか、大幅に弱体化しています。
|
||||
|
||||
kmyblueは、Fedibirdではありません。Fedibirdは大規模サーバー向けに設定していると思われる機能があり、例えば購読機能がその代表例です。Fedibirdの購読は擬似的なフォロー体験を与えるものですが、本物のフォローではないため、購読対象の投稿が配送されることを確約したものではありません。小規模サーバーだとかえって不便になる機能を、kmyblueは避けています。
|
||||
|
||||
## kmyblueの独自機能
|
||||
|
||||
以下に列挙したものはあくまで代表的なものです。これ以外にも、細かい仕様変更などが多数含まれます。
|
||||
|
||||
- 絵文字リアクション
|
||||
- ローカル公開(Local Public)(リモートサーバーの連合タイムラインには流れませんが、フォロワーのホームタイムラインには流れます。**ローカル限定とは異なります**)
|
||||
- ブックマークの分類
|
||||
- 自分の投稿を検索できる人を投稿ごとに設定(検索許可・Searchability)
|
||||
- 投稿の引用、ひかえめな引用(参照)
|
||||
- ドメイン・アカウント・キーワードなど特定条件を満たした投稿を記録する機能(購読・アンテナ)
|
||||
- フォロワーの一部を指名して投稿を送る機能(サークル)(ダイレクトメッセージとは異なります)
|
||||
- リスト新着投稿の通知
|
||||
- 投稿のフィルタリングにおいて、自分がフォローしている相手の投稿を除外
|
||||
- フォロー・フォロワー数を隠す機能
|
||||
- 指定した時間が経過したあとに投稿を自動削除する機能
|
||||
- モデレーション機能の拡張
|
||||
|
||||
## 英語のサポートについて
|
||||
|
||||
kmyblueのメイン開発者である[雪あすか](https://kmy.blue/@askyq)は、英語の読み書きがほとんどできません。そのため、ドキュメントの英語化、海外向け公式アカウントの新設などを行う予定はありません。
|
||||
|
||||
要望やバグ報告はIssueに書いて構いませんが、Issue画面内の説明やテンプレートはすべて日本語になっています。投稿が難しければ、Discussionに投稿してください。こちらで必要と判断したものは、改めてIssueとして起票します。
|
||||
|
||||
そのほか開発者へ質問があれば、[@askyq@kmy.blue](https://kmy.blue/@askyq)へ英語のまま送ってください。
|
||||
|
||||
ただしkmyblueのドキュメント、[@askyq@kmy.blue](https://kmy.blue/@askyq)内のkmyblueフォークに関係する投稿を、許可なく翻訳して公開することは問題ありません。
|
||||
|
||||
## 開発者のアカウントについて
|
||||
|
||||
kmyblueのメイン開発者である[雪あすか](https://kmy.blue/@askyq)は、用途別にアカウントを分けるようなことはせず、すべての発言を1つのアカウントで行っています。そのため、kmyblueの開発だけでなく、成人向け同人作品の話も混ざっています。
|
||||
|
||||
このうち、公開範囲「公開」「ローカル公開」「非収載」であるkmyblueフォークの開発に関係する投稿に限り抽出し、翻訳の有無に関係なく公開することを許可します。これはkmyblueフォークの利用者にとって公共性の高いコンテンツであると思われます。これは、日本と欧米では一般的に考えられている児童ポルノの基準が異なり、欧米のサーバーの中にはこのアカウントをフォローしづらいものもあるという懸念を考慮したものです。
|
||||
|
|
4
app.json
|
@ -17,10 +17,6 @@
|
|||
"description": "The secret key base",
|
||||
"generator": "secret"
|
||||
},
|
||||
"OTP_SECRET": {
|
||||
"description": "One-time password secret",
|
||||
"generator": "secret"
|
||||
},
|
||||
"SINGLE_USER_MODE": {
|
||||
"description": "Should the instance run in single user mode? (Disable registrations, redirect to front page)",
|
||||
"value": "false",
|
||||
|
|
|
@ -2,13 +2,17 @@
|
|||
|
||||
module Admin
|
||||
class RulesController < BaseController
|
||||
before_action :set_rule, except: [:index, :create]
|
||||
before_action :set_rule, except: [:index, :new, :create]
|
||||
|
||||
def index
|
||||
authorize :rule, :index?
|
||||
|
||||
@rules = Rule.ordered
|
||||
@rule = Rule.new
|
||||
@rules = Rule.ordered.includes(:translations)
|
||||
end
|
||||
|
||||
def new
|
||||
authorize :rule, :create?
|
||||
@rule = Rule.new
|
||||
end
|
||||
|
||||
def edit
|
||||
|
@ -23,8 +27,7 @@ module Admin
|
|||
if @rule.save
|
||||
redirect_to admin_rules_path
|
||||
else
|
||||
@rules = Rule.ordered
|
||||
render :index
|
||||
render :new
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -46,6 +49,22 @@ module Admin
|
|||
redirect_to admin_rules_path
|
||||
end
|
||||
|
||||
def move_up
|
||||
authorize @rule, :update?
|
||||
|
||||
@rule.move!(-1)
|
||||
|
||||
redirect_to admin_rules_path
|
||||
end
|
||||
|
||||
def move_down
|
||||
authorize @rule, :update?
|
||||
|
||||
@rule.move!(+1)
|
||||
|
||||
redirect_to admin_rules_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_rule
|
||||
|
@ -54,7 +73,7 @@ module Admin
|
|||
|
||||
def resource_params
|
||||
params
|
||||
.expect(rule: [:text, :hint, :priority])
|
||||
.expect(rule: [:text, :hint, :priority, translations_attributes: [[:id, :language, :text, :hint, :_destroy]]])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -50,6 +50,10 @@ class Api::BaseController < ApplicationController
|
|||
nil
|
||||
end
|
||||
|
||||
def require_client_credentials!
|
||||
render json: { error: 'This method requires an client credentials authentication' }, status: 403 if doorkeeper_token.resource_owner_id.present?
|
||||
end
|
||||
|
||||
def require_authenticated_user!
|
||||
render json: { error: 'This method requires an authenticated user' }, status: 401 unless current_user
|
||||
end
|
||||
|
@ -72,6 +76,13 @@ class Api::BaseController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
# Redefine `require_functional!` to properly output JSON instead of HTML redirects
|
||||
def require_functional!
|
||||
return if current_user.functional?
|
||||
|
||||
require_user!
|
||||
end
|
||||
|
||||
def render_empty
|
||||
render json: {}, status: 200
|
||||
end
|
||||
|
|
|
@ -42,37 +42,22 @@ class Api::Fasp::BaseController < ApplicationController
|
|||
end
|
||||
|
||||
def validate_signature!
|
||||
signature_input = request.headers['signature-input']&.encode('UTF-8')
|
||||
raise Error, 'signature-input is missing' if signature_input.blank?
|
||||
raise Error, 'signature-input is missing' if request.headers['signature-input'].blank?
|
||||
|
||||
provider = nil
|
||||
|
||||
Linzer.verify!(request.rack_request, no_older_than: 5.minutes) do |keyid|
|
||||
provider = Fasp::Provider.find(keyid)
|
||||
Linzer.new_ed25519_public_key(provider.provider_public_key_pem, keyid)
|
||||
end
|
||||
|
||||
keyid = signature_input.match(KEYID_PATTERN)[1]
|
||||
provider = Fasp::Provider.find(keyid)
|
||||
linzer_request = Linzer.new_request(
|
||||
request.method,
|
||||
request.original_url,
|
||||
{},
|
||||
{
|
||||
'content-digest' => request.headers['content-digest'],
|
||||
'signature-input' => signature_input,
|
||||
'signature' => request.headers['signature'],
|
||||
}
|
||||
)
|
||||
message = Linzer::Message.new(linzer_request)
|
||||
key = Linzer.new_ed25519_public_key(provider.provider_public_key_pem, keyid)
|
||||
signature = Linzer::Signature.build(message.headers)
|
||||
Linzer.verify(key, message, signature)
|
||||
@current_provider = provider
|
||||
end
|
||||
|
||||
def sign_response
|
||||
response.headers['content-digest'] = "sha-256=:#{OpenSSL::Digest.base64digest('sha256', response.body || '')}:"
|
||||
|
||||
linzer_response = Linzer.new_response(response.body, response.status, { 'content-digest' => response.headers['content-digest'] })
|
||||
message = Linzer::Message.new(linzer_response)
|
||||
key = Linzer.new_ed25519_key(current_provider.server_private_key_pem)
|
||||
signature = Linzer.sign(key, message, %w(@status content-digest))
|
||||
|
||||
response.headers.merge!(signature.to_h)
|
||||
Linzer.sign!(response, key:, components: %w(@status content-digest))
|
||||
end
|
||||
|
||||
def check_fasp_enabled
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::Fasp::DataSharing::V0::BackfillRequestsController < Api::Fasp::BaseController
|
||||
def create
|
||||
backfill_request = current_provider.fasp_backfill_requests.new(backfill_request_params)
|
||||
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
if backfill_request.save
|
||||
render json: { backfillRequest: { id: backfill_request.id } }, status: 201
|
||||
else
|
||||
head 422
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def backfill_request_params
|
||||
params
|
||||
.permit(:category, :maxCount)
|
||||
.to_unsafe_h
|
||||
.transform_keys { |k| k.to_s.underscore }
|
||||
end
|
||||
end
|
|
@ -0,0 +1,10 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::Fasp::DataSharing::V0::ContinuationsController < Api::Fasp::BaseController
|
||||
def create
|
||||
backfill_request = current_provider.fasp_backfill_requests.find(params[:backfill_request_id])
|
||||
Fasp::BackfillWorker.perform_async(backfill_request.id)
|
||||
|
||||
head 204
|
||||
end
|
||||
end
|
|
@ -0,0 +1,25 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::Fasp::DataSharing::V0::EventSubscriptionsController < Api::Fasp::BaseController
|
||||
def create
|
||||
subscription = current_provider.fasp_subscriptions.create!(subscription_params)
|
||||
|
||||
render json: { subscription: { id: subscription.id } }, status: 201
|
||||
end
|
||||
|
||||
def destroy
|
||||
subscription = current_provider.fasp_subscriptions.find(params[:id])
|
||||
subscription.destroy
|
||||
|
||||
head 204
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def subscription_params
|
||||
params
|
||||
.permit(:category, :subscriptionType, :maxBatchSize, threshold: {})
|
||||
.to_unsafe_h
|
||||
.transform_keys { |k| k.to_s.underscore }
|
||||
end
|
||||
end
|
|
@ -10,6 +10,7 @@ class Api::V1::AccountsController < Api::BaseController
|
|||
before_action -> { doorkeeper_authorize! :write, :'write:accounts' }, only: [:create]
|
||||
|
||||
before_action :require_user!, except: [:index, :show, :create]
|
||||
before_action :require_client_credentials!, only: [:create]
|
||||
before_action :set_account, except: [:index, :create]
|
||||
before_action :set_accounts, only: [:index]
|
||||
before_action :check_account_approval, except: [:index, :create]
|
||||
|
|
|
@ -18,7 +18,7 @@ class Api::V1::FeaturedTagsController < Api::BaseController
|
|||
end
|
||||
|
||||
def destroy
|
||||
RemoveFeaturedTagWorker.perform_async(current_account.id, @featured_tag.id)
|
||||
RemoveFeaturedTagService.new.call(current_account, @featured_tag)
|
||||
render_empty
|
||||
end
|
||||
|
||||
|
|
|
@ -56,11 +56,11 @@ class Api::V1::FiltersController < Api::BaseController
|
|||
end
|
||||
|
||||
def resource_params
|
||||
params.permit(:phrase, :expires_in, :irreversible, :exclude_follows, :exclude_localusers, :with_quote, :with_profile, :whole_word, context: [])
|
||||
params.permit(:phrase, :expires_in, :irreversible, :exclude_follows, :exclude_localusers, :with_profile, :whole_word, context: [])
|
||||
end
|
||||
|
||||
def filter_params
|
||||
resource_params.slice(:phrase, :expires_in, :irreversible, :exclude_follows, :exclude_localusers, :with_quote, :with_profile, :context)
|
||||
resource_params.slice(:phrase, :expires_in, :irreversible, :exclude_follows, :exclude_localusers, :with_profile, :context)
|
||||
end
|
||||
|
||||
def keyword_params
|
||||
|
|
|
@ -18,6 +18,6 @@ class Api::V1::Instances::RulesController < Api::V1::Instances::BaseController
|
|||
private
|
||||
|
||||
def set_rules
|
||||
@rules = Rule.ordered
|
||||
@rules = Rule.ordered.includes(:translations)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::TagsController < Api::BaseController
|
||||
before_action -> { doorkeeper_authorize! :follow, :write, :'write:follows' }, except: :show
|
||||
before_action -> { doorkeeper_authorize! :follow, :write, :'write:follows' }, only: [:follow, :unfollow]
|
||||
before_action -> { doorkeeper_authorize! :write, :'write:accounts' }, only: [:feature, :unfeature]
|
||||
before_action :require_user!, except: :show
|
||||
before_action :set_or_create_tag
|
||||
|
||||
|
@ -23,6 +24,16 @@ class Api::V1::TagsController < Api::BaseController
|
|||
render json: @tag, serializer: REST::TagSerializer
|
||||
end
|
||||
|
||||
def feature
|
||||
CreateFeaturedTagService.new.call(current_account, @tag)
|
||||
render json: @tag, serializer: REST::TagSerializer
|
||||
end
|
||||
|
||||
def unfeature
|
||||
RemoveFeaturedTagService.new.call(current_account, @tag)
|
||||
render json: @tag, serializer: REST::TagSerializer
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_or_create_tag
|
||||
|
|
|
@ -7,7 +7,7 @@ class Api::V1::Trends::TagsController < Api::BaseController
|
|||
|
||||
after_action :insert_pagination_headers
|
||||
|
||||
DEFAULT_TAGS_LIMIT = (ENV['MAX_TRENDING_TAGS'] || 10).to_i
|
||||
DEFAULT_TAGS_LIMIT = 10
|
||||
|
||||
deprecate_api '2022-03-30', only: :index, if: -> { request.path == '/api/v1/trends' }
|
||||
|
||||
|
|
|
@ -43,6 +43,6 @@ class Api::V2::FiltersController < Api::BaseController
|
|||
end
|
||||
|
||||
def resource_params
|
||||
params.permit(:title, :expires_in, :filter_action, :exclude_follows, :exclude_localusers, :with_quote, :with_profile, context: [], keywords_attributes: [:id, :keyword, :whole_word, :_destroy])
|
||||
params.permit(:title, :expires_in, :filter_action, :exclude_follows, :exclude_localusers, :with_profile, context: [], keywords_attributes: [:id, :keyword, :whole_word, :_destroy])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::V2::InstancesController < Api::BaseController
|
||||
skip_before_action :require_authenticated_user!, unless: :limited_federation_mode?
|
||||
skip_before_action :require_authenticated_user!
|
||||
skip_around_action :set_locale
|
||||
|
||||
vary_by ''
|
||||
|
|
|
@ -72,10 +72,24 @@ class ApplicationController < ActionController::Base
|
|||
def require_functional!
|
||||
return if current_user.functional?
|
||||
|
||||
if current_user.confirmed?
|
||||
redirect_to edit_user_registration_path
|
||||
else
|
||||
redirect_to auth_setup_path
|
||||
respond_to do |format|
|
||||
format.any do
|
||||
if current_user.confirmed?
|
||||
redirect_to edit_user_registration_path
|
||||
else
|
||||
redirect_to auth_setup_path
|
||||
end
|
||||
end
|
||||
|
||||
format.json do
|
||||
if !current_user.confirmed?
|
||||
render json: { error: 'Your login is missing a confirmed e-mail address' }, status: 403
|
||||
elsif !current_user.approved?
|
||||
render json: { error: 'Your login is currently pending approval' }, status: 403
|
||||
elsif !current_user.functional?
|
||||
render json: { error: 'Your login is currently disabled' }, status: 403
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -126,7 +126,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController
|
|||
end
|
||||
|
||||
def set_rules
|
||||
@rules = Rule.ordered
|
||||
@rules = Rule.ordered.includes(:translations)
|
||||
end
|
||||
|
||||
def require_rules_acceptance!
|
||||
|
@ -138,7 +138,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController
|
|||
set_locale { render :rules }
|
||||
end
|
||||
|
||||
def is_flashing_format? # rubocop:disable Naming/PredicateName
|
||||
def is_flashing_format? # rubocop:disable Naming/PredicatePrefix
|
||||
if params[:action] == 'create'
|
||||
false # Disable flash messages for sign-up
|
||||
else
|
||||
|
|
|
@ -197,9 +197,7 @@ class Auth::SessionsController < Devise::SessionsController
|
|||
)
|
||||
|
||||
# Only send a notification email every hour at most
|
||||
return if redis.get("2fa_failure_notification:#{user.id}").present?
|
||||
|
||||
redis.set("2fa_failure_notification:#{user.id}", '1', ex: 1.hour)
|
||||
return if redis.set("2fa_failure_notification:#{user.id}", '1', ex: 1.hour, get: true).present?
|
||||
|
||||
UserMailer.failed_2fa(user, request.remote_ip, request.user_agent, Time.now.utc).deliver_later!
|
||||
end
|
||||
|
|
|
@ -16,7 +16,7 @@ module Localized
|
|||
def requested_locale
|
||||
requested_locale_name = available_locale_or_nil(params[:lang])
|
||||
requested_locale_name ||= available_locale_or_nil(current_user.locale) if respond_to?(:user_signed_in?) && user_signed_in?
|
||||
requested_locale_name ||= http_accept_language if ENV['DEFAULT_LOCALE'].blank?
|
||||
requested_locale_name ||= http_accept_language unless ENV['FORCE_DEFAULT_LOCALE'] == 'true'
|
||||
requested_locale_name
|
||||
end
|
||||
|
||||
|
|
|
@ -22,6 +22,18 @@ module SignatureVerification
|
|||
request.headers['Signature'].present?
|
||||
end
|
||||
|
||||
def signature_key_id
|
||||
signed_request.key_id
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def signed_request
|
||||
@signed_request ||= SignedRequest.new(request) if signed_request?
|
||||
rescue SignatureVerificationError
|
||||
nil
|
||||
end
|
||||
|
||||
def signature_verification_failure_reason
|
||||
@signature_verification_failure_reason
|
||||
end
|
||||
|
@ -30,12 +42,6 @@ module SignatureVerification
|
|||
@signature_verification_failure_code || 401
|
||||
end
|
||||
|
||||
def signature_key_id
|
||||
signature_params['keyId']
|
||||
rescue Mastodon::SignatureVerificationError
|
||||
nil
|
||||
end
|
||||
|
||||
def signed_request_account
|
||||
signed_request_actor.is_a?(Account) ? signed_request_actor : nil
|
||||
end
|
||||
|
@ -44,38 +50,20 @@ module SignatureVerification
|
|||
return @signed_request_actor if defined?(@signed_request_actor)
|
||||
|
||||
raise Mastodon::SignatureVerificationError, 'Request not signed' unless signed_request?
|
||||
raise Mastodon::SignatureVerificationError, 'Incompatible request signature. keyId and signature are required' if missing_required_signature_parameters?
|
||||
raise Mastodon::SignatureVerificationError, 'Unsupported signature algorithm (only rsa-sha256 and hs2019 are supported)' unless %w(rsa-sha256 hs2019).include?(signature_algorithm)
|
||||
raise Mastodon::SignatureVerificationError, 'Signed request date outside acceptable time window' unless matches_time_window?
|
||||
|
||||
verify_signature_strength!
|
||||
verify_body_digest!
|
||||
actor = actor_from_key_id
|
||||
|
||||
actor = actor_from_key_id(signature_params['keyId'])
|
||||
raise Mastodon::SignatureVerificationError, "Public key not found for key #{signature_key_id}" if actor.nil?
|
||||
|
||||
raise Mastodon::SignatureVerificationError, "Public key not found for key #{signature_params['keyId']}" if actor.nil?
|
||||
|
||||
signature = Base64.decode64(signature_params['signature'])
|
||||
compare_signed_string = build_signed_string(include_query_string: true)
|
||||
|
||||
return actor unless verify_signature(actor, signature, compare_signed_string).nil?
|
||||
|
||||
# Compatibility quirk with older Mastodon versions
|
||||
compare_signed_string = build_signed_string(include_query_string: false)
|
||||
return actor unless verify_signature(actor, signature, compare_signed_string).nil?
|
||||
return (@signed_request_actor = actor) if signed_request.verified?(actor)
|
||||
|
||||
actor = stoplight_wrapper.run { actor_refresh_key!(actor) }
|
||||
|
||||
raise Mastodon::SignatureVerificationError, "Could not refresh public key #{signature_params['keyId']}" if actor.nil?
|
||||
raise Mastodon::SignatureVerificationError, "Could not refresh public key #{signature_key_id}" if actor.nil?
|
||||
|
||||
compare_signed_string = build_signed_string(include_query_string: true)
|
||||
return actor unless verify_signature(actor, signature, compare_signed_string).nil?
|
||||
return (@signed_request_actor = actor) if signed_request.verified?(actor)
|
||||
|
||||
# Compatibility quirk with older Mastodon versions
|
||||
compare_signed_string = build_signed_string(include_query_string: false)
|
||||
return actor unless verify_signature(actor, signature, compare_signed_string).nil?
|
||||
|
||||
fail_with! "Verification failed for #{actor.to_log_human_identifier} #{actor.uri} using rsa-sha256 (RSASSA-PKCS1-v1_5 with SHA-256)", signed_string: compare_signed_string, signature: signature_params['signature']
|
||||
fail_with! "Verification failed for #{actor.to_log_human_identifier} #{actor.uri}"
|
||||
rescue Mastodon::SignatureVerificationError => e
|
||||
fail_with! e.message
|
||||
rescue *Mastodon::HTTP_CONNECTION_ERRORS => e
|
||||
|
@ -86,12 +74,6 @@ module SignatureVerification
|
|||
fail_with! 'Fetching attempt skipped because of recent connection failure'
|
||||
end
|
||||
|
||||
def request_body
|
||||
@request_body ||= request.raw_post
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def fail_with!(message, **options)
|
||||
Rails.logger.debug { "Signature verification failed: #{message}" }
|
||||
|
||||
|
@ -99,123 +81,8 @@ module SignatureVerification
|
|||
@signed_request_actor = nil
|
||||
end
|
||||
|
||||
def signature_params
|
||||
@signature_params ||= SignatureParser.parse(request.headers['Signature'])
|
||||
rescue SignatureParser::ParsingError
|
||||
raise Mastodon::SignatureVerificationError, 'Error parsing signature parameters'
|
||||
end
|
||||
|
||||
def signature_algorithm
|
||||
signature_params.fetch('algorithm', 'hs2019')
|
||||
end
|
||||
|
||||
def signed_headers
|
||||
signature_params.fetch('headers', signature_algorithm == 'hs2019' ? '(created)' : 'date').downcase.split
|
||||
end
|
||||
|
||||
def verify_signature_strength!
|
||||
raise Mastodon::SignatureVerificationError, 'Mastodon requires the Date header or (created) pseudo-header to be signed' unless signed_headers.include?('date') || signed_headers.include?('(created)')
|
||||
raise Mastodon::SignatureVerificationError, 'Mastodon requires the Digest header or (request-target) pseudo-header to be signed' unless signed_headers.include?(HttpSignatureDraft::REQUEST_TARGET) || signed_headers.include?('digest')
|
||||
raise Mastodon::SignatureVerificationError, 'Mastodon requires the Host header to be signed when doing a GET request' if request.get? && !signed_headers.include?('host')
|
||||
raise Mastodon::SignatureVerificationError, 'Mastodon requires the Digest header to be signed when doing a POST request' if request.post? && !signed_headers.include?('digest')
|
||||
end
|
||||
|
||||
def verify_body_digest!
|
||||
return unless signed_headers.include?('digest')
|
||||
raise Mastodon::SignatureVerificationError, 'Digest header missing' unless request.headers.key?('Digest')
|
||||
|
||||
digests = request.headers['Digest'].split(',').map { |digest| digest.split('=', 2) }.map { |key, value| [key.downcase, value] }
|
||||
sha256 = digests.assoc('sha-256')
|
||||
raise Mastodon::SignatureVerificationError, "Mastodon only supports SHA-256 in Digest header. Offered algorithms: #{digests.map(&:first).join(', ')}" if sha256.nil?
|
||||
|
||||
return if body_digest == sha256[1]
|
||||
|
||||
digest_size = begin
|
||||
Base64.strict_decode64(sha256[1].strip).length
|
||||
rescue ArgumentError
|
||||
raise Mastodon::SignatureVerificationError, "Invalid Digest value. The provided Digest value is not a valid base64 string. Given digest: #{sha256[1]}"
|
||||
end
|
||||
|
||||
raise Mastodon::SignatureVerificationError, "Invalid Digest value. The provided Digest value is not a SHA-256 digest. Given digest: #{sha256[1]}" if digest_size != 32
|
||||
|
||||
raise Mastodon::SignatureVerificationError, "Invalid Digest value. Computed SHA-256 digest: #{body_digest}; given: #{sha256[1]}"
|
||||
end
|
||||
|
||||
def verify_signature(actor, signature, compare_signed_string)
|
||||
if actor.keypair.public_key.verify(OpenSSL::Digest.new('SHA256'), signature, compare_signed_string)
|
||||
@signed_request_actor = actor
|
||||
@signed_request_actor
|
||||
end
|
||||
rescue OpenSSL::PKey::RSAError
|
||||
nil
|
||||
end
|
||||
|
||||
def build_signed_string(include_query_string: true)
|
||||
signed_headers.map do |signed_header|
|
||||
case signed_header
|
||||
when HttpSignatureDraft::REQUEST_TARGET
|
||||
if include_query_string
|
||||
"#{HttpSignatureDraft::REQUEST_TARGET}: #{request.method.downcase} #{request.original_fullpath}"
|
||||
else
|
||||
# Current versions of Mastodon incorrectly omit the query string from the (request-target) pseudo-header.
|
||||
# Therefore, temporarily support such incorrect signatures for compatibility.
|
||||
# TODO: remove eventually some time after release of the fixed version
|
||||
"#{HttpSignatureDraft::REQUEST_TARGET}: #{request.method.downcase} #{request.path}"
|
||||
end
|
||||
when '(created)'
|
||||
raise Mastodon::SignatureVerificationError, 'Invalid pseudo-header (created) for rsa-sha256' unless signature_algorithm == 'hs2019'
|
||||
raise Mastodon::SignatureVerificationError, 'Pseudo-header (created) used but corresponding argument missing' if signature_params['created'].blank?
|
||||
|
||||
"(created): #{signature_params['created']}"
|
||||
when '(expires)'
|
||||
raise Mastodon::SignatureVerificationError, 'Invalid pseudo-header (expires) for rsa-sha256' unless signature_algorithm == 'hs2019'
|
||||
raise Mastodon::SignatureVerificationError, 'Pseudo-header (expires) used but corresponding argument missing' if signature_params['expires'].blank?
|
||||
|
||||
"(expires): #{signature_params['expires']}"
|
||||
else
|
||||
"#{signed_header}: #{request.headers[to_header_name(signed_header)]}"
|
||||
end
|
||||
end.join("\n")
|
||||
end
|
||||
|
||||
def matches_time_window?
|
||||
created_time = nil
|
||||
expires_time = nil
|
||||
|
||||
begin
|
||||
if signature_algorithm == 'hs2019' && signature_params['created'].present?
|
||||
created_time = Time.at(signature_params['created'].to_i).utc
|
||||
elsif request.headers['Date'].present?
|
||||
created_time = Time.httpdate(request.headers['Date']).utc
|
||||
end
|
||||
|
||||
expires_time = Time.at(signature_params['expires'].to_i).utc if signature_params['expires'].present?
|
||||
rescue ArgumentError => e
|
||||
raise Mastodon::SignatureVerificationError, "Invalid Date header: #{e.message}"
|
||||
end
|
||||
|
||||
expires_time ||= created_time + 5.minutes unless created_time.nil?
|
||||
expires_time = [expires_time, created_time + EXPIRATION_WINDOW_LIMIT].min unless created_time.nil?
|
||||
|
||||
return false if created_time.present? && created_time > Time.now.utc + CLOCK_SKEW_MARGIN
|
||||
return false if expires_time.present? && Time.now.utc > expires_time + CLOCK_SKEW_MARGIN
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
def body_digest
|
||||
@body_digest ||= Digest::SHA256.base64digest(request_body)
|
||||
end
|
||||
|
||||
def to_header_name(name)
|
||||
name.split('-').map(&:capitalize).join('-')
|
||||
end
|
||||
|
||||
def missing_required_signature_parameters?
|
||||
signature_params['keyId'].blank? || signature_params['signature'].blank?
|
||||
end
|
||||
|
||||
def actor_from_key_id(key_id)
|
||||
def actor_from_key_id
|
||||
key_id = signature_key_id
|
||||
domain = key_id.start_with?('acct:') ? key_id.split('@').last : key_id
|
||||
|
||||
if domain_not_allowed?(domain)
|
||||
|
|
|
@ -8,6 +8,7 @@ module WebAppControllerConcern
|
|||
|
||||
before_action :redirect_unauthenticated_to_permalinks!
|
||||
before_action :set_referer_header
|
||||
before_action :redirect_to_tos_interstitial!
|
||||
|
||||
content_security_policy do |p|
|
||||
policy = ContentSecurityPolicy.new
|
||||
|
@ -45,6 +46,13 @@ module WebAppControllerConcern
|
|||
|
||||
protected
|
||||
|
||||
def redirect_to_tos_interstitial!
|
||||
return unless current_user&.require_tos_interstitial?
|
||||
|
||||
@terms_of_service = TermsOfService.published.first
|
||||
render 'terms_of_service_interstitial/show', layout: 'auth'
|
||||
end
|
||||
|
||||
def set_referer_header
|
||||
response.set_header('Referrer-Policy', Setting.allow_referrer_origin ? 'strict-origin-when-cross-origin' : 'same-origin')
|
||||
end
|
||||
|
|
|
@ -47,6 +47,6 @@ class FiltersController < ApplicationController
|
|||
end
|
||||
|
||||
def resource_params
|
||||
params.expect(custom_filter: [:title, :expires_in, :filter_action, :exclude_follows, :exclude_localusers, :exclude_quote, :exclude_profile, context: [], keywords_attributes: [[:id, :keyword, :whole_word, :_destroy]]])
|
||||
params.expect(custom_filter: [:title, :expires_in, :filter_action, :exclude_follows, :exclude_localusers, :exclude_profile, context: [], keywords_attributes: [[:id, :keyword, :whole_word, :_destroy]]])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -12,7 +12,7 @@ class Settings::FeaturedTagsController < Settings::BaseController
|
|||
end
|
||||
|
||||
def create
|
||||
@featured_tag = CreateFeaturedTagService.new.call(current_account, featured_tag_params[:name], force: false)
|
||||
@featured_tag = CreateFeaturedTagService.new.call(current_account, featured_tag_params[:name], raise_error: false)
|
||||
|
||||
if @featured_tag.valid?
|
||||
redirect_to settings_featured_tags_path
|
||||
|
|
|
@ -4,8 +4,19 @@ class TermsOfServiceController < ApplicationController
|
|||
include WebAppControllerConcern
|
||||
|
||||
skip_before_action :require_functional!
|
||||
skip_before_action :redirect_to_tos_interstitial!
|
||||
|
||||
before_action :clear_redirect_interstitial!
|
||||
|
||||
def show
|
||||
expires_in(15.seconds, public: true, stale_while_revalidate: 30.seconds, stale_if_error: 1.day) unless user_signed_in?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def clear_redirect_interstitial!
|
||||
return unless user_signed_in?
|
||||
|
||||
current_user.update(require_tos_interstitial: false)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -29,12 +29,19 @@ module ContextHelper
|
|||
limited_scope: { 'kmyblue' => 'http://kmy.blue/ns#', 'limitedScope' => 'kmyblue:limitedScope' },
|
||||
other_setting: { 'fedibird' => 'http://fedibird.com/ns#', 'otherSetting' => 'fedibird:otherSetting' },
|
||||
references: { 'fedibird' => 'http://fedibird.com/ns#', 'references' => { '@id' => 'fedibird:references', '@type' => '@id' } },
|
||||
quote_uri: { 'fedibird' => 'http://fedibird.com/ns#', 'quoteUri' => 'fedibird:quoteUri' },
|
||||
keywords: { 'schema' => 'http://schema.org#', 'keywords' => 'schema:keywords' },
|
||||
license: { 'schema' => 'http://schema.org#', 'license' => 'schema:license' },
|
||||
suspended: { 'toot' => 'http://joinmastodon.org/ns#', 'suspended' => 'toot:suspended' },
|
||||
attribution_domains: { 'toot' => 'http://joinmastodon.org/ns#', 'attributionDomains' => { '@id' => 'toot:attributionDomains', '@type' => '@id' } },
|
||||
misskey_license: { 'misskey' => 'https://misskey-hub.net/ns#', '_misskey_license' => 'misskey:_misskey_license' },
|
||||
quote_requests: { 'QuoteRequest' => 'https://w3id.org/fep/044f#QuoteRequest' },
|
||||
interaction_policies: {
|
||||
'gts' => 'https://gotosocial.org/ns#',
|
||||
'interactionPolicy' => { '@id' => 'gts:interactionPolicy', '@type' => '@id' },
|
||||
'canQuote' => { '@id' => 'gts:canQuote', '@type' => '@id' },
|
||||
'automaticApproval' => { '@id' => 'gts:automaticApproval', '@type' => '@id' },
|
||||
'manualApproval' => { '@id' => 'gts:manualApproval', '@type' => '@id' },
|
||||
},
|
||||
}.freeze
|
||||
|
||||
def full_context
|
||||
|
|
|
@ -31,14 +31,7 @@ module FormattingHelper
|
|||
end
|
||||
|
||||
def status_content_format(status)
|
||||
MastodonOTELTracer.in_span('HtmlAwareFormatter rendering') do |span|
|
||||
span.add_attributes(
|
||||
'app.formatter.content.type' => 'status',
|
||||
'app.formatter.content.origin' => status.local? ? 'local' : 'remote'
|
||||
)
|
||||
|
||||
html_aware_format(status.text, status.local?, markdown: status.markdown, preloaded_accounts: [status.account] + (status.respond_to?(:active_mentions) ? status.active_mentions.map(&:account) : []))
|
||||
end
|
||||
html_aware_format(status.text, status.local?, markdown: status.markdown, preloaded_accounts: [status.account] + (status.respond_to?(:active_mentions) ? status.active_mentions.map(&:account) : []))
|
||||
end
|
||||
|
||||
def rss_status_content_format(status)
|
||||
|
@ -50,14 +43,7 @@ module FormattingHelper
|
|||
end
|
||||
|
||||
def account_bio_format(account)
|
||||
MastodonOTELTracer.in_span('HtmlAwareFormatter rendering') do |span|
|
||||
span.add_attributes(
|
||||
'app.formatter.content.type' => 'account_bio',
|
||||
'app.formatter.content.origin' => account.local? ? 'local' : 'remote'
|
||||
)
|
||||
|
||||
html_aware_format(account.note, account.local?, markdown: account.user&.setting_bio_markdown)
|
||||
end
|
||||
html_aware_format(account.note, account.local?, markdown: account.user&.setting_bio_markdown)
|
||||
end
|
||||
|
||||
def account_field_value_format(field, with_rel_me: true)
|
||||
|
|
|
@ -26,6 +26,8 @@ module JsonLdHelper
|
|||
# The url attribute can be a string, an array of strings, or an array of objects.
|
||||
# The objects could include a mimeType. Not-included mimeType means it's text/html.
|
||||
def url_to_href(value, preferred_type = nil)
|
||||
value = [value] if value.is_a?(Hash)
|
||||
|
||||
single_value = if value.is_a?(Array) && !value.first.is_a?(String)
|
||||
value.find { |link| preferred_type.nil? || ((link['mimeType'].presence || 'text/html') == preferred_type) }
|
||||
elsif value.is_a?(Array)
|
||||
|
@ -41,6 +43,15 @@ module JsonLdHelper
|
|||
end
|
||||
end
|
||||
|
||||
def url_to_media_type(value, preferred_type = nil)
|
||||
value = [value] if value.is_a?(Hash)
|
||||
return unless value.is_a?(Array) && !value.first.is_a?(String)
|
||||
|
||||
single_value = value.find { |link| preferred_type.nil? || ((link['mimeType'].presence || 'text/html') == preferred_type) }
|
||||
|
||||
single_value['mediaType'] unless single_value.nil?
|
||||
end
|
||||
|
||||
def as_array(value)
|
||||
if value.nil?
|
||||
[]
|
||||
|
@ -80,6 +91,18 @@ module JsonLdHelper
|
|||
!haystack.casecmp(needle).zero?
|
||||
end
|
||||
|
||||
def safe_prefetched_embed(account, object, context)
|
||||
return unless object.is_a?(Hash)
|
||||
|
||||
# NOTE: Replacing the object's context by that of the parent activity is
|
||||
# not sound, but it's consistent with the rest of the codebase
|
||||
object = object.merge({ '@context' => context })
|
||||
|
||||
return if value_or_id(first_of_value(object['attributedTo'])) != account.uri || non_matching_uri_hosts?(account.uri, object['id'])
|
||||
|
||||
object
|
||||
end
|
||||
|
||||
def canonicalize(json)
|
||||
graph = RDF::Graph.new << JSON::LD::API.toRdf(json, documentLoader: method(:load_jsonld_context))
|
||||
graph.dump(:normalize)
|
||||
|
|
|
@ -15,7 +15,6 @@ module KmyblueCapabilitiesHelper
|
|||
kmyblue_limited_scope
|
||||
kmyblue_antenna
|
||||
kmyblue_bookmark_category
|
||||
kmyblue_quote
|
||||
kmyblue_searchability_limited
|
||||
kmyblue_circle_history
|
||||
kmyblue_list_notification
|
||||
|
@ -41,7 +40,6 @@ module KmyblueCapabilitiesHelper
|
|||
capabilities = %i(
|
||||
enable_wide_emoji
|
||||
status_reference
|
||||
quote
|
||||
emoji_keywords
|
||||
circle
|
||||
)
|
||||
|
|
|
@ -4,7 +4,7 @@ module RoutingHelper
|
|||
extend ActiveSupport::Concern
|
||||
|
||||
include ActionView::Helpers::AssetTagHelper
|
||||
include Webpacker::Helper
|
||||
include ViteRails::TagHelpers
|
||||
|
||||
included do
|
||||
include Rails.application.routes.url_helpers
|
||||
|
@ -25,7 +25,7 @@ module RoutingHelper
|
|||
end
|
||||
|
||||
def frontend_asset_path(source, **)
|
||||
asset_pack_path("media/#{source}", **)
|
||||
vite_asset_path(source, **)
|
||||
end
|
||||
|
||||
def frontend_asset_url(source, **)
|
||||
|
|
|
@ -4,11 +4,13 @@ module ThemeHelper
|
|||
def theme_style_tags(theme)
|
||||
if theme == 'system'
|
||||
''.html_safe.tap do |tags|
|
||||
tags << stylesheet_pack_tag('mastodon-light', media: 'not all and (prefers-color-scheme: dark)', crossorigin: 'anonymous')
|
||||
tags << stylesheet_pack_tag('default', media: '(prefers-color-scheme: dark)', crossorigin: 'anonymous')
|
||||
tags << vite_stylesheet_tag('styles/mastodon-light.scss', media: 'not all and (prefers-color-scheme: dark)', crossorigin: 'anonymous')
|
||||
tags << vite_stylesheet_tag('styles/application.scss', media: '(prefers-color-scheme: dark)', crossorigin: 'anonymous')
|
||||
end
|
||||
elsif theme == 'default'
|
||||
vite_stylesheet_tag 'styles/application.scss', media: 'all', crossorigin: 'anonymous'
|
||||
else
|
||||
stylesheet_pack_tag theme, media: 'all', crossorigin: 'anonymous'
|
||||
vite_stylesheet_tag "styles/#{theme}.scss", media: 'all', crossorigin: 'anonymous'
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import './public-path';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
import Rails from '@rails/ujs';
|
||||
|
@ -345,7 +344,7 @@ async function mountReactComponent(element: Element) {
|
|||
);
|
||||
|
||||
const { default: Component } = (await import(
|
||||
`@/mastodon/components/admin/${componentName}`
|
||||
`@/mastodon/components/admin/${componentName}.jsx`
|
||||
)) as { default: React.ComponentType };
|
||||
|
||||
const root = createRoot(element);
|
||||
|
|
|
@ -1,11 +1,6 @@
|
|||
import './public-path';
|
||||
import { loadLocale } from 'mastodon/locales';
|
||||
import main from 'mastodon/main';
|
||||
|
||||
import { start } from '../mastodon/common';
|
||||
import { loadLocale } from '../mastodon/locales';
|
||||
import { loadPolyfills } from '../mastodon/polyfills';
|
||||
|
||||
start();
|
||||
import { loadPolyfills } from 'mastodon/polyfills';
|
||||
|
||||
loadPolyfills()
|
||||
.then(loadLocale)
|
||||
|
|
3
app/javascript/entrypoints/common.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
import { start } from 'mastodon/common';
|
||||
|
||||
start();
|
|
@ -1,15 +1,11 @@
|
|||
import './public-path';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
import { afterInitialRender } from 'mastodon/hooks/useRenderSignal';
|
||||
|
||||
import { start } from '../mastodon/common';
|
||||
import { Status } from '../mastodon/features/standalone/status';
|
||||
import { loadPolyfills } from '../mastodon/polyfills';
|
||||
import ready from '../mastodon/ready';
|
||||
|
||||
start();
|
||||
|
||||
function loaded() {
|
||||
const mountNode = document.getElementById('mastodon-status');
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import './public-path';
|
||||
import ready from '../mastodon/ready';
|
||||
|
||||
ready(() => {
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
/* Placeholder file to have `inert.scss` compiled by Webpack
|
||||
This is used by the `wicg-inert` polyfill */
|
||||
|
||||
import '../styles/inert.scss';
|
|
@ -1,3 +0,0 @@
|
|||
import '../styles/mailer.scss';
|
||||
|
||||
require.context('../icons');
|
|
@ -1,23 +0,0 @@
|
|||
// Dynamically set webpack's loading path depending on a meta header, in order
|
||||
// to share the same assets regardless of instance configuration.
|
||||
// See https://webpack.js.org/guides/public-path/#on-the-fly
|
||||
|
||||
function removeOuterSlashes(string: string) {
|
||||
return string.replace(/^\/*/, '').replace(/\/*$/, '');
|
||||
}
|
||||
|
||||
function formatPublicPath(host = '', path = '') {
|
||||
let formattedHost = removeOuterSlashes(host);
|
||||
if (formattedHost && !/^http/i.test(formattedHost)) {
|
||||
formattedHost = `//${formattedHost}`;
|
||||
}
|
||||
const formattedPath = removeOuterSlashes(path);
|
||||
return `${formattedHost}/${formattedPath}/`;
|
||||
}
|
||||
|
||||
const cdnHost = document.querySelector<HTMLMetaElement>('meta[name=cdn-host]');
|
||||
|
||||
__webpack_public_path__ = formatPublicPath(
|
||||
cdnHost ? cdnHost.content : '',
|
||||
process.env.PUBLIC_OUTPUT_PATH,
|
||||
);
|
|
@ -1,7 +1,5 @@
|
|||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
import './public-path';
|
||||
|
||||
import { IntlMessageFormat } from 'intl-messageformat';
|
||||
import type { MessageDescriptor, PrimitiveType } from 'react-intl';
|
||||
import { defineMessages } from 'react-intl';
|
||||
|
@ -10,7 +8,6 @@ import Rails from '@rails/ujs';
|
|||
import axios from 'axios';
|
||||
import { throttle } from 'lodash';
|
||||
|
||||
import { start } from '../mastodon/common';
|
||||
import { timeAgoString } from '../mastodon/components/relative_timestamp';
|
||||
import emojify from '../mastodon/features/emoji/emoji';
|
||||
import loadKeyboardExtensions from '../mastodon/load_keyboard_extensions';
|
||||
|
@ -20,8 +17,6 @@ import ready from '../mastodon/ready';
|
|||
|
||||
import 'cocoon-js-vanilla';
|
||||
|
||||
start();
|
||||
|
||||
const messages = defineMessages({
|
||||
usernameTaken: {
|
||||
id: 'username.taken',
|
||||
|
@ -153,9 +148,7 @@ function loaded() {
|
|||
const reactComponents = document.querySelectorAll('[data-component]');
|
||||
|
||||
if (reactComponents.length > 0) {
|
||||
import(
|
||||
/* webpackChunkName: "containers/media_container" */ '../mastodon/containers/media_container'
|
||||
)
|
||||
import('../mastodon/containers/media_container')
|
||||
.then(({ default: MediaContainer }) => {
|
||||
reactComponents.forEach((component) => {
|
||||
Array.from(component.children).forEach((child) => {
|
||||
|
|
|
@ -8,8 +8,6 @@ and performs no other task.
|
|||
|
||||
*/
|
||||
|
||||
import './public-path';
|
||||
|
||||
import axios from 'axios';
|
||||
|
||||
interface JRDLink {
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
import './public-path';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
import { start } from '../mastodon/common';
|
||||
import ComposeContainer from '../mastodon/containers/compose_container';
|
||||
import { loadPolyfills } from '../mastodon/polyfills';
|
||||
import ready from '../mastodon/ready';
|
||||
|
||||
start();
|
||||
|
||||
function loaded() {
|
||||
const mountNode = document.getElementById('mastodon-compose');
|
||||
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
import './public-path';
|
||||
import axios from 'axios';
|
||||
|
||||
import ready from '../mastodon/ready';
|
||||
|
||||
async function checkConfirmation() {
|
||||
const response = await axios.get('/api/v1/emails/check_confirmation');
|
||||
const response = await axios.get('/api/v1/emails/check_confirmation', {
|
||||
headers: { Accept: 'application/json' },
|
||||
withCredentials: true,
|
||||
});
|
||||
|
||||
if (response.data) {
|
||||
if (response.status === 200 && response.data === true) {
|
||||
window.location.href = '/start';
|
||||
}
|
||||
}
|
||||
|
|
BIN
app/javascript/icons/android-chrome-144x144.png
Normal file → Executable file
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 8.6 KiB |
BIN
app/javascript/icons/android-chrome-192x192.png
Normal file → Executable file
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 11 KiB |
BIN
app/javascript/icons/android-chrome-256x256.png
Normal file → Executable file
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 14 KiB |
BIN
app/javascript/icons/android-chrome-36x36.png
Normal file → Executable file
Before Width: | Height: | Size: 950 B After Width: | Height: | Size: 1.8 KiB |
BIN
app/javascript/icons/android-chrome-384x384.png
Normal file → Executable file
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 24 KiB |
BIN
app/javascript/icons/android-chrome-48x48.png
Normal file → Executable file
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 3.1 KiB |
BIN
app/javascript/icons/android-chrome-512x512.png
Normal file → Executable file
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 37 KiB |
BIN
app/javascript/icons/android-chrome-72x72.png
Normal file → Executable file
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 4.6 KiB |
BIN
app/javascript/icons/android-chrome-96x96.png
Normal file → Executable file
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 6 KiB |
BIN
app/javascript/icons/apple-touch-icon-1024x1024.png
Normal file → Executable file
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 112 KiB |
BIN
app/javascript/icons/apple-touch-icon-114x114.png
Normal file → Executable file
Before Width: | Height: | Size: 4 KiB After Width: | Height: | Size: 6.9 KiB |
BIN
app/javascript/icons/apple-touch-icon-120x120.png
Normal file → Executable file
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 7.3 KiB |
BIN
app/javascript/icons/apple-touch-icon-144x144.png
Normal file → Executable file
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 8.6 KiB |
BIN
app/javascript/icons/apple-touch-icon-152x152.png
Normal file → Executable file
Before Width: | Height: | Size: 6 KiB After Width: | Height: | Size: 8.9 KiB |
BIN
app/javascript/icons/apple-touch-icon-167x167.png
Normal file → Executable file
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 9.8 KiB |
BIN
app/javascript/icons/apple-touch-icon-180x180.png
Normal file → Executable file
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 950 B |
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 31 KiB |
BIN
app/javascript/icons/apple-touch-icon-57x57.png
Normal file → Executable file
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 3.7 KiB |
BIN
app/javascript/icons/apple-touch-icon-60x60.png
Normal file → Executable file
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 3.9 KiB |
BIN
app/javascript/icons/apple-touch-icon-72x72.png
Normal file → Executable file
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 4.6 KiB |
BIN
app/javascript/icons/apple-touch-icon-76x76.png
Normal file → Executable file
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 3.2 KiB |
BIN
app/javascript/icons/favicon-16x16.png
Normal file → Executable file
Before Width: | Height: | Size: 6 KiB After Width: | Height: | Size: 986 B |
BIN
app/javascript/icons/favicon-32x32.png
Normal file → Executable file
Before Width: | Height: | Size: 6 KiB After Width: | Height: | Size: 1.7 KiB |
BIN
app/javascript/icons/favicon-48x48.png
Normal file → Executable file
Before Width: | Height: | Size: 6 KiB After Width: | Height: | Size: 3.1 KiB |