Compare commits
68 commits
kb_develop
...
kb15.1-lts
Author | SHA1 | Date | |
---|---|---|---|
|
df88076e68 | ||
|
be567228ef | ||
|
74a6238d10 | ||
|
c96ee91ced | ||
|
9a53eefc9c | ||
|
75d3b2dfd0 | ||
|
aadde1bbaa | ||
|
428abf33f2 | ||
|
fdab2c9464 | ||
|
c712424cdb | ||
|
eff82af854 | ||
|
ab36c152f9 | ||
|
fc5b558b32 | ||
|
77ff94d3d2 | ||
|
edcf3d9234 | ||
|
cae93e79a4 | ||
|
83a98cb81a | ||
|
889edc560a | ||
|
2e0d918d7d | ||
|
3b4312476f | ||
|
4fba4f8c82 | ||
|
25de2f57ee | ||
|
24aa122ad1 | ||
|
cc857e57c6 | ||
|
6d5aa58f88 | ||
|
81cd489208 | ||
|
55b5364534 | ||
|
2e8b752c55 | ||
|
d82ffdccbb | ||
|
5c72b46a4e | ||
|
aa46348c03 | ||
|
404f467fcf | ||
|
4a2d3929c5 | ||
|
ceba0f082e | ||
|
7de8d5ffca | ||
|
74291dfb77 | ||
|
f07707a9bb | ||
|
931553844d | ||
|
243a85ec8d | ||
|
cbf1349370 | ||
|
b8fdffe824 | ||
|
c91e06bcad | ||
|
b2ce9bb4c7 | ||
|
19d1392b33 | ||
|
09cf617d7f | ||
|
784d1bfb29 | ||
|
754b03d8cb | ||
|
f397550311 | ||
|
97db4bd4dd | ||
|
1e19242134 | ||
|
4e6f13a0fb | ||
|
f517f0dbef | ||
|
53624b1b54 | ||
|
a473988969 | ||
|
4ad1e955eb | ||
|
66ef4b9984 | ||
|
ce2481a81b | ||
|
efa74a6c44 | ||
|
bdceb1dacf | ||
|
e13453aec4 | ||
|
25e8a6eaeb | ||
|
c828e7731c | ||
|
6734b6550f | ||
|
6398d7b784 | ||
|
1283c3544c | ||
|
8ac00533ff | ||
|
1b3472bec8 | ||
|
deee164acf |
2323 changed files with 46111 additions and 72570 deletions
|
@ -1,59 +0,0 @@
|
||||||
---
|
|
||||||
:position: before
|
|
||||||
:position_in_additional_file_patterns: before
|
|
||||||
:position_in_class: before
|
|
||||||
:position_in_factory: before
|
|
||||||
:position_in_fixture: before
|
|
||||||
:position_in_routes: before
|
|
||||||
:position_in_serializer: before
|
|
||||||
:position_in_test: before
|
|
||||||
:classified_sort: true
|
|
||||||
:exclude_controllers: true
|
|
||||||
:exclude_factories: true
|
|
||||||
:exclude_fixtures: true
|
|
||||||
:exclude_helpers: true
|
|
||||||
:exclude_scaffolds: true
|
|
||||||
:exclude_serializers: true
|
|
||||||
:exclude_sti_subclasses: true
|
|
||||||
:exclude_tests: true
|
|
||||||
:force: false
|
|
||||||
:format_markdown: false
|
|
||||||
:format_rdoc: false
|
|
||||||
:format_yard: false
|
|
||||||
:frozen: false
|
|
||||||
:ignore_model_sub_dir: false
|
|
||||||
:ignore_unknown_models: false
|
|
||||||
:include_version: false
|
|
||||||
:show_complete_foreign_keys: false
|
|
||||||
:show_foreign_keys: false
|
|
||||||
:show_indexes: false
|
|
||||||
:simple_indexes: false
|
|
||||||
:sort: false
|
|
||||||
:timestamp: false
|
|
||||||
:trace: false
|
|
||||||
:with_comment: true
|
|
||||||
:with_column_comments: true
|
|
||||||
:with_table_comments: true
|
|
||||||
:active_admin: false
|
|
||||||
:command:
|
|
||||||
:debug: false
|
|
||||||
:hide_default_column_types: ''
|
|
||||||
:hide_limit_column_types: 'integer,boolean'
|
|
||||||
:ignore_columns:
|
|
||||||
:ignore_routes:
|
|
||||||
:models: true
|
|
||||||
:routes: false
|
|
||||||
:skip_on_db_migrate: false
|
|
||||||
:target_action: :do_annotations
|
|
||||||
:wrapper:
|
|
||||||
:wrapper_close:
|
|
||||||
:wrapper_open:
|
|
||||||
:classes_default_to_s: []
|
|
||||||
:additional_file_patterns: []
|
|
||||||
:model_dir:
|
|
||||||
- app/models
|
|
||||||
:require: []
|
|
||||||
:root_dir:
|
|
||||||
- ''
|
|
||||||
|
|
||||||
:show_check_constraints: false
|
|
|
@ -1,6 +1,10 @@
|
||||||
|
[production]
|
||||||
defaults
|
defaults
|
||||||
> 0.2%
|
> 0.2%
|
||||||
firefox >= 78
|
firefox >= 78
|
||||||
ios >= 15.6
|
ios >= 15.6
|
||||||
not dead
|
not dead
|
||||||
not OperaMini all
|
not OperaMini all
|
||||||
|
|
||||||
|
[development]
|
||||||
|
supports es6-module
|
||||||
|
|
|
@ -10,7 +10,6 @@ services:
|
||||||
RAILS_ENV: development
|
RAILS_ENV: development
|
||||||
NODE_ENV: development
|
NODE_ENV: development
|
||||||
BIND: 0.0.0.0
|
BIND: 0.0.0.0
|
||||||
BOOTSNAP_CACHE_DIR: /tmp
|
|
||||||
REDIS_HOST: redis
|
REDIS_HOST: redis
|
||||||
REDIS_PORT: '6379'
|
REDIS_PORT: '6379'
|
||||||
DB_HOST: db
|
DB_HOST: db
|
||||||
|
@ -21,13 +20,12 @@ services:
|
||||||
ES_HOST: es
|
ES_HOST: es
|
||||||
ES_PORT: '9200'
|
ES_PORT: '9200'
|
||||||
LIBRE_TRANSLATE_ENDPOINT: http://libretranslate:5000
|
LIBRE_TRANSLATE_ENDPOINT: http://libretranslate:5000
|
||||||
LOCAL_DOMAIN: ${LOCAL_DOMAIN:-localhost:3000}
|
|
||||||
# Overrides default command so things don't shut down after the process ends.
|
# Overrides default command so things don't shut down after the process ends.
|
||||||
command: sleep infinity
|
command: sleep infinity
|
||||||
ports:
|
ports:
|
||||||
- '3000:3000'
|
- '127.0.0.1:3000:3000'
|
||||||
- '3035:3035'
|
- '127.0.0.1:3035:3035'
|
||||||
- '4000:4000'
|
- '127.0.0.1:4000:4000'
|
||||||
networks:
|
networks:
|
||||||
- external_network
|
- external_network
|
||||||
- internal_network
|
- internal_network
|
||||||
|
@ -71,7 +69,7 @@ services:
|
||||||
hard: -1
|
hard: -1
|
||||||
|
|
||||||
libretranslate:
|
libretranslate:
|
||||||
image: libretranslate/libretranslate:v1.6.2
|
image: libretranslate/libretranslate:v1.6.1
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- lt-data:/home/libretranslate/.local
|
- lt-data:/home/libretranslate/.local
|
||||||
|
|
|
@ -20,9 +20,3 @@ postgres14
|
||||||
redis
|
redis
|
||||||
elasticsearch
|
elasticsearch
|
||||||
chart
|
chart
|
||||||
.yarn/
|
|
||||||
!.yarn/patches
|
|
||||||
!.yarn/plugins
|
|
||||||
!.yarn/releases
|
|
||||||
!.yarn/sdks
|
|
||||||
!.yarn/versions
|
|
||||||
|
|
|
@ -45,17 +45,6 @@ ES_PASS=password
|
||||||
SECRET_KEY_BASE=
|
SECRET_KEY_BASE=
|
||||||
OTP_SECRET=
|
OTP_SECRET=
|
||||||
|
|
||||||
# Encryption secrets
|
|
||||||
# ------------------
|
|
||||||
# Must be available (and set to same values) for all server processes
|
|
||||||
# These are private/secret values, do not share outside hosting environment
|
|
||||||
# Use `bin/rails db:encryption:init` to generate fresh secrets
|
|
||||||
# Do NOT change these secrets once in use, as this would cause data loss and other issues
|
|
||||||
# ------------------
|
|
||||||
# ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY=
|
|
||||||
# ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT=
|
|
||||||
# ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY=
|
|
||||||
|
|
||||||
# Web Push
|
# Web Push
|
||||||
# --------
|
# --------
|
||||||
# Generate with `bundle exec rails mastodon:webpush:generate_vapid_key`
|
# Generate with `bundle exec rails mastodon:webpush:generate_vapid_key`
|
||||||
|
@ -79,9 +68,6 @@ AWS_ACCESS_KEY_ID=
|
||||||
AWS_SECRET_ACCESS_KEY=
|
AWS_SECRET_ACCESS_KEY=
|
||||||
S3_ALIAS_HOST=files.example.com
|
S3_ALIAS_HOST=files.example.com
|
||||||
|
|
||||||
# Optional list of hosts that are allowed to serve media for your instance
|
|
||||||
# EXTRA_MEDIA_HOSTS=https://data.example1.com,https://data.example2.com
|
|
||||||
|
|
||||||
# IP and session retention
|
# IP and session retention
|
||||||
# -----------------------
|
# -----------------------
|
||||||
# Make sure to modify the scheduling of ip_cleanup_scheduler in config/sidekiq.yml
|
# Make sure to modify the scheduling of ip_cleanup_scheduler in config/sidekiq.yml
|
||||||
|
@ -89,27 +75,3 @@ S3_ALIAS_HOST=files.example.com
|
||||||
# -----------------------
|
# -----------------------
|
||||||
IP_RETENTION_PERIOD=31556952
|
IP_RETENTION_PERIOD=31556952
|
||||||
SESSION_RETENTION_PERIOD=31556952
|
SESSION_RETENTION_PERIOD=31556952
|
||||||
|
|
||||||
# Fetch All Replies Behavior
|
|
||||||
# --------------------------
|
|
||||||
# When a user expands a post (DetailedStatus view), fetch all of its replies
|
|
||||||
# (default: false)
|
|
||||||
FETCH_REPLIES_ENABLED=false
|
|
||||||
|
|
||||||
# Period to wait between fetching replies (in minutes)
|
|
||||||
FETCH_REPLIES_COOLDOWN_MINUTES=15
|
|
||||||
|
|
||||||
# Period to wait after a post is first created before fetching its replies (in minutes)
|
|
||||||
FETCH_REPLIES_INITIAL_WAIT_MINUTES=5
|
|
||||||
|
|
||||||
# Max number of replies to fetch - total, recursively through a whole reply tree
|
|
||||||
FETCH_REPLIES_MAX_GLOBAL=1000
|
|
||||||
|
|
||||||
# Max number of replies to fetch - for a single post
|
|
||||||
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
|
|
||||||
|
|
13
.eslintignore
Normal file
13
.eslintignore
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
/build/**
|
||||||
|
/coverage/**
|
||||||
|
/db/**
|
||||||
|
/lib/**
|
||||||
|
/log/**
|
||||||
|
/node_modules/**
|
||||||
|
/nonobox/**
|
||||||
|
/public/**
|
||||||
|
!/public/embed.js
|
||||||
|
/spec/**
|
||||||
|
/tmp/**
|
||||||
|
/vendor/**
|
||||||
|
!.eslintrc.js
|
368
.eslintrc.js
Normal file
368
.eslintrc.js
Normal file
|
@ -0,0 +1,368 @@
|
||||||
|
// @ts-check
|
||||||
|
const { defineConfig } = require('eslint-define-config');
|
||||||
|
|
||||||
|
module.exports = defineConfig({
|
||||||
|
root: true,
|
||||||
|
|
||||||
|
extends: [
|
||||||
|
'eslint:recommended',
|
||||||
|
'plugin:react/recommended',
|
||||||
|
'plugin:react-hooks/recommended',
|
||||||
|
'plugin:jsx-a11y/recommended',
|
||||||
|
'plugin:import/recommended',
|
||||||
|
'plugin:promise/recommended',
|
||||||
|
'plugin:jsdoc/recommended',
|
||||||
|
],
|
||||||
|
|
||||||
|
env: {
|
||||||
|
browser: true,
|
||||||
|
node: true,
|
||||||
|
es6: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
parser: '@typescript-eslint/parser',
|
||||||
|
|
||||||
|
plugins: [
|
||||||
|
'react',
|
||||||
|
'jsx-a11y',
|
||||||
|
'import',
|
||||||
|
'promise',
|
||||||
|
'@typescript-eslint',
|
||||||
|
'formatjs',
|
||||||
|
],
|
||||||
|
|
||||||
|
parserOptions: {
|
||||||
|
sourceType: 'module',
|
||||||
|
ecmaFeatures: {
|
||||||
|
jsx: true,
|
||||||
|
},
|
||||||
|
ecmaVersion: 2021,
|
||||||
|
requireConfigFile: false,
|
||||||
|
babelOptions: {
|
||||||
|
configFile: false,
|
||||||
|
presets: ['@babel/react', '@babel/env'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
settings: {
|
||||||
|
react: {
|
||||||
|
version: 'detect',
|
||||||
|
},
|
||||||
|
'import/ignore': [
|
||||||
|
'node_modules',
|
||||||
|
'\\.(css|scss|json)$',
|
||||||
|
],
|
||||||
|
'import/resolver': {
|
||||||
|
typescript: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
rules: {
|
||||||
|
'consistent-return': 'error',
|
||||||
|
'dot-notation': 'error',
|
||||||
|
eqeqeq: ['error', 'always', { 'null': 'ignore' }],
|
||||||
|
'indent': ['error', 2],
|
||||||
|
'jsx-quotes': ['error', 'prefer-single'],
|
||||||
|
'semi': ['error', 'always'],
|
||||||
|
'no-case-declarations': 'off',
|
||||||
|
'no-catch-shadow': 'error',
|
||||||
|
'no-console': [
|
||||||
|
'warn',
|
||||||
|
{
|
||||||
|
allow: [
|
||||||
|
'error',
|
||||||
|
'warn',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'no-empty': ['error', { "allowEmptyCatch": true }],
|
||||||
|
'no-restricted-properties': [
|
||||||
|
'error',
|
||||||
|
{ property: 'substring', message: 'Use .slice instead of .substring.' },
|
||||||
|
{ property: 'substr', message: 'Use .slice instead of .substr.' },
|
||||||
|
],
|
||||||
|
'no-restricted-syntax': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
|
selector: 'Literal[value=/•/], JSXText[value=/•/]',
|
||||||
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
|
message: "Use '·' (middle dot) instead of '•' (bullet)",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'no-unused-expressions': 'error',
|
||||||
|
'no-unused-vars': 'off',
|
||||||
|
'@typescript-eslint/no-unused-vars': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
vars: 'all',
|
||||||
|
args: 'after-used',
|
||||||
|
destructuredArrayIgnorePattern: '^_',
|
||||||
|
ignoreRestSiblings: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'valid-typeof': 'error',
|
||||||
|
|
||||||
|
'react/jsx-filename-extension': ['error', { extensions: ['.jsx', 'tsx'] }],
|
||||||
|
'react/jsx-boolean-value': 'error',
|
||||||
|
'react/display-name': 'off',
|
||||||
|
'react/jsx-fragments': ['error', 'syntax'],
|
||||||
|
'react/jsx-equals-spacing': 'error',
|
||||||
|
'react/jsx-no-bind': 'error',
|
||||||
|
'react/jsx-no-useless-fragment': 'error',
|
||||||
|
'react/jsx-no-target-blank': 'off',
|
||||||
|
'react/jsx-tag-spacing': 'error',
|
||||||
|
'react/jsx-uses-react': 'off', // not needed with new JSX transform
|
||||||
|
'react/jsx-wrap-multilines': 'error',
|
||||||
|
'react/react-in-jsx-scope': 'off', // not needed with new JSX transform
|
||||||
|
'react/self-closing-comp': 'error',
|
||||||
|
|
||||||
|
// recommended values found in https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/v6.8.0/src/index.js#L46
|
||||||
|
'jsx-a11y/click-events-have-key-events': 'off',
|
||||||
|
'jsx-a11y/label-has-associated-control': 'off',
|
||||||
|
'jsx-a11y/media-has-caption': 'off',
|
||||||
|
'jsx-a11y/no-autofocus': 'off',
|
||||||
|
// recommended rule is:
|
||||||
|
// 'jsx-a11y/no-interactive-element-to-noninteractive-role': [
|
||||||
|
// 'error',
|
||||||
|
// {
|
||||||
|
// tr: ['none', 'presentation'],
|
||||||
|
// canvas: ['img'],
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
'jsx-a11y/no-interactive-element-to-noninteractive-role': 'off',
|
||||||
|
// recommended rule is:
|
||||||
|
// 'jsx-a11y/no-noninteractive-tabindex': [
|
||||||
|
// 'error',
|
||||||
|
// {
|
||||||
|
// tags: [],
|
||||||
|
// roles: ['tabpanel'],
|
||||||
|
// allowExpressionValues: true,
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
'jsx-a11y/no-noninteractive-tabindex': 'off',
|
||||||
|
// recommended is full 'error'
|
||||||
|
'jsx-a11y/no-static-element-interactions': [
|
||||||
|
'warn',
|
||||||
|
{
|
||||||
|
handlers: [
|
||||||
|
'onClick',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
// See https://github.com/import-js/eslint-plugin-import/blob/v2.29.1/config/recommended.js
|
||||||
|
'import/extensions': [
|
||||||
|
'error',
|
||||||
|
'always',
|
||||||
|
{
|
||||||
|
js: 'never',
|
||||||
|
jsx: 'never',
|
||||||
|
mjs: 'never',
|
||||||
|
ts: 'never',
|
||||||
|
tsx: 'never',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'import/first': 'error',
|
||||||
|
'import/newline-after-import': 'error',
|
||||||
|
'import/no-anonymous-default-export': 'error',
|
||||||
|
'import/no-extraneous-dependencies': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
devDependencies: [
|
||||||
|
'.eslintrc.js',
|
||||||
|
'config/webpack/**',
|
||||||
|
'app/javascript/mastodon/performance.js',
|
||||||
|
'app/javascript/mastodon/test_setup.js',
|
||||||
|
'app/javascript/**/__tests__/**',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'import/no-amd': 'error',
|
||||||
|
'import/no-commonjs': 'error',
|
||||||
|
'import/no-import-module-exports': 'error',
|
||||||
|
'import/no-relative-packages': 'error',
|
||||||
|
'import/no-self-import': 'error',
|
||||||
|
'import/no-useless-path-segments': 'error',
|
||||||
|
'import/no-webpack-loader-syntax': 'error',
|
||||||
|
|
||||||
|
'import/order': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
alphabetize: { order: 'asc' },
|
||||||
|
'newlines-between': 'always',
|
||||||
|
groups: [
|
||||||
|
'builtin',
|
||||||
|
'external',
|
||||||
|
'internal',
|
||||||
|
'parent',
|
||||||
|
['index', 'sibling'],
|
||||||
|
'object',
|
||||||
|
],
|
||||||
|
pathGroups: [
|
||||||
|
// React core packages
|
||||||
|
{
|
||||||
|
pattern: '{react,react-dom,react-dom/client,prop-types}',
|
||||||
|
group: 'builtin',
|
||||||
|
position: 'after',
|
||||||
|
},
|
||||||
|
// I18n
|
||||||
|
{
|
||||||
|
pattern: '{react-intl,intl-messageformat}',
|
||||||
|
group: 'builtin',
|
||||||
|
position: 'after',
|
||||||
|
},
|
||||||
|
// Common React utilities
|
||||||
|
{
|
||||||
|
pattern: '{classnames,react-helmet,react-router,react-router-dom}',
|
||||||
|
group: 'external',
|
||||||
|
position: 'before',
|
||||||
|
},
|
||||||
|
// Immutable / Redux / data store
|
||||||
|
{
|
||||||
|
pattern: '{immutable,@reduxjs/toolkit,react-redux,react-immutable-proptypes,react-immutable-pure-component}',
|
||||||
|
group: 'external',
|
||||||
|
position: 'before',
|
||||||
|
},
|
||||||
|
// Internal packages
|
||||||
|
{
|
||||||
|
pattern: '{mastodon/**}',
|
||||||
|
group: 'internal',
|
||||||
|
position: 'after',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
pathGroupsExcludedImportTypes: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
'promise/always-return': 'off',
|
||||||
|
'promise/catch-or-return': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
allowFinally: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'promise/no-callback-in-promise': 'off',
|
||||||
|
'promise/no-nesting': 'off',
|
||||||
|
'promise/no-promise-in-callback': 'off',
|
||||||
|
|
||||||
|
'formatjs/blocklist-elements': 'error',
|
||||||
|
'formatjs/enforce-default-message': ['error', 'literal'],
|
||||||
|
'formatjs/enforce-description': 'off', // description values not currently used
|
||||||
|
'formatjs/enforce-id': 'off', // Explicit IDs are used in the project
|
||||||
|
'formatjs/enforce-placeholders': 'off', // Issues in short_number.jsx
|
||||||
|
'formatjs/enforce-plural-rules': 'error',
|
||||||
|
'formatjs/no-camel-case': 'off', // disabledAccount is only non-conforming
|
||||||
|
'formatjs/no-complex-selectors': 'error',
|
||||||
|
'formatjs/no-emoji': 'error',
|
||||||
|
'formatjs/no-id': 'off', // IDs are used for translation keys
|
||||||
|
'formatjs/no-invalid-icu': 'error',
|
||||||
|
'formatjs/no-literal-string-in-jsx': 'off', // Should be looked at, but mainly flagging punctuation outside of strings
|
||||||
|
'formatjs/no-multiple-whitespaces': 'error',
|
||||||
|
'formatjs/no-offset': 'error',
|
||||||
|
'formatjs/no-useless-message': 'error',
|
||||||
|
'formatjs/prefer-formatted-message': 'error',
|
||||||
|
'formatjs/prefer-pound-in-plural': 'error',
|
||||||
|
|
||||||
|
'jsdoc/check-types': 'off',
|
||||||
|
'jsdoc/no-undefined-types': 'off',
|
||||||
|
'jsdoc/require-jsdoc': 'off',
|
||||||
|
'jsdoc/require-param-description': 'off',
|
||||||
|
'jsdoc/require-property-description': 'off',
|
||||||
|
'jsdoc/require-returns-description': 'off',
|
||||||
|
'jsdoc/require-returns': 'off',
|
||||||
|
},
|
||||||
|
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: [
|
||||||
|
'.eslintrc.js',
|
||||||
|
'*.config.js',
|
||||||
|
'.*rc.js',
|
||||||
|
'ide-helper.js',
|
||||||
|
'config/webpack/**/*',
|
||||||
|
'config/formatjs-formatter.js',
|
||||||
|
],
|
||||||
|
|
||||||
|
env: {
|
||||||
|
commonjs: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
parserOptions: {
|
||||||
|
sourceType: 'script',
|
||||||
|
},
|
||||||
|
|
||||||
|
rules: {
|
||||||
|
'import/no-commonjs': 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: [
|
||||||
|
'**/*.ts',
|
||||||
|
'**/*.tsx',
|
||||||
|
],
|
||||||
|
|
||||||
|
extends: [
|
||||||
|
'eslint:recommended',
|
||||||
|
'plugin:@typescript-eslint/strict-type-checked',
|
||||||
|
'plugin:@typescript-eslint/stylistic-type-checked',
|
||||||
|
'plugin:react/recommended',
|
||||||
|
'plugin:react-hooks/recommended',
|
||||||
|
'plugin:jsx-a11y/recommended',
|
||||||
|
'plugin:import/recommended',
|
||||||
|
'plugin:import/typescript',
|
||||||
|
'plugin:promise/recommended',
|
||||||
|
'plugin:jsdoc/recommended-typescript',
|
||||||
|
],
|
||||||
|
|
||||||
|
parserOptions: {
|
||||||
|
projectService: true,
|
||||||
|
tsconfigRootDir: __dirname,
|
||||||
|
},
|
||||||
|
|
||||||
|
rules: {
|
||||||
|
// Disable formatting rules that have been enabled in the base config
|
||||||
|
'indent': 'off',
|
||||||
|
|
||||||
|
// This is not needed as we use noImplicitReturns, which handles this in addition to understanding types
|
||||||
|
'consistent-return': 'off',
|
||||||
|
|
||||||
|
'import/consistent-type-specifier-style': ['error', 'prefer-top-level'],
|
||||||
|
|
||||||
|
'@typescript-eslint/consistent-type-definitions': ['warn', 'interface'],
|
||||||
|
'@typescript-eslint/consistent-type-exports': 'error',
|
||||||
|
'@typescript-eslint/consistent-type-imports': 'error',
|
||||||
|
"@typescript-eslint/prefer-nullish-coalescing": ['error', { ignorePrimitives: { boolean: true } }],
|
||||||
|
"@typescript-eslint/no-restricted-imports": [
|
||||||
|
"warn",
|
||||||
|
{
|
||||||
|
"name": "react-redux",
|
||||||
|
"importNames": ["useSelector", "useDispatch"],
|
||||||
|
"message": "Use typed hooks `useAppDispatch` and `useAppSelector` instead."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@typescript-eslint/restrict-template-expressions": ['warn', { allowNumber: true }],
|
||||||
|
'jsdoc/require-jsdoc': 'off',
|
||||||
|
|
||||||
|
// Those rules set stricter rules for TS files
|
||||||
|
// to enforce better practices when converting from JS
|
||||||
|
'import/no-default-export': 'warn',
|
||||||
|
'react/prefer-stateless-function': 'warn',
|
||||||
|
'react/function-component-definition': ['error', { namedComponents: 'arrow-function' }],
|
||||||
|
'react/jsx-uses-react': 'off', // not needed with new JSX transform
|
||||||
|
'react/react-in-jsx-scope': 'off', // not needed with new JSX transform
|
||||||
|
'react/prop-types': 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: [
|
||||||
|
'**/__tests__/*.js',
|
||||||
|
'**/__tests__/*.jsx',
|
||||||
|
],
|
||||||
|
|
||||||
|
env: {
|
||||||
|
jest: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
],
|
||||||
|
});
|
74
.github/ISSUE_TEMPLATE/3.troubleshooting.yml
vendored
74
.github/ISSUE_TEMPLATE/3.troubleshooting.yml
vendored
|
@ -1,74 +0,0 @@
|
||||||
name: Deployment troubleshooting
|
|
||||||
description: |
|
|
||||||
You are a server administrator and you are encountering a technical issue during installation, upgrade or operations of Mastodon.
|
|
||||||
labels: ['status/to triage']
|
|
||||||
type: 'Troubleshooting'
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
Make sure that you are submitting a new bug that was not previously reported or already fixed.
|
|
||||||
|
|
||||||
Please use a concise and distinct title for the issue.
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Steps to reproduce the problem
|
|
||||||
description: What were you trying to do?
|
|
||||||
value: |
|
|
||||||
1.
|
|
||||||
2.
|
|
||||||
3.
|
|
||||||
...
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: input
|
|
||||||
attributes:
|
|
||||||
label: Expected behaviour
|
|
||||||
description: What should have happened?
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: input
|
|
||||||
attributes:
|
|
||||||
label: Actual behaviour
|
|
||||||
description: What happened?
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Detailed description
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: input
|
|
||||||
attributes:
|
|
||||||
label: Mastodon instance
|
|
||||||
description: The address of the Mastodon instance where you experienced the issue
|
|
||||||
placeholder: mastodon.social
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: input
|
|
||||||
attributes:
|
|
||||||
label: Mastodon version
|
|
||||||
description: |
|
|
||||||
This is displayed at the bottom of the About page, eg. `v4.4.0-alpha.1`
|
|
||||||
placeholder: v4.3.0
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Environment
|
|
||||||
description: |
|
|
||||||
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)
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Technical details
|
|
||||||
description: |
|
|
||||||
Any additional technical details you may have, like logs or error traces
|
|
||||||
validations:
|
|
||||||
required: false
|
|
10
.github/renovate.json5
vendored
10
.github/renovate.json5
vendored
|
@ -15,8 +15,6 @@
|
||||||
// to `null` after any other rule set it to something.
|
// to `null` after any other rule set it to something.
|
||||||
dependencyDashboardHeader: 'This issue lists Renovate updates and detected dependencies. Read the [Dependency Dashboard](https://docs.renovatebot.com/key-concepts/dashboard/) docs to learn more. Before approving any upgrade: read the description and comments in the [`renovate.json5` file](https://github.com/mastodon/mastodon/blob/main/.github/renovate.json5).',
|
dependencyDashboardHeader: 'This issue lists Renovate updates and detected dependencies. Read the [Dependency Dashboard](https://docs.renovatebot.com/key-concepts/dashboard/) docs to learn more. Before approving any upgrade: read the description and comments in the [`renovate.json5` file](https://github.com/mastodon/mastodon/blob/main/.github/renovate.json5).',
|
||||||
postUpdateOptions: ['yarnDedupeHighest'],
|
postUpdateOptions: ['yarnDedupeHighest'],
|
||||||
// The types are now included in recent versions,we ignore them here until we upgrade and remove the dependency
|
|
||||||
ignoreDeps: ['@types/emoji-mart'],
|
|
||||||
packageRules: [
|
packageRules: [
|
||||||
{
|
{
|
||||||
// Require Dependency Dashboard Approval for major version bumps of these node packages
|
// Require Dependency Dashboard Approval for major version bumps of these node packages
|
||||||
|
@ -99,13 +97,7 @@
|
||||||
{
|
{
|
||||||
// Group all eslint-related packages with `eslint` in the same PR
|
// Group all eslint-related packages with `eslint` in the same PR
|
||||||
matchManagers: ['npm'],
|
matchManagers: ['npm'],
|
||||||
matchPackageNames: [
|
matchPackageNames: ['eslint', 'eslint-*', '@typescript-eslint/*'],
|
||||||
'eslint',
|
|
||||||
'eslint-*',
|
|
||||||
'typescript-eslint',
|
|
||||||
'@eslint/*',
|
|
||||||
'globals',
|
|
||||||
],
|
|
||||||
matchUpdateTypes: ['patch', 'minor'],
|
matchUpdateTypes: ['patch', 'minor'],
|
||||||
groupName: 'eslint (non-major)',
|
groupName: 'eslint (non-major)',
|
||||||
},
|
},
|
||||||
|
|
4
.github/workflows/build-security.yml
vendored
4
.github/workflows/build-security.yml
vendored
|
@ -24,6 +24,8 @@ jobs:
|
||||||
uses: ./.github/workflows/build-container-image.yml
|
uses: ./.github/workflows/build-container-image.yml
|
||||||
with:
|
with:
|
||||||
file_to_build: Dockerfile
|
file_to_build: Dockerfile
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
use_native_arm64_builder: true
|
||||||
cache: false
|
cache: false
|
||||||
push_to_images: |
|
push_to_images: |
|
||||||
tootsuite/mastodon
|
tootsuite/mastodon
|
||||||
|
@ -44,6 +46,8 @@ jobs:
|
||||||
uses: ./.github/workflows/build-container-image.yml
|
uses: ./.github/workflows/build-container-image.yml
|
||||||
with:
|
with:
|
||||||
file_to_build: streaming/Dockerfile
|
file_to_build: streaming/Dockerfile
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
use_native_arm64_builder: true
|
||||||
cache: false
|
cache: false
|
||||||
push_to_images: |
|
push_to_images: |
|
||||||
tootsuite/mastodon-streaming
|
tootsuite/mastodon-streaming
|
||||||
|
|
2
.github/workflows/bundler-audit.yml
vendored
2
.github/workflows/bundler-audit.yml
vendored
|
@ -39,4 +39,4 @@ jobs:
|
||||||
bundler-cache: true
|
bundler-cache: true
|
||||||
|
|
||||||
- name: Run bundler-audit
|
- name: Run bundler-audit
|
||||||
run: bin/bundler-audit check --update
|
run: bundle exec bundler-audit check --update
|
||||||
|
|
12
.github/workflows/check-i18n.yml
vendored
12
.github/workflows/check-i18n.yml
vendored
|
@ -24,7 +24,7 @@ permissions:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check-i18n:
|
check-i18n:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
@ -41,18 +41,18 @@ jobs:
|
||||||
git diff --exit-code
|
git diff --exit-code
|
||||||
|
|
||||||
- name: Check locale file normalization
|
- name: Check locale file normalization
|
||||||
run: bin/i18n-tasks check-normalized
|
run: bundle exec i18n-tasks check-normalized
|
||||||
|
|
||||||
- name: Check for unused strings
|
- name: Check for unused strings
|
||||||
run: bin/i18n-tasks unused
|
run: bundle exec i18n-tasks unused
|
||||||
|
|
||||||
- name: Check for missing strings in English YML
|
- name: Check for missing strings in English YML
|
||||||
run: |
|
run: |
|
||||||
bin/i18n-tasks add-missing -l en
|
bundle exec i18n-tasks add-missing -l en
|
||||||
git diff --exit-code
|
git diff --exit-code
|
||||||
|
|
||||||
- name: Check for wrong string interpolations
|
- name: Check for wrong string interpolations
|
||||||
run: bin/i18n-tasks check-consistent-interpolations
|
run: bundle exec i18n-tasks check-consistent-interpolations
|
||||||
|
|
||||||
- name: Check that all required locale files exist
|
- name: Check that all required locale files exist
|
||||||
run: bin/rake repo:check_locales_files
|
run: bundle exec rake repo:check_locales_files
|
||||||
|
|
|
@ -46,11 +46,11 @@ jobs:
|
||||||
uses: ./.github/actions/setup-ruby
|
uses: ./.github/actions/setup-ruby
|
||||||
|
|
||||||
- name: Run i18n normalize task
|
- name: Run i18n normalize task
|
||||||
run: bin/i18n-tasks normalize
|
run: bundle exec i18n-tasks normalize
|
||||||
|
|
||||||
# Create or update the pull request
|
# Create or update the pull request
|
||||||
- name: Create Pull Request
|
- name: Create Pull Request
|
||||||
uses: peter-evans/create-pull-request@v7.0.6
|
uses: peter-evans/create-pull-request@v7.0.5
|
||||||
with:
|
with:
|
||||||
commit-message: 'New Crowdin translations'
|
commit-message: 'New Crowdin translations'
|
||||||
title: 'New Crowdin Translations for ${{ github.base_ref || github.ref_name }} (automated)'
|
title: 'New Crowdin Translations for ${{ github.base_ref || github.ref_name }} (automated)'
|
||||||
|
|
2
.github/workflows/lint-css.yml
vendored
2
.github/workflows/lint-css.yml
vendored
|
@ -43,4 +43,4 @@ jobs:
|
||||||
uses: ./.github/actions/setup-javascript
|
uses: ./.github/actions/setup-javascript
|
||||||
|
|
||||||
- name: Stylelint
|
- name: Stylelint
|
||||||
run: yarn lint:css --custom-formatter @csstools/stylelint-formatter-github
|
run: yarn lint:css -f github
|
||||||
|
|
2
.github/workflows/lint-haml.yml
vendored
2
.github/workflows/lint-haml.yml
vendored
|
@ -46,4 +46,4 @@ jobs:
|
||||||
- name: Run haml-lint
|
- name: Run haml-lint
|
||||||
run: |
|
run: |
|
||||||
echo "::add-matcher::.github/workflows/haml-lint-problem-matcher.json"
|
echo "::add-matcher::.github/workflows/haml-lint-problem-matcher.json"
|
||||||
bin/haml-lint --reporter github
|
bundle exec haml-lint --reporter github
|
||||||
|
|
6
.github/workflows/lint-js.yml
vendored
6
.github/workflows/lint-js.yml
vendored
|
@ -14,7 +14,7 @@ on:
|
||||||
- 'tsconfig.json'
|
- 'tsconfig.json'
|
||||||
- '.nvmrc'
|
- '.nvmrc'
|
||||||
- '.prettier*'
|
- '.prettier*'
|
||||||
- 'eslint.config.mjs'
|
- '.eslint*'
|
||||||
- '**/*.js'
|
- '**/*.js'
|
||||||
- '**/*.jsx'
|
- '**/*.jsx'
|
||||||
- '**/*.ts'
|
- '**/*.ts'
|
||||||
|
@ -28,7 +28,7 @@ on:
|
||||||
- 'tsconfig.json'
|
- 'tsconfig.json'
|
||||||
- '.nvmrc'
|
- '.nvmrc'
|
||||||
- '.prettier*'
|
- '.prettier*'
|
||||||
- 'eslint.config.mjs'
|
- '.eslint*'
|
||||||
- '**/*.js'
|
- '**/*.js'
|
||||||
- '**/*.jsx'
|
- '**/*.jsx'
|
||||||
- '**/*.ts'
|
- '**/*.ts'
|
||||||
|
@ -47,7 +47,7 @@ jobs:
|
||||||
uses: ./.github/actions/setup-javascript
|
uses: ./.github/actions/setup-javascript
|
||||||
|
|
||||||
- name: ESLint
|
- name: ESLint
|
||||||
run: yarn workspaces foreach --all --parallel run lint:js --max-warnings 0
|
run: yarn lint:js --max-warnings 0
|
||||||
|
|
||||||
- name: Typecheck
|
- name: Typecheck
|
||||||
run: yarn typecheck
|
run: yarn typecheck
|
||||||
|
|
2
.github/workflows/lint-ruby.yml
vendored
2
.github/workflows/lint-ruby.yml
vendored
|
@ -12,7 +12,6 @@ on:
|
||||||
- 'Gemfile*'
|
- 'Gemfile*'
|
||||||
- '.rubocop*.yml'
|
- '.rubocop*.yml'
|
||||||
- '.ruby-version'
|
- '.ruby-version'
|
||||||
- 'bin/rubocop'
|
|
||||||
- 'config/brakeman.ignore'
|
- 'config/brakeman.ignore'
|
||||||
- '**/*.rb'
|
- '**/*.rb'
|
||||||
- '**/*.rake'
|
- '**/*.rake'
|
||||||
|
@ -23,7 +22,6 @@ on:
|
||||||
- 'Gemfile*'
|
- 'Gemfile*'
|
||||||
- '.rubocop*.yml'
|
- '.rubocop*.yml'
|
||||||
- '.ruby-version'
|
- '.ruby-version'
|
||||||
- 'bin/rubocop'
|
|
||||||
- 'config/brakeman.ignore'
|
- 'config/brakeman.ignore'
|
||||||
- '**/*.rb'
|
- '**/*.rb'
|
||||||
- '**/*.rake'
|
- '**/*.rake'
|
||||||
|
|
21
.github/workflows/test-migrations.yml
vendored
21
.github/workflows/test-migrations.yml
vendored
|
@ -15,7 +15,6 @@ on:
|
||||||
- '**/*.rb'
|
- '**/*.rb'
|
||||||
- '.github/workflows/test-migrations.yml'
|
- '.github/workflows/test-migrations.yml'
|
||||||
- 'lib/tasks/tests.rake'
|
- 'lib/tasks/tests.rake'
|
||||||
- 'lib/tasks/db.rake'
|
|
||||||
|
|
||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
|
@ -36,8 +35,6 @@ jobs:
|
||||||
postgres:
|
postgres:
|
||||||
- 14-alpine
|
- 14-alpine
|
||||||
- 15-alpine
|
- 15-alpine
|
||||||
- 16-alpine
|
|
||||||
- 17-alpine
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
postgres:
|
postgres:
|
||||||
|
@ -67,6 +64,7 @@ jobs:
|
||||||
DB_HOST: localhost
|
DB_HOST: localhost
|
||||||
DB_USER: postgres
|
DB_USER: postgres
|
||||||
DB_PASS: postgres
|
DB_PASS: postgres
|
||||||
|
DISABLE_SIMPLECOV: true
|
||||||
RAILS_ENV: test
|
RAILS_ENV: test
|
||||||
BUNDLE_CLEAN: true
|
BUNDLE_CLEAN: true
|
||||||
BUNDLE_FROZEN: true
|
BUNDLE_FROZEN: true
|
||||||
|
@ -80,18 +78,6 @@ jobs:
|
||||||
- name: Set up Ruby environment
|
- name: Set up Ruby environment
|
||||||
uses: ./.github/actions/setup-ruby
|
uses: ./.github/actions/setup-ruby
|
||||||
|
|
||||||
- name: Ensure no errors with `db:prepare`
|
|
||||||
run: |
|
|
||||||
bin/rails db:drop
|
|
||||||
bin/rails db:prepare
|
|
||||||
bin/rails db:migrate
|
|
||||||
|
|
||||||
- name: Ensure no errors with `db:prepare` and SKIP_POST_DEPLOYMENT_MIGRATIONS
|
|
||||||
run: |
|
|
||||||
bin/rails db:drop
|
|
||||||
SKIP_POST_DEPLOYMENT_MIGRATIONS=true bin/rails db:prepare
|
|
||||||
bin/rails db:migrate
|
|
||||||
|
|
||||||
- name: Test "one step migration" flow
|
- name: Test "one step migration" flow
|
||||||
run: |
|
run: |
|
||||||
bin/rails db:drop
|
bin/rails db:drop
|
||||||
|
@ -105,11 +91,6 @@ jobs:
|
||||||
bin/rails db:drop
|
bin/rails db:drop
|
||||||
bin/rails db:create
|
bin/rails db:create
|
||||||
SKIP_POST_DEPLOYMENT_MIGRATIONS=true bin/rails tests:migrations:prepare_database
|
SKIP_POST_DEPLOYMENT_MIGRATIONS=true bin/rails tests:migrations:prepare_database
|
||||||
|
|
||||||
# Migrate up to v4.2.0 breakpoint
|
|
||||||
bin/rails db:migrate VERSION=20230907150100
|
|
||||||
|
|
||||||
# Migrate the rest
|
|
||||||
SKIP_POST_DEPLOYMENT_MIGRATIONS=true bin/rails db:migrate
|
SKIP_POST_DEPLOYMENT_MIGRATIONS=true bin/rails db:migrate
|
||||||
bin/rails db:migrate
|
bin/rails db:migrate
|
||||||
bin/rails tests:migrations:check_database
|
bin/rails tests:migrations:check_database
|
||||||
|
|
28
.github/workflows/test-ruby.yml
vendored
28
.github/workflows/test-ruby.yml
vendored
|
@ -110,7 +110,7 @@ jobs:
|
||||||
DB_HOST: localhost
|
DB_HOST: localhost
|
||||||
DB_USER: postgres
|
DB_USER: postgres
|
||||||
DB_PASS: postgres
|
DB_PASS: postgres
|
||||||
COVERAGE: ${{ matrix.ruby-version == '.ruby-version' }}
|
DISABLE_SIMPLECOV: ${{ matrix.ruby-version != '.ruby-version' }}
|
||||||
RAILS_ENV: test
|
RAILS_ENV: test
|
||||||
ALLOW_NOPAM: true
|
ALLOW_NOPAM: true
|
||||||
PAM_ENABLED: true
|
PAM_ENABLED: true
|
||||||
|
@ -128,8 +128,8 @@ jobs:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
ruby-version:
|
ruby-version:
|
||||||
|
- '3.1'
|
||||||
- '3.2'
|
- '3.2'
|
||||||
- '3.3'
|
|
||||||
- '.ruby-version'
|
- '.ruby-version'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
@ -147,7 +147,7 @@ jobs:
|
||||||
uses: ./.github/actions/setup-ruby
|
uses: ./.github/actions/setup-ruby
|
||||||
with:
|
with:
|
||||||
ruby-version: ${{ matrix.ruby-version}}
|
ruby-version: ${{ matrix.ruby-version}}
|
||||||
additional-system-dependencies: ffmpeg imagemagick libpam-dev
|
additional-system-dependencies: ffmpeg libpam-dev
|
||||||
|
|
||||||
- name: Load database schema
|
- name: Load database schema
|
||||||
run: |
|
run: |
|
||||||
|
@ -171,7 +171,7 @@ jobs:
|
||||||
|
|
||||||
- name: Upload coverage reports to Codecov
|
- name: Upload coverage reports to Codecov
|
||||||
if: matrix.ruby-version == '.ruby-version'
|
if: matrix.ruby-version == '.ruby-version'
|
||||||
uses: codecov/codecov-action@v5
|
uses: codecov/codecov-action@v4
|
||||||
with:
|
with:
|
||||||
files: coverage/lcov/*.lcov
|
files: coverage/lcov/*.lcov
|
||||||
env:
|
env:
|
||||||
|
@ -179,7 +179,7 @@ jobs:
|
||||||
|
|
||||||
test-libvips:
|
test-libvips:
|
||||||
name: Libvips tests
|
name: Libvips tests
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-24.04
|
||||||
|
|
||||||
needs:
|
needs:
|
||||||
- build
|
- build
|
||||||
|
@ -212,7 +212,7 @@ jobs:
|
||||||
DB_HOST: localhost
|
DB_HOST: localhost
|
||||||
DB_USER: postgres
|
DB_USER: postgres
|
||||||
DB_PASS: postgres
|
DB_PASS: postgres
|
||||||
COVERAGE: ${{ matrix.ruby-version == '.ruby-version' }}
|
DISABLE_SIMPLECOV: ${{ matrix.ruby-version != '.ruby-version' }}
|
||||||
RAILS_ENV: test
|
RAILS_ENV: test
|
||||||
ALLOW_NOPAM: true
|
ALLOW_NOPAM: true
|
||||||
PAM_ENABLED: true
|
PAM_ENABLED: true
|
||||||
|
@ -230,8 +230,8 @@ jobs:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
ruby-version:
|
ruby-version:
|
||||||
|
- '3.1'
|
||||||
- '3.2'
|
- '3.2'
|
||||||
- '3.3'
|
|
||||||
- '.ruby-version'
|
- '.ruby-version'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
@ -249,7 +249,7 @@ jobs:
|
||||||
uses: ./.github/actions/setup-ruby
|
uses: ./.github/actions/setup-ruby
|
||||||
with:
|
with:
|
||||||
ruby-version: ${{ matrix.ruby-version}}
|
ruby-version: ${{ matrix.ruby-version}}
|
||||||
additional-system-dependencies: ffmpeg libpam-dev
|
additional-system-dependencies: ffmpeg libpam-dev libyaml-dev
|
||||||
|
|
||||||
- name: Load database schema
|
- name: Load database schema
|
||||||
run: './bin/rails db:create db:schema:load db:seed'
|
run: './bin/rails db:create db:schema:load db:seed'
|
||||||
|
@ -258,7 +258,7 @@ jobs:
|
||||||
|
|
||||||
- name: Upload coverage reports to Codecov
|
- name: Upload coverage reports to Codecov
|
||||||
if: matrix.ruby-version == '.ruby-version'
|
if: matrix.ruby-version == '.ruby-version'
|
||||||
uses: codecov/codecov-action@v5
|
uses: codecov/codecov-action@v4
|
||||||
with:
|
with:
|
||||||
files: coverage/lcov/mastodon.lcov
|
files: coverage/lcov/mastodon.lcov
|
||||||
env:
|
env:
|
||||||
|
@ -299,6 +299,7 @@ jobs:
|
||||||
DB_HOST: localhost
|
DB_HOST: localhost
|
||||||
DB_USER: postgres
|
DB_USER: postgres
|
||||||
DB_PASS: postgres
|
DB_PASS: postgres
|
||||||
|
DISABLE_SIMPLECOV: true
|
||||||
RAILS_ENV: test
|
RAILS_ENV: test
|
||||||
BUNDLE_WITH: test
|
BUNDLE_WITH: test
|
||||||
ES_ENABLED: false
|
ES_ENABLED: false
|
||||||
|
@ -309,8 +310,8 @@ jobs:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
ruby-version:
|
ruby-version:
|
||||||
|
- '3.1'
|
||||||
- '3.2'
|
- '3.2'
|
||||||
- '3.3'
|
|
||||||
- '.ruby-version'
|
- '.ruby-version'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
@ -329,7 +330,7 @@ jobs:
|
||||||
uses: ./.github/actions/setup-ruby
|
uses: ./.github/actions/setup-ruby
|
||||||
with:
|
with:
|
||||||
ruby-version: ${{ matrix.ruby-version}}
|
ruby-version: ${{ matrix.ruby-version}}
|
||||||
additional-system-dependencies: ffmpeg imagemagick
|
additional-system-dependencies: ffmpeg
|
||||||
|
|
||||||
- name: Set up Javascript environment
|
- name: Set up Javascript environment
|
||||||
uses: ./.github/actions/setup-javascript
|
uses: ./.github/actions/setup-javascript
|
||||||
|
@ -415,6 +416,7 @@ jobs:
|
||||||
DB_HOST: localhost
|
DB_HOST: localhost
|
||||||
DB_USER: postgres
|
DB_USER: postgres
|
||||||
DB_PASS: postgres
|
DB_PASS: postgres
|
||||||
|
DISABLE_SIMPLECOV: true
|
||||||
RAILS_ENV: test
|
RAILS_ENV: test
|
||||||
BUNDLE_WITH: test
|
BUNDLE_WITH: test
|
||||||
ES_ENABLED: true
|
ES_ENABLED: true
|
||||||
|
@ -425,8 +427,8 @@ jobs:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
ruby-version:
|
ruby-version:
|
||||||
|
- '3.1'
|
||||||
- '3.2'
|
- '3.2'
|
||||||
- '3.3'
|
|
||||||
- '.ruby-version'
|
- '.ruby-version'
|
||||||
search-image:
|
search-image:
|
||||||
- docker.elastic.co/elasticsearch/elasticsearch:7.17.13
|
- docker.elastic.co/elasticsearch/elasticsearch:7.17.13
|
||||||
|
@ -448,7 +450,7 @@ jobs:
|
||||||
uses: ./.github/actions/setup-ruby
|
uses: ./.github/actions/setup-ruby
|
||||||
with:
|
with:
|
||||||
ruby-version: ${{ matrix.ruby-version}}
|
ruby-version: ${{ matrix.ruby-version}}
|
||||||
additional-system-dependencies: ffmpeg imagemagick
|
additional-system-dependencies: ffmpeg
|
||||||
|
|
||||||
- name: Set up Javascript environment
|
- name: Set up Javascript environment
|
||||||
uses: ./.github/actions/setup-javascript
|
uses: ./.github/actions/setup-javascript
|
||||||
|
|
2
.nvmrc
2
.nvmrc
|
@ -1 +1 @@
|
||||||
22.14
|
20.17
|
||||||
|
|
|
@ -63,7 +63,6 @@ docker-compose.override.yml
|
||||||
|
|
||||||
# Ignore emoji map file
|
# Ignore emoji map file
|
||||||
/app/javascript/mastodon/features/emoji/emoji_map.json
|
/app/javascript/mastodon/features/emoji/emoji_map.json
|
||||||
/app/javascript/mastodon/features/emoji/emoji_sheet.json
|
|
||||||
|
|
||||||
# Ignore locale files
|
# Ignore locale files
|
||||||
/app/javascript/mastodon/locales/*.json
|
/app/javascript/mastodon/locales/*.json
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
singleQuote: true,
|
singleQuote: true,
|
||||||
jsxSingleQuote: true
|
jsxSingleQuote: true
|
||||||
};
|
}
|
||||||
|
|
11
.rubocop.yml
11
.rubocop.yml
|
@ -8,7 +8,7 @@ AllCops:
|
||||||
- lib/mastodon/migration_helpers.rb
|
- lib/mastodon/migration_helpers.rb
|
||||||
ExtraDetails: true
|
ExtraDetails: true
|
||||||
NewCops: enable
|
NewCops: enable
|
||||||
TargetRubyVersion: 3.2 # Oldest supported ruby version
|
TargetRubyVersion: 3.1 # Oldest supported ruby version
|
||||||
|
|
||||||
inherit_from:
|
inherit_from:
|
||||||
- .rubocop/layout.yml
|
- .rubocop/layout.yml
|
||||||
|
@ -18,7 +18,6 @@ inherit_from:
|
||||||
- .rubocop/rspec_rails.yml
|
- .rubocop/rspec_rails.yml
|
||||||
- .rubocop/rspec.yml
|
- .rubocop/rspec.yml
|
||||||
- .rubocop/style.yml
|
- .rubocop/style.yml
|
||||||
- .rubocop/i18n.yml
|
|
||||||
- .rubocop/custom.yml
|
- .rubocop/custom.yml
|
||||||
- .rubocop_todo.yml
|
- .rubocop_todo.yml
|
||||||
- .rubocop/strict.yml
|
- .rubocop/strict.yml
|
||||||
|
@ -27,10 +26,10 @@ inherit_mode:
|
||||||
merge:
|
merge:
|
||||||
- Exclude
|
- Exclude
|
||||||
|
|
||||||
plugins:
|
require:
|
||||||
- rubocop-capybara
|
|
||||||
- rubocop-i18n
|
|
||||||
- rubocop-performance
|
|
||||||
- rubocop-rails
|
- rubocop-rails
|
||||||
- rubocop-rspec
|
- rubocop-rspec
|
||||||
- rubocop-rspec_rails
|
- rubocop-rspec_rails
|
||||||
|
- rubocop-performance
|
||||||
|
- rubocop-capybara
|
||||||
|
- ./lib/linter/rubocop_middle_dot
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
I18n/RailsI18n:
|
|
||||||
Enabled: true
|
|
||||||
Exclude:
|
|
||||||
- 'config/**/*'
|
|
||||||
- 'db/**/*'
|
|
||||||
- 'lib/**/*'
|
|
||||||
- 'spec/**/*'
|
|
||||||
I18n/GetText:
|
|
||||||
Enabled: false
|
|
||||||
|
|
||||||
I18n/RailsI18n/DecorateStringFormattingUsingInterpolation:
|
|
||||||
Enabled: false
|
|
|
@ -2,9 +2,6 @@
|
||||||
Rails/BulkChangeTable:
|
Rails/BulkChangeTable:
|
||||||
Enabled: false # Conflicts with strong_migrations features
|
Enabled: false # Conflicts with strong_migrations features
|
||||||
|
|
||||||
Rails/Delegate:
|
|
||||||
Enabled: false
|
|
||||||
|
|
||||||
Rails/FilePath:
|
Rails/FilePath:
|
||||||
EnforcedStyle: arguments
|
EnforcedStyle: arguments
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
---
|
---
|
||||||
Style/ArrayIntersect:
|
|
||||||
Enabled: false
|
|
||||||
|
|
||||||
Style/ClassAndModuleChildren:
|
Style/ClassAndModuleChildren:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
|
@ -22,13 +19,6 @@ Style/HashSyntax:
|
||||||
EnforcedShorthandSyntax: either
|
EnforcedShorthandSyntax: either
|
||||||
EnforcedStyle: ruby19_no_mixed_keys
|
EnforcedStyle: ruby19_no_mixed_keys
|
||||||
|
|
||||||
Style/IfUnlessModifier:
|
|
||||||
Exclude:
|
|
||||||
- '**/*.haml'
|
|
||||||
|
|
||||||
Style/KeywordArgumentsMerging:
|
|
||||||
Enabled: false
|
|
||||||
|
|
||||||
Style/NumericLiterals:
|
Style/NumericLiterals:
|
||||||
AllowedPatterns:
|
AllowedPatterns:
|
||||||
- \d{4}_\d{2}_\d{2}_\d{6}
|
- \d{4}_\d{2}_\d{2}_\d{6}
|
||||||
|
@ -47,9 +37,6 @@ Style/RedundantFetchBlock:
|
||||||
Style/RescueStandardError:
|
Style/RescueStandardError:
|
||||||
EnforcedStyle: implicit
|
EnforcedStyle: implicit
|
||||||
|
|
||||||
Style/SafeNavigationChainLength:
|
|
||||||
Enabled: false
|
|
||||||
|
|
||||||
Style/SymbolArray:
|
Style/SymbolArray:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
|
@ -58,6 +45,3 @@ Style/TrailingCommaInArrayLiteral:
|
||||||
|
|
||||||
Style/TrailingCommaInHashLiteral:
|
Style/TrailingCommaInHashLiteral:
|
||||||
EnforcedStyleForMultiline: comma
|
EnforcedStyleForMultiline: comma
|
||||||
|
|
||||||
Style/WordArray:
|
|
||||||
MinSize: 3 # Override default of 2
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# This configuration was generated by
|
# This configuration was generated by
|
||||||
# `rubocop --auto-gen-config --auto-gen-only-exclude --no-offense-counts --no-auto-gen-timestamp`
|
# `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.66.1.
|
||||||
# The point is for the user to remove these configuration records
|
# The point is for the user to remove these configuration records
|
||||||
# one by one as the offenses are removed from the code base.
|
# one by one as the offenses are removed from the code base.
|
||||||
# Note that changes in the inspected code, or installation of new
|
# Note that changes in the inspected code, or installation of new
|
||||||
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
Lint/NonLocalExitFromIterator:
|
Lint/NonLocalExitFromIterator:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'app/helpers/json_ld_helper.rb'
|
- 'app/helpers/jsonld_helper.rb'
|
||||||
|
|
||||||
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
|
||||||
Metrics/AbcSize:
|
Metrics/AbcSize:
|
||||||
|
@ -39,6 +39,7 @@ Rails/OutputSafety:
|
||||||
# Configuration parameters: AllowedVars.
|
# Configuration parameters: AllowedVars.
|
||||||
Style/FetchEnvVar:
|
Style/FetchEnvVar:
|
||||||
Exclude:
|
Exclude:
|
||||||
|
- 'app/lib/translation_service.rb'
|
||||||
- 'config/environments/production.rb'
|
- 'config/environments/production.rb'
|
||||||
- 'config/initializers/2_limited_federation_mode.rb'
|
- 'config/initializers/2_limited_federation_mode.rb'
|
||||||
- 'config/initializers/3_omniauth.rb'
|
- 'config/initializers/3_omniauth.rb'
|
||||||
|
@ -49,7 +50,7 @@ Style/FetchEnvVar:
|
||||||
- 'lib/tasks/repo.rake'
|
- 'lib/tasks/repo.rake'
|
||||||
|
|
||||||
# This cop supports safe autocorrection (--autocorrect).
|
# This cop supports safe autocorrection (--autocorrect).
|
||||||
# Configuration parameters: EnforcedStyle, MaxUnannotatedPlaceholdersAllowed, Mode, AllowedMethods, AllowedPatterns.
|
# Configuration parameters: EnforcedStyle, MaxUnannotatedPlaceholdersAllowed, AllowedMethods, AllowedPatterns.
|
||||||
# SupportedStyles: annotated, template, unannotated
|
# SupportedStyles: annotated, template, unannotated
|
||||||
# AllowedMethods: redirect
|
# AllowedMethods: redirect
|
||||||
Style/FormatStringToken:
|
Style/FormatStringToken:
|
||||||
|
@ -62,10 +63,31 @@ Style/FormatStringToken:
|
||||||
Style/GuardClause:
|
Style/GuardClause:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
|
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||||
|
Style/HashTransformValues:
|
||||||
|
Exclude:
|
||||||
|
- 'app/serializers/rest/web_push_subscription_serializer.rb'
|
||||||
|
- 'app/services/import_service.rb'
|
||||||
|
|
||||||
|
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||||
|
Style/MapToHash:
|
||||||
|
Exclude:
|
||||||
|
- 'app/models/status.rb'
|
||||||
|
|
||||||
|
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||||
|
# Configuration parameters: EnforcedStyle.
|
||||||
|
# SupportedStyles: literals, strict
|
||||||
|
Style/MutableConstant:
|
||||||
|
Exclude:
|
||||||
|
- 'app/models/tag.rb'
|
||||||
|
- 'app/services/delete_account_service.rb'
|
||||||
|
- 'lib/mastodon/migration_warning.rb'
|
||||||
|
|
||||||
# Configuration parameters: AllowedMethods.
|
# Configuration parameters: AllowedMethods.
|
||||||
# AllowedMethods: respond_to_missing?
|
# AllowedMethods: respond_to_missing?
|
||||||
Style/OptionalBooleanParameter:
|
Style/OptionalBooleanParameter:
|
||||||
Exclude:
|
Exclude:
|
||||||
|
- 'app/helpers/jsonld_helper.rb'
|
||||||
- 'app/lib/admin/system_check/message.rb'
|
- 'app/lib/admin/system_check/message.rb'
|
||||||
- 'app/lib/request.rb'
|
- 'app/lib/request.rb'
|
||||||
- 'app/lib/webfinger.rb'
|
- 'app/lib/webfinger.rb'
|
||||||
|
@ -86,3 +108,10 @@ Style/RedundantConstantBase:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'config/environments/production.rb'
|
- 'config/environments/production.rb'
|
||||||
- 'config/initializers/sidekiq.rb'
|
- 'config/initializers/sidekiq.rb'
|
||||||
|
|
||||||
|
# This cop supports safe autocorrection (--autocorrect).
|
||||||
|
# Configuration parameters: WordRegex.
|
||||||
|
# SupportedStyles: percent, brackets
|
||||||
|
Style/WordArray:
|
||||||
|
EnforcedStyle: percent
|
||||||
|
MinSize: 3
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
3.4.3
|
3.3.5
|
||||||
|
|
192
CHANGELOG.md
192
CHANGELOG.md
|
@ -2,190 +2,6 @@
|
||||||
|
|
||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
## [4.3.7] - 2025-04-02
|
|
||||||
|
|
||||||
### Add
|
|
||||||
|
|
||||||
- Add delay to profile updates to debounce them (#34137 by @ClearlyClaire)
|
|
||||||
- Add support for paginating partial collections in `SynchronizeFollowersService` (#34272 and #34277 by @ClearlyClaire)
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Change account suspensions to be federated to recently-followed accounts as well (#34294 by @ClearlyClaire)
|
|
||||||
- Change `AccountReachFinder` to consider statuses based on suspension date (#32805 and #34291 by @ClearlyClaire and @mjankowski)
|
|
||||||
- Change user archive signed URL TTL from 10 seconds to 1 hour (#34254 by @ClearlyClaire)
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Fix static version of animated PNG emojis not being properly extracted (#34337 by @ClearlyClaire)
|
|
||||||
- Fix filters not applying in detailed view, favourites and bookmarks (#34259 and #34260 by @ClearlyClaire)
|
|
||||||
- Fix handling of malformed/unusual HTML (#34201 by @ClearlyClaire)
|
|
||||||
- Fix `CacheBuster` being queued for missing media attachments (#34253 by @ClearlyClaire)
|
|
||||||
- Fix incorrect URL being used when cache busting (#34189 by @ClearlyClaire)
|
|
||||||
- Fix streaming server refusing unix socket path in `DATABASE_URL` (#34091 by @ClearlyClaire)
|
|
||||||
- Fix “x” hotkey not working on boosted filtered posts (#33758 by @ClearlyClaire)
|
|
||||||
|
|
||||||
## [4.3.6] - 2025-03-13
|
|
||||||
|
|
||||||
### Security
|
|
||||||
|
|
||||||
- Update dependency `omniauth-saml`
|
|
||||||
- Update dependency `rack`
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Fix Stoplight errors when using `REDIS_NAMESPACE` (#34126 by @ClearlyClaire)
|
|
||||||
|
|
||||||
## [4.3.5] - 2025-03-10
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Change hashtag suggestion to prefer personal history capitalization (#34070 by @ClearlyClaire)
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Fix processing errors for some HEIF images from iOS 18 (#34086 by @renchap)
|
|
||||||
- Fix streaming server not filtering unknown-language posts from public timelines (#33774 by @ClearlyClaire)
|
|
||||||
- Fix preview cards under Content Warnings not being shown in detailed statuses (#34068 by @ClearlyClaire)
|
|
||||||
- Fix username and display name being hidden on narrow screens in moderation interface (#33064 by @ClearlyClaire)
|
|
||||||
|
|
||||||
## [4.3.4] - 2025-02-27
|
|
||||||
|
|
||||||
### Security
|
|
||||||
|
|
||||||
- Update dependencies
|
|
||||||
- Change HTML sanitization to remove unusable and unused `embed` tag (#34021 by @ClearlyClaire, [GHSA-mq2m-hr29-8gqf](https://github.com/mastodon/mastodon/security/advisories/GHSA-mq2m-hr29-8gqf))
|
|
||||||
- Fix rate-limit on sign-up email verification ([GHSA-v39f-c9jj-8w7h](https://github.com/mastodon/mastodon/security/advisories/GHSA-v39f-c9jj-8w7h))
|
|
||||||
- Fix improper disclosure of domain blocks to unverified users ([GHSA-94h4-fj37-c825](https://github.com/mastodon/mastodon/security/advisories/GHSA-94h4-fj37-c825))
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Change preview cards to be shown when Content Warnings are expanded (#33827 by @ClearlyClaire)
|
|
||||||
- Change warnings against changing encryption secrets to be even more noticeable (#33631 by @ClearlyClaire)
|
|
||||||
- Change `mastodon:setup` to prevent overwriting already-configured servers (#33603, #33616, and #33684 by @ClearlyClaire and @mjankowski)
|
|
||||||
- Change notifications from moderators to not be filtered (#32974 and #33654 by @ClearlyClaire and @mjankowski)
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Fix `GET /api/v2/notifications/:id` and `POST /api/v2/notifications/:id/dismiss` for ungrouped notifications (#33990 by @ClearlyClaire)
|
|
||||||
- Fix issue with some versions of libvips on some systems (#33853 by @kleisauke)
|
|
||||||
- Fix handling of duplicate mentions in incoming status `Update` (#33911 by @ClearlyClaire)
|
|
||||||
- Fix inefficiencies in timeline generation (#33839 and #33842 by @ClearlyClaire)
|
|
||||||
- Fix emoji rewrite adding unnecessary curft to the DOM for most emoji (#33818 by @ClearlyClaire)
|
|
||||||
- Fix `tootctl feeds build` not building list timelines (#33783 by @ClearlyClaire)
|
|
||||||
- Fix flaky test in `/api/v2/notifications` tests (#33773 by @ClearlyClaire)
|
|
||||||
- Fix incorrect signature after HTTP redirect (#33757 and #33769 by @ClearlyClaire)
|
|
||||||
- Fix polls not being validated on edition (#33755 by @ClearlyClaire)
|
|
||||||
- Fix media preview height in compose form when 3 or more images are attached (#33571 by @ClearlyClaire)
|
|
||||||
- Fix preview card sizing in “Author attribution” in profile settings (#33482 by @ClearlyClaire)
|
|
||||||
- Fix processing of incoming notifications for unfilterable types (#33429 by @ClearlyClaire)
|
|
||||||
- Fix featured tags for remote accounts not being kept up to date (#33372, #33406, and #33425 by @ClearlyClaire and @mjankowski)
|
|
||||||
- Fix notification polling showing a loading bar in web UI (#32960 by @Gargron)
|
|
||||||
- Fix accounts table long display name (#29316 by @WebCoder49)
|
|
||||||
- Fix exclusive lists interfering with notifications (#28162 by @ShadowJonathan)
|
|
||||||
|
|
||||||
## [4.3.3] - 2025-01-16
|
|
||||||
|
|
||||||
### Security
|
|
||||||
|
|
||||||
- Fix insufficient validation of account URIs ([GHSA-5wxh-3p65-r4g6](https://github.com/mastodon/mastodon/security/advisories/GHSA-5wxh-3p65-r4g6))
|
|
||||||
- Update dependencies
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Fix `libyaml` missing from `Dockerfile` build stage (#33591 by @vmstan)
|
|
||||||
- Fix incorrect notification settings migration for non-followers (#33348 by @ClearlyClaire)
|
|
||||||
- Fix down clause for notification policy v2 migrations (#33340 by @jesseplusplus)
|
|
||||||
- Fix error decrementing status count when `FeaturedTags#last_status_at` is `nil` (#33320 by @ClearlyClaire)
|
|
||||||
- Fix last paginated notification group only including data on a single notification (#33271 by @ClearlyClaire)
|
|
||||||
- Fix processing of mentions for post edits with an existing corresponding silent mention (#33227 by @ClearlyClaire)
|
|
||||||
- Fix deletion of unconfirmed users with Webauthn set (#33186 by @ClearlyClaire)
|
|
||||||
- Fix empty authors preview card serialization (#33151, #33466 by @mjankowski and @ClearlyClaire)
|
|
||||||
|
|
||||||
## [4.3.2] - 2024-12-03
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Add `tootctl feeds vacuum` (#33065 by @ClearlyClaire)
|
|
||||||
- Add error message when user tries to follow their own account (#31910 by @lenikadali)
|
|
||||||
- Add client_secret_expires_at to OAuth Applications (#30317 by @ThisIsMissEm)
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Change design of Content Warnings and filters (#32543 by @ClearlyClaire)
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Fix processing incoming post edits with mentions to unresolvable accounts (#33129 by @ClearlyClaire)
|
|
||||||
- Fix error when including multiple instances of `embed.js` (#33107 by @YKWeyer)
|
|
||||||
- Fix inactive users' timelines being backfilled on follow and unsuspend (#33094 by @ClearlyClaire)
|
|
||||||
- Fix direct inbox delivery pushing posts into inactive followers' timelines (#33067 by @ClearlyClaire)
|
|
||||||
- Fix `TagFollow` records not being correctly handled in account operations (#33063 by @ClearlyClaire)
|
|
||||||
- Fix pushing hashtag-followed posts to feeds of inactive users (#33018 by @Gargron)
|
|
||||||
- Fix duplicate notifications in notification groups when using slow mode (#33014 by @ClearlyClaire)
|
|
||||||
- Fix posts made in the future being allowed to trend (#32996 by @ClearlyClaire)
|
|
||||||
- Fix uploading higher-than-wide GIF profile picture with libvips enabled (#32911 by @ClearlyClaire)
|
|
||||||
- Fix domain attribution field having autocorrect and autocapitalize enabled (#32903 by @ClearlyClaire)
|
|
||||||
- Fix titles being escaped twice (#32889 by @ClearlyClaire)
|
|
||||||
- Fix list creation limit check (#32869 by @ClearlyClaire)
|
|
||||||
- Fix error in `tootctl email_domain_blocks` when supplying `--with-dns-records` (#32863 by @mjankowski)
|
|
||||||
- Fix `min_id` and `max_id` causing error in search API (#32857 by @Gargron)
|
|
||||||
- Fix inefficiencies when processing removal of posts that use featured tags (#32787 by @ClearlyClaire)
|
|
||||||
- Fix alt-text pop-in not using the translated description (#32766 by @ClearlyClaire)
|
|
||||||
- Fix preview cards with long titles erroneously causing layout changes (#32678 by @ClearlyClaire)
|
|
||||||
- Fix embed modal layout on mobile (#32641 by @DismalShadowX)
|
|
||||||
- Fix and improve batch attachment deletion handling when using OpenStack Swift (#32637 by @hugogameiro)
|
|
||||||
- Fix blocks not being applied on link timeline (#32625 by @tribela)
|
|
||||||
- Fix follow counters being incorrectly changed (#32622 by @oneiros)
|
|
||||||
- Fix 'unknown' media attachment type rendering (#32613 and #32713 by @ThisIsMissEm and @renatolond)
|
|
||||||
- Fix tl language native name (#32606 by @seav)
|
|
||||||
|
|
||||||
### Security
|
|
||||||
|
|
||||||
- Update dependencies
|
|
||||||
|
|
||||||
## [4.3.1] - 2024-10-21
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Add more explicit explanations about author attribution and `fediverse:creator` (#32383 by @ClearlyClaire)
|
|
||||||
- Add ability to group follow notifications in WebUI, can be disabled in the column settings (#32520 by @renchap)
|
|
||||||
- Add back a 6 hours mute duration option (#32522 by @renchap)
|
|
||||||
- Add note about not changing ActiveRecord encryption secrets once they are set (#32413, #32476, #32512, and #32537 by @ClearlyClaire and @mjankowski)
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Change translation feature to translate to selected regional variant (e.g. pt-BR) if available (#32428 by @c960657)
|
|
||||||
|
|
||||||
### Removed
|
|
||||||
|
|
||||||
- Remove ability to get embed code for remote posts (#32578 by @ClearlyClaire)\
|
|
||||||
Getting the embed code is only reliable for local posts.\
|
|
||||||
It never worked for non-Mastodon servers, and stopped working correctly with the changes made in 4.3.0.\
|
|
||||||
We have therefore decided to remove the menu entry while we investigate solutions.
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Fix follow recommendation moderation page default language when using regional variant (#32580 by @ClearlyClaire)
|
|
||||||
- Fix column-settings spacing in local timeline in advanced view (#32567 by @lindwurm)
|
|
||||||
- Fix broken i18n in text welcome mailer tags area (#32571 by @mjankowski)
|
|
||||||
- Fix missing or incorrect cache-control headers for Streaming server (#32551 by @ThisIsMissEm)
|
|
||||||
- Fix only the first paragraph being displayed in some notifications (#32348 by @ClearlyClaire)
|
|
||||||
- Fix reblog icons on account media view (#32506 by @tribela)
|
|
||||||
- Fix Content-Security-Policy not allowing OpenStack SWIFT object storage URI (#32439 by @kenkiku1021)
|
|
||||||
- Fix back arrow pointing to the incorrect direction in RTL languages (#32485 by @renchap)
|
|
||||||
- Fix streaming server using `REDIS_USERNAME` instead of `REDIS_USER` (#32493 by @ThisIsMissEm)
|
|
||||||
- Fix follow recommendation carrousel scrolling on RTL layouts (#32462 and #32505 by @ClearlyClaire)
|
|
||||||
- Fix follow recommendation suppressions not applying immediately (#32392 by @ClearlyClaire)
|
|
||||||
- Fix language of push notifications (#32415 by @ClearlyClaire)
|
|
||||||
- Fix mute duration not being shown in list of muted accounts in web UI (#32388 by @ClearlyClaire)
|
|
||||||
- Fix “Mark every notification as read” not updating the read marker if scrolled down (#32385 by @ClearlyClaire)
|
|
||||||
- Fix “Mention” appearing for otherwise filtered posts (#32356 by @ClearlyClaire)
|
|
||||||
- Fix notification requests from suspended accounts still being listed (#32354 by @ClearlyClaire)
|
|
||||||
- Fix list edition modal styling (#32358 and #32367 by @ClearlyClaire and @vmstan)
|
|
||||||
- Fix 4 columns barely not fitting on 1920px screen (#32361 by @ClearlyClaire)
|
|
||||||
- Fix icon alignment in applications list (#32293 by @mjankowski)
|
|
||||||
|
|
||||||
## [4.3.0] - 2024-10-08
|
## [4.3.0] - 2024-10-08
|
||||||
|
|
||||||
The following changelog entries focus on changes visible to users, administrators, client developers or federated software developers, but there has also been a lot of code modernization, refactoring, and tooling work, in particular by @mjankowski.
|
The following changelog entries focus on changes visible to users, administrators, client developers or federated software developers, but there has also been a lot of code modernization, refactoring, and tooling work, in particular by @mjankowski.
|
||||||
|
@ -210,7 +26,7 @@ The following changelog entries focus on changes visible to users, administrator
|
||||||
- `GET /api/v2/notifications`: https://docs.joinmastodon.org/methods/grouped_notifications/#get-grouped
|
- `GET /api/v2/notifications`: https://docs.joinmastodon.org/methods/grouped_notifications/#get-grouped
|
||||||
- `GET /api/v2/notifications/:group_key`: https://docs.joinmastodon.org/methods/grouped_notifications/#get-notification-group
|
- `GET /api/v2/notifications/:group_key`: https://docs.joinmastodon.org/methods/grouped_notifications/#get-notification-group
|
||||||
- `GET /api/v2/notifications/:group_key/accounts`: https://docs.joinmastodon.org/methods/grouped_notifications/#get-group-accounts
|
- `GET /api/v2/notifications/:group_key/accounts`: https://docs.joinmastodon.org/methods/grouped_notifications/#get-group-accounts
|
||||||
- `POST /api/v2/notifications/:group_key/dismiss`: https://docs.joinmastodon.org/methods/grouped_notifications/#dismiss-group
|
- `POST /api/v2/notifications/:group_key/dimsiss`: https://docs.joinmastodon.org/methods/grouped_notifications/#dismiss-group
|
||||||
- `GET /api/v2/notifications/:unread_count`: https://docs.joinmastodon.org/methods/grouped_notifications/#unread-group-count
|
- `GET /api/v2/notifications/:unread_count`: https://docs.joinmastodon.org/methods/grouped_notifications/#unread-group-count
|
||||||
- **Add notification policies, filtered notifications and notification requests** (#29366, #29529, #29433, #29565, #29567, #29572, #29575, #29588, #29646, #29652, #29658, #29666, #29693, #29699, #29737, #29706, #29570, #29752, #29810, #29826, #30114, #30251, #30559, #29868, #31008, #31011, #30996, #31149, #31220, #31222, #31225, #31242, #31262, #31250, #31273, #31310, #31316, #31322, #31329, #31324, #31331, #31343, #31342, #31309, #31358, #31378, #31406, #31256, #31456, #31419, #31457, #31508, #31540, #31541, #31723, #32062 and #32281 by @ClearlyClaire, @Gargron, @TheEssem, @mgmn, @oneiros, and @renchap)\
|
- **Add notification policies, filtered notifications and notification requests** (#29366, #29529, #29433, #29565, #29567, #29572, #29575, #29588, #29646, #29652, #29658, #29666, #29693, #29699, #29737, #29706, #29570, #29752, #29810, #29826, #30114, #30251, #30559, #29868, #31008, #31011, #30996, #31149, #31220, #31222, #31225, #31242, #31262, #31250, #31273, #31310, #31316, #31322, #31329, #31324, #31331, #31343, #31342, #31309, #31358, #31378, #31406, #31256, #31456, #31419, #31457, #31508, #31540, #31541, #31723, #32062 and #32281 by @ClearlyClaire, @Gargron, @TheEssem, @mgmn, @oneiros, and @renchap)\
|
||||||
The old “Block notifications from non-followers”, “Block notifications from people you don't follow” and “Block direct messages from people you don't follow” notification settings have been replaced by a new set of settings found directly in the notification column.\
|
The old “Block notifications from non-followers”, “Block notifications from people you don't follow” and “Block direct messages from people you don't follow” notification settings have been replaced by a new set of settings found directly in the notification column.\
|
||||||
|
@ -235,7 +51,7 @@ The following changelog entries focus on changes visible to users, administrator
|
||||||
- **Add notifications of severed relationships** (#27511, #29665, #29668, #29670, #29700, #29714, #29712, and #29731 by @ClearlyClaire and @Gargron)\
|
- **Add notifications of severed relationships** (#27511, #29665, #29668, #29670, #29700, #29714, #29712, and #29731 by @ClearlyClaire and @Gargron)\
|
||||||
Notify local users when they lose relationships as a result of a local moderator blocking a remote account or server, allowing the affected user to retrieve the list of broken relationships.\
|
Notify local users when they lose relationships as a result of a local moderator blocking a remote account or server, allowing the affected user to retrieve the list of broken relationships.\
|
||||||
Note that this does not notify remote users.\
|
Note that this does not notify remote users.\
|
||||||
This adds the `severed_relationships` notification type to the REST API and streaming, with a new [`event` attribute](https://docs.joinmastodon.org/entities/Notification/#relationship_severance_event).
|
This adds the `severed_relationships` notification type to the REST API and streaming, with a new [`relationship_severance_event` attribute](https://docs.joinmastodon.org/entities/Notification/#relationship_severance_event).
|
||||||
- **Add hover cards in web UI** (#30754, #30864, #30850, #30879, #30928, #30949, #30948, #30931, and #31300 by @ClearlyClaire, @Gargron, and @renchap)\
|
- **Add hover cards in web UI** (#30754, #30864, #30850, #30879, #30928, #30949, #30948, #30931, and #31300 by @ClearlyClaire, @Gargron, and @renchap)\
|
||||||
Hovering over an avatar or username will now display a hover card with the first two lines of the user's description and their first two profile fields.\
|
Hovering over an avatar or username will now display a hover card with the first two lines of the user's description and their first two profile fields.\
|
||||||
This can be disabled in the “Animations and accessibility” section of the preferences.
|
This can be disabled in the “Animations and accessibility” section of the preferences.
|
||||||
|
@ -251,7 +67,7 @@ The following changelog entries focus on changes visible to users, administrator
|
||||||
```html
|
```html
|
||||||
<meta name="fediverse:creator" content="username@domain" />
|
<meta name="fediverse:creator" content="username@domain" />
|
||||||
```
|
```
|
||||||
On the API side, this is represented by a new `authors` attribute to the `PreviewCard` entity: https://docs.joinmastodon.org/entities/PreviewCard/#authors \
|
On the API side, this is represented by a new `authors` attribute to the `PreviewCard` entity: https://docs.joinmastodon.org/entities/PreviewCard/#authors\
|
||||||
Users can allow arbitrary domains to use `fediverse:creator` to credit them by visiting `/settings/verification`.\
|
Users can allow arbitrary domains to use `fediverse:creator` to credit them by visiting `/settings/verification`.\
|
||||||
This is federated as a new `attributionDomains` property in the `http://joinmastodon.org/ns` namespace, containing an array of domain names: https://docs.joinmastodon.org/spec/activitypub/#properties-used-1
|
This is federated as a new `attributionDomains` property in the `http://joinmastodon.org/ns` namespace, containing an array of domain names: https://docs.joinmastodon.org/spec/activitypub/#properties-used-1
|
||||||
- **Add in-app notifications for moderation actions and warnings** (#30065, #30082, and #30081 by @ClearlyClaire)\
|
- **Add in-app notifications for moderation actions and warnings** (#30065, #30082, and #30081 by @ClearlyClaire)\
|
||||||
|
@ -541,7 +357,7 @@ The following changelog entries focus on changes visible to users, administrator
|
||||||
- Fix empty environment variables not using default nil value (#27400 by @renchap)
|
- Fix empty environment variables not using default nil value (#27400 by @renchap)
|
||||||
- Fix language sorting in settings (#27158 by @gunchleoc)
|
- Fix language sorting in settings (#27158 by @gunchleoc)
|
||||||
|
|
||||||
## [4.2.11] - 2024-08-16
|
## |4.2.11] - 2024-08-16
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
|
390
Dockerfile
390
Dockerfile
|
@ -1,7 +1,7 @@
|
||||||
# syntax=docker/dockerfile:1.12
|
# syntax=docker/dockerfile:1.9
|
||||||
|
|
||||||
# This file is designed for production server deployment, not local development work
|
# This file is designed for production server deployment, not local development work
|
||||||
# For a containerized local dev environment, see: https://github.com/mastodon/mastodon/blob/main/docs/DEVELOPMENT.md#docker
|
# For a containerized local dev environment, see: https://github.com/mastodon/mastodon/blob/main/README.md#docker
|
||||||
|
|
||||||
# Please see https://docs.docker.com/engine/reference/builder for information about
|
# Please see https://docs.docker.com/engine/reference/builder for information about
|
||||||
# the extended buildx capabilities used in this file.
|
# the extended buildx capabilities used in this file.
|
||||||
|
@ -9,20 +9,19 @@
|
||||||
# See: https://docs.docker.com/build/building/multi-platform/
|
# See: https://docs.docker.com/build/building/multi-platform/
|
||||||
ARG TARGETPLATFORM=${TARGETPLATFORM}
|
ARG TARGETPLATFORM=${TARGETPLATFORM}
|
||||||
ARG BUILDPLATFORM=${BUILDPLATFORM}
|
ARG BUILDPLATFORM=${BUILDPLATFORM}
|
||||||
ARG BASE_REGISTRY="docker.io"
|
|
||||||
|
|
||||||
# Ruby image to use for base image, change with [--build-arg RUBY_VERSION="3.4.x"]
|
# Ruby image to use for base image, change with [--build-arg RUBY_VERSION="3.3.x"]
|
||||||
# renovate: datasource=docker depName=docker.io/ruby
|
# renovate: datasource=docker depName=docker.io/ruby
|
||||||
ARG RUBY_VERSION="3.4.2"
|
ARG RUBY_VERSION="3.3.5"
|
||||||
# # Node.js version to use in base image, change with [--build-arg NODE_MAJOR_VERSION="20"]
|
# # Node version to use in base image, change with [--build-arg NODE_MAJOR_VERSION="20"]
|
||||||
# renovate: datasource=node-version depName=node
|
# renovate: datasource=node-version depName=node
|
||||||
ARG NODE_MAJOR_VERSION="22"
|
ARG NODE_MAJOR_VERSION="20"
|
||||||
# Debian image to use for base image, change with [--build-arg DEBIAN_VERSION="bookworm"]
|
# Debian image to use for base image, change with [--build-arg DEBIAN_VERSION="bookworm"]
|
||||||
ARG DEBIAN_VERSION="bookworm"
|
ARG DEBIAN_VERSION="bookworm"
|
||||||
# Node.js image to use for base image based on combined variables (ex: 20-bookworm-slim)
|
# Node image to use for base image based on combined variables (ex: 20-bookworm-slim)
|
||||||
FROM ${BASE_REGISTRY}/node:${NODE_MAJOR_VERSION}-${DEBIAN_VERSION}-slim AS node
|
FROM docker.io/node:${NODE_MAJOR_VERSION}-${DEBIAN_VERSION}-slim AS node
|
||||||
# Ruby image to use for base image based on combined variables (ex: 3.4.x-slim-bookworm)
|
# Ruby image to use for base image based on combined variables (ex: 3.3.x-slim-bookworm)
|
||||||
FROM ${BASE_REGISTRY}/ruby:${RUBY_VERSION}-slim-${DEBIAN_VERSION} AS ruby
|
FROM docker.io/ruby:${RUBY_VERSION}-slim-${DEBIAN_VERSION} AS ruby
|
||||||
|
|
||||||
# Resulting version string is vX.X.X-MASTODON_VERSION_PRERELEASE+MASTODON_VERSION_METADATA
|
# Resulting version string is vX.X.X-MASTODON_VERSION_PRERELEASE+MASTODON_VERSION_METADATA
|
||||||
# Example: v4.3.0-nightly.2023.11.09+pr-123456
|
# Example: v4.3.0-nightly.2023.11.09+pr-123456
|
||||||
|
@ -30,8 +29,6 @@ FROM ${BASE_REGISTRY}/ruby:${RUBY_VERSION}-slim-${DEBIAN_VERSION} AS ruby
|
||||||
ARG MASTODON_VERSION_PRERELEASE=""
|
ARG MASTODON_VERSION_PRERELEASE=""
|
||||||
# Append build metadata or fork information to version.rb [--build-arg MASTODON_VERSION_METADATA="pr-123456"]
|
# Append build metadata or fork information to version.rb [--build-arg MASTODON_VERSION_METADATA="pr-123456"]
|
||||||
ARG MASTODON_VERSION_METADATA=""
|
ARG MASTODON_VERSION_METADATA=""
|
||||||
# Will be available as Mastodon::Version.source_commit
|
|
||||||
ARG SOURCE_COMMIT=""
|
|
||||||
|
|
||||||
# Allow Ruby on Rails to serve static files
|
# Allow Ruby on Rails to serve static files
|
||||||
# See: https://docs.joinmastodon.org/admin/config/#rails_serve_static_files
|
# See: https://docs.joinmastodon.org/admin/config/#rails_serve_static_files
|
||||||
|
@ -48,31 +45,30 @@ ARG GID="991"
|
||||||
|
|
||||||
# Apply Mastodon build options based on options above
|
# Apply Mastodon build options based on options above
|
||||||
ENV \
|
ENV \
|
||||||
# Apply Mastodon version information
|
# Apply Mastodon version information
|
||||||
MASTODON_VERSION_PRERELEASE="${MASTODON_VERSION_PRERELEASE}" \
|
MASTODON_VERSION_PRERELEASE="${MASTODON_VERSION_PRERELEASE}" \
|
||||||
MASTODON_VERSION_METADATA="${MASTODON_VERSION_METADATA}" \
|
MASTODON_VERSION_METADATA="${MASTODON_VERSION_METADATA}" \
|
||||||
SOURCE_COMMIT="${SOURCE_COMMIT}" \
|
# Apply Mastodon static files and YJIT options
|
||||||
# Apply Mastodon static files and YJIT options
|
|
||||||
RAILS_SERVE_STATIC_FILES=${RAILS_SERVE_STATIC_FILES} \
|
RAILS_SERVE_STATIC_FILES=${RAILS_SERVE_STATIC_FILES} \
|
||||||
RUBY_YJIT_ENABLE=${RUBY_YJIT_ENABLE} \
|
RUBY_YJIT_ENABLE=${RUBY_YJIT_ENABLE} \
|
||||||
# Apply timezone
|
# Apply timezone
|
||||||
TZ=${TZ}
|
TZ=${TZ}
|
||||||
|
|
||||||
ENV \
|
ENV \
|
||||||
# Configure the IP to bind Mastodon to when serving traffic
|
# Configure the IP to bind Mastodon to when serving traffic
|
||||||
BIND="0.0.0.0" \
|
BIND="0.0.0.0" \
|
||||||
# Use production settings for Yarn, Node.js and related tools
|
# Use production settings for Yarn, Node and related nodejs based tools
|
||||||
NODE_ENV="production" \
|
NODE_ENV="production" \
|
||||||
# Use production settings for Ruby on Rails
|
# Use production settings for Ruby on Rails
|
||||||
RAILS_ENV="production" \
|
RAILS_ENV="production" \
|
||||||
# Add Ruby and Mastodon installation to the PATH
|
# Add Ruby and Mastodon installation to the PATH
|
||||||
DEBIAN_FRONTEND="noninteractive" \
|
DEBIAN_FRONTEND="noninteractive" \
|
||||||
PATH="${PATH}:/opt/ruby/bin:/opt/mastodon/bin" \
|
PATH="${PATH}:/opt/ruby/bin:/opt/mastodon/bin" \
|
||||||
# Optimize jemalloc 5.x performance
|
# Optimize jemalloc 5.x performance
|
||||||
MALLOC_CONF="narenas:2,background_thread:true,thp:never,dirty_decay_ms:1000,muzzy_decay_ms:0" \
|
MALLOC_CONF="narenas:2,background_thread:true,thp:never,dirty_decay_ms:1000,muzzy_decay_ms:0" \
|
||||||
# Enable libvips, should not be changed
|
# Enable libvips, should not be changed
|
||||||
MASTODON_USE_LIBVIPS=true \
|
MASTODON_USE_LIBVIPS=true \
|
||||||
# Sidekiq will touch tmp/sidekiq_process_has_started_and_will_begin_processing_jobs to indicate it is ready. This can be used for a readiness check in Kubernetes
|
# Sidekiq will touch tmp/sidekiq_process_has_started_and_will_begin_processing_jobs to indicate it is ready. This can be used for a readiness check in Kubernetes
|
||||||
MASTODON_SIDEKIQ_READY_FILENAME=sidekiq_process_has_started_and_will_begin_processing_jobs
|
MASTODON_SIDEKIQ_READY_FILENAME=sidekiq_process_has_started_and_will_begin_processing_jobs
|
||||||
|
|
||||||
# Set default shell used for running commands
|
# Set default shell used for running commands
|
||||||
|
@ -83,110 +79,119 @@ ARG TARGETPLATFORM
|
||||||
RUN echo "Target platform is $TARGETPLATFORM"
|
RUN echo "Target platform is $TARGETPLATFORM"
|
||||||
|
|
||||||
RUN \
|
RUN \
|
||||||
# Remove automatic apt cache Docker cleanup scripts
|
# Remove automatic apt cache Docker cleanup scripts
|
||||||
rm -f /etc/apt/apt.conf.d/docker-clean; \
|
rm -f /etc/apt/apt.conf.d/docker-clean; \
|
||||||
# Sets timezone
|
# Sets timezone
|
||||||
echo "${TZ}" > /etc/localtime; \
|
echo "${TZ}" > /etc/localtime; \
|
||||||
# Creates mastodon user/group and sets home directory
|
# Creates mastodon user/group and sets home directory
|
||||||
groupadd -g "${GID}" mastodon; \
|
groupadd -g "${GID}" mastodon; \
|
||||||
useradd -l -u "${UID}" -g "${GID}" -m -d /opt/mastodon mastodon; \
|
useradd -l -u "${UID}" -g "${GID}" -m -d /opt/mastodon mastodon; \
|
||||||
# Creates /mastodon symlink to /opt/mastodon
|
# Creates /mastodon symlink to /opt/mastodon
|
||||||
ln -s /opt/mastodon /mastodon;
|
ln -s /opt/mastodon /mastodon;
|
||||||
|
|
||||||
# Set /opt/mastodon as working directory
|
# Set /opt/mastodon as working directory
|
||||||
WORKDIR /opt/mastodon
|
WORKDIR /opt/mastodon
|
||||||
|
|
||||||
# Add backport repository for some specific packages where we need the latest version
|
|
||||||
RUN echo 'deb http://deb.debian.org/debian bookworm-backports main' >> /etc/apt/sources.list
|
|
||||||
|
|
||||||
# hadolint ignore=DL3008,DL3005
|
# hadolint ignore=DL3008,DL3005
|
||||||
RUN \
|
RUN \
|
||||||
# Mount Apt cache and lib directories from Docker buildx caches
|
# Mount Apt cache and lib directories from Docker buildx caches
|
||||||
--mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \
|
--mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \
|
||||||
--mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \
|
--mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \
|
||||||
# Apt update & upgrade to check for security updates to Debian image
|
# Apt update & upgrade to check for security updates to Debian image
|
||||||
apt-get update; \
|
apt-get update; \
|
||||||
apt-get dist-upgrade -yq; \
|
apt-get dist-upgrade -yq; \
|
||||||
# Install jemalloc, curl and other necessary components
|
# Install jemalloc, curl and other necessary components
|
||||||
apt-get install -y --no-install-recommends \
|
apt-get install -y --no-install-recommends \
|
||||||
curl \
|
curl \
|
||||||
file \
|
file \
|
||||||
libjemalloc2 \
|
libjemalloc2 \
|
||||||
patchelf \
|
patchelf \
|
||||||
procps \
|
procps \
|
||||||
tini \
|
tini \
|
||||||
tzdata \
|
tzdata \
|
||||||
wget \
|
wget \
|
||||||
; \
|
; \
|
||||||
# Patch Ruby to use jemalloc
|
# Patch Ruby to use jemalloc
|
||||||
patchelf --add-needed libjemalloc.so.2 /usr/local/bin/ruby; \
|
patchelf --add-needed libjemalloc.so.2 /usr/local/bin/ruby; \
|
||||||
# Discard patchelf after use
|
# Discard patchelf after use
|
||||||
apt-get purge -y \
|
apt-get purge -y \
|
||||||
patchelf \
|
patchelf \
|
||||||
;
|
;
|
||||||
|
|
||||||
# Create temporary build layer from base image
|
# Create temporary build layer from base image
|
||||||
FROM ruby AS build
|
FROM ruby AS build
|
||||||
|
|
||||||
|
# Copy Node package configuration files into working directory
|
||||||
|
COPY package.json yarn.lock .yarnrc.yml /opt/mastodon/
|
||||||
|
COPY .yarn /opt/mastodon/.yarn
|
||||||
|
|
||||||
|
COPY --from=node /usr/local/bin /usr/local/bin
|
||||||
|
COPY --from=node /usr/local/lib /usr/local/lib
|
||||||
|
|
||||||
ARG TARGETPLATFORM
|
ARG TARGETPLATFORM
|
||||||
|
|
||||||
# hadolint ignore=DL3008
|
# hadolint ignore=DL3008
|
||||||
RUN \
|
RUN \
|
||||||
# Mount Apt cache and lib directories from Docker buildx caches
|
# Mount Apt cache and lib directories from Docker buildx caches
|
||||||
--mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \
|
--mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \
|
||||||
--mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \
|
--mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \
|
||||||
# Install build tools and bundler dependencies from APT
|
# Install build tools and bundler dependencies from APT
|
||||||
apt-get install -y --no-install-recommends \
|
apt-get install -y --no-install-recommends \
|
||||||
autoconf \
|
autoconf \
|
||||||
automake \
|
automake \
|
||||||
build-essential \
|
build-essential \
|
||||||
cmake \
|
cmake \
|
||||||
git \
|
git \
|
||||||
libgdbm-dev \
|
libgdbm-dev \
|
||||||
libglib2.0-dev \
|
libglib2.0-dev \
|
||||||
libgmp-dev \
|
libgmp-dev \
|
||||||
libicu-dev \
|
libicu-dev \
|
||||||
libidn-dev \
|
libidn-dev \
|
||||||
libpq-dev \
|
libpq-dev \
|
||||||
libssl-dev \
|
libssl-dev \
|
||||||
libtool \
|
libtool \
|
||||||
libyaml-dev \
|
meson \
|
||||||
meson \
|
nasm \
|
||||||
nasm \
|
pkg-config \
|
||||||
pkg-config \
|
shared-mime-info \
|
||||||
shared-mime-info \
|
xz-utils \
|
||||||
xz-utils \
|
# libvips components
|
||||||
# libvips components
|
libcgif-dev \
|
||||||
libcgif-dev \
|
libexif-dev \
|
||||||
libexif-dev \
|
libexpat1-dev \
|
||||||
libexpat1-dev \
|
libgirepository1.0-dev \
|
||||||
libgirepository1.0-dev \
|
libheif-dev \
|
||||||
libheif-dev/bookworm-backports \
|
libimagequant-dev \
|
||||||
libimagequant-dev \
|
libjpeg62-turbo-dev \
|
||||||
libjpeg62-turbo-dev \
|
liblcms2-dev \
|
||||||
liblcms2-dev \
|
liborc-dev \
|
||||||
liborc-dev \
|
libspng-dev \
|
||||||
libspng-dev \
|
libtiff-dev \
|
||||||
libtiff-dev \
|
libwebp-dev \
|
||||||
libwebp-dev \
|
|
||||||
# ffmpeg components
|
# ffmpeg components
|
||||||
libdav1d-dev \
|
libdav1d-dev \
|
||||||
liblzma-dev \
|
liblzma-dev \
|
||||||
libmp3lame-dev \
|
libmp3lame-dev \
|
||||||
libopus-dev \
|
libopus-dev \
|
||||||
libsnappy-dev \
|
libsnappy-dev \
|
||||||
libvorbis-dev \
|
libvorbis-dev \
|
||||||
libvpx-dev \
|
libvpx-dev \
|
||||||
libx264-dev \
|
libx264-dev \
|
||||||
libx265-dev \
|
libx265-dev \
|
||||||
;
|
;
|
||||||
|
|
||||||
|
RUN \
|
||||||
|
# Configure Corepack
|
||||||
|
rm /usr/local/bin/yarn*; \
|
||||||
|
corepack enable; \
|
||||||
|
corepack prepare --activate;
|
||||||
|
|
||||||
# Create temporary libvips specific build layer from build layer
|
# Create temporary libvips specific build layer from build layer
|
||||||
FROM build AS libvips
|
FROM build AS libvips
|
||||||
|
|
||||||
# libvips version to compile, change with [--build-arg VIPS_VERSION="8.15.2"]
|
# libvips version to compile, change with [--build-arg VIPS_VERSION="8.15.2"]
|
||||||
# renovate: datasource=github-releases depName=libvips packageName=libvips/libvips
|
# renovate: datasource=github-releases depName=libvips packageName=libvips/libvips
|
||||||
ARG VIPS_VERSION=8.16.1
|
ARG VIPS_VERSION=8.15.3
|
||||||
# libvips download URL, change with [--build-arg VIPS_URL="https://github.com/libvips/libvips/releases/download"]
|
# 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
|
ARG VIPS_URL=https://github.com/libvips/libvips/releases/download
|
||||||
|
|
||||||
|
@ -209,7 +214,7 @@ FROM build AS ffmpeg
|
||||||
|
|
||||||
# ffmpeg version to compile, change with [--build-arg FFMPEG_VERSION="7.0.x"]
|
# ffmpeg version to compile, change with [--build-arg FFMPEG_VERSION="7.0.x"]
|
||||||
# renovate: datasource=repology depName=ffmpeg packageName=openpkg_current/ffmpeg
|
# renovate: datasource=repology depName=ffmpeg packageName=openpkg_current/ffmpeg
|
||||||
ARG FFMPEG_VERSION=7.1
|
ARG FFMPEG_VERSION=7.0.2
|
||||||
# ffmpeg download URL, change with [--build-arg FFMPEG_URL="https://ffmpeg.org/releases"]
|
# ffmpeg download URL, change with [--build-arg FFMPEG_URL="https://ffmpeg.org/releases"]
|
||||||
ARG FFMPEG_URL=https://ffmpeg.org/releases
|
ARG FFMPEG_URL=https://ffmpeg.org/releases
|
||||||
|
|
||||||
|
@ -223,28 +228,28 @@ WORKDIR /usr/local/ffmpeg/src/ffmpeg-${FFMPEG_VERSION}
|
||||||
# Configure and compile ffmpeg
|
# Configure and compile ffmpeg
|
||||||
RUN \
|
RUN \
|
||||||
./configure \
|
./configure \
|
||||||
--prefix=/usr/local/ffmpeg \
|
--prefix=/usr/local/ffmpeg \
|
||||||
--toolchain=hardened \
|
--toolchain=hardened \
|
||||||
--disable-debug \
|
--disable-debug \
|
||||||
--disable-devices \
|
--disable-devices \
|
||||||
--disable-doc \
|
--disable-doc \
|
||||||
--disable-ffplay \
|
--disable-ffplay \
|
||||||
--disable-network \
|
--disable-network \
|
||||||
--disable-static \
|
--disable-static \
|
||||||
--enable-ffmpeg \
|
--enable-ffmpeg \
|
||||||
--enable-ffprobe \
|
--enable-ffprobe \
|
||||||
--enable-gpl \
|
--enable-gpl \
|
||||||
--enable-libdav1d \
|
--enable-libdav1d \
|
||||||
--enable-libmp3lame \
|
--enable-libmp3lame \
|
||||||
--enable-libopus \
|
--enable-libopus \
|
||||||
--enable-libsnappy \
|
--enable-libsnappy \
|
||||||
--enable-libvorbis \
|
--enable-libvorbis \
|
||||||
--enable-libvpx \
|
--enable-libvpx \
|
||||||
--enable-libwebp \
|
--enable-libwebp \
|
||||||
--enable-libx264 \
|
--enable-libx264 \
|
||||||
--enable-libx265 \
|
--enable-libx265 \
|
||||||
--enable-shared \
|
--enable-shared \
|
||||||
--enable-version3 \
|
--enable-version3 \
|
||||||
; \
|
; \
|
||||||
make -j$(nproc); \
|
make -j$(nproc); \
|
||||||
make install;
|
make install;
|
||||||
|
@ -258,57 +263,58 @@ ARG TARGETPLATFORM
|
||||||
COPY Gemfile* /opt/mastodon/
|
COPY Gemfile* /opt/mastodon/
|
||||||
|
|
||||||
RUN \
|
RUN \
|
||||||
# Mount Ruby Gem caches
|
# Mount Ruby Gem caches
|
||||||
--mount=type=cache,id=gem-cache-${TARGETPLATFORM},target=/usr/local/bundle/cache/,sharing=locked \
|
--mount=type=cache,id=gem-cache-${TARGETPLATFORM},target=/usr/local/bundle/cache/,sharing=locked \
|
||||||
# Configure bundle to prevent changes to Gemfile and Gemfile.lock
|
# Configure bundle to prevent changes to Gemfile and Gemfile.lock
|
||||||
bundle config set --global frozen "true"; \
|
bundle config set --global frozen "true"; \
|
||||||
# Configure bundle to not cache downloaded Gems
|
# Configure bundle to not cache downloaded Gems
|
||||||
bundle config set --global cache_all "false"; \
|
bundle config set --global cache_all "false"; \
|
||||||
# Configure bundle to only process production Gems
|
# Configure bundle to only process production Gems
|
||||||
bundle config set --local without "development test"; \
|
bundle config set --local without "development test"; \
|
||||||
# Configure bundle to not warn about root user
|
# Configure bundle to not warn about root user
|
||||||
bundle config set silence_root_warning "true"; \
|
bundle config set silence_root_warning "true"; \
|
||||||
# Download and install required Gems
|
# Download and install required Gems
|
||||||
bundle install -j"$(nproc)";
|
bundle install -j"$(nproc)";
|
||||||
|
|
||||||
|
# Create temporary node specific build layer from build layer
|
||||||
|
FROM build AS yarn
|
||||||
|
|
||||||
|
ARG TARGETPLATFORM
|
||||||
|
|
||||||
|
# Copy Node package configuration files into working directory
|
||||||
|
COPY package.json yarn.lock .yarnrc.yml /opt/mastodon/
|
||||||
|
COPY streaming/package.json /opt/mastodon/streaming/
|
||||||
|
COPY .yarn /opt/mastodon/.yarn
|
||||||
|
|
||||||
|
# hadolint ignore=DL3008
|
||||||
|
RUN \
|
||||||
|
--mount=type=cache,id=corepack-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/corepack,sharing=locked \
|
||||||
|
--mount=type=cache,id=yarn-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/yarn,sharing=locked \
|
||||||
|
# Install Node packages
|
||||||
|
yarn workspaces focus --production @mastodon/mastodon;
|
||||||
|
|
||||||
# Create temporary assets build layer from build layer
|
# Create temporary assets build layer from build layer
|
||||||
FROM build AS precompiler
|
FROM build AS precompiler
|
||||||
|
|
||||||
ARG TARGETPLATFORM
|
# Copy Mastodon sources into precompiler layer
|
||||||
|
|
||||||
# Copy Mastodon sources into layer
|
|
||||||
COPY . /opt/mastodon/
|
COPY . /opt/mastodon/
|
||||||
|
|
||||||
# Copy Node.js binaries/libraries into layer
|
# Copy bundler and node packages from build layer to container
|
||||||
COPY --from=node /usr/local/bin /usr/local/bin
|
COPY --from=yarn /opt/mastodon /opt/mastodon/
|
||||||
COPY --from=node /usr/local/lib /usr/local/lib
|
|
||||||
|
|
||||||
RUN \
|
|
||||||
# Configure Corepack
|
|
||||||
rm /usr/local/bin/yarn*; \
|
|
||||||
corepack enable; \
|
|
||||||
corepack prepare --activate;
|
|
||||||
|
|
||||||
# hadolint ignore=DL3008
|
|
||||||
RUN \
|
|
||||||
--mount=type=cache,id=corepack-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/corepack,sharing=locked \
|
|
||||||
--mount=type=cache,id=yarn-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/yarn,sharing=locked \
|
|
||||||
# Install Node.js packages
|
|
||||||
yarn workspaces focus --production @mastodon/mastodon;
|
|
||||||
|
|
||||||
# Copy libvips components into layer for precompiler
|
|
||||||
COPY --from=libvips /usr/local/libvips/bin /usr/local/bin
|
|
||||||
COPY --from=libvips /usr/local/libvips/lib /usr/local/lib
|
|
||||||
# Copy bundler packages into layer for precompiler
|
|
||||||
COPY --from=bundler /opt/mastodon /opt/mastodon/
|
COPY --from=bundler /opt/mastodon /opt/mastodon/
|
||||||
COPY --from=bundler /usr/local/bundle/ /usr/local/bundle/
|
COPY --from=bundler /usr/local/bundle/ /usr/local/bundle/
|
||||||
|
# Copy libvips components to layer for precompiler
|
||||||
|
COPY --from=libvips /usr/local/libvips/bin /usr/local/bin
|
||||||
|
COPY --from=libvips /usr/local/libvips/lib /usr/local/lib
|
||||||
|
|
||||||
|
ARG TARGETPLATFORM
|
||||||
|
|
||||||
RUN \
|
RUN \
|
||||||
ldconfig; \
|
ldconfig; \
|
||||||
# Use Ruby on Rails to create Mastodon assets
|
# Use Ruby on Rails to create Mastodon assets
|
||||||
SECRET_KEY_BASE_DUMMY=1 \
|
SECRET_KEY_BASE_DUMMY=1 \
|
||||||
bundle exec rails assets:precompile; \
|
bundle exec rails assets:precompile; \
|
||||||
# Cleanup temporary files
|
# Cleanup temporary files
|
||||||
rm -fr /opt/mastodon/tmp;
|
rm -fr /opt/mastodon/tmp;
|
||||||
|
|
||||||
# Prep final Mastodon Ruby layer
|
# Prep final Mastodon Ruby layer
|
||||||
|
@ -318,49 +324,49 @@ ARG TARGETPLATFORM
|
||||||
|
|
||||||
# hadolint ignore=DL3008
|
# hadolint ignore=DL3008
|
||||||
RUN \
|
RUN \
|
||||||
# Mount Apt cache and lib directories from Docker buildx caches
|
# Mount Apt cache and lib directories from Docker buildx caches
|
||||||
--mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \
|
--mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \
|
||||||
--mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \
|
--mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \
|
||||||
# Mount Corepack and Yarn caches from Docker buildx caches
|
# Mount Corepack and Yarn caches from Docker buildx caches
|
||||||
--mount=type=cache,id=corepack-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/corepack,sharing=locked \
|
--mount=type=cache,id=corepack-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/corepack,sharing=locked \
|
||||||
--mount=type=cache,id=yarn-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/yarn,sharing=locked \
|
--mount=type=cache,id=yarn-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/yarn,sharing=locked \
|
||||||
# Apt update install non-dev versions of necessary components
|
# Apt update install non-dev versions of necessary components
|
||||||
apt-get install -y --no-install-recommends \
|
apt-get install -y --no-install-recommends \
|
||||||
libexpat1 \
|
libexpat1 \
|
||||||
libglib2.0-0 \
|
libglib2.0-0 \
|
||||||
libicu72 \
|
libicu72 \
|
||||||
libidn12 \
|
libidn12 \
|
||||||
libpq5 \
|
libpq5 \
|
||||||
libreadline8 \
|
libreadline8 \
|
||||||
libssl3 \
|
libssl3 \
|
||||||
libyaml-0-2 \
|
libyaml-0-2 \
|
||||||
# libvips components
|
# libvips components
|
||||||
libcgif0 \
|
libcgif0 \
|
||||||
libexif12 \
|
libexif12 \
|
||||||
libheif1/bookworm-backports \
|
libheif1 \
|
||||||
libimagequant0 \
|
libimagequant0 \
|
||||||
libjpeg62-turbo \
|
libjpeg62-turbo \
|
||||||
liblcms2-2 \
|
liblcms2-2 \
|
||||||
liborc-0.4-0 \
|
liborc-0.4-0 \
|
||||||
libspng0 \
|
libspng0 \
|
||||||
libtiff6 \
|
libtiff6 \
|
||||||
libwebp7 \
|
libwebp7 \
|
||||||
libwebpdemux2 \
|
libwebpdemux2 \
|
||||||
libwebpmux3 \
|
libwebpmux3 \
|
||||||
# ffmpeg components
|
# ffmpeg components
|
||||||
libdav1d6 \
|
libdav1d6 \
|
||||||
libmp3lame0 \
|
libmp3lame0 \
|
||||||
libopencore-amrnb0 \
|
libopencore-amrnb0 \
|
||||||
libopencore-amrwb0 \
|
libopencore-amrwb0 \
|
||||||
libopus0 \
|
libopus0 \
|
||||||
libsnappy1v5 \
|
libsnappy1v5 \
|
||||||
libtheora0 \
|
libtheora0 \
|
||||||
libvorbis0a \
|
libvorbis0a \
|
||||||
libvorbisenc2 \
|
libvorbisenc2 \
|
||||||
libvorbisfile3 \
|
libvorbisfile3 \
|
||||||
libvpx7 \
|
libvpx7 \
|
||||||
libx264-164 \
|
libx264-164 \
|
||||||
libx265-199 \
|
libx265-199 \
|
||||||
;
|
;
|
||||||
|
|
||||||
# Copy Mastodon sources into final layer
|
# Copy Mastodon sources into final layer
|
||||||
|
@ -380,7 +386,7 @@ COPY --from=ffmpeg /usr/local/ffmpeg/lib /usr/local/lib
|
||||||
|
|
||||||
RUN \
|
RUN \
|
||||||
ldconfig; \
|
ldconfig; \
|
||||||
# Smoketest media processors
|
# Smoketest media processors
|
||||||
vips -v; \
|
vips -v; \
|
||||||
ffmpeg -version; \
|
ffmpeg -version; \
|
||||||
ffprobe -version;
|
ffprobe -version;
|
||||||
|
@ -390,10 +396,10 @@ RUN \
|
||||||
bundle exec bootsnap precompile --gemfile app/ lib/;
|
bundle exec bootsnap precompile --gemfile app/ lib/;
|
||||||
|
|
||||||
RUN \
|
RUN \
|
||||||
# Pre-create and chown system volume to Mastodon user
|
# Pre-create and chown system volume to Mastodon user
|
||||||
mkdir -p /opt/mastodon/public/system; \
|
mkdir -p /opt/mastodon/public/system; \
|
||||||
chown mastodon:mastodon /opt/mastodon/public/system; \
|
chown mastodon:mastodon /opt/mastodon/public/system; \
|
||||||
# Set Mastodon user as owner of tmp folder
|
# Set Mastodon user as owner of tmp folder
|
||||||
chown -R mastodon:mastodon /opt/mastodon/tmp;
|
chown -R mastodon:mastodon /opt/mastodon/tmp;
|
||||||
|
|
||||||
# Set the running user for resulting container
|
# Set the running user for resulting container
|
||||||
|
|
76
Gemfile
76
Gemfile
|
@ -1,12 +1,12 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
source 'https://rubygems.org'
|
source 'https://rubygems.org'
|
||||||
ruby '>= 3.2.0', '< 3.5.0'
|
ruby '>= 3.1.0'
|
||||||
|
|
||||||
gem 'propshaft'
|
gem 'propshaft'
|
||||||
gem 'puma', '~> 6.3'
|
gem 'puma', '~> 6.3'
|
||||||
gem 'rack', '~> 2.2.7'
|
gem 'rack', '~> 2.2.7'
|
||||||
gem 'rails', '~> 8.0'
|
gem 'rails', '~> 7.1.1'
|
||||||
gem 'thor', '~> 1.2'
|
gem 'thor', '~> 1.2'
|
||||||
|
|
||||||
gem 'dotenv'
|
gem 'dotenv'
|
||||||
|
@ -14,19 +14,18 @@ gem 'haml-rails', '~>2.0'
|
||||||
gem 'pg', '~> 1.5'
|
gem 'pg', '~> 1.5'
|
||||||
gem 'pghero'
|
gem 'pghero'
|
||||||
|
|
||||||
gem 'aws-sdk-core', '< 3.216.0', require: false # TODO: https://github.com/mastodon/mastodon/pull/34173#issuecomment-2733378873
|
|
||||||
gem 'aws-sdk-s3', '~> 1.123', require: false
|
gem 'aws-sdk-s3', '~> 1.123', require: false
|
||||||
gem 'blurhash', '~> 0.1'
|
gem 'blurhash', '~> 0.1'
|
||||||
gem 'fog-core', '<= 2.6.0'
|
gem 'fog-core', '<= 2.5.0'
|
||||||
gem 'fog-openstack', '~> 1.0', require: false
|
gem 'fog-openstack', '~> 1.0', require: false
|
||||||
gem 'jd-paperclip-azure', '~> 3.0', require: false
|
|
||||||
gem 'kt-paperclip', '~> 7.2'
|
gem 'kt-paperclip', '~> 7.2'
|
||||||
|
gem 'md-paperclip-azure', '~> 2.2', require: false
|
||||||
gem 'ruby-vips', '~> 2.2', require: false
|
gem 'ruby-vips', '~> 2.2', require: false
|
||||||
|
|
||||||
gem 'active_model_serializers', '~> 0.10'
|
gem 'active_model_serializers', '~> 0.10'
|
||||||
gem 'addressable', '~> 2.8'
|
gem 'addressable', '~> 2.8'
|
||||||
gem 'bootsnap', '~> 1.18.0', require: false
|
gem 'bootsnap', '~> 1.18.0', require: false
|
||||||
gem 'browser'
|
gem 'browser', '< 6' # https://github.com/fnando/browser/issues/543
|
||||||
gem 'charlock_holmes', '~> 0.7.7'
|
gem 'charlock_holmes', '~> 0.7.7'
|
||||||
gem 'chewy', '~> 7.3'
|
gem 'chewy', '~> 7.3'
|
||||||
gem 'devise', '~> 4.9'
|
gem 'devise', '~> 4.9'
|
||||||
|
@ -40,7 +39,7 @@ gem 'net-ldap', '~> 0.18'
|
||||||
|
|
||||||
gem 'omniauth', '~> 2.0'
|
gem 'omniauth', '~> 2.0'
|
||||||
gem 'omniauth-cas', '~> 3.0.0.beta.1'
|
gem 'omniauth-cas', '~> 3.0.0.beta.1'
|
||||||
gem 'omniauth_openid_connect', '~> 0.8.0'
|
gem 'omniauth_openid_connect', '~> 0.6.1'
|
||||||
gem 'omniauth-rails_csrf_protection', '~> 1.0'
|
gem 'omniauth-rails_csrf_protection', '~> 1.0'
|
||||||
gem 'omniauth-saml', '~> 2.0'
|
gem 'omniauth-saml', '~> 2.0'
|
||||||
|
|
||||||
|
@ -48,24 +47,21 @@ gem 'color_diff', '~> 0.1'
|
||||||
gem 'csv', '~> 3.2'
|
gem 'csv', '~> 3.2'
|
||||||
gem 'discard', '~> 1.2'
|
gem 'discard', '~> 1.2'
|
||||||
gem 'doorkeeper', '~> 5.6'
|
gem 'doorkeeper', '~> 5.6'
|
||||||
gem 'faraday-httpclient'
|
|
||||||
gem 'fast_blank', '~> 1.0'
|
gem 'fast_blank', '~> 1.0'
|
||||||
gem 'fastimage'
|
gem 'fastimage'
|
||||||
gem 'hiredis', '~> 0.6'
|
gem 'hiredis', '~> 0.6'
|
||||||
gem 'htmlentities', '~> 4.3'
|
gem 'htmlentities', '~> 4.3'
|
||||||
gem 'http', '~> 5.2.0'
|
gem 'http', '~> 5.2.0'
|
||||||
gem 'http_accept_language', '~> 2.1'
|
gem 'http_accept_language', '~> 2.1'
|
||||||
gem 'httplog', '~> 1.7.0', require: false
|
gem 'httplog', '~> 1.7.0'
|
||||||
gem 'i18n'
|
gem 'i18n'
|
||||||
gem 'idn-ruby', require: 'idn'
|
gem 'idn-ruby', require: 'idn'
|
||||||
gem 'inline_svg'
|
gem 'inline_svg'
|
||||||
gem 'irb', '~> 1.8'
|
gem 'irb', '~> 1.8'
|
||||||
gem 'kaminari', '~> 1.2'
|
gem 'kaminari', '~> 1.2'
|
||||||
gem 'link_header', '~> 0.0'
|
gem 'link_header', '~> 0.0'
|
||||||
gem 'linzer', '~> 0.6.1'
|
|
||||||
gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock'
|
gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock'
|
||||||
gem 'mime-types', '~> 3.6.0', require: 'mime/types/columnar'
|
gem 'mime-types', '~> 3.5.0', require: 'mime/types/columnar'
|
||||||
gem 'mutex_m'
|
|
||||||
gem 'nokogiri', '~> 1.15'
|
gem 'nokogiri', '~> 1.15'
|
||||||
gem 'oj', '~> 3.14'
|
gem 'oj', '~> 3.14'
|
||||||
gem 'ox', '~> 2.14'
|
gem 'ox', '~> 2.14'
|
||||||
|
@ -75,13 +71,13 @@ gem 'public_suffix', '~> 6.0'
|
||||||
gem 'pundit', '~> 2.3'
|
gem 'pundit', '~> 2.3'
|
||||||
gem 'rack-attack', '~> 6.6'
|
gem 'rack-attack', '~> 6.6'
|
||||||
gem 'rack-cors', '~> 2.0', require: 'rack/cors'
|
gem 'rack-cors', '~> 2.0', require: 'rack/cors'
|
||||||
gem 'rails-i18n', '~> 8.0'
|
gem 'rails-i18n', '~> 7.0'
|
||||||
gem 'redcarpet', '~> 3.6'
|
gem 'redcarpet', '~> 3.6'
|
||||||
gem 'redis', '~> 4.5', require: ['redis', 'redis/connection/hiredis']
|
gem 'redis', '~> 4.5', require: ['redis', 'redis/connection/hiredis']
|
||||||
gem 'redis-namespace', '~> 1.10'
|
gem 'redis-namespace', '~> 1.10'
|
||||||
gem 'rqrcode', '~> 2.2'
|
gem 'rqrcode', '~> 2.2'
|
||||||
gem 'ruby-progressbar', '~> 1.13'
|
gem 'ruby-progressbar', '~> 1.13'
|
||||||
gem 'sanitize', '~> 7.0'
|
gem 'sanitize', '~> 6.0'
|
||||||
gem 'scenic', '~> 1.7'
|
gem 'scenic', '~> 1.7'
|
||||||
gem 'sidekiq', '~> 6.5'
|
gem 'sidekiq', '~> 6.5'
|
||||||
gem 'sidekiq-bulk', '~> 0.2.0'
|
gem 'sidekiq-bulk', '~> 0.2.0'
|
||||||
|
@ -96,31 +92,29 @@ gem 'twitter-text', '~> 3.1.0'
|
||||||
gem 'tzinfo-data', '~> 1.2023'
|
gem 'tzinfo-data', '~> 1.2023'
|
||||||
gem 'webauthn', '~> 3.0'
|
gem 'webauthn', '~> 3.0'
|
||||||
gem 'webpacker', '~> 5.4'
|
gem 'webpacker', '~> 5.4'
|
||||||
gem 'webpush', github: 'mastodon/webpush', ref: '9631ac63045cfabddacc69fc06e919b4c13eb913'
|
gem 'webpush', github: 'ClearlyClaire/webpush', ref: 'f14a4d52e201128b1b00245d11b6de80d6cfdcd9'
|
||||||
|
|
||||||
gem 'json-ld'
|
gem 'json-ld'
|
||||||
gem 'json-ld-preloaded', '~> 3.2'
|
gem 'json-ld-preloaded', '~> 3.2'
|
||||||
gem 'rdf-normalize', '~> 0.5'
|
gem 'rdf-normalize', '~> 0.5'
|
||||||
|
|
||||||
gem 'prometheus_exporter', '~> 2.2', require: false
|
gem 'opentelemetry-api', '~> 1.4.0'
|
||||||
|
|
||||||
gem 'opentelemetry-api', '~> 1.5.0'
|
|
||||||
|
|
||||||
group :opentelemetry do
|
group :opentelemetry do
|
||||||
gem 'opentelemetry-exporter-otlp', '~> 0.30.0', require: false
|
gem 'opentelemetry-exporter-otlp', '~> 0.29.0', require: false
|
||||||
gem 'opentelemetry-instrumentation-active_job', '~> 0.8.0', require: false
|
gem 'opentelemetry-instrumentation-active_job', '~> 0.7.1', require: false
|
||||||
gem 'opentelemetry-instrumentation-active_model_serializers', '~> 0.22.0', require: false
|
gem 'opentelemetry-instrumentation-active_model_serializers', '~> 0.20.1', require: false
|
||||||
gem 'opentelemetry-instrumentation-concurrent_ruby', '~> 0.22.0', require: false
|
gem 'opentelemetry-instrumentation-concurrent_ruby', '~> 0.21.2', require: false
|
||||||
gem 'opentelemetry-instrumentation-excon', '~> 0.23.0', require: false
|
gem 'opentelemetry-instrumentation-excon', '~> 0.22.0', require: false
|
||||||
gem 'opentelemetry-instrumentation-faraday', '~> 0.26.0', require: false
|
gem 'opentelemetry-instrumentation-faraday', '~> 0.24.1', require: false
|
||||||
gem 'opentelemetry-instrumentation-http', '~> 0.24.0', require: false
|
gem 'opentelemetry-instrumentation-http', '~> 0.23.2', require: false
|
||||||
gem 'opentelemetry-instrumentation-http_client', '~> 0.23.0', require: false
|
gem 'opentelemetry-instrumentation-http_client', '~> 0.22.3', require: false
|
||||||
gem 'opentelemetry-instrumentation-net_http', '~> 0.23.0', require: false
|
gem 'opentelemetry-instrumentation-net_http', '~> 0.22.4', require: false
|
||||||
gem 'opentelemetry-instrumentation-pg', '~> 0.30.0', require: false
|
gem 'opentelemetry-instrumentation-pg', '~> 0.29.0', require: false
|
||||||
gem 'opentelemetry-instrumentation-rack', '~> 0.26.0', require: false
|
gem 'opentelemetry-instrumentation-rack', '~> 0.24.1', require: false
|
||||||
gem 'opentelemetry-instrumentation-rails', '~> 0.36.0', require: false
|
gem 'opentelemetry-instrumentation-rails', '~> 0.31.0', require: false
|
||||||
gem 'opentelemetry-instrumentation-redis', '~> 0.26.0', require: false
|
gem 'opentelemetry-instrumentation-redis', '~> 0.25.3', require: false
|
||||||
gem 'opentelemetry-instrumentation-sidekiq', '~> 0.26.0', require: false
|
gem 'opentelemetry-instrumentation-sidekiq', '~> 0.25.2', require: false
|
||||||
gem 'opentelemetry-sdk', '~> 1.4', require: false
|
gem 'opentelemetry-sdk', '~> 1.4', require: false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -129,7 +123,7 @@ group :test do
|
||||||
gem 'flatware-rspec'
|
gem 'flatware-rspec'
|
||||||
|
|
||||||
# Adds RSpec Error/Warning annotations to GitHub PRs on the Files tab
|
# Adds RSpec Error/Warning annotations to GitHub PRs on the Files tab
|
||||||
gem 'rspec-github', '~> 3.0', require: false
|
gem 'rspec-github', '~> 2.4', require: false
|
||||||
|
|
||||||
# RSpec helpers for email specs
|
# RSpec helpers for email specs
|
||||||
gem 'email_spec'
|
gem 'email_spec'
|
||||||
|
@ -147,6 +141,9 @@ group :test do
|
||||||
# Used to mock environment variables
|
# Used to mock environment variables
|
||||||
gem 'climate_control'
|
gem 'climate_control'
|
||||||
|
|
||||||
|
# Add back helpers functions removed in Rails 5.1
|
||||||
|
gem 'rails-controller-testing', '~> 1.0'
|
||||||
|
|
||||||
# Validate schemas in specs
|
# Validate schemas in specs
|
||||||
gem 'json-schema', '~> 5.0'
|
gem 'json-schema', '~> 5.0'
|
||||||
|
|
||||||
|
@ -155,7 +152,7 @@ group :test do
|
||||||
|
|
||||||
gem 'shoulda-matchers'
|
gem 'shoulda-matchers'
|
||||||
|
|
||||||
# Coverage formatter for RSpec
|
# Coverage formatter for RSpec test if DISABLE_SIMPLECOV is false
|
||||||
gem 'simplecov', '~> 0.22', require: false
|
gem 'simplecov', '~> 0.22', require: false
|
||||||
gem 'simplecov-lcov', '~> 0.8', require: false
|
gem 'simplecov-lcov', '~> 0.8', require: false
|
||||||
|
|
||||||
|
@ -167,14 +164,13 @@ group :development do
|
||||||
# Code linting CLI and plugins
|
# Code linting CLI and plugins
|
||||||
gem 'rubocop', require: false
|
gem 'rubocop', require: false
|
||||||
gem 'rubocop-capybara', require: false
|
gem 'rubocop-capybara', require: false
|
||||||
gem 'rubocop-i18n', require: false
|
|
||||||
gem 'rubocop-performance', require: false
|
gem 'rubocop-performance', require: false
|
||||||
gem 'rubocop-rails', require: false
|
gem 'rubocop-rails', require: false
|
||||||
gem 'rubocop-rspec', require: false
|
gem 'rubocop-rspec', require: false
|
||||||
gem 'rubocop-rspec_rails', require: false
|
gem 'rubocop-rspec_rails', require: false
|
||||||
|
|
||||||
# Annotates modules with schema
|
# Annotates modules with schema
|
||||||
gem 'annotaterb', '~> 4.13', require: false
|
gem 'annotate', '~> 3.2'
|
||||||
|
|
||||||
# Enhanced error message pages for development
|
# Enhanced error message pages for development
|
||||||
gem 'better_errors', '~> 2.9'
|
gem 'better_errors', '~> 2.9'
|
||||||
|
@ -185,7 +181,7 @@ group :development do
|
||||||
gem 'letter_opener_web', '~> 3.0'
|
gem 'letter_opener_web', '~> 3.0'
|
||||||
|
|
||||||
# Security analysis CLI tools
|
# Security analysis CLI tools
|
||||||
gem 'brakeman', '~> 7.0', require: false
|
gem 'brakeman', '~> 6.0', require: false
|
||||||
gem 'bundler-audit', '~> 0.9', require: false
|
gem 'bundler-audit', '~> 0.9', require: false
|
||||||
|
|
||||||
# Linter CLI for HAML files
|
# Linter CLI for HAML files
|
||||||
|
@ -197,7 +193,7 @@ end
|
||||||
|
|
||||||
group :development, :test do
|
group :development, :test do
|
||||||
# Interactive Debugging tools
|
# Interactive Debugging tools
|
||||||
gem 'debug', '~> 1.8', require: false
|
gem 'debug', '~> 1.8'
|
||||||
|
|
||||||
# Generate fake data values
|
# Generate fake data values
|
||||||
gem 'faker', '~> 3.2'
|
gem 'faker', '~> 3.2'
|
||||||
|
@ -209,7 +205,7 @@ group :development, :test do
|
||||||
gem 'memory_profiler', require: false
|
gem 'memory_profiler', require: false
|
||||||
gem 'ruby-prof', require: false
|
gem 'ruby-prof', require: false
|
||||||
gem 'stackprof', require: false
|
gem 'stackprof', require: false
|
||||||
gem 'test-prof', require: false
|
gem 'test-prof'
|
||||||
|
|
||||||
# RSpec runner for rails
|
# RSpec runner for rails
|
||||||
gem 'rspec-rails', '~> 7.0'
|
gem 'rspec-rails', '~> 7.0'
|
||||||
|
@ -224,7 +220,7 @@ gem 'concurrent-ruby', require: false
|
||||||
gem 'connection_pool', require: false
|
gem 'connection_pool', require: false
|
||||||
gem 'xorcist', '~> 1.1'
|
gem 'xorcist', '~> 1.1'
|
||||||
|
|
||||||
gem 'net-http', '~> 0.6.0'
|
gem 'net-http', '~> 0.4.0'
|
||||||
gem 'rubyzip', '~> 2.3'
|
gem 'rubyzip', '~> 2.3'
|
||||||
|
|
||||||
gem 'hcaptcha', '~> 7.1'
|
gem 'hcaptcha', '~> 7.1'
|
||||||
|
|
789
Gemfile.lock
789
Gemfile.lock
File diff suppressed because it is too large
Load diff
124
README.md
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フォークの利用者にとって公共性の高いコンテンツであると思われます。これは、日本と欧米では一般的に考えられている児童ポルノの基準が異なり、欧米のサーバーの中にはこのアカウントをフォローしづらいものもあるという懸念を考慮したものです。
|
||||||
|
|
2
Rakefile
2
Rakefile
|
@ -3,6 +3,6 @@
|
||||||
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
||||||
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
||||||
|
|
||||||
require_relative 'config/application'
|
require File.expand_path('config/application', __dir__)
|
||||||
|
|
||||||
Rails.application.load_tasks
|
Rails.application.load_tasks
|
||||||
|
|
2
Vagrantfile
vendored
2
Vagrantfile
vendored
|
@ -174,7 +174,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
||||||
if config.vm.networks.any? { |type, options| type == :private_network }
|
if config.vm.networks.any? { |type, options| type == :private_network }
|
||||||
config.vm.synced_folder ".", "/vagrant", type: "nfs", mount_options: ['rw', 'actimeo=1']
|
config.vm.synced_folder ".", "/vagrant", type: "nfs", mount_options: ['rw', 'actimeo=1']
|
||||||
else
|
else
|
||||||
config.vm.synced_folder ".", "/vagrant", type: "rsync", create: true, rsync__args: ["--verbose", "--archive", "--delete", "-z"]
|
config.vm.synced_folder ".", "/vagrant"
|
||||||
end
|
end
|
||||||
|
|
||||||
# Otherwise, you can access the site at http://localhost:3000 and http://localhost:4000 , http://localhost:8080
|
# Otherwise, you can access the site at http://localhost:3000 and http://localhost:4000 , http://localhost:8080
|
||||||
|
|
|
@ -49,7 +49,7 @@ class ActivityPub::CollectionsController < ActivityPub::BaseController
|
||||||
|
|
||||||
def collection_presenter
|
def collection_presenter
|
||||||
ActivityPub::CollectionPresenter.new(
|
ActivityPub::CollectionPresenter.new(
|
||||||
id: ActivityPub::TagManager.instance.collection_uri_for(@account, params[:id]),
|
id: account_collection_url(@account, params[:id]),
|
||||||
type: @type,
|
type: @type,
|
||||||
size: @size,
|
size: @size,
|
||||||
items: @items
|
items: @items
|
||||||
|
|
|
@ -41,8 +41,12 @@ class ActivityPub::OutboxesController < ActivityPub::BaseController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def outbox_url(...)
|
def outbox_url(**kwargs)
|
||||||
ActivityPub::TagManager.instance.outbox_uri_for(@account, ...)
|
if params[:account_username].present?
|
||||||
|
account_outbox_url(@account, **kwargs)
|
||||||
|
else
|
||||||
|
instance_actor_outbox_url(**kwargs)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def next_page
|
def next_page
|
||||||
|
|
|
@ -34,8 +34,7 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def resource_params
|
def resource_params
|
||||||
params
|
params.require(:admin_account_action).permit(:type, :report_id, :warning_preset_id, :text, :send_email_notification, :include_statuses)
|
||||||
.expect(admin_account_action: [:type, :report_id, :warning_preset_id, :text, :send_email_notification, :include_statuses])
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -29,8 +29,10 @@ module Admin
|
||||||
private
|
private
|
||||||
|
|
||||||
def resource_params
|
def resource_params
|
||||||
params
|
params.require(:account_moderation_note).permit(
|
||||||
.expect(account_moderation_note: [:content, :target_account_id])
|
:content,
|
||||||
|
:target_account_id
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_account_moderation_note
|
def set_account_moderation_note
|
||||||
|
|
|
@ -172,8 +172,7 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def form_account_batch_params
|
def form_account_batch_params
|
||||||
params
|
params.require(:form_account_batch).permit(:action, account_ids: [])
|
||||||
.expect(form_account_batch: [:action, account_ids: []])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def action_from_button
|
def action_from_button
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Admin::Announcements::DistributionsController < Admin::BaseController
|
|
||||||
before_action :set_announcement
|
|
||||||
|
|
||||||
def create
|
|
||||||
authorize @announcement, :distribute?
|
|
||||||
@announcement.touch(:notification_sent_at)
|
|
||||||
Admin::DistributeAnnouncementNotificationWorker.perform_async(@announcement.id)
|
|
||||||
redirect_to admin_announcements_path
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def set_announcement
|
|
||||||
@announcement = Announcement.find(params[:announcement_id])
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,16 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Admin::Announcements::PreviewsController < Admin::BaseController
|
|
||||||
before_action :set_announcement
|
|
||||||
|
|
||||||
def show
|
|
||||||
authorize @announcement, :distribute?
|
|
||||||
@user_count = @announcement.scope_for_notification.count
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def set_announcement
|
|
||||||
@announcement = Announcement.find(params[:announcement_id])
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,17 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Admin::Announcements::TestsController < Admin::BaseController
|
|
||||||
before_action :set_announcement
|
|
||||||
|
|
||||||
def create
|
|
||||||
authorize @announcement, :distribute?
|
|
||||||
UserMailer.announcement_published(current_user, @announcement).deliver_later!
|
|
||||||
redirect_to admin_announcements_path
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def set_announcement
|
|
||||||
@announcement = Announcement.find(params[:announcement_id])
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -6,7 +6,6 @@ class Admin::AnnouncementsController < Admin::BaseController
|
||||||
|
|
||||||
def index
|
def index
|
||||||
authorize :announcement, :index?
|
authorize :announcement, :index?
|
||||||
@published_announcements_count = Announcement.published.async_count
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def new
|
def new
|
||||||
|
@ -84,7 +83,6 @@ class Admin::AnnouncementsController < Admin::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def resource_params
|
def resource_params
|
||||||
params
|
params.require(:announcement).permit(:text, :scheduled_at, :starts_at, :ends_at, :all_day)
|
||||||
.expect(announcement: [:text, :scheduled_at, :starts_at, :ends_at, :all_day])
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,14 +7,14 @@ module Admin
|
||||||
|
|
||||||
layout 'admin'
|
layout 'admin'
|
||||||
|
|
||||||
before_action :set_referrer_policy_header
|
before_action :set_cache_headers
|
||||||
|
|
||||||
after_action :verify_authorized
|
after_action :verify_authorized
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_referrer_policy_header
|
def set_cache_headers
|
||||||
response.headers['Referrer-Policy'] = 'same-origin'
|
response.cache_control.replace(private: true, no_store: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_user
|
def set_user
|
||||||
|
|
|
@ -41,8 +41,9 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def resource_params
|
def resource_params
|
||||||
params
|
params.require(:user).permit(
|
||||||
.expect(user: [:unconfirmed_email])
|
:unconfirmed_email
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -67,13 +67,11 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def resource_params
|
def resource_params
|
||||||
params
|
params.require(:custom_emoji).permit(:shortcode, :image, :category_id, :visible_in_picker, :aliases_raw, :license)
|
||||||
.expect(custom_emoji: [:shortcode, :image, :category_id, :visible_in_picker, :aliases_raw, :license])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_params
|
def update_params
|
||||||
params
|
params.require(:custom_emoji).permit(:category_id, :visible_in_picker, :aliases_raw, :license)
|
||||||
.expect(custom_emoji: [:category_id, :visible_in_picker, :aliases_raw, :license])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def filtered_custom_emojis
|
def filtered_custom_emojis
|
||||||
|
@ -103,8 +101,7 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def form_custom_emoji_batch_params
|
def form_custom_emoji_batch_params
|
||||||
params
|
params.require(:form_custom_emoji_batch).permit(:action, :category_id, :category_name, custom_emoji_ids: [])
|
||||||
.expect(form_custom_emoji_batch: [:action, :category_id, :category_name, custom_emoji_ids: []])
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,7 +6,6 @@ class Admin::Disputes::AppealsController < Admin::BaseController
|
||||||
def index
|
def index
|
||||||
authorize :appeal, :index?
|
authorize :appeal, :index?
|
||||||
|
|
||||||
@pending_appeals_count = Appeal.pending.async_count
|
|
||||||
@appeals = filtered_appeals.page(params[:page])
|
@appeals = filtered_appeals.page(params[:page])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,6 @@ class Admin::DomainAllowsController < Admin::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def resource_params
|
def resource_params
|
||||||
params
|
params.require(:domain_allow).permit(:domain)
|
||||||
.expect(domain_allow: [:domain])
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -35,9 +35,7 @@ module Admin
|
||||||
rescue Mastodon::NotPermittedError
|
rescue Mastodon::NotPermittedError
|
||||||
flash[:alert] = I18n.t('admin.domain_blocks.not_permitted')
|
flash[:alert] = I18n.t('admin.domain_blocks.not_permitted')
|
||||||
else
|
else
|
||||||
flash[:notice] = I18n.t('admin.domain_blocks.created_msg')
|
redirect_to admin_instances_path(limited: '1'), notice: I18n.t('admin.domain_blocks.created_msg')
|
||||||
ensure
|
|
||||||
redirect_to admin_instances_path(limited: '1')
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def new
|
def new
|
||||||
|
@ -126,14 +124,9 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def form_domain_block_batch_params
|
def form_domain_block_batch_params
|
||||||
params
|
params.require(:form_domain_block_batch).permit(domain_blocks_attributes: [:enabled, :domain, :severity, :reject_media, :reject_favourite, :reject_reply_exclude_followers,
|
||||||
.expect(
|
:reject_send_sensitive, :reject_hashtag, :reject_straight_follow, :reject_new_follow, :reject_friend, :block_trends, :detect_invalid_subscription,
|
||||||
form_domain_block_batch: [
|
:reject_reports, :private_comment, :public_comment, :obfuscate, :hidden])
|
||||||
domain_blocks_attributes: [[:enabled, :domain, :severity, :reject_media, :reject_reports, :private_comment, :public_comment, :obfuscate,
|
|
||||||
:reject_favourite, :reject_reply_exclude_followers, :reject_send_sensitive, :reject_hashtag,
|
|
||||||
:reject_straight_follow, :reject_new_follow, :reject_friend, :block_trends, :detect_invalid_subscription, :hidden]],
|
|
||||||
]
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def action_from_button
|
def action_from_button
|
||||||
|
|
|
@ -5,7 +5,7 @@ module Admin
|
||||||
def index
|
def index
|
||||||
authorize :email_domain_block, :index?
|
authorize :email_domain_block, :index?
|
||||||
|
|
||||||
@email_domain_blocks = EmailDomainBlock.parents.includes(:children).order(id: :desc).page(params[:page])
|
@email_domain_blocks = EmailDomainBlock.where(parent_id: nil).includes(:children).order(id: :desc).page(params[:page])
|
||||||
@form = Form::EmailDomainBlockBatch.new
|
@form = Form::EmailDomainBlockBatch.new
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -58,17 +58,18 @@ module Admin
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_resolved_records
|
def set_resolved_records
|
||||||
@resolved_records = DomainResource.new(@email_domain_block.domain).mx
|
Resolv::DNS.open do |dns|
|
||||||
|
dns.timeouts = 5
|
||||||
|
@resolved_records = dns.getresources(@email_domain_block.domain, Resolv::DNS::Resource::IN::MX).to_a
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def resource_params
|
def resource_params
|
||||||
params
|
params.require(:email_domain_block).permit(:domain, :allow_with_approval, other_domains: [])
|
||||||
.expect(email_domain_block: [:domain, :allow_with_approval, other_domains: []])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def form_email_domain_block_batch_params
|
def form_email_domain_block_batch_params
|
||||||
params
|
params.require(:form_email_domain_block_batch).permit(email_domain_block_ids: [])
|
||||||
.expect(form_email_domain_block_batch: [email_domain_block_ids: []])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def action_from_button
|
def action_from_button
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Admin::Fasp::Debug::CallbacksController < Admin::BaseController
|
|
||||||
def index
|
|
||||||
authorize [:admin, :fasp, :provider], :update?
|
|
||||||
|
|
||||||
@callbacks = Fasp::DebugCallback
|
|
||||||
.includes(:fasp_provider)
|
|
||||||
.order(created_at: :desc)
|
|
||||||
end
|
|
||||||
|
|
||||||
def destroy
|
|
||||||
authorize [:admin, :fasp, :provider], :update?
|
|
||||||
|
|
||||||
callback = Fasp::DebugCallback.find(params[:id])
|
|
||||||
callback.destroy
|
|
||||||
|
|
||||||
redirect_to admin_fasp_debug_callbacks_path
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,19 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Admin::Fasp::DebugCallsController < Admin::BaseController
|
|
||||||
before_action :set_provider
|
|
||||||
|
|
||||||
def create
|
|
||||||
authorize [:admin, @provider], :update?
|
|
||||||
|
|
||||||
@provider.perform_debug_call
|
|
||||||
|
|
||||||
redirect_to admin_fasp_providers_path
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def set_provider
|
|
||||||
@provider = Fasp::Provider.find(params[:provider_id])
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,47 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Admin::Fasp::ProvidersController < Admin::BaseController
|
|
||||||
before_action :set_provider, only: [:show, :edit, :update, :destroy]
|
|
||||||
|
|
||||||
def index
|
|
||||||
authorize [:admin, :fasp, :provider], :index?
|
|
||||||
|
|
||||||
@providers = Fasp::Provider.order(confirmed: :asc, created_at: :desc)
|
|
||||||
end
|
|
||||||
|
|
||||||
def show
|
|
||||||
authorize [:admin, @provider], :show?
|
|
||||||
end
|
|
||||||
|
|
||||||
def edit
|
|
||||||
authorize [:admin, @provider], :update?
|
|
||||||
end
|
|
||||||
|
|
||||||
def update
|
|
||||||
authorize [:admin, @provider], :update?
|
|
||||||
|
|
||||||
if @provider.update(provider_params)
|
|
||||||
redirect_to admin_fasp_providers_path
|
|
||||||
else
|
|
||||||
render :edit
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def destroy
|
|
||||||
authorize [:admin, @provider], :destroy?
|
|
||||||
|
|
||||||
@provider.destroy
|
|
||||||
|
|
||||||
redirect_to admin_fasp_providers_path
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def provider_params
|
|
||||||
params.expect(fasp_provider: [capabilities_attributes: {}])
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_provider
|
|
||||||
@provider = Fasp::Provider.find(params[:id])
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,23 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Admin::Fasp::RegistrationsController < Admin::BaseController
|
|
||||||
before_action :set_provider
|
|
||||||
|
|
||||||
def new
|
|
||||||
authorize [:admin, @provider], :create?
|
|
||||||
end
|
|
||||||
|
|
||||||
def create
|
|
||||||
authorize [:admin, @provider], :create?
|
|
||||||
|
|
||||||
@provider.update_info!(confirm: true)
|
|
||||||
|
|
||||||
redirect_to edit_admin_fasp_provider_path(@provider)
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def set_provider
|
|
||||||
@provider = Fasp::Provider.find(params[:provider_id])
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -37,8 +37,7 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def form_account_batch_params
|
def form_account_batch_params
|
||||||
params
|
params.require(:form_account_batch).permit(:action, account_ids: [])
|
||||||
.expect(form_account_batch: [:action, account_ids: []])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def filter_params
|
def filter_params
|
||||||
|
|
|
@ -79,11 +79,11 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def resource_params
|
def resource_params
|
||||||
params.expect(friend_domain: [:domain, :inbox_url, :available, :pseudo_relay, :delivery_local, :unlocked, :allow_all_posts])
|
params.require(:friend_domain).permit(:domain, :inbox_url, :available, :pseudo_relay, :delivery_local, :unlocked, :allow_all_posts)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_resource_params
|
def update_resource_params
|
||||||
params.expect(friend_domain: [:inbox_url, :available, :pseudo_relay, :delivery_local, :unlocked, :allow_all_posts])
|
params.require(:friend_domain).permit(:inbox_url, :available, :pseudo_relay, :delivery_local, :unlocked, :allow_all_posts)
|
||||||
end
|
end
|
||||||
|
|
||||||
def warn_signatures_not_enabled!
|
def warn_signatures_not_enabled!
|
||||||
|
|
|
@ -5,8 +5,6 @@ module Admin
|
||||||
before_action :set_instances, only: :index
|
before_action :set_instances, only: :index
|
||||||
before_action :set_instance, except: :index
|
before_action :set_instance, except: :index
|
||||||
|
|
||||||
LOGS_LIMIT = 5
|
|
||||||
|
|
||||||
def index
|
def index
|
||||||
authorize :instance, :index?
|
authorize :instance, :index?
|
||||||
preload_delivery_failures!
|
preload_delivery_failures!
|
||||||
|
@ -15,7 +13,7 @@ module Admin
|
||||||
def show
|
def show
|
||||||
authorize :instance, :show?
|
authorize :instance, :show?
|
||||||
@time_period = (6.days.ago.to_date...Time.now.utc.to_date)
|
@time_period = (6.days.ago.to_date...Time.now.utc.to_date)
|
||||||
@action_logs = Admin::ActionLogFilter.new(target_domain: @instance.domain).results.limit(LOGS_LIMIT)
|
@action_logs = Admin::ActionLogFilter.new(target_domain: @instance.domain).results.limit(5)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
|
|
@ -32,15 +32,14 @@ module Admin
|
||||||
|
|
||||||
def deactivate_all
|
def deactivate_all
|
||||||
authorize :invite, :deactivate_all?
|
authorize :invite, :deactivate_all?
|
||||||
Invite.available.in_batches.touch_all(:expires_at)
|
Invite.available.in_batches.update_all(expires_at: Time.now.utc)
|
||||||
redirect_to admin_invites_path
|
redirect_to admin_invites_path
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def resource_params
|
def resource_params
|
||||||
params
|
params.require(:invite).permit(:max_uses, :expires_in)
|
||||||
.expect(invite: [:max_uses, :expires_in])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def filtered_invites
|
def filtered_invites
|
||||||
|
|
|
@ -44,8 +44,7 @@ module Admin
|
||||||
private
|
private
|
||||||
|
|
||||||
def resource_params
|
def resource_params
|
||||||
params
|
params.require(:ip_block).permit(:ip, :severity, :comment, :expires_in)
|
||||||
.expect(ip_block: [:ip, :severity, :comment, :expires_in])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def action_from_button
|
def action_from_button
|
||||||
|
@ -53,8 +52,7 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def form_ip_block_batch_params
|
def form_ip_block_batch_params
|
||||||
params
|
params.require(:form_ip_block_batch).permit(ip_block_ids: [])
|
||||||
.expect(form_ip_block_batch: [ip_block_ids: []])
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -82,16 +82,16 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def resource_params
|
def resource_params
|
||||||
params.expect(ng_rule: [:title, :expires_in, :available, :account_domain, :account_username, :account_display_name,
|
params.require(:ng_rule).permit(:title, :expires_in, :available, :account_domain, :account_username, :account_display_name,
|
||||||
:account_note, :account_field_name, :account_field_value, :account_avatar_state,
|
:account_note, :account_field_name, :account_field_value, :account_avatar_state,
|
||||||
:account_header_state, :account_include_local, :status_spoiler_text, :status_text, :status_tag,
|
:account_header_state, :account_include_local, :status_spoiler_text, :status_text, :status_tag,
|
||||||
:status_sensitive_state, :status_cw_state, :status_media_state, :status_poll_state,
|
:status_sensitive_state, :status_cw_state, :status_media_state, :status_poll_state,
|
||||||
:status_mention_state, :status_reference_state,
|
:status_mention_state, :status_reference_state,
|
||||||
:status_quote_state, :status_reply_state, :status_media_threshold, :status_poll_threshold,
|
:status_quote_state, :status_reply_state, :status_media_threshold, :status_poll_threshold,
|
||||||
:status_mention_threshold, :status_allow_follower_mention,
|
:status_mention_threshold, :status_allow_follower_mention,
|
||||||
:reaction_allow_follower, :emoji_reaction_name, :emoji_reaction_origin_domain,
|
:reaction_allow_follower, :emoji_reaction_name, :emoji_reaction_origin_domain,
|
||||||
:status_reference_threshold, :account_allow_followed_by_local, :record_history_also_local,
|
:status_reference_threshold, :account_allow_followed_by_local, :record_history_also_local,
|
||||||
status_visibility: [], status_searchability: [], reaction_type: []])
|
status_visibility: [], status_searchability: [], reaction_type: [])
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_words!
|
def test_words!
|
||||||
|
|
|
@ -21,10 +21,6 @@ module Admin
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
def avoid_save?
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def after_update_redirect_path
|
def after_update_redirect_path
|
||||||
|
|
|
@ -13,12 +13,6 @@ module Admin
|
||||||
|
|
||||||
return unless validate
|
return unless validate
|
||||||
|
|
||||||
if avoid_save?
|
|
||||||
flash[:notice] = I18n.t('generic.changes_saved_msg')
|
|
||||||
redirect_to after_update_redirect_path
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
@admin_settings = Form::AdminSettings.new(settings_params)
|
@admin_settings = Form::AdminSettings.new(settings_params)
|
||||||
|
|
||||||
if @admin_settings.save
|
if @admin_settings.save
|
||||||
|
@ -39,18 +33,14 @@ module Admin
|
||||||
admin_ng_words_path
|
admin_ng_words_path
|
||||||
end
|
end
|
||||||
|
|
||||||
def avoid_save?
|
|
||||||
false
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def settings_params
|
def settings_params
|
||||||
params.expect(form_admin_settings: [*Form::AdminSettings::KEYS])
|
params.require(:form_admin_settings).permit(*Form::AdminSettings::KEYS)
|
||||||
end
|
end
|
||||||
|
|
||||||
def settings_params_test
|
def settings_params_test
|
||||||
params.expect(form_admin_settings: [ng_words_test: [keywords: [], regexps: [], strangers: [], temporary_ids: []]])['ng_words_test']
|
params.require(:form_admin_settings)[:ng_words_test]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -21,7 +21,6 @@ module Admin
|
||||||
@relay = Relay.new(resource_params)
|
@relay = Relay.new(resource_params)
|
||||||
|
|
||||||
if @relay.save
|
if @relay.save
|
||||||
log_action :create, @relay
|
|
||||||
@relay.enable!
|
@relay.enable!
|
||||||
redirect_to admin_relays_path
|
redirect_to admin_relays_path
|
||||||
else
|
else
|
||||||
|
@ -32,21 +31,18 @@ module Admin
|
||||||
def destroy
|
def destroy
|
||||||
authorize :relay, :update?
|
authorize :relay, :update?
|
||||||
@relay.destroy
|
@relay.destroy
|
||||||
log_action :destroy, @relay
|
|
||||||
redirect_to admin_relays_path
|
redirect_to admin_relays_path
|
||||||
end
|
end
|
||||||
|
|
||||||
def enable
|
def enable
|
||||||
authorize :relay, :update?
|
authorize :relay, :update?
|
||||||
@relay.enable!
|
@relay.enable!
|
||||||
log_action :enable, @relay
|
|
||||||
redirect_to admin_relays_path
|
redirect_to admin_relays_path
|
||||||
end
|
end
|
||||||
|
|
||||||
def disable
|
def disable
|
||||||
authorize :relay, :update?
|
authorize :relay, :update?
|
||||||
@relay.disable!
|
@relay.disable!
|
||||||
log_action :disable, @relay
|
|
||||||
redirect_to admin_relays_path
|
redirect_to admin_relays_path
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -57,8 +53,7 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def resource_params
|
def resource_params
|
||||||
params
|
params.require(:relay).permit(:inbox_url)
|
||||||
.expect(relay: [:inbox_url])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def warn_signatures_not_enabled!
|
def warn_signatures_not_enabled!
|
||||||
|
|
|
@ -47,8 +47,10 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def resource_params
|
def resource_params
|
||||||
params
|
params.require(:report_note).permit(
|
||||||
.expect(report_note: [:content, :report_id])
|
:content,
|
||||||
|
:report_id
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_report_note
|
def set_report_note
|
||||||
|
|
|
@ -61,8 +61,7 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def resource_params
|
def resource_params
|
||||||
params
|
params.require(:user_role).permit(:name, :color, :highlighted, :position, permissions_as_keys: [])
|
||||||
.expect(user_role: [:name, :color, :highlighted, :position, permissions_as_keys: []])
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -53,8 +53,7 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def resource_params
|
def resource_params
|
||||||
params
|
params.require(:rule).permit(:text, :hint, :priority)
|
||||||
.expect(rule: [:text, :hint, :priority])
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -37,7 +37,7 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def settings_params
|
def settings_params
|
||||||
params.expect(form_admin_settings: [*Form::AdminSettings::KEYS])
|
params.require(:form_admin_settings).permit(*Form::AdminSettings::KEYS)
|
||||||
end
|
end
|
||||||
|
|
||||||
def settings_params_test
|
def settings_params_test
|
||||||
|
|
|
@ -28,8 +28,7 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def settings_params
|
def settings_params
|
||||||
params
|
params.require(:form_admin_settings).permit(*Form::AdminSettings::KEYS)
|
||||||
.expect(form_admin_settings: [*Form::AdminSettings::KEYS])
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,7 +6,7 @@ module Admin
|
||||||
|
|
||||||
def index
|
def index
|
||||||
authorize :software_update, :index?
|
authorize :software_update, :index?
|
||||||
@software_updates = SoftwareUpdate.by_version.filter(&:pending?)
|
@software_updates = SoftwareUpdate.all.sort_by(&:gem_version)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -28,7 +28,7 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def settings_params
|
def settings_params
|
||||||
params.expect(form_admin_settings: [*Form::AdminSettings::KEYS])
|
params.require(:form_admin_settings).permit(*Form::AdminSettings::KEYS)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -28,7 +28,7 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def settings_params
|
def settings_params
|
||||||
params.expect(form_admin_settings: [*Form::AdminSettings::KEYS])
|
params.require(:form_admin_settings).permit(*Form::AdminSettings::KEYS)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,8 +16,6 @@ module Admin
|
||||||
|
|
||||||
def show
|
def show
|
||||||
authorize [:admin, @status], :show?
|
authorize [:admin, @status], :show?
|
||||||
|
|
||||||
@status_batch_action = Admin::StatusBatchAction.new
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def batch
|
def batch
|
||||||
|
@ -98,8 +96,7 @@ module Admin
|
||||||
helper_method :batched_ordered_status_edits
|
helper_method :batched_ordered_status_edits
|
||||||
|
|
||||||
def admin_status_batch_action_params
|
def admin_status_batch_action_params
|
||||||
params
|
params.require(:admin_status_batch_action).permit(status_ids: [])
|
||||||
.expect(admin_status_batch_action: [status_ids: []])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def after_create_redirect_path
|
def after_create_redirect_path
|
||||||
|
|
|
@ -37,8 +37,7 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def tag_params
|
def tag_params
|
||||||
params
|
params.require(:tag).permit(:name, :display_name, :trendable, :usable, :listable)
|
||||||
.expect(tag: [:name, :display_name, :trendable, :usable, :listable])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def filtered_tags
|
def filtered_tags
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Admin::TermsOfService::DistributionsController < Admin::BaseController
|
|
||||||
before_action :set_terms_of_service
|
|
||||||
|
|
||||||
def create
|
|
||||||
authorize @terms_of_service, :distribute?
|
|
||||||
@terms_of_service.touch(:notification_sent_at)
|
|
||||||
Admin::DistributeTermsOfServiceNotificationWorker.perform_async(@terms_of_service.id)
|
|
||||||
redirect_to admin_terms_of_service_index_path
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def set_terms_of_service
|
|
||||||
@terms_of_service = TermsOfService.find(params[:terms_of_service_id])
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,37 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Admin::TermsOfService::DraftsController < Admin::BaseController
|
|
||||||
before_action :set_terms_of_service
|
|
||||||
|
|
||||||
def show
|
|
||||||
authorize :terms_of_service, :create?
|
|
||||||
end
|
|
||||||
|
|
||||||
def update
|
|
||||||
authorize @terms_of_service, :update?
|
|
||||||
|
|
||||||
@terms_of_service.published_at = Time.now.utc if params[:action_type] == 'publish'
|
|
||||||
|
|
||||||
if @terms_of_service.update(resource_params)
|
|
||||||
log_action(:publish, @terms_of_service) if @terms_of_service.published?
|
|
||||||
redirect_to @terms_of_service.published? ? admin_terms_of_service_index_path : admin_terms_of_service_draft_path
|
|
||||||
else
|
|
||||||
render :show
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def set_terms_of_service
|
|
||||||
@terms_of_service = TermsOfService.draft.first || TermsOfService.new(text: current_terms_of_service&.text, effective_date: 10.days.from_now)
|
|
||||||
end
|
|
||||||
|
|
||||||
def current_terms_of_service
|
|
||||||
TermsOfService.live.first
|
|
||||||
end
|
|
||||||
|
|
||||||
def resource_params
|
|
||||||
params
|
|
||||||
.expect(terms_of_service: [:text, :changelog, :effective_date])
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,38 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Admin::TermsOfService::GeneratesController < Admin::BaseController
|
|
||||||
before_action :set_instance_presenter
|
|
||||||
|
|
||||||
def show
|
|
||||||
authorize :terms_of_service, :create?
|
|
||||||
|
|
||||||
@generator = TermsOfService::Generator.new(
|
|
||||||
domain: @instance_presenter.domain,
|
|
||||||
admin_email: @instance_presenter.contact.email
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def create
|
|
||||||
authorize :terms_of_service, :create?
|
|
||||||
|
|
||||||
@generator = TermsOfService::Generator.new(resource_params)
|
|
||||||
|
|
||||||
if @generator.valid?
|
|
||||||
TermsOfService.create!(text: @generator.render)
|
|
||||||
redirect_to admin_terms_of_service_draft_path
|
|
||||||
else
|
|
||||||
render :show
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def set_instance_presenter
|
|
||||||
@instance_presenter = InstancePresenter.new
|
|
||||||
end
|
|
||||||
|
|
||||||
def resource_params
|
|
||||||
params
|
|
||||||
.expect(terms_of_service_generator: [*TermsOfService::Generator::VARIABLES])
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,8 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Admin::TermsOfService::HistoriesController < Admin::BaseController
|
|
||||||
def show
|
|
||||||
authorize :terms_of_service, :index?
|
|
||||||
@terms_of_service = TermsOfService.published.all
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,16 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Admin::TermsOfService::PreviewsController < Admin::BaseController
|
|
||||||
before_action :set_terms_of_service
|
|
||||||
|
|
||||||
def show
|
|
||||||
authorize @terms_of_service, :distribute?
|
|
||||||
@user_count = @terms_of_service.scope_for_notification.count
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def set_terms_of_service
|
|
||||||
@terms_of_service = TermsOfService.find(params[:terms_of_service_id])
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,17 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Admin::TermsOfService::TestsController < Admin::BaseController
|
|
||||||
before_action :set_terms_of_service
|
|
||||||
|
|
||||||
def create
|
|
||||||
authorize @terms_of_service, :distribute?
|
|
||||||
UserMailer.terms_of_service_changed(current_user, @terms_of_service).deliver_later!
|
|
||||||
redirect_to admin_terms_of_service_preview_path(@terms_of_service)
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def set_terms_of_service
|
|
||||||
@terms_of_service = TermsOfService.find(params[:terms_of_service_id])
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,8 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Admin::TermsOfServiceController < Admin::BaseController
|
|
||||||
def index
|
|
||||||
authorize :terms_of_service, :index?
|
|
||||||
@terms_of_service = TermsOfService.published.first
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -4,7 +4,6 @@ class Admin::Trends::Links::PreviewCardProvidersController < Admin::BaseControll
|
||||||
def index
|
def index
|
||||||
authorize :preview_card_provider, :review?
|
authorize :preview_card_provider, :review?
|
||||||
|
|
||||||
@pending_preview_card_providers_count = PreviewCardProvider.unreviewed.async_count
|
|
||||||
@preview_card_providers = filtered_preview_card_providers.page(params[:page])
|
@preview_card_providers = filtered_preview_card_providers.page(params[:page])
|
||||||
@form = Trends::PreviewCardProviderBatch.new
|
@form = Trends::PreviewCardProviderBatch.new
|
||||||
end
|
end
|
||||||
|
@ -31,8 +30,7 @@ class Admin::Trends::Links::PreviewCardProvidersController < Admin::BaseControll
|
||||||
end
|
end
|
||||||
|
|
||||||
def trends_preview_card_provider_batch_params
|
def trends_preview_card_provider_batch_params
|
||||||
params
|
params.require(:trends_preview_card_provider_batch).permit(:action, preview_card_provider_ids: [])
|
||||||
.expect(trends_preview_card_provider_batch: [:action, preview_card_provider_ids: []])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def action_from_button
|
def action_from_button
|
||||||
|
|
|
@ -4,7 +4,7 @@ class Admin::Trends::LinksController < Admin::BaseController
|
||||||
def index
|
def index
|
||||||
authorize :preview_card, :review?
|
authorize :preview_card, :review?
|
||||||
|
|
||||||
@locales = PreviewCardTrend.locales
|
@locales = PreviewCardTrend.pluck('distinct language')
|
||||||
@preview_cards = filtered_preview_cards.page(params[:page])
|
@preview_cards = filtered_preview_cards.page(params[:page])
|
||||||
@form = Trends::PreviewCardBatch.new
|
@form = Trends::PreviewCardBatch.new
|
||||||
end
|
end
|
||||||
|
@ -31,8 +31,7 @@ class Admin::Trends::LinksController < Admin::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def trends_preview_card_batch_params
|
def trends_preview_card_batch_params
|
||||||
params
|
params.require(:trends_preview_card_batch).permit(:action, preview_card_ids: [])
|
||||||
.expect(trends_preview_card_batch: [:action, preview_card_ids: []])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def action_from_button
|
def action_from_button
|
||||||
|
|
|
@ -4,7 +4,7 @@ class Admin::Trends::StatusesController < Admin::BaseController
|
||||||
def index
|
def index
|
||||||
authorize [:admin, :status], :review?
|
authorize [:admin, :status], :review?
|
||||||
|
|
||||||
@locales = StatusTrend.locales
|
@locales = StatusTrend.pluck('distinct language')
|
||||||
@statuses = filtered_statuses.page(params[:page])
|
@statuses = filtered_statuses.page(params[:page])
|
||||||
@form = Trends::StatusBatch.new
|
@form = Trends::StatusBatch.new
|
||||||
end
|
end
|
||||||
|
@ -31,8 +31,7 @@ class Admin::Trends::StatusesController < Admin::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def trends_status_batch_params
|
def trends_status_batch_params
|
||||||
params
|
params.require(:trends_status_batch).permit(:action, status_ids: [])
|
||||||
.expect(trends_status_batch: [:action, status_ids: []])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def action_from_button
|
def action_from_button
|
||||||
|
|
|
@ -4,7 +4,6 @@ class Admin::Trends::TagsController < Admin::BaseController
|
||||||
def index
|
def index
|
||||||
authorize :tag, :review?
|
authorize :tag, :review?
|
||||||
|
|
||||||
@pending_tags_count = Tag.pending_review.async_count
|
|
||||||
@tags = filtered_tags.page(params[:page])
|
@tags = filtered_tags.page(params[:page])
|
||||||
@form = Trends::TagBatch.new
|
@form = Trends::TagBatch.new
|
||||||
end
|
end
|
||||||
|
@ -31,8 +30,7 @@ class Admin::Trends::TagsController < Admin::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def trends_tag_batch_params
|
def trends_tag_batch_params
|
||||||
params
|
params.require(:trends_tag_batch).permit(:action, tag_ids: [])
|
||||||
.expect(trends_tag_batch: [:action, tag_ids: []])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def action_from_button
|
def action_from_button
|
||||||
|
|
|
@ -28,8 +28,7 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def resource_params
|
def resource_params
|
||||||
params
|
params.require(:user).permit(:role_id)
|
||||||
.expect(user: [:role_id])
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -52,8 +52,7 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def warning_preset_params
|
def warning_preset_params
|
||||||
params
|
params.require(:account_warning_preset).permit(:title, :text)
|
||||||
.expect(account_warning_preset: [:title, :text])
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -74,8 +74,7 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def resource_params
|
def resource_params
|
||||||
params
|
params.require(:webhook).permit(:url, :template, events: [])
|
||||||
.expect(webhook: [:url, :template, events: []])
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
51
app/controllers/antennas_controller.rb
Normal file
51
app/controllers/antennas_controller.rb
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class AntennasController < ApplicationController
|
||||||
|
layout 'admin'
|
||||||
|
|
||||||
|
before_action :authenticate_user!
|
||||||
|
before_action :set_antenna, only: [:edit, :update, :destroy]
|
||||||
|
before_action :set_body_classes
|
||||||
|
before_action :set_cache_headers
|
||||||
|
|
||||||
|
def index
|
||||||
|
@antennas = current_account.antennas.includes(:antenna_domains).includes(:antenna_tags).includes(:antenna_accounts)
|
||||||
|
end
|
||||||
|
|
||||||
|
def edit; end
|
||||||
|
|
||||||
|
def update
|
||||||
|
if @antenna.update(resource_params)
|
||||||
|
redirect_to antennas_path
|
||||||
|
else
|
||||||
|
render action: :edit
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
@antenna.destroy
|
||||||
|
redirect_to antennas_path
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def set_antenna
|
||||||
|
@antenna = current_account.antennas.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def resource_params
|
||||||
|
params.require(:antenna).permit(:title, :available, :expires_in)
|
||||||
|
end
|
||||||
|
|
||||||
|
def thin_resource_params
|
||||||
|
params.require(:antenna).permit(:title)
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_body_classes
|
||||||
|
@body_classes = 'admin'
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_cache_headers
|
||||||
|
response.cache_control.replace(private: true, no_store: true)
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,81 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Api::Fasp::BaseController < ApplicationController
|
|
||||||
class Error < ::StandardError; end
|
|
||||||
|
|
||||||
DIGEST_PATTERN = /sha-256=:(.*?):/
|
|
||||||
KEYID_PATTERN = /keyid="(.*?)"/
|
|
||||||
|
|
||||||
attr_reader :current_provider
|
|
||||||
|
|
||||||
skip_forgery_protection
|
|
||||||
|
|
||||||
before_action :check_fasp_enabled
|
|
||||||
before_action :require_authentication
|
|
||||||
after_action :sign_response
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def require_authentication
|
|
||||||
validate_content_digest!
|
|
||||||
validate_signature!
|
|
||||||
rescue Error, Linzer::Error, ActiveRecord::RecordNotFound => e
|
|
||||||
logger.debug("FASP Authentication error: #{e}")
|
|
||||||
authentication_error
|
|
||||||
end
|
|
||||||
|
|
||||||
def authentication_error
|
|
||||||
respond_to do |format|
|
|
||||||
format.json { head 401 }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def validate_content_digest!
|
|
||||||
content_digest_header = request.headers['content-digest']
|
|
||||||
raise Error, 'content-digest missing' if content_digest_header.blank?
|
|
||||||
|
|
||||||
digest_received = content_digest_header.match(DIGEST_PATTERN)[1]
|
|
||||||
|
|
||||||
digest_computed = OpenSSL::Digest.base64digest('sha256', request.body&.string || '')
|
|
||||||
|
|
||||||
raise Error, 'content-digest does not match' if digest_received != digest_computed
|
|
||||||
end
|
|
||||||
|
|
||||||
def validate_signature!
|
|
||||||
signature_input = request.headers['signature-input']&.encode('UTF-8')
|
|
||||||
raise Error, 'signature-input is missing' if signature_input.blank?
|
|
||||||
|
|
||||||
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)
|
|
||||||
end
|
|
||||||
|
|
||||||
def check_fasp_enabled
|
|
||||||
raise ActionController::RoutingError unless Mastodon::Feature.fasp_enabled?
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,15 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Api::Fasp::Debug::V0::Callback::ResponsesController < Api::Fasp::BaseController
|
|
||||||
def create
|
|
||||||
Fasp::DebugCallback.create(
|
|
||||||
fasp_provider: current_provider,
|
|
||||||
ip: request.remote_ip,
|
|
||||||
request_body: request.raw_post
|
|
||||||
)
|
|
||||||
|
|
||||||
respond_to do |format|
|
|
||||||
format.json { head 201 }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,26 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Api::Fasp::RegistrationsController < Api::Fasp::BaseController
|
|
||||||
skip_before_action :require_authentication
|
|
||||||
|
|
||||||
def create
|
|
||||||
@current_provider = Fasp::Provider.create!(
|
|
||||||
name: params[:name],
|
|
||||||
base_url: params[:baseUrl],
|
|
||||||
remote_identifier: params[:serverId],
|
|
||||||
provider_public_key_base64: params[:publicKey]
|
|
||||||
)
|
|
||||||
|
|
||||||
render json: registration_confirmation
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def registration_confirmation
|
|
||||||
{
|
|
||||||
faspId: current_provider.id.to_s,
|
|
||||||
publicKey: current_provider.server_public_key_base64,
|
|
||||||
registrationCompletionUri: new_admin_fasp_provider_registration_url(current_provider),
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -14,7 +14,7 @@ class Api::V1::Accounts::CredentialsController < Api::BaseController
|
||||||
@account = current_account
|
@account = current_account
|
||||||
UpdateAccountService.new.call(@account, account_params, raise_error: true)
|
UpdateAccountService.new.call(@account, account_params, raise_error: true)
|
||||||
current_user.update(user_params) if user_params
|
current_user.update(user_params) if user_params
|
||||||
ActivityPub::UpdateDistributionWorker.perform_in(ActivityPub::UpdateDistributionWorker::DEBOUNCE_DELAY, @account.id)
|
ActivityPub::UpdateDistributionWorker.perform_async(@account.id)
|
||||||
render json: @account, serializer: REST::CredentialAccountSerializer
|
render json: @account, serializer: REST::CredentialAccountSerializer
|
||||||
rescue ActiveRecord::RecordInvalid => e
|
rescue ActiveRecord::RecordInvalid => e
|
||||||
render json: ValidationErrorFormatter.new(e).as_json, status: 422
|
render json: ValidationErrorFormatter.new(e).as_json, status: 422
|
||||||
|
@ -34,7 +34,6 @@ class Api::V1::Accounts::CredentialsController < Api::BaseController
|
||||||
:searchability,
|
:searchability,
|
||||||
:hide_collections,
|
:hide_collections,
|
||||||
:indexable,
|
:indexable,
|
||||||
attribution_domains: [],
|
|
||||||
fields_attributes: [:name, :value]
|
fields_attributes: [:name, :value]
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,66 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Api::V1::Accounts::EndorsementsController < Api::BaseController
|
|
||||||
include Authorization
|
|
||||||
|
|
||||||
before_action -> { authorize_if_got_token! :read, :'read:accounts' }, only: :index
|
|
||||||
before_action -> { doorkeeper_authorize! :write, :'write:accounts' }, except: :index
|
|
||||||
before_action :require_user!, except: :index
|
|
||||||
before_action :set_account
|
|
||||||
before_action :set_endorsed_accounts, only: :index
|
|
||||||
after_action :insert_pagination_headers, only: :index
|
|
||||||
|
|
||||||
def index
|
|
||||||
cache_if_unauthenticated!
|
|
||||||
render json: @endorsed_accounts, each_serializer: REST::AccountSerializer
|
|
||||||
end
|
|
||||||
|
|
||||||
def create
|
|
||||||
AccountPin.find_or_create_by!(account: current_account, target_account: @account)
|
|
||||||
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships_presenter
|
|
||||||
end
|
|
||||||
|
|
||||||
def destroy
|
|
||||||
pin = AccountPin.find_by(account: current_account, target_account: @account)
|
|
||||||
pin&.destroy!
|
|
||||||
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships_presenter
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def set_account
|
|
||||||
@account = Account.find(params[:account_id])
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_endorsed_accounts
|
|
||||||
@endorsed_accounts = @account.unavailable? ? [] : paginated_endorsed_accounts
|
|
||||||
end
|
|
||||||
|
|
||||||
def paginated_endorsed_accounts
|
|
||||||
@account.endorsed_accounts.without_suspended.includes(:account_stat, :user).paginate_by_max_id(
|
|
||||||
limit_param(DEFAULT_ACCOUNTS_LIMIT),
|
|
||||||
params[:max_id],
|
|
||||||
params[:since_id]
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def relationships_presenter
|
|
||||||
AccountRelationshipsPresenter.new([@account], current_user.account_id)
|
|
||||||
end
|
|
||||||
|
|
||||||
def next_path
|
|
||||||
api_v1_account_endorsements_url pagination_params(max_id: pagination_max_id) if records_continue?
|
|
||||||
end
|
|
||||||
|
|
||||||
def prev_path
|
|
||||||
api_v1_account_endorsements_url pagination_params(since_id: pagination_since_id) unless @endorsed_accounts.empty?
|
|
||||||
end
|
|
||||||
|
|
||||||
def pagination_collection
|
|
||||||
@endorsed_accounts
|
|
||||||
end
|
|
||||||
|
|
||||||
def records_continue?
|
|
||||||
@endorsed_accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -6,7 +6,7 @@ class Api::V1::Accounts::ExcludeAntennasController < Api::BaseController
|
||||||
before_action :set_account
|
before_action :set_account
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@antennas = @account.suspended? ? [] : current_account.antennas.where("exclude_accounts @> '#{@account.id}'")
|
@antennas = @account.suspended? ? [] : current_account.antennas.where('exclude_accounts @> \'[?]\'', @account.id)
|
||||||
render json: @antennas, each_serializer: REST::AntennaSerializer
|
render json: @antennas, each_serializer: REST::AntennaSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ class Api::V1::Accounts::FamiliarFollowersController < Api::BaseController
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_accounts
|
def set_accounts
|
||||||
@accounts = Account.without_suspended.where(id: account_ids).select(:id, :hide_collections)
|
@accounts = Account.without_suspended.where(id: account_ids).select('id, hide_collections')
|
||||||
end
|
end
|
||||||
|
|
||||||
def familiar_followers
|
def familiar_followers
|
||||||
|
|
|
@ -17,6 +17,6 @@ class Api::V1::Accounts::FeaturedTagsController < Api::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_featured_tags
|
def set_featured_tags
|
||||||
@featured_tags = @account.unavailable? ? [] : @account.featured_tags
|
@featured_tags = @account.suspended? ? [] : @account.featured_tags
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::Accounts::IdentityProofsController < Api::BaseController
|
class Api::V1::Accounts::IdentityProofsController < Api::BaseController
|
||||||
include DeprecationConcern
|
|
||||||
|
|
||||||
deprecate_api '2022-03-30'
|
|
||||||
|
|
||||||
before_action :require_user!
|
before_action :require_user!
|
||||||
before_action :set_account
|
before_action :set_account
|
||||||
|
|
||||||
|
|
30
app/controllers/api/v1/accounts/pins_controller.rb
Normal file
30
app/controllers/api/v1/accounts/pins_controller.rb
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Api::V1::Accounts::PinsController < Api::BaseController
|
||||||
|
include Authorization
|
||||||
|
|
||||||
|
before_action -> { doorkeeper_authorize! :write, :'write:accounts' }
|
||||||
|
before_action :require_user!
|
||||||
|
before_action :set_account
|
||||||
|
|
||||||
|
def create
|
||||||
|
AccountPin.find_or_create_by!(account: current_account, target_account: @account)
|
||||||
|
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships_presenter
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
pin = AccountPin.find_by(account: current_account, target_account: @account)
|
||||||
|
pin&.destroy!
|
||||||
|
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships_presenter
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def set_account
|
||||||
|
@account = Account.find(params[:account_id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def relationships_presenter
|
||||||
|
AccountRelationshipsPresenter.new([@account], current_user.account_id)
|
||||||
|
end
|
||||||
|
end
|
|
@ -16,7 +16,6 @@ class Api::V1::AccountsController < Api::BaseController
|
||||||
before_action :check_account_confirmation, except: [:index, :create]
|
before_action :check_account_confirmation, except: [:index, :create]
|
||||||
before_action :check_enabled_registrations, only: [:create]
|
before_action :check_enabled_registrations, only: [:create]
|
||||||
before_action :check_accounts_limit, only: [:index]
|
before_action :check_accounts_limit, only: [:index]
|
||||||
before_action :check_following_self, only: [:follow]
|
|
||||||
|
|
||||||
skip_before_action :require_authenticated_user!, only: :create
|
skip_before_action :require_authenticated_user!, only: :create
|
||||||
|
|
||||||
|
@ -107,12 +106,8 @@ class Api::V1::AccountsController < Api::BaseController
|
||||||
raise(Mastodon::ValidationError) if account_ids.size > DEFAULT_ACCOUNTS_LIMIT
|
raise(Mastodon::ValidationError) if account_ids.size > DEFAULT_ACCOUNTS_LIMIT
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_following_self
|
def relationships(**options)
|
||||||
render json: { error: I18n.t('accounts.self_follow_error') }, status: 403 if current_user.account.id == @account.id
|
AccountRelationshipsPresenter.new([@account], current_user.account_id, **options)
|
||||||
end
|
|
||||||
|
|
||||||
def relationships(**)
|
|
||||||
AccountRelationshipsPresenter.new([@account], current_user.account_id, **)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def account_ids
|
def account_ids
|
||||||
|
@ -124,7 +119,7 @@ class Api::V1::AccountsController < Api::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def account_params
|
def account_params
|
||||||
params.permit(:username, :email, :password, :agreement, :locale, :reason, :time_zone, :invite_code, :date_of_birth)
|
params.permit(:username, :email, :password, :agreement, :locale, :reason, :time_zone, :invite_code)
|
||||||
end
|
end
|
||||||
|
|
||||||
def invite
|
def invite
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue